diff options
Diffstat (limited to 'editor')
161 files changed, 7520 insertions, 4893 deletions
diff --git a/editor/SCsub b/editor/SCsub index a9343f7f36..4fa287c33b 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -5,149 +5,14 @@ env.editor_sources = [] import os import os.path -from compat import encode_utf8, byte_to_str, open_utf8, escape_string - -def make_certs_header(target, source, env): - - src = source[0].srcnode().abspath - dst = target[0].srcnode().abspath - f = open(src, "rb") - g = open_utf8(dst, "w") - buf = f.read() - decomp_size = len(buf) - import zlib - buf = zlib.compress(buf) - - g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") - g.write("#ifndef _CERTS_RAW_H\n") - g.write("#define _CERTS_RAW_H\n") - g.write("static const int _certs_compressed_size = " + str(len(buf)) + ";\n") - g.write("static const int _certs_uncompressed_size = " + str(decomp_size) + ";\n") - g.write("static const unsigned char _certs_compressed[] = {\n") - for i in range(len(buf)): - g.write("\t" + byte_to_str(buf[i]) + ",\n") - g.write("};\n") - g.write("#endif") - - g.close() - f.close() - - -def make_doc_header(target, source, env): - - dst = target[0].srcnode().abspath - g = open_utf8(dst, "w") - buf = "" - docbegin = "" - docend = "" - for s in source: - src = s.srcnode().abspath - if not src.endswith(".xml"): - continue - with open_utf8(src, "r") as f: - content = f.read() - buf += content - - buf = encode_utf8(docbegin + buf + docend) - decomp_size = len(buf) - import zlib - buf = zlib.compress(buf) - - g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") - g.write("#ifndef _DOC_DATA_RAW_H\n") - g.write("#define _DOC_DATA_RAW_H\n") - g.write("static const int _doc_data_compressed_size = " + str(len(buf)) + ";\n") - g.write("static const int _doc_data_uncompressed_size = " + str(decomp_size) + ";\n") - g.write("static const unsigned char _doc_data_compressed[] = {\n") - for i in range(len(buf)): - g.write("\t" + byte_to_str(buf[i]) + ",\n") - g.write("};\n") - - g.write("#endif") - - g.close() - - -def make_fonts_header(target, source, env): - - dst = target[0].srcnode().abspath - - g = open_utf8(dst, "w") - - g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") - g.write("#ifndef _EDITOR_FONTS_H\n") - g.write("#define _EDITOR_FONTS_H\n") - - # saving uncompressed, since freetype will reference from memory pointer - xl_names = [] - for i in range(len(source)): - with open(source[i].srcnode().abspath, "rb")as f: - buf = f.read() - - name = os.path.splitext(os.path.basename(source[i].srcnode().abspath))[0] - - g.write("static const int _font_" + name + "_size = " + str(len(buf)) + ";\n") - g.write("static const unsigned char _font_" + name + "[] = {\n") - for i in range(len(buf)): - g.write("\t" + byte_to_str(buf[i]) + ",\n") - - g.write("};\n") - - g.write("#endif") - - g.close() - +from platform_methods import run_in_subprocess +from compat import open_utf8 +import editor_builders -def make_translations_header(target, source, env): - - dst = target[0].srcnode().abspath - - g = open_utf8(dst, "w") - - g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") - g.write("#ifndef _EDITOR_TRANSLATIONS_H\n") - g.write("#define _EDITOR_TRANSLATIONS_H\n") - - import zlib - import os.path - - paths = [node.srcnode().abspath for node in source] - sorted_paths = sorted(paths, key=lambda path: os.path.splitext(os.path.basename(path))[0]) - - xl_names = [] - for i in range(len(sorted_paths)): - with open(sorted_paths[i], "rb") as f: - buf = f.read() - decomp_size = len(buf) - buf = zlib.compress(buf) - name = os.path.splitext(os.path.basename(sorted_paths[i]))[0] - - g.write("static const unsigned char _translation_" + name + "_compressed[] = {\n") - for i in range(len(buf)): - g.write("\t" + byte_to_str(buf[i]) + ",\n") - - g.write("};\n") - - xl_names.append([name, len(buf), str(decomp_size)]) - - g.write("struct EditorTranslationList {\n") - g.write("\tconst char* lang;\n") - g.write("\tint comp_size;\n") - g.write("\tint uncomp_size;\n") - g.write("\tconst unsigned char* data;\n") - g.write("};\n\n") - g.write("static EditorTranslationList _editor_translations[] = {\n") - for x in xl_names: - g.write("\t{ \"" + x[0] + "\", " + str(x[1]) + ", " + str(x[2]) + ", _translation_" + x[0] + "_compressed},\n") - g.write("\t{NULL, 0, 0, NULL}\n") - g.write("};\n") - - g.write("#endif") - - g.close() def _make_doc_data_class_path(to_path): - g = open_utf8(os.path.join(to_path,"doc_data_class_path.gen.h"), "w") + # NOTE: It is safe to generate this file here, since this is still executed serially + g = open_utf8(os.path.join(to_path, "doc_data_class_path.gen.h"), "w") g.write("static const int _doc_data_class_path_count = " + str(len(env.doc_class_path)) + ";\n") g.write("struct _DocDataClassPath { const char* name; const char* path; };\n") @@ -169,6 +34,8 @@ if env['tools']: reg_exporters += '\tregister_' + e + '_exporter();\n' reg_exporters_inc += '#include "platform/' + e + '/export/export.h"\n' reg_exporters += '}\n' + + # NOTE: It is safe to generate this file here, since this is still executed serially with open_utf8("register_exporters.gen.cpp", "w") as f: f.write(reg_exporters_inc) f.write(reg_exporters) @@ -192,24 +59,38 @@ if env['tools']: docs = sorted(docs) env.Depends("#editor/doc_data_compressed.gen.h", docs) - env.CommandNoCache("#editor/doc_data_compressed.gen.h", docs, make_doc_header) + env.CommandNoCache("#editor/doc_data_compressed.gen.h", docs, run_in_subprocess(editor_builders.make_doc_header)) + # Certificates env.Depends("#editor/certs_compressed.gen.h", "#thirdparty/certs/ca-certificates.crt") - env.CommandNoCache("#editor/certs_compressed.gen.h", "#thirdparty/certs/ca-certificates.crt", make_certs_header) + env.CommandNoCache("#editor/certs_compressed.gen.h", "#thirdparty/certs/ca-certificates.crt", run_in_subprocess(editor_builders.make_certs_header)) import glob + path = env.Dir('.').abspath # Translations tlist = glob.glob(path + "/translations/*.po") env.Depends('#editor/translations.gen.h', tlist) - env.CommandNoCache('#editor/translations.gen.h', tlist, make_translations_header) + env.CommandNoCache('#editor/translations.gen.h', tlist, run_in_subprocess(editor_builders.make_translations_header)) # Fonts flist = glob.glob(path + "/../thirdparty/fonts/*.ttf") flist.append(glob.glob(path + "/../thirdparty/fonts/*.otf")) env.Depends('#editor/builtin_fonts.gen.h', flist) - env.CommandNoCache('#editor/builtin_fonts.gen.h', flist, make_fonts_header) + env.CommandNoCache('#editor/builtin_fonts.gen.h', flist, run_in_subprocess(editor_builders.make_fonts_header)) + + # Authors + env.Depends('#editor/authors.gen.h', "../AUTHORS.md") + env.CommandNoCache('#editor/authors.gen.h', "../AUTHORS.md", run_in_subprocess(editor_builders.make_authors_header)) + + # Donors + env.Depends('#editor/donors.gen.h', "../DONORS.md") + env.CommandNoCache('#editor/donors.gen.h', "../DONORS.md", run_in_subprocess(editor_builders.make_donors_header)) + + # License + env.Depends('#editor/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"]) + env.CommandNoCache('#editor/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"], run_in_subprocess(editor_builders.make_license_header)) env.add_source_files(env.editor_sources, "*.cpp") env.add_source_files(env.editor_sources, ["#thirdparty/misc/clipper.cpp"]) diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 42d5ea120e..4c4830ad7a 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -231,10 +231,10 @@ public: if (Variant::can_convert(args[idx].get_type(), t)) { Variant old = args[idx]; Variant *ptrs[1] = { &old }; - args[idx] = Variant::construct(t, (const Variant **)ptrs, 1, err); + args.write[idx] = Variant::construct(t, (const Variant **)ptrs, 1, err); } else { - args[idx] = Variant::construct(t, NULL, 0, err); + args.write[idx] = Variant::construct(t, NULL, 0, err); } change_notify_deserved = true; d_new["args"] = args; @@ -248,7 +248,7 @@ public: _fix_node_path(value); } - args[idx] = value; + args.write[idx] = value; d_new["args"] = args; mergeable = true; } @@ -3014,12 +3014,12 @@ PropertyInfo AnimationTrackEditor::_find_hint_for_track(int p_idx, NodePath &r_b if (res.is_valid()) { property_info_base = res; if (r_current_val) { - *r_current_val = res->get(leftover_path[leftover_path.size() - 1]); + *r_current_val = res->get_indexed(leftover_path); } } else if (node) { property_info_base = node; if (r_current_val) { - *r_current_val = node->get(leftover_path[leftover_path.size() - 1]); + *r_current_val = node->get_indexed(leftover_path); } } @@ -3053,31 +3053,31 @@ static Vector<String> _get_bezier_subindices_for_type(Variant::Type p_type, bool subindices.push_back(""); } break; case Variant::VECTOR2: { - subindices.push_back(".x"); - subindices.push_back(".y"); + subindices.push_back(":x"); + subindices.push_back(":y"); } break; case Variant::VECTOR3: { - subindices.push_back(".x"); - subindices.push_back(".y"); - subindices.push_back(".z"); + subindices.push_back(":x"); + subindices.push_back(":y"); + subindices.push_back(":z"); } break; case Variant::QUAT: { - subindices.push_back(".x"); - subindices.push_back(".y"); - subindices.push_back(".z"); - subindices.push_back(".w"); + subindices.push_back(":x"); + subindices.push_back(":y"); + subindices.push_back(":z"); + subindices.push_back(":w"); } break; case Variant::COLOR: { - subindices.push_back(".r"); - subindices.push_back(".g"); - subindices.push_back(".b"); - subindices.push_back(".a"); + subindices.push_back(":r"); + subindices.push_back(":g"); + subindices.push_back(":b"); + subindices.push_back(":a"); } break; case Variant::PLANE: { - subindices.push_back(".x"); - subindices.push_back(".y"); - subindices.push_back(".z"); - subindices.push_back(".d"); + subindices.push_back(":x"); + subindices.push_back(":y"); + subindices.push_back(":z"); + subindices.push_back(":d"); } break; default: { if (r_valid) { @@ -3288,35 +3288,23 @@ void AnimationTrackEditor::_update_tracks() { if (root && root->has_node_and_resource(path)) { RES res; + NodePath base_path; Vector<StringName> leftover_path; Node *node = root->get_node_and_resource(path, res, leftover_path, true); + PropertyInfo pinfo = _find_hint_for_track(i, base_path); Object *object = node; if (res.is_valid()) { object = res.ptr(); - } else { - object = node; } if (object && !leftover_path.empty()) { - //not a property (value track?) - PropertyInfo pinfo; - pinfo.name = leftover_path[leftover_path.size() - 1]; - //now let's see if we can get more info about it - - List<PropertyInfo> plist; - object->get_property_list(&plist); - - for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) { - - if (E->get().name == leftover_path[leftover_path.size() - 1]) { - pinfo = E->get(); - break; - } + if (pinfo.name.empty()) { + pinfo.name = leftover_path[leftover_path.size() - 1]; } for (int j = 0; j < track_edit_plugins.size(); j++) { - track_edit = track_edit_plugins[j]->create_value_track_edit(object, pinfo.type, pinfo.name, pinfo.hint, pinfo.hint_string, pinfo.usage); + track_edit = track_edit_plugins.write[j]->create_value_track_edit(object, pinfo.type, pinfo.name, pinfo.hint, pinfo.hint_string, pinfo.usage); if (track_edit) { break; } @@ -3327,7 +3315,7 @@ void AnimationTrackEditor::_update_tracks() { if (animation->track_get_type(i) == Animation::TYPE_AUDIO) { for (int j = 0; j < track_edit_plugins.size(); j++) { - track_edit = track_edit_plugins[j]->create_audio_track_edit(); + track_edit = track_edit_plugins.write[j]->create_audio_track_edit(); if (track_edit) { break; } @@ -3344,7 +3332,7 @@ void AnimationTrackEditor::_update_tracks() { if (node && Object::cast_to<AnimationPlayer>(node)) { for (int j = 0; j < track_edit_plugins.size(); j++) { - track_edit = track_edit_plugins[j]->create_animation_track_edit(node); + track_edit = track_edit_plugins.write[j]->create_animation_track_edit(node); if (track_edit) { break; } diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp index d0c91f10d9..6d444c5422 100644 --- a/editor/animation_track_editor_plugins.cpp +++ b/editor/animation_track_editor_plugins.cpp @@ -271,8 +271,8 @@ void AnimationTrackEditAudio::draw_key(int p_index, float p_pixels_sec, int p_x, float min = preview->get_min(ofs, ofs_n) * 0.5 + 0.5; int idx = i - from_x; - lines[idx * 2 + 0] = Vector2(i, rect.position.y + min * rect.size.y); - lines[idx * 2 + 1] = Vector2(i, rect.position.y + max * rect.size.y); + lines.write[idx * 2 + 0] = Vector2(i, rect.position.y + min * rect.size.y); + lines.write[idx * 2 + 1] = Vector2(i, rect.position.y + max * rect.size.y); } Vector<Color> color; @@ -883,8 +883,8 @@ void AnimationTrackEditTypeAudio::draw_key(int p_index, float p_pixels_sec, int float min = preview->get_min(ofs, ofs_n) * 0.5 + 0.5; int idx = i - from_x; - lines[idx * 2 + 0] = Vector2(i, rect.position.y + min * rect.size.y); - lines[idx * 2 + 1] = Vector2(i, rect.position.y + max * rect.size.y); + lines.write[idx * 2 + 0] = Vector2(i, rect.position.y + min * rect.size.y); + lines.write[idx * 2 + 1] = Vector2(i, rect.position.y + max * rect.size.y); } Vector<Color> color; diff --git a/editor/audio_stream_preview.cpp b/editor/audio_stream_preview.cpp index 6ee4d7f4b0..6ae5ec43a9 100644 --- a/editor/audio_stream_preview.cpp +++ b/editor/audio_stream_preview.cpp @@ -118,8 +118,8 @@ void AudioStreamPreviewGenerator::_preview_thread(void *p_preview) { uint8_t pfrom = CLAMP((min * 0.5 + 0.5) * 255, 0, 255); uint8_t pto = CLAMP((max * 0.5 + 0.5) * 255, 0, 255); - preview->preview->preview[(ofs_write + i) * 2 + 0] = pfrom; - preview->preview->preview[(ofs_write + i) * 2 + 1] = pto; + preview->preview->preview.write[(ofs_write + i) * 2 + 0] = pfrom; + preview->preview->preview.write[(ofs_write + i) * 2 + 1] = pto; } frames_todo -= to_read; diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 925f97de8e..9d4333bc29 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -725,7 +725,7 @@ void CodeTextEditor::_complete_request() { int i = 0; for (List<String>::Element *E = entries.front(); E; E = E->next()) { - strs[i++] = E->get(); + strs.write[i++] = E->get(); } text_editor->code_complete(strs, forced); @@ -745,7 +745,7 @@ bool CodeTextEditor::_add_font_size(int p_delta) { if (font.is_valid()) { int new_size = CLAMP(font->get_size() + p_delta, 8 * EDSCALE, 96 * EDSCALE); - zoom_nb->set_text(itos(100 * new_size / 14) + "%"); + zoom_nb->set_text(itos(100 * new_size / (14 * EDSCALE)) + "%"); if (new_size != font->get_size()) { EditorSettings::get_singleton()->set("interface/editor/code_font_size", new_size / EDSCALE); @@ -1246,6 +1246,29 @@ CodeTextEditor::CodeTextEditor() { status_bar->add_child(memnew(Label)); //to keep the height if the other labels are not visible + warning_label = memnew(Label); + status_bar->add_child(warning_label); + warning_label->set_align(Label::ALIGN_RIGHT); + warning_label->set_valign(Label::VALIGN_CENTER); + warning_label->set_v_size_flags(SIZE_FILL); + warning_label->set_default_cursor_shape(CURSOR_POINTING_HAND); + warning_label->set_mouse_filter(MOUSE_FILTER_STOP); + warning_label->set_text(TTR("Warnings:")); + warning_label->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); + + warning_count_label = memnew(Label); + status_bar->add_child(warning_count_label); + warning_count_label->set_valign(Label::VALIGN_CENTER); + warning_count_label->set_v_size_flags(SIZE_FILL); + warning_count_label->set_autowrap(true); // workaround to prevent resizing the label on each change, do not touch + warning_count_label->set_clip_text(true); // workaround to prevent resizing the label on each change, do not touch + warning_count_label->set_custom_minimum_size(Size2(40, 1) * EDSCALE); + warning_count_label->set_align(Label::ALIGN_RIGHT); + warning_count_label->set_default_cursor_shape(CURSOR_POINTING_HAND); + warning_count_label->set_mouse_filter(MOUSE_FILTER_STOP); + warning_count_label->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); + warning_count_label->set_text("0"); + Label *zoom_txt = memnew(Label); status_bar->add_child(zoom_txt); zoom_txt->set_align(Label::ALIGN_RIGHT); @@ -1318,7 +1341,7 @@ CodeTextEditor::CodeTextEditor() { font_resize_val = 0; font_size = EditorSettings::get_singleton()->get("interface/editor/code_font_size"); - zoom_nb->set_text(itos(100 * font_size / 14) + "%"); + zoom_nb->set_text(itos(100 * font_size / (14 * EDSCALE)) + "%"); font_resize_timer = memnew(Timer); add_child(font_resize_timer); font_resize_timer->set_one_shot(true); diff --git a/editor/code_editor.h b/editor/code_editor.h index 903f61d87d..ee47eff9a8 100644 --- a/editor/code_editor.h +++ b/editor/code_editor.h @@ -142,6 +142,8 @@ class CodeTextEditor : public VBoxContainer { TextEdit *text_editor; FindReplaceBar *find_replace_bar; HBoxContainer *status_bar; + Label *warning_label; + Label *warning_count_label; Label *line_nb; Label *col_nb; @@ -214,6 +216,8 @@ public: void update_line_and_column() { _line_col_changed(); } TextEdit *get_text_edit() { return text_editor; } FindReplaceBar *get_find_replace_bar() { return find_replace_bar; } + Label *get_warning_label() const { return warning_label; } + Label *get_warning_count_label() const { return warning_count_label; } virtual void apply_code() {} void set_code_complete_func(CodeTextEditorCodeCompleteFunc p_code_complete_func, void *p_ud); diff --git a/editor/collada/collada.cpp b/editor/collada/collada.cpp index 734229d014..fa7e37eb1f 100644 --- a/editor/collada/collada.cpp +++ b/editor/collada/collada.cpp @@ -191,7 +191,7 @@ Transform Collada::Node::get_global_transform() const { return default_transform; } -Vector<float> Collada::AnimationTrack::get_value_at_time(float p_time) { +Vector<float> Collada::AnimationTrack::get_value_at_time(float p_time) const { ERR_FAIL_COND_V(keys.size() == 0, Vector<float>()); int i = 0; @@ -225,22 +225,22 @@ Vector<float> Collada::AnimationTrack::get_value_at_time(float p_time) { ret.resize(16); Transform tr; // i wonder why collada matrices are transposed, given that's opposed to opengl.. - ret[0] = interp.basis.elements[0][0]; - ret[1] = interp.basis.elements[0][1]; - ret[2] = interp.basis.elements[0][2]; - ret[4] = interp.basis.elements[1][0]; - ret[5] = interp.basis.elements[1][1]; - ret[6] = interp.basis.elements[1][2]; - ret[8] = interp.basis.elements[2][0]; - ret[9] = interp.basis.elements[2][1]; - ret[10] = interp.basis.elements[2][2]; - ret[3] = interp.origin.x; - ret[7] = interp.origin.y; - ret[11] = interp.origin.z; - ret[12] = 0; - ret[13] = 0; - ret[14] = 0; - ret[15] = 1; + ret.write[0] = interp.basis.elements[0][0]; + ret.write[1] = interp.basis.elements[0][1]; + ret.write[2] = interp.basis.elements[0][2]; + ret.write[4] = interp.basis.elements[1][0]; + ret.write[5] = interp.basis.elements[1][1]; + ret.write[6] = interp.basis.elements[1][2]; + ret.write[8] = interp.basis.elements[2][0]; + ret.write[9] = interp.basis.elements[2][1]; + ret.write[10] = interp.basis.elements[2][2]; + ret.write[3] = interp.origin.x; + ret.write[7] = interp.origin.y; + ret.write[11] = interp.origin.z; + ret.write[12] = 0; + ret.write[13] = 0; + ret.write[14] = 0; + ret.write[15] = 1; return ret; } else { @@ -249,7 +249,7 @@ Vector<float> Collada::AnimationTrack::get_value_at_time(float p_time) { dest.resize(keys[i].data.size()); for (int j = 0; j < dest.size(); j++) { - dest[j] = keys[i].data[j] * c + keys[i - 1].data[j] * (1.0 - c); + dest.write[j] = keys[i].data[j] * c + keys[i - 1].data[j] * (1.0 - c); } return dest; //interpolate one by one @@ -452,7 +452,7 @@ Transform Collada::_read_transform(XMLParser &parser) { Vector<float> farr; farr.resize(16); for (int i = 0; i < 16; i++) { - farr[i] = array[i].to_double(); + farr.write[i] = array[i].to_double(); } return _read_transform_from_array(farr); @@ -1104,7 +1104,7 @@ void Collada::_parse_mesh_geometry(XMLParser &parser, String p_id, String p_name int from = prim.indices.size(); prim.indices.resize(from + values.size()); for (int i = 0; i < values.size(); i++) - prim.indices[from + i] = values[i]; + prim.indices.write[from + i] = values[i]; } else if (prim.vertex_size > 0) { prim.indices = values; @@ -1884,7 +1884,7 @@ void Collada::_parse_animation(XMLParser &parser) { track.keys.resize(key_count); for (int j = 0; j < key_count; j++) { - track.keys[j].time = time_keys[j]; + track.keys.write[j].time = time_keys[j]; state.animation_length = MAX(state.animation_length, time_keys[j]); } @@ -1905,9 +1905,9 @@ void Collada::_parse_animation(XMLParser &parser) { ERR_CONTINUE((output.size() / stride) != key_count); for (int j = 0; j < key_count; j++) { - track.keys[j].data.resize(output_len); + track.keys.write[j].data.resize(output_len); for (int k = 0; k < output_len; k++) - track.keys[j].data[k] = output[l + j * stride + k]; //super weird but should work: + track.keys.write[j].data.write[k] = output[l + j * stride + k]; //super weird but should work: } if (sampler.has("INTERPOLATION")) { @@ -1919,9 +1919,9 @@ void Collada::_parse_animation(XMLParser &parser) { for (int j = 0; j < key_count; j++) { if (interps[j] == "BEZIER") - track.keys[j].interp_type = AnimationTrack::INTERP_BEZIER; + track.keys.write[j].interp_type = AnimationTrack::INTERP_BEZIER; else - track.keys[j].interp_type = AnimationTrack::INTERP_LINEAR; + track.keys.write[j].interp_type = AnimationTrack::INTERP_LINEAR; } } @@ -1939,8 +1939,8 @@ void Collada::_parse_animation(XMLParser &parser) { ERR_CONTINUE(outangents.size() != key_count * 2 * names.size()); for (int j = 0; j < key_count; j++) { - track.keys[j].in_tangent = Vector2(intangents[j * 2 * names.size() + 0 + l * 2], intangents[j * 2 * names.size() + 1 + l * 2]); - track.keys[j].out_tangent = Vector2(outangents[j * 2 * names.size() + 0 + l * 2], outangents[j * 2 * names.size() + 1 + l * 2]); + track.keys.write[j].in_tangent = Vector2(intangents[j * 2 * names.size() + 0 + l * 2], intangents[j * 2 * names.size() + 1 + l * 2]); + track.keys.write[j].out_tangent = Vector2(outangents[j * 2 * names.size() + 0 + l * 2], outangents[j * 2 * names.size() + 1 + l * 2]); } } @@ -2118,7 +2118,7 @@ void Collada::_joint_set_owner(Collada::Node *p_node, NodeSkeleton *p_owner) { for (int i = 0; i < nj->children.size(); i++) { - _joint_set_owner(nj->children[i], p_owner); + _joint_set_owner(nj->children.write[i], p_owner); } } } @@ -2147,7 +2147,7 @@ void Collada::_create_skeletons(Collada::Node **p_node, NodeSkeleton *p_skeleton } for (int i = 0; i < node->children.size(); i++) { - _create_skeletons(&node->children[i], p_skeleton); + _create_skeletons(&node->children.write[i], p_skeleton); } } @@ -2314,7 +2314,7 @@ bool Collada::_optimize_skeletons(VisualScene *p_vscene, Node *p_node) { for (int i = 0; i < gp->children.size(); i++) { if (gp->children[i] == parent) { - gp->children[i] = node; + gp->children.write[i] = node; found = true; break; } @@ -2330,7 +2330,7 @@ bool Collada::_optimize_skeletons(VisualScene *p_vscene, Node *p_node) { if (p_vscene->root_nodes[i] == parent) { - p_vscene->root_nodes[i] = node; + p_vscene->root_nodes.write[i] = node; found = true; break; } @@ -2466,7 +2466,7 @@ void Collada::_optimize() { VisualScene &vs = E->get(); for (int i = 0; i < vs.root_nodes.size(); i++) { - _create_skeletons(&vs.root_nodes[i]); + _create_skeletons(&vs.root_nodes.write[i]); } for (int i = 0; i < vs.root_nodes.size(); i++) { diff --git a/editor/collada/collada.h b/editor/collada/collada.h index ec3284bc5c..7535162f74 100644 --- a/editor/collada/collada.h +++ b/editor/collada/collada.h @@ -312,7 +312,7 @@ public: total += weights[i].weight; if (total) for (int i = 0; i < 4; i++) - weights[i].weight /= total; + weights.write[i].weight /= total; } } @@ -515,7 +515,7 @@ public: Key() { interp_type = INTERP_LINEAR; } }; - Vector<float> get_value_at_time(float p_time); + Vector<float> get_value_at_time(float p_time) const; Vector<Key> keys; diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index c4f4e28fec..da73a3930a 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -51,7 +51,7 @@ public: if (name.begins_with("bind/")) { int which = name.get_slice("/", 1).to_int() - 1; ERR_FAIL_INDEX_V(which, params.size(), false); - params[which] = p_value; + params.write[which] = p_value; } else return false; diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 6b2a072e20..5dd5b7fcc5 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -40,6 +40,11 @@ void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode) { + type_list.clear(); + ClassDB::get_class_list(&type_list); + ScriptServer::get_global_class_list(&type_list); + type_list.sort_custom<StringName::AlphCompare>(); + recent->clear(); FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::READ); @@ -81,7 +86,7 @@ void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode) { memdelete(f); } - _update_favorite_list(); + _save_and_update_favorite_list(); // Restore valid window bounds or pop up at default size. if (EditorSettings::get_singleton()->has_setting("interface/dialogs/create_new_node_bounds")) { @@ -173,10 +178,28 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p if (p_types.has(p_type)) return; - if (!ClassDB::is_parent_class(p_type, base_type) || p_type == base_type) + + bool cpp_type = ClassDB::class_exists(p_type); + EditorData &ed = EditorNode::get_singleton()->get_editor_data(); + + if (p_type == base_type) return; - String inherits = ClassDB::get_parent_class(p_type); + if (cpp_type) { + if (!ClassDB::is_parent_class(p_type, base_type)) + return; + } else { + if (!ScriptServer::is_global_class(p_type) || !ed.script_class_is_parent(p_type, base_type)) + return; + + String script_path = ScriptServer::get_global_class_path(p_type); + if (script_path.find("res://addons/", 0) != -1) { + if (!EditorNode::get_singleton()->is_addon_plugin_enabled(script_path.get_slicec('/', 3))) + return; + } + } + + String inherits = cpp_type ? ClassDB::get_parent_class(p_type) : ed.script_class_get_base(p_type); TreeItem *parent = p_root; @@ -189,17 +212,32 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p if (p_types.has(inherits)) parent = p_types[inherits]; + else if (ScriptServer::is_global_class(inherits)) + return; } + bool can_instance = (cpp_type && ClassDB::can_instance(p_type)) || ScriptServer::is_global_class(p_type); + TreeItem *item = search_options->create_item(parent); - item->set_text(0, p_type); - if (!ClassDB::can_instance(p_type)) { + if (cpp_type) { + item->set_text(0, p_type); + } else { + item->set_metadata(0, p_type); + item->set_text(0, p_type + " (" + ScriptServer::get_global_class_path(p_type).get_file() + ")"); + } + if (!can_instance) { item->set_custom_color(0, get_color("disabled_font_color", "Editor")); item->set_selectable(0, false); } else { bool is_search_subsequence = search_box->get_text().is_subsequence_ofi(p_type); String to_select_type = *to_select ? (*to_select)->get_text(0) : ""; - bool current_item_is_preffered = ClassDB::is_parent_class(p_type, preferred_search_result_type) && !ClassDB::is_parent_class(to_select_type, preferred_search_result_type); + to_select_type = to_select_type.split(" ")[0]; + bool current_item_is_preffered; + if (cpp_type) { + current_item_is_preffered = ClassDB::is_parent_class(p_type, preferred_search_result_type) && !ClassDB::is_parent_class(to_select_type, preferred_search_result_type); + } else { + current_item_is_preffered = ed.script_class_is_parent(p_type, preferred_search_result_type) && !ed.script_class_is_parent(to_select_type, preferred_search_result_type); + } if (*to_select && p_type.length() < (*to_select)->get_text(0).length()) { current_item_is_preffered = true; } @@ -217,16 +255,19 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p // don't collapse the root node collapse &= (item != p_root); // don't collapse abstract nodes on the first tree level - collapse &= ((parent != p_root) || (ClassDB::can_instance(p_type))); + collapse &= ((parent != p_root) || (can_instance)); item->set_collapsed(collapse); } const String &description = EditorHelp::get_doc_data()->class_list[p_type].brief_description; item->set_tooltip(0, description); - if (has_icon(p_type, "EditorIcons")) { + if (cpp_type && has_icon(p_type, "EditorIcons")) { item->set_icon(0, get_icon(p_type, "EditorIcons")); + } else if (!cpp_type && has_icon(ScriptServer::get_global_class_base(p_type), "EditorIcons")) { + + item->set_icon(0, get_icon(ScriptServer::get_global_class_base(p_type), "EditorIcons")); } p_types[p_type] = item; @@ -243,47 +284,38 @@ void CreateDialog::_update_search() { _parse_fs(EditorFileSystem::get_singleton()->get_filesystem()); */ - List<StringName> global_classes; - ScriptServer::get_global_class_list(&global_classes); - - Map<String, List<String> > global_class_map; - for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) { - String base = ScriptServer::get_global_class_base(E->get()); - if (!global_class_map.has(base)) { - global_class_map[base] = List<String>(); - } - global_class_map[base].push_back(E->get()); - } - HashMap<String, TreeItem *> types; TreeItem *root = search_options->create_item(); + EditorData &ed = EditorNode::get_singleton()->get_editor_data(); root->set_text(0, base_type); if (has_icon(base_type, "EditorIcons")) { root->set_icon(0, get_icon(base_type, "EditorIcons")); } - List<StringName>::Element *I = type_list.front(); TreeItem *to_select = search_box->get_text() == base_type ? root : NULL; - for (; I; I = I->next()) { + for (List<StringName>::Element *I = type_list.front(); I; I = I->next()) { String type = I->get(); + bool cpp_type = ClassDB::class_exists(type); if (base_type == "Node" && type.begins_with("Editor")) continue; // do not show editor nodes - if (!ClassDB::can_instance(type)) + if (cpp_type && !ClassDB::can_instance(type)) continue; // can't create what can't be instanced bool skip = false; - for (Set<StringName>::Element *E = type_blacklist.front(); E && !skip; E = E->next()) { - if (ClassDB::is_parent_class(type, E->get())) - skip = true; + if (cpp_type) { + for (Set<StringName>::Element *E = type_blacklist.front(); E && !skip; E = E->next()) { + if (ClassDB::is_parent_class(type, E->get())) + skip = true; + } + if (skip) + continue; } - if (skip) - continue; if (search_box->get_text() == "") { add_type(type, types, root, &to_select); @@ -291,7 +323,7 @@ void CreateDialog::_update_search() { bool found = false; String type = I->get(); - while (type != "" && ClassDB::is_parent_class(type, base_type) && type != base_type) { + while (type != "" && (cpp_type ? ClassDB::is_parent_class(type, base_type) : ed.script_class_is_parent(type, base_type)) && type != base_type) { if (search_box->get_text().is_subsequence_ofi(type)) { found = true; @@ -305,32 +337,6 @@ void CreateDialog::_update_search() { add_type(I->get(), types, root, &to_select); } - if (global_class_map.has(type) && ClassDB::is_parent_class(type, base_type)) { - for (List<String>::Element *J = global_class_map[type].front(); J; J = J->next()) { - bool show = search_box->get_text().is_subsequence_ofi(J->get()); - - if (!show) - continue; - - if (!types.has(type)) - add_type(type, types, root, &to_select); - - TreeItem *ti; - if (types.has(type)) - ti = types[type]; - else - ti = search_options->get_root(); - - TreeItem *item = search_options->create_item(ti); - item->set_metadata(0, J->get()); - item->set_text(0, J->get() + " (" + ScriptServer::get_global_class_path(J->get()).get_file() + ")"); - item->set_icon(0, _get_editor_icon(type)); - if (!to_select || J->get() == search_box->get_text()) { - to_select = item; - } - } - } - if (EditorNode::get_editor_data().get_custom_types().has(type) && ClassDB::is_parent_class(type, base_type)) { //there are custom types based on this... cool. @@ -419,6 +425,8 @@ void CreateDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { connect("confirmed", this, "_confirmed"); + search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_clear_button_enabled(true); favorite->set_icon(get_icon("Favorites", "EditorIcons")); } break; case NOTIFICATION_EXIT_TREE: { @@ -537,8 +545,7 @@ void CreateDialog::_favorite_toggled() { favorite->set_pressed(false); } - _save_favorite_list(); - _update_favorite_list(); + _save_and_update_favorite_list(); } void CreateDialog::_save_favorite_list() { @@ -548,8 +555,11 @@ void CreateDialog::_save_favorite_list() { if (f) { for (int i = 0; i < favorite_list.size(); i++) { - - f->store_line(favorite_list[i]); + String l = favorite_list[i]; + String name = l.split(" ")[0]; + if (!(ClassDB::class_exists(name) || ScriptServer::is_global_class(name))) + continue; + f->store_line(l); } memdelete(f); } @@ -560,11 +570,15 @@ void CreateDialog::_update_favorite_list() { favorites->clear(); TreeItem *root = favorites->create_item(); for (int i = 0; i < favorite_list.size(); i++) { - TreeItem *ti = favorites->create_item(root); String l = favorite_list[i]; + String name = l.split(" ")[0]; + if (!(ClassDB::class_exists(name) || ScriptServer::is_global_class(name))) + continue; + TreeItem *ti = favorites->create_item(root); ti->set_text(0, l); ti->set_icon(0, _get_editor_icon(l)); } + emit_signal("favorites_updated"); } void CreateDialog::_history_selected() { @@ -667,6 +681,10 @@ void CreateDialog::drop_data_fw(const Point2 &p_point, const Variant &p_data, Co } } + _save_and_update_favorite_list(); +} + +void CreateDialog::_save_and_update_favorite_list() { _save_favorite_list(); _update_favorite_list(); } @@ -682,21 +700,20 @@ void CreateDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("_favorite_selected"), &CreateDialog::_favorite_selected); ClassDB::bind_method(D_METHOD("_history_activated"), &CreateDialog::_history_activated); ClassDB::bind_method(D_METHOD("_favorite_activated"), &CreateDialog::_favorite_activated); + ClassDB::bind_method(D_METHOD("_save_and_update_favorite_list"), &CreateDialog::_save_and_update_favorite_list); ClassDB::bind_method("get_drag_data_fw", &CreateDialog::get_drag_data_fw); ClassDB::bind_method("can_drop_data_fw", &CreateDialog::can_drop_data_fw); ClassDB::bind_method("drop_data_fw", &CreateDialog::drop_data_fw); ADD_SIGNAL(MethodInfo("create")); + ADD_SIGNAL(MethodInfo("favorites_updated")); } CreateDialog::CreateDialog() { is_replace_mode = false; - ClassDB::get_class_list(&type_list); - type_list.sort_custom<StringName::AlphCompare>(); - set_resizable(true); HSplitContainer *hsc = memnew(HSplitContainer); @@ -762,4 +779,6 @@ CreateDialog::CreateDialog() { type_blacklist.insert("PluginScript"); // PluginScript must be initialized before use, which is not possible here type_blacklist.insert("ScriptCreateDialog"); // This is an exposed editor Node that doesn't have an Editor prefix. + + EDITOR_DEF("interface/editors/derive_script_globals_by_name", true); } diff --git a/editor/create_dialog.h b/editor/create_dialog.h index f8eec231a4..6df9eebc8c 100644 --- a/editor/create_dialog.h +++ b/editor/create_dialog.h @@ -90,6 +90,8 @@ protected: void _notification(int p_what); static void _bind_methods(); + void _save_and_update_favorite_list(); + public: Object *instance_selected(); String get_selected_type(); diff --git a/editor/doc/doc_data.cpp b/editor/doc/doc_data.cpp index 542dca74e0..91a29f5717 100644 --- a/editor/doc/doc_data.cpp +++ b/editor/doc/doc_data.cpp @@ -58,7 +58,7 @@ void DocData::merge_from(const DocData &p_data) { for (int i = 0; i < c.methods.size(); i++) { - MethodDoc &m = c.methods[i]; + MethodDoc &m = c.methods.write[i]; for (int j = 0; j < cf.methods.size(); j++) { @@ -72,13 +72,13 @@ void DocData::merge_from(const DocData &p_data) { Vector<bool> arg_used; arg_used.resize(arg_count); for (int l = 0; l < arg_count; ++l) - arg_used[l] = false; + arg_used.write[l] = false; // also there is no guarantee that argument ordering will match, so we // have to check one by one so we make sure we have an exact match for (int k = 0; k < arg_count; ++k) { for (int l = 0; l < arg_count; ++l) if (cf.methods[j].arguments[k].type == m.arguments[l].type && !arg_used[l]) { - arg_used[l] = true; + arg_used.write[l] = true; break; } } @@ -98,7 +98,7 @@ void DocData::merge_from(const DocData &p_data) { for (int i = 0; i < c.signals.size(); i++) { - MethodDoc &m = c.signals[i]; + MethodDoc &m = c.signals.write[i]; for (int j = 0; j < cf.signals.size(); j++) { @@ -113,7 +113,7 @@ void DocData::merge_from(const DocData &p_data) { for (int i = 0; i < c.constants.size(); i++) { - ConstantDoc &m = c.constants[i]; + ConstantDoc &m = c.constants.write[i]; for (int j = 0; j < cf.constants.size(); j++) { @@ -128,7 +128,7 @@ void DocData::merge_from(const DocData &p_data) { for (int i = 0; i < c.properties.size(); i++) { - PropertyDoc &p = c.properties[i]; + PropertyDoc &p = c.properties.write[i]; for (int j = 0; j < cf.properties.size(); j++) { @@ -146,7 +146,7 @@ void DocData::merge_from(const DocData &p_data) { for (int i = 0; i < c.theme_properties.size(); i++) { - PropertyDoc &p = c.theme_properties[i]; + PropertyDoc &p = c.theme_properties.write[i]; for (int j = 0; j < cf.theme_properties.size(); j++) { @@ -535,13 +535,14 @@ void DocData::generate(bool p_basic_types) { } List<StringName> constants; - Variant::get_numeric_constants_for_type(Variant::Type(i), &constants); + Variant::get_constants_for_type(Variant::Type(i), &constants); for (List<StringName>::Element *E = constants.front(); E; E = E->next()) { ConstantDoc constant; constant.name = E->get(); - constant.value = itos(Variant::get_numeric_constant_value(Variant::Type(i), E->get())); + Variant value = Variant::get_constant_value(Variant::Type(i), E->get()); + constant.value = value.get_type() == Variant::INT ? itos(value) : value.get_construct_string(); c.constants.push_back(constant); } } @@ -1020,7 +1021,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri for (int i = 0; i < c.methods.size(); i++) { - MethodDoc &m = c.methods[i]; + const MethodDoc &m = c.methods[i]; String qualifiers; if (m.qualifiers != "") @@ -1040,7 +1041,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri for (int j = 0; j < m.arguments.size(); j++) { - ArgumentDoc &a = m.arguments[j]; + const ArgumentDoc &a = m.arguments[j]; String enum_text; if (a.enumeration != String()) { @@ -1075,7 +1076,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri if (c.properties[i].enumeration != String()) { enum_text = " enum=\"" + c.properties[i].enumeration + "\""; } - PropertyDoc &p = c.properties[i]; + const PropertyDoc &p = c.properties[i]; _write_string(f, 2, "<member name=\"" + p.name + "\" type=\"" + p.type + "\" setter=\"" + p.setter + "\" getter=\"" + p.getter + "\"" + enum_text + ">"); _write_string(f, 3, p.description.strip_edges().xml_escape()); _write_string(f, 2, "</member>"); @@ -1090,11 +1091,11 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri _write_string(f, 1, "<signals>"); for (int i = 0; i < c.signals.size(); i++) { - MethodDoc &m = c.signals[i]; + const MethodDoc &m = c.signals[i]; _write_string(f, 2, "<signal name=\"" + m.name + "\">"); for (int j = 0; j < m.arguments.size(); j++) { - ArgumentDoc &a = m.arguments[j]; + const ArgumentDoc &a = m.arguments[j]; _write_string(f, 3, "<argument index=\"" + itos(j) + "\" name=\"" + a.name.xml_escape() + "\" type=\"" + a.type.xml_escape() + "\">"); _write_string(f, 3, "</argument>"); } @@ -1113,7 +1114,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri for (int i = 0; i < c.constants.size(); i++) { - ConstantDoc &k = c.constants[i]; + const ConstantDoc &k = c.constants[i]; if (k.enumeration != String()) { _write_string(f, 2, "<constant name=\"" + k.name + "\" value=\"" + k.value + "\" enum=\"" + k.enumeration + "\">"); } else { @@ -1132,7 +1133,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri _write_string(f, 1, "<theme_items>"); for (int i = 0; i < c.theme_properties.size(); i++) { - PropertyDoc &p = c.theme_properties[i]; + const PropertyDoc &p = c.theme_properties[i]; _write_string(f, 2, "<theme_item name=\"" + p.name + "\" type=\"" + p.type + "\">"); _write_string(f, 2, "</theme_item>"); } diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp index 4b09db0a9e..e4602f0f94 100644 --- a/editor/editor_about.cpp +++ b/editor/editor_about.cpp @@ -113,7 +113,7 @@ ScrollContainer *EditorAbout::_populate_list(const String &p_name, const List<St EditorAbout::EditorAbout() { set_title(TTR("Thanks from the Godot community!")); - get_ok()->set_text(TTR("Thanks!")); + get_ok()->set_text(TTR("OK")); set_hide_on_ok(true); set_resizable(true); diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index 2f0982e5d9..d12c85861b 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -598,7 +598,7 @@ void EditorAutoloadSettings::drop_data_fw(const Point2 &p_point, const Variant & int i = 0; for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) { - orders[i++] = E->get().order; + orders.write[i++] = E->get().order; } orders.sort(); diff --git a/editor/editor_builders.py b/editor/editor_builders.py new file mode 100644 index 0000000000..6c2f9e298e --- /dev/null +++ b/editor/editor_builders.py @@ -0,0 +1,412 @@ +"""Functions used to generate source files during build time + +All such functions are invoked in a subprocess on Windows to prevent build flakiness. + +""" +import os +import os.path +from platform_methods import subprocess_main +from compat import encode_utf8, byte_to_str, open_utf8, escape_string + + +def make_certs_header(target, source, env): + + src = source[0] + dst = target[0] + f = open(src, "rb") + g = open_utf8(dst, "w") + buf = f.read() + decomp_size = len(buf) + import zlib + buf = zlib.compress(buf) + + g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + g.write("#ifndef _CERTS_RAW_H\n") + g.write("#define _CERTS_RAW_H\n") + g.write("static const int _certs_compressed_size = " + str(len(buf)) + ";\n") + g.write("static const int _certs_uncompressed_size = " + str(decomp_size) + ";\n") + g.write("static const unsigned char _certs_compressed[] = {\n") + for i in range(len(buf)): + g.write("\t" + byte_to_str(buf[i]) + ",\n") + g.write("};\n") + g.write("#endif") + + g.close() + f.close() + + +def make_doc_header(target, source, env): + + dst = target[0] + g = open_utf8(dst, "w") + buf = "" + docbegin = "" + docend = "" + for src in source: + if not src.endswith(".xml"): + continue + with open_utf8(src, "r") as f: + content = f.read() + buf += content + + buf = encode_utf8(docbegin + buf + docend) + decomp_size = len(buf) + import zlib + buf = zlib.compress(buf) + + g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + g.write("#ifndef _DOC_DATA_RAW_H\n") + g.write("#define _DOC_DATA_RAW_H\n") + g.write("static const int _doc_data_compressed_size = " + str(len(buf)) + ";\n") + g.write("static const int _doc_data_uncompressed_size = " + str(decomp_size) + ";\n") + g.write("static const unsigned char _doc_data_compressed[] = {\n") + for i in range(len(buf)): + g.write("\t" + byte_to_str(buf[i]) + ",\n") + g.write("};\n") + + g.write("#endif") + + g.close() + + +def make_fonts_header(target, source, env): + + dst = target[0] + + g = open_utf8(dst, "w") + + g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + g.write("#ifndef _EDITOR_FONTS_H\n") + g.write("#define _EDITOR_FONTS_H\n") + + # saving uncompressed, since freetype will reference from memory pointer + xl_names = [] + for i in range(len(source)): + with open(source[i], "rb")as f: + buf = f.read() + + name = os.path.splitext(os.path.basename(source[i]))[0] + + g.write("static const int _font_" + name + "_size = " + str(len(buf)) + ";\n") + g.write("static const unsigned char _font_" + name + "[] = {\n") + for i in range(len(buf)): + g.write("\t" + byte_to_str(buf[i]) + ",\n") + + g.write("};\n") + + g.write("#endif") + + g.close() + + +def make_translations_header(target, source, env): + + dst = target[0] + + g = open_utf8(dst, "w") + + g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + g.write("#ifndef _EDITOR_TRANSLATIONS_H\n") + g.write("#define _EDITOR_TRANSLATIONS_H\n") + + import zlib + import os.path + + sorted_paths = sorted(source, key=lambda path: os.path.splitext(os.path.basename(path))[0]) + + xl_names = [] + for i in range(len(sorted_paths)): + with open(sorted_paths[i], "rb") as f: + buf = f.read() + decomp_size = len(buf) + buf = zlib.compress(buf) + name = os.path.splitext(os.path.basename(sorted_paths[i]))[0] + + g.write("static const unsigned char _translation_" + name + "_compressed[] = {\n") + for i in range(len(buf)): + g.write("\t" + byte_to_str(buf[i]) + ",\n") + + g.write("};\n") + + xl_names.append([name, len(buf), str(decomp_size)]) + + g.write("struct EditorTranslationList {\n") + g.write("\tconst char* lang;\n") + g.write("\tint comp_size;\n") + g.write("\tint uncomp_size;\n") + g.write("\tconst unsigned char* data;\n") + g.write("};\n\n") + g.write("static EditorTranslationList _editor_translations[] = {\n") + for x in xl_names: + g.write("\t{ \"" + x[0] + "\", " + str(x[1]) + ", " + str(x[2]) + ", _translation_" + x[0] + "_compressed},\n") + g.write("\t{NULL, 0, 0, NULL}\n") + g.write("};\n") + + g.write("#endif") + + g.close() + + +def make_authors_header(target, source, env): + + sections = ["Project Founders", "Lead Developer", "Project Manager", "Developers"] + sections_id = ["dev_founders", "dev_lead", "dev_manager", "dev_names"] + + src = source[0] + dst = target[0] + f = open_utf8(src, "r") + g = open_utf8(dst, "w") + + g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + g.write("#ifndef _EDITOR_AUTHORS_H\n") + g.write("#define _EDITOR_AUTHORS_H\n") + + current_section = "" + reading = False + + def close_section(): + g.write("\t0\n") + g.write("};\n") + + for line in f: + if reading: + if line.startswith(" "): + g.write("\t\"" + escape_string(line.strip()) + "\",\n") + continue + if line.startswith("## "): + if reading: + close_section() + reading = False + for i in range(len(sections)): + if line.strip().endswith(sections[i]): + current_section = escape_string(sections_id[i]) + reading = True + g.write("static const char *" + current_section + "[] = {\n") + break + + if reading: + close_section() + + g.write("#endif\n") + + g.close() + f.close() + +def make_donors_header(target, source, env): + + sections = ["Platinum sponsors", "Gold sponsors", "Mini sponsors", "Gold donors", "Silver donors", "Bronze donors"] + sections_id = ["donor_s_plat", "donor_s_gold", "donor_s_mini", "donor_gold", "donor_silver", "donor_bronze"] + + src = source[0] + dst = target[0] + f = open_utf8(src, "r") + g = open_utf8(dst, "w") + + g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + g.write("#ifndef _EDITOR_DONORS_H\n") + g.write("#define _EDITOR_DONORS_H\n") + + current_section = "" + reading = False + + def close_section(): + g.write("\t0\n") + g.write("};\n") + + for line in f: + if reading >= 0: + if line.startswith(" "): + g.write("\t\"" + escape_string(line.strip()) + "\",\n") + continue + if line.startswith("## "): + if reading: + close_section() + reading = False + for i in range(len(sections)): + if line.strip().endswith(sections[i]): + current_section = escape_string(sections_id[i]) + reading = True + g.write("static const char *" + current_section + "[] = {\n") + break + + if reading: + close_section() + + g.write("#endif\n") + + g.close() + f.close() + + +def make_license_header(target, source, env): + + src_copyright = source[0] + src_license = source[1] + dst = target[0] + f = open_utf8(src_license, "r") + fc = open_utf8(src_copyright, "r") + g = open_utf8(dst, "w") + + g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + g.write("#ifndef _EDITOR_LICENSE_H\n") + g.write("#define _EDITOR_LICENSE_H\n") + g.write("static const char *about_license =") + + for line in f: + escaped_string = escape_string(line.strip()) + g.write("\n\t\"" + escaped_string + "\\n\"") + + g.write(";\n") + + tp_current = 0 + tp_file = "" + tp_comment = "" + tp_copyright = "" + tp_license = "" + + tp_licensename = "" + tp_licensebody = "" + + tp = [] + tp_licensetext = [] + for line in fc: + if line.startswith("#"): + continue + + if line.startswith("Files:"): + tp_file = line[6:].strip() + tp_current = 1 + elif line.startswith("Comment:"): + tp_comment = line[8:].strip() + tp_current = 2 + elif line.startswith("Copyright:"): + tp_copyright = line[10:].strip() + tp_current = 3 + elif line.startswith("License:"): + if tp_current != 0: + tp_license = line[8:].strip() + tp_current = 4 + else: + tp_licensename = line[8:].strip() + tp_current = 5 + elif line.startswith(" "): + if tp_current == 1: + tp_file += "\n" + line.strip() + elif tp_current == 3: + tp_copyright += "\n" + line.strip() + elif tp_current == 5: + if line.strip() == ".": + tp_licensebody += "\n" + else: + tp_licensebody += line[1:] + else: + if tp_current != 0: + if tp_current == 5: + tp_licensetext.append([tp_licensename, tp_licensebody]) + + tp_licensename = "" + tp_licensebody = "" + else: + added = False + for i in tp: + if i[0] == tp_comment: + i[1].append([tp_file, tp_copyright, tp_license]) + added = True + break + if not added: + tp.append([tp_comment,[[tp_file, tp_copyright, tp_license]]]) + + tp_file = [] + tp_comment = "" + tp_copyright = [] + tp_license = "" + tp_current = 0 + + tp_licensetext.append([tp_licensename, tp_licensebody]) + + about_thirdparty = "" + about_tp_copyright_count = "" + about_tp_license = "" + about_tp_copyright = "" + about_tp_file = "" + + for i in tp: + about_thirdparty += "\t\"" + i[0] + "\",\n" + about_tp_copyright_count += str(len(i[1])) + ", " + for j in i[1]: + file_body = "" + copyright_body = "" + for k in j[0].split("\n"): + if file_body != "": + file_body += "\\n\"\n" + escaped_string = escape_string(k.strip()) + file_body += "\t\"" + escaped_string + for k in j[1].split("\n"): + if copyright_body != "": + copyright_body += "\\n\"\n" + escaped_string = escape_string(k.strip()) + copyright_body += "\t\"" + escaped_string + + about_tp_file += "\t" + file_body + "\",\n" + about_tp_copyright += "\t" + copyright_body + "\",\n" + about_tp_license += "\t\"" + j[2] + "\",\n" + + about_license_name = "" + about_license_body = "" + + for i in tp_licensetext: + body = "" + for j in i[1].split("\n"): + if body != "": + body += "\\n\"\n" + escaped_string = escape_string(j.strip()) + body += "\t\"" + escaped_string + + about_license_name += "\t\"" + i[0] + "\",\n" + about_license_body += "\t" + body + "\",\n" + + g.write("static const char *about_thirdparty[] = {\n") + g.write(about_thirdparty) + g.write("\t0\n") + g.write("};\n") + g.write("#define THIRDPARTY_COUNT " + str(len(tp)) + "\n") + + g.write("static const int about_tp_copyright_count[] = {\n\t") + g.write(about_tp_copyright_count) + g.write("0\n};\n") + + g.write("static const char *about_tp_file[] = {\n") + g.write(about_tp_file) + g.write("\t0\n") + g.write("};\n") + + g.write("static const char *about_tp_copyright[] = {\n") + g.write(about_tp_copyright) + g.write("\t0\n") + g.write("};\n") + + g.write("static const char *about_tp_license[] = {\n") + g.write(about_tp_license) + g.write("\t0\n") + g.write("};\n") + + g.write("static const char *about_license_name[] = {\n") + g.write(about_license_name) + g.write("\t0\n") + g.write("};\n") + g.write("#define LICENSE_COUNT " + str(len(tp_licensetext)) + "\n") + + g.write("static const char *about_license_body[] = {\n") + g.write(about_license_body) + g.write("\t0\n") + g.write("};\n") + + g.write("#endif\n") + + g.close() + fc.close() + f.close() + + +if __name__ == '__main__': + subprocess_main(globals()) diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index 4dde893c6d..f4ef11eb36 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -62,7 +62,7 @@ void EditorHistory::cleanup_history() { fail = true; } else { //after level, clip - history[i].path.resize(j); + history.write[i].path.resize(j); } break; @@ -100,14 +100,14 @@ void EditorHistory::_add_object(ObjectID p_object, const String &p_property, int if (p_property != "" && has_prev) { //add a sub property - History &pr = history[current]; + History &pr = history.write[current]; h = pr; h.path.resize(h.level + 1); h.path.push_back(o); h.level++; } else if (p_level_change != -1 && has_prev) { //add a sub property - History &pr = history[current]; + History &pr = history.write[current]; h = pr; ERR_FAIL_INDEX(p_level_change, h.path.size()); h.level = p_level_change; @@ -206,7 +206,7 @@ ObjectID EditorHistory::get_current() { if (current < 0 || current >= history.size()) return 0; - History &h = history[current]; + History &h = history.write[current]; Object *obj = ObjectDB::get_instance(h.path[h.level].object); if (!obj) return 0; @@ -558,7 +558,7 @@ void EditorData::move_edited_scene_index(int p_idx, int p_to_idx) { ERR_FAIL_INDEX(p_idx, edited_scene.size()); ERR_FAIL_INDEX(p_to_idx, edited_scene.size()); - SWAP(edited_scene[p_idx], edited_scene[p_to_idx]); + SWAP(edited_scene.write[p_idx], edited_scene.write[p_to_idx]); } void EditorData::remove_scene(int p_idx) { ERR_FAIL_INDEX(p_idx, edited_scene.size()); @@ -644,7 +644,7 @@ bool EditorData::check_and_update_scene(int p_idx) { //transfer selection List<Node *> new_selection; - for (List<Node *>::Element *E = edited_scene[p_idx].selection.front(); E; E = E->next()) { + for (List<Node *>::Element *E = edited_scene.write[p_idx].selection.front(); E; E = E->next()) { NodePath p = edited_scene[p_idx].root->get_path_to(E->get()); Node *new_node = new_scene->get_node(p); if (new_node) @@ -654,8 +654,8 @@ bool EditorData::check_and_update_scene(int p_idx) { new_scene->set_filename(edited_scene[p_idx].root->get_filename()); memdelete(edited_scene[p_idx].root); - edited_scene[p_idx].root = new_scene; - edited_scene[p_idx].selection = new_selection; + edited_scene.write[p_idx].root = new_scene; + edited_scene.write[p_idx].selection = new_selection; return true; } @@ -685,7 +685,7 @@ Node *EditorData::get_edited_scene_root(int p_idx) { void EditorData::set_edited_scene_root(Node *p_root) { ERR_FAIL_INDEX(current_edited_scene, edited_scene.size()); - edited_scene[current_edited_scene].root = p_root; + edited_scene.write[current_edited_scene].root = p_root; } int EditorData::get_edited_scene_count() const { @@ -707,10 +707,10 @@ Vector<EditorData::EditedScene> EditorData::get_edited_scenes() const { void EditorData::set_edited_scene_version(uint64_t version, int p_scene_idx) { ERR_FAIL_INDEX(current_edited_scene, edited_scene.size()); if (p_scene_idx < 0) { - edited_scene[current_edited_scene].version = version; + edited_scene.write[current_edited_scene].version = version; } else { ERR_FAIL_INDEX(p_scene_idx, edited_scene.size()); - edited_scene[p_scene_idx].version = version; + edited_scene.write[p_scene_idx].version = version; } } @@ -793,7 +793,7 @@ String EditorData::get_scene_path(int p_idx) const { void EditorData::set_edited_scene_live_edit_root(const NodePath &p_root) { ERR_FAIL_INDEX(current_edited_scene, edited_scene.size()); - edited_scene[current_edited_scene].live_edit_root = p_root; + edited_scene.write[current_edited_scene].live_edit_root = p_root; } NodePath EditorData::get_edited_scene_live_edit_root() { @@ -806,7 +806,7 @@ void EditorData::save_edited_scene_state(EditorSelection *p_selection, EditorHis ERR_FAIL_INDEX(current_edited_scene, edited_scene.size()); - EditedScene &es = edited_scene[current_edited_scene]; + EditedScene &es = edited_scene.write[current_edited_scene]; es.selection = p_selection->get_selected_node_list(); es.history_current = p_history->current; es.history_stored = p_history->history; @@ -817,7 +817,7 @@ void EditorData::save_edited_scene_state(EditorSelection *p_selection, EditorHis Dictionary EditorData::restore_edited_scene_state(EditorSelection *p_selection, EditorHistory *p_history) { ERR_FAIL_INDEX_V(current_edited_scene, edited_scene.size(), Dictionary()); - EditedScene &es = edited_scene[current_edited_scene]; + EditedScene &es = edited_scene.write[current_edited_scene]; p_history->current = es.history_current; p_history->history = es.history_stored; @@ -853,6 +853,41 @@ void EditorData::get_plugin_window_layout(Ref<ConfigFile> p_layout) { } } +bool EditorData::script_class_is_parent(const String &p_class, const String &p_inherits) { + if (!ScriptServer::is_global_class(p_class)) + return false; + String base = script_class_get_base(p_class); + while (p_inherits != base) { + if (ClassDB::class_exists(base)) { + return ClassDB::is_parent_class(base, p_inherits); + } else if (ScriptServer::is_global_class(base)) { + base = script_class_get_base(base); + } else { + return false; + } + } + return true; +} + +StringName EditorData::script_class_get_base(const String &p_class) { + + if (!ScriptServer::is_global_class(p_class)) + return StringName(); + + String path = ScriptServer::get_global_class_path(p_class); + + Ref<Script> script = ResourceLoader::load(path, "Script"); + if (script.is_null()) + return StringName(); + + Ref<Script> base_script = script->get_base_script(); + if (base_script.is_null()) { + return ScriptServer::get_global_class_base(p_class); + } + + return script->get_language()->get_global_class_name(base_script->get_path()); +} + EditorData::EditorData() { current_edited_scene = -1; diff --git a/editor/editor_data.h b/editor/editor_data.h index 0ecef8ae31..fac6635cd2 100644 --- a/editor/editor_data.h +++ b/editor/editor_data.h @@ -211,6 +211,9 @@ public: void notify_edited_scene_changed(); void notify_resource_saved(const Ref<Resource> &p_resource); + bool script_class_is_parent(const String &p_class, const String &p_inherits); + StringName script_class_get_base(const String &p_class); + EditorData(); }; diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index 317fffad64..5c911a00ca 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -187,7 +187,7 @@ void EditorExportPreset::remove_patch(int p_idx) { void EditorExportPreset::set_patch(int p_index, const String &p_path) { ERR_FAIL_INDEX(p_index, patches.size()); - patches[p_index] = p_path; + patches.write[p_index] = p_path; EditorExport::singleton->save_presets(); } String EditorExportPreset::get_patch(int p_index) { @@ -295,7 +295,7 @@ Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_pa MD5Final(&ctx); sd.md5.resize(16); for (int i = 0; i < 16; i++) { - sd.md5[i] = ctx.digest[i]; + sd.md5.write[i] = ctx.digest[i]; } } @@ -584,9 +584,9 @@ EditorExportPlatform::ExportNotifier::ExportNotifier(EditorExportPlatform &p_pla //initial export plugin callback for (int i = 0; i < export_plugins.size(); i++) { if (export_plugins[i]->get_script_instance()) { //script based - export_plugins[i]->_export_begin_script(features.features_pv, p_debug, p_path, p_flags); + export_plugins.write[i]->_export_begin_script(features.features_pv, p_debug, p_path, p_flags); } else { - export_plugins[i]->_export_begin(features.features, p_debug, p_path, p_flags); + export_plugins.write[i]->_export_begin(features.features, p_debug, p_path, p_flags); } } } @@ -594,7 +594,7 @@ EditorExportPlatform::ExportNotifier::ExportNotifier(EditorExportPlatform &p_pla EditorExportPlatform::ExportNotifier::~ExportNotifier() { Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins(); for (int i = 0; i < export_plugins.size(); i++) { - export_plugins[i]->_export_end(); + export_plugins.write[i]->_export_end(); } } @@ -632,7 +632,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, 0, paths.size()); } - export_plugins[i]->_clear(); + export_plugins.write[i]->_clear(); } FeatureContainers feature_containers = get_feature_containers(p_preset); @@ -687,9 +687,9 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & bool do_export = true; for (int i = 0; i < export_plugins.size(); i++) { if (export_plugins[i]->get_script_instance()) { //script based - export_plugins[i]->_export_file_script(path, type, features_pv); + export_plugins.write[i]->_export_file_script(path, type, features_pv); } else { - export_plugins[i]->_export_file(path, type, features); + export_plugins.write[i]->_export_file(path, type, features); } if (p_so_func) { for (int j = 0; j < export_plugins[i]->shared_objects.size(); j++) { @@ -709,7 +709,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & if (export_plugins[i]->skipped) { do_export = false; } - export_plugins[i]->_clear(); + export_plugins.write[i]->_clear(); if (!do_export) break; //apologies, not exporting @@ -751,7 +751,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & Vector<uint8_t> new_file; new_file.resize(utf8.length()); for (int j = 0; j < utf8.length(); j++) { - new_file[j] = utf8[j]; + new_file.write[j] = utf8[j]; } p_func(p_udata, from + ".remap", new_file, idx, total); @@ -1130,7 +1130,7 @@ void EditorExport::load_config() { for (int i = 0; i < export_platforms.size(); i++) { if (export_platforms[i]->get_name() == platform) { - preset = export_platforms[i]->create_preset(); + preset = export_platforms.write[i]->create_preset(); break; } } @@ -1203,7 +1203,7 @@ bool EditorExport::poll_export_platforms() { bool changed = false; for (int i = 0; i < export_platforms.size(); i++) { - if (export_platforms[i]->poll_devices()) { + if (export_platforms.write[i]->poll_devices()) { changed = true; } } diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 8a8a21543b..d240f4ed25 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -558,7 +558,9 @@ void EditorFileDialog::_item_list_item_rmb_selected(int p_item, const Vector2 &p } if (single_item_selected) { item_menu->add_separator(); - item_menu->add_icon_item(get_icon("Filesystem", "EditorIcons"), TTR("Show In File Manager"), ITEM_MENU_SHOW_IN_EXPLORER); + Dictionary item_meta = item_list->get_item_metadata(p_item); + String item_text = item_meta["dir"] ? TTR("Open In File Manager") : TTR("Show In File Manager"); + item_menu->add_icon_item(get_icon("Filesystem", "EditorIcons"), item_text, ITEM_MENU_SHOW_IN_EXPLORER); } if (item_menu->get_item_count() > 0) { @@ -582,7 +584,7 @@ void EditorFileDialog::_item_list_rmb_clicked(const Vector2 &p_pos) { } item_menu->add_icon_item(get_icon("Reload", "EditorIcons"), TTR("Refresh"), ITEM_MENU_REFRESH, KEY_F5); item_menu->add_separator(); - item_menu->add_icon_item(get_icon("Filesystem", "EditorIcons"), TTR("Show In File Manager"), ITEM_MENU_SHOW_IN_EXPLORER); + item_menu->add_icon_item(get_icon("Filesystem", "EditorIcons"), TTR("Open In File Manager"), ITEM_MENU_SHOW_IN_EXPLORER); item_menu->set_position(item_list->get_global_position() + p_pos); item_menu->popup(); @@ -1135,7 +1137,7 @@ void EditorFileDialog::_favorite_move_up() { if (a_idx == -1 || b_idx == -1) return; - SWAP(favorited[a_idx], favorited[b_idx]); + SWAP(favorited.write[a_idx], favorited.write[b_idx]); EditorSettings::get_singleton()->set_favorite_dirs(favorited); @@ -1155,7 +1157,7 @@ void EditorFileDialog::_favorite_move_down() { if (a_idx == -1 || b_idx == -1) return; - SWAP(favorited[a_idx], favorited[b_idx]); + SWAP(favorited.write[a_idx], favorited.write[b_idx]); EditorSettings::get_singleton()->set_favorite_dirs(favorited); diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index d8ab41fa05..671ac755b2 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -1366,6 +1366,7 @@ void EditorFileSystem::update_script_classes() { } ScriptServer::save_global_classes(); + emit_signal("script_classes_updated"); } void EditorFileSystem::_queue_update_script_classes() { @@ -1704,6 +1705,7 @@ void EditorFileSystem::_bind_methods() { ADD_SIGNAL(MethodInfo("filesystem_changed")); ADD_SIGNAL(MethodInfo("sources_changed", PropertyInfo(Variant::BOOL, "exist"))); ADD_SIGNAL(MethodInfo("resources_reimported", PropertyInfo(Variant::POOL_STRING_ARRAY, "resources"))); + ADD_SIGNAL(MethodInfo("script_classes_updated")); } void EditorFileSystem::_update_extensions() { diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 727383b960..60826aa81b 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -253,7 +253,8 @@ void EditorHelpSearch::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { //_update_icons - search_box->add_icon_override("right_icon", get_icon("Search", "EditorIcons")); + search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_clear_button_enabled(true); connect("confirmed", this, "_confirmed"); _update_search(); @@ -267,7 +268,8 @@ void EditorHelpSearch::_notification(int p_what) { } else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { //_update_icons - search_box->add_icon_override("right_icon", get_icon("Search", "EditorIcons")); + search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_clear_button_enabled(true); } else if (p_what == NOTIFICATION_PROCESS) { if (search.is_valid()) { @@ -381,7 +383,8 @@ void EditorHelpIndex::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { //_update_icons - search_box->add_icon_override("right_icon", get_icon("Search", "EditorIcons")); + search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_clear_button_enabled(true); _update_class_list(); connect("confirmed", this, "_tree_item_selected"); @@ -392,7 +395,8 @@ void EditorHelpIndex::_notification(int p_what) { } else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { //_update_icons - search_box->add_icon_override("right_icon", get_icon("Search", "EditorIcons")); + search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_clear_button_enabled(true); } } @@ -541,6 +545,7 @@ void EditorHelp::_class_desc_select(const String &p_select) { String class_name; if (select.find(".") != -1) { class_name = select.get_slice(".", 0); + select = select.get_slice(".", 1); } else { class_name = "@GlobalScope"; } @@ -713,16 +718,22 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { if (p_class == edited_class) return OK; //already there + edited_class = p_class; + _update_doc(); + return OK; +} + +void EditorHelp::_update_doc() { + scroll_locked = true; class_desc->clear(); method_line.clear(); section_line.clear(); - edited_class = p_class; _init_colors(); - DocData::ClassDoc cd = doc->class_list[p_class]; //make a copy, so we can sort without worrying + DocData::ClassDoc cd = doc->class_list[edited_class]; //make a copy, so we can sort without worrying Ref<Font> doc_font = get_font("doc", "EditorFonts"); Ref<Font> doc_title_font = get_font("doc_title", "EditorFonts"); @@ -734,7 +745,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { class_desc->push_color(title_color); class_desc->add_text(TTR("Class:") + " "); class_desc->push_color(headline_color); - _add_text(p_class); + _add_text(edited_class); class_desc->pop(); class_desc->pop(); class_desc->pop(); @@ -1214,6 +1225,18 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { constant_line[constants[i].name] = class_desc->get_line_count() - 2; class_desc->push_font(doc_code_font); + + if (constants[i].value.begins_with("Color(") && constants[i].value.ends_with(")")) { + String stripped = constants[i].value.replace(" ", "").replace("Color(", "").replace(")", ""); + Vector<float> color = stripped.split_floats(","); + if (color.size() >= 3) { + class_desc->push_color(Color(color[0], color[1], color[2])); + static const CharType prefix[3] = { 0x25CF /* filled circle */, ' ', 0 }; + class_desc->add_text(String(prefix)); + class_desc->pop(); + } + } + class_desc->push_color(headline_color); _add_text(constants[i].name); class_desc->pop(); @@ -1223,6 +1246,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { class_desc->push_color(value_color); _add_text(constants[i].value); class_desc->pop(); + class_desc->pop(); if (constants[i].description != "") { class_desc->push_font(doc_font); @@ -1440,8 +1464,6 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { } scroll_locked = false; - - return OK; } void EditorHelp::_request_help(const String &p_string) { @@ -1738,9 +1760,6 @@ void EditorHelp::_add_text(const String &p_bbcode) { _add_text_to_rt(p_bbcode, class_desc); } -void EditorHelp::_update_doc() { -} - void EditorHelp::generate_doc() { doc = memnew(DocData); @@ -1763,6 +1782,7 @@ void EditorHelp::_notification(int p_what) { case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { class_desc->add_color_override("selection_color", get_color("text_editor/theme/selection_color", "Editor")); + _update_doc(); } break; diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 488980db07..99a2b2aa67 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -43,6 +43,9 @@ Size2 EditorProperty::get_minimum_size() const { Size2 ms; + Ref<Font> font = get_font("font", "Tree"); + ms.height = font->get_height(); + for (int i = 0; i < get_child_count(); i++) { Control *c = Object::cast_to<Control>(get_child(i)); @@ -70,12 +73,10 @@ Size2 EditorProperty::get_minimum_size() const { ms.width += check->get_width() + get_constant("hseparator", "Tree"); } - if (bottom_editor != NULL) { - Ref<Font> font = get_font("font", "Tree"); - ms.height += font->get_height(); + if (bottom_editor != NULL && bottom_editor->is_visible()) { ms.height += get_constant("vseparation", "Tree"); Size2 bems = bottom_editor->get_combined_minimum_size(); - bems.width += get_constant("item_margin", "Tree"); + //bems.width += get_constant("item_margin", "Tree"); ms.height += bems.height; ms.width = MAX(ms.width, bems.width); } @@ -98,6 +99,7 @@ void EditorProperty::_notification(int p_what) { int child_room = size.width * (1.0 - split_ratio); Ref<Font> font = get_font("font", "Tree"); int height = font->get_height(); + bool no_children = true; //compute room needed for (int i = 0; i < get_child_count(); i++) { @@ -113,11 +115,16 @@ void EditorProperty::_notification(int p_what) { Size2 minsize = c->get_combined_minimum_size(); child_room = MAX(child_room, minsize.width); height = MAX(height, minsize.height); + no_children = false; } - text_size = MAX(0, size.width - child_room + 4 * EDSCALE); - - rect = Rect2(text_size, 0, size.width - text_size, height); + if (no_children) { + text_size = size.width; + rect = Rect2(size.width - 1, 0, 1, height); + } else { + text_size = MAX(0, size.width - (child_room + 4 * EDSCALE)); + rect = Rect2(size.width - child_room, 0, child_room, height); + } if (bottom_editor) { @@ -178,7 +185,7 @@ void EditorProperty::_notification(int p_what) { draw_style_box(sb, Rect2(Vector2(), size)); } - if (right_child_rect != Rect2()) { + if (draw_top_bg && right_child_rect != Rect2()) { draw_rect(right_child_rect, dark_color); } if (bottom_child_rect != Rect2()) { @@ -189,7 +196,7 @@ void EditorProperty::_notification(int p_what) { if (draw_red) { color = get_color("error_color", "Editor"); } else { - color = get_color("font_color", "Tree"); + color = get_color("property_color", "Editor"); } if (label.find(".") != -1) { color.a = 0.5; //this should be un-hacked honestly, as it's used for editor overrides @@ -787,6 +794,8 @@ void EditorProperty::_bind_methods() { EditorProperty::EditorProperty() { + draw_top_bg = true; + object = NULL; split_ratio = 0.5; selectable = true; text_size = 0; @@ -1613,32 +1622,10 @@ void EditorInspector::update_tree() { for (List<EditorInspectorPlugin::AddedEditor>::Element *F = editors.front(); F; F = F->next()) { EditorProperty *ep = Object::cast_to<EditorProperty>(F->get().property_editor); - current_vbox->add_child(F->get().property_editor); if (ep) { - + //set all this before the control gets the ENTER_TREE notification ep->object = object; - ep->connect("property_changed", this, "_property_changed"); - if (p.usage & PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED) { - ep->connect("property_changed", this, "_property_changed_update_all", varray(), CONNECT_DEFERRED); - } - ep->connect("property_keyed", this, "_property_keyed"); - ep->connect("property_keyed_with_value", this, "_property_keyed_with_value"); - ep->connect("property_checked", this, "_property_checked"); - ep->connect("selected", this, "_property_selected"); - ep->connect("multiple_properties_changed", this, "_multiple_properties_changed"); - ep->connect("resource_selected", this, "_resource_selected", varray(), CONNECT_DEFERRED); - ep->connect("object_id_selected", this, "_object_id_selected", varray(), CONNECT_DEFERRED); - if (doc_hint != String()) { - ep->set_tooltip(property_prefix + p.name + "::" + doc_hint); - } else { - ep->set_tooltip(property_prefix + p.name); - } - ep->set_draw_red(draw_red); - ep->set_use_folding(use_folding); - ep->set_checkable(checkable); - ep->set_checked(checked); - ep->set_keying(keying); if (F->get().properties.size()) { @@ -1664,8 +1651,35 @@ void EditorInspector::update_tree() { editor_property_map[prop].push_back(ep); } } + ep->set_draw_red(draw_red); + ep->set_use_folding(use_folding); + ep->set_checkable(checkable); + ep->set_checked(checked); + ep->set_keying(keying); ep->set_read_only(read_only); + } + + current_vbox->add_child(F->get().property_editor); + + if (ep) { + + ep->connect("property_changed", this, "_property_changed"); + if (p.usage & PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED) { + ep->connect("property_changed", this, "_property_changed_update_all", varray(), CONNECT_DEFERRED); + } + ep->connect("property_keyed", this, "_property_keyed"); + ep->connect("property_keyed_with_value", this, "_property_keyed_with_value"); + ep->connect("property_checked", this, "_property_checked"); + ep->connect("selected", this, "_property_selected"); + ep->connect("multiple_properties_changed", this, "_multiple_properties_changed"); + ep->connect("resource_selected", this, "_resource_selected", varray(), CONNECT_DEFERRED); + ep->connect("object_id_selected", this, "_object_id_selected", varray(), CONNECT_DEFERRED); + if (doc_hint != String()) { + ep->set_tooltip(property_prefix + p.name + "::" + doc_hint); + } else { + ep->set_tooltip(property_prefix + p.name); + } ep->update_property(); ep->update_reload_status(); diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 454622d662..ebe2124a40 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -68,6 +68,7 @@ private: bool can_revert; bool use_folding; + bool draw_top_bg; bool _might_be_in_instance(); bool _is_property_different(const Variant &p_current, const Variant &p_orig, int p_usage); @@ -149,6 +150,8 @@ public: String get_tooltip_text() const; + void set_draw_top_bg(bool p_draw) { draw_top_bg = p_draw; } + EditorProperty(); }; diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 158eedfb0f..b3ec717d85 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -54,7 +54,11 @@ void EditorLog::_error_handler(void *p_self, const char *p_func, const char *p_f self->emit_signal("show_request"); */ - self->add_message(err_str, true); + if (p_type == ERR_HANDLER_WARNING) { + self->add_message(err_str, MSG_TYPE_WARNING); + } else { + self->add_message(err_str, MSG_TYPE_ERROR); + } } void EditorLog::_notification(int p_what) { @@ -95,22 +99,32 @@ void EditorLog::clear() { _clear_request(); } -void EditorLog::add_message(const String &p_msg, bool p_error) { +void EditorLog::add_message(const String &p_msg, MessageType p_type) { log->add_newline(); - if (p_error) { - log->push_color(get_color("error_color", "Editor")); - Ref<Texture> icon = get_icon("Error", "EditorIcons"); - log->add_image(icon); - log->add_text(" "); - tool_button->set_icon(icon); + bool restore = p_type != MSG_TYPE_STD; + switch (p_type) { + case MSG_TYPE_ERROR: { + log->push_color(get_color("error_color", "Editor")); + Ref<Texture> icon = get_icon("Error", "EditorIcons"); + log->add_image(icon); + log->add_text(" "); + tool_button->set_icon(icon); + } break; + case MSG_TYPE_WARNING: { + log->push_color(get_color("warning_color", "Editor")); + Ref<Texture> icon = get_icon("Warning", "EditorIcons"); + log->add_image(icon); + log->add_text(" "); + tool_button->set_icon(icon); + } break; } log->add_text(p_msg); //button->set_text(p_msg); - if (p_error) + if (restore) log->pop(); } diff --git a/editor/editor_log.h b/editor/editor_log.h index f9bc82de7d..8d0310d914 100644 --- a/editor/editor_log.h +++ b/editor/editor_log.h @@ -42,6 +42,7 @@ #include "scene/gui/panel_container.h" #include "scene/gui/texture_rect.h" #include "scene/gui/tool_button.h" + class EditorLog : public VBoxContainer { GDCLASS(EditorLog, VBoxContainer); @@ -68,7 +69,13 @@ protected: void _notification(int p_what); public: - void add_message(const String &p_msg, bool p_error = false); + enum MessageType { + MSG_TYPE_STD, + MSG_TYPE_ERROR, + MSG_TYPE_WARNING + }; + + void add_message(const String &p_msg, MessageType p_type = MSG_TYPE_STD); void set_tool_button(ToolButton *p_tool_button); void deinit(); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index b366ebd911..5748de9d1b 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -62,6 +62,8 @@ #include "editor/import/editor_scene_importer_gltf.h" #include "editor/import/resource_importer_bitmask.h" #include "editor/import/resource_importer_csv_translation.h" +#include "editor/import/resource_importer_image.h" +#include "editor/import/resource_importer_layered_texture.h" #include "editor/import/resource_importer_obj.h" #include "editor/import/resource_importer_scene.h" #include "editor/import/resource_importer_texture.h" @@ -108,6 +110,7 @@ #include "editor/plugins/shader_graph_editor_plugin.h" #include "editor/plugins/skeleton_2d_editor_plugin.h" #include "editor/plugins/skeleton_editor_plugin.h" +#include "editor/plugins/skeleton_ik_editor_plugin.h" #include "editor/plugins/spatial_editor_plugin.h" #include "editor/plugins/sprite_editor_plugin.h" #include "editor/plugins/sprite_frames_editor_plugin.h" @@ -598,7 +601,7 @@ void EditorNode::save_resource_in_path(const Ref<Resource> &p_resource, const St Error err = ResourceSaver::save(path, p_resource, flg | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS); if (err != OK) { - show_accept(TTR("Error saving resource!"), TTR("I see...")); + show_accept(TTR("Error saving resource!"), TTR("OK")); return; } @@ -688,15 +691,15 @@ void EditorNode::_dialog_display_save_error(String p_file, Error p_error) { case ERR_FILE_CANT_WRITE: { - show_accept(TTR("Can't open file for writing:") + " " + p_file.get_extension(), TTR("I see...")); + show_accept(TTR("Can't open file for writing:") + " " + p_file.get_extension(), TTR("OK")); } break; case ERR_FILE_UNRECOGNIZED: { - show_accept(TTR("Requested file format unknown:") + " " + p_file.get_extension(), TTR("I see...")); + show_accept(TTR("Requested file format unknown:") + " " + p_file.get_extension(), TTR("OK")); } break; default: { - show_accept(TTR("Error while saving."), TTR("I see...")); + show_accept(TTR("Error while saving."), TTR("OK")); } break; } } @@ -710,23 +713,23 @@ void EditorNode::_dialog_display_load_error(String p_file, Error p_error) { case ERR_CANT_OPEN: { - show_accept(vformat(TTR("Can't open '%s'. The file could have been moved or deleted."), p_file.get_file()), TTR("I see...")); + show_accept(vformat(TTR("Can't open '%s'. The file could have been moved or deleted."), p_file.get_file()), TTR("OK")); } break; case ERR_PARSE_ERROR: { - show_accept(vformat(TTR("Error while parsing '%s'."), p_file.get_file()), TTR("I see...")); + show_accept(vformat(TTR("Error while parsing '%s'."), p_file.get_file()), TTR("OK")); } break; case ERR_FILE_CORRUPT: { - show_accept(vformat(TTR("Unexpected end of file '%s'."), p_file.get_file()), TTR("I see...")); + show_accept(vformat(TTR("Unexpected end of file '%s'."), p_file.get_file()), TTR("OK")); } break; case ERR_FILE_NOT_FOUND: { - show_accept(vformat(TTR("Missing '%s' or its dependencies."), p_file.get_file()), TTR("I see...")); + show_accept(vformat(TTR("Missing '%s' or its dependencies."), p_file.get_file()), TTR("OK")); } break; default: { - show_accept(vformat(TTR("Error while loading '%s'."), p_file.get_file()), TTR("I see...")); + show_accept(vformat(TTR("Error while loading '%s'."), p_file.get_file()), TTR("OK")); } break; } } @@ -946,8 +949,6 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { int x = (img->get_width() - vp_size) / 2; int y = (img->get_height() - vp_size) / 2; - img->convert(Image::FORMAT_RGB8); - if (vp_size < preview_size) { // just square it. img->crop_from_point(x, y, vp_size, vp_size); @@ -962,6 +963,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { // We could get better pictures with better filters img->resize(preview_size, preview_size, Image::INTERPOLATE_CUBIC); } + img->convert(Image::FORMAT_RGB8); img->flip_y(); @@ -989,7 +991,7 @@ void EditorNode::_save_scene(String p_file, int idx) { if (!scene) { - show_accept(TTR("This operation can't be done without a tree root."), TTR("I see...")); + show_accept(TTR("This operation can't be done without a tree root."), TTR("OK")); return; } @@ -1017,7 +1019,7 @@ void EditorNode::_save_scene(String p_file, int idx) { if (err != OK) { - show_accept(TTR("Couldn't save scene. Likely dependencies (instances or inheritance) couldn't be satisfied."), TTR("I see...")); + show_accept(TTR("Couldn't save scene. Likely dependencies (instances or inheritance) couldn't be satisfied."), TTR("OK")); return; } @@ -1025,7 +1027,7 @@ void EditorNode::_save_scene(String p_file, int idx) { // (hacky but needed for the tree to update properly) Node *dummy_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE); if (!dummy_scene) { - show_accept(TTR("Couldn't save scene. Likely dependencies (instances or inheritance) couldn't be satisfied."), TTR("I see...")); + show_accept(TTR("Couldn't save scene. Likely dependencies (instances or inheritance) couldn't be satisfied."), TTR("OK")); return; } memdelete(dummy_scene); @@ -1187,7 +1189,7 @@ void EditorNode::_dialog_action(String p_file) { ml = ResourceLoader::load(p_file, "MeshLibrary"); if (ml.is_null()) { - show_accept(TTR("Can't load MeshLibrary for merging!"), TTR("I see...")); + show_accept(TTR("Can't load MeshLibrary for merging!"), TTR("OK")); return; } } @@ -1200,7 +1202,7 @@ void EditorNode::_dialog_action(String p_file) { Error err = ResourceSaver::save(p_file, ml); if (err) { - show_accept(TTR("Error saving MeshLibrary!"), TTR("I see...")); + show_accept(TTR("Error saving MeshLibrary!"), TTR("OK")); return; } @@ -1212,7 +1214,7 @@ void EditorNode::_dialog_action(String p_file) { tileset = ResourceLoader::load(p_file, "TileSet"); if (tileset.is_null()) { - show_accept(TTR("Can't load TileSet for merging!"), TTR("I see...")); + show_accept(TTR("Can't load TileSet for merging!"), TTR("OK")); return; } @@ -1225,7 +1227,7 @@ void EditorNode::_dialog_action(String p_file) { Error err = ResourceSaver::save(p_file, tileset); if (err) { - show_accept("Error saving TileSet!", "I see..."); + show_accept(TTR("Error saving TileSet!"), TTR("OK")); return; } } break; @@ -1502,7 +1504,7 @@ void EditorNode::_edit_current() { if (main_plugin) { // special case if use of external editor is true - if (main_plugin->get_name() == "Script" && (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")) || overrides_external_editor(current_obj))) { + if (main_plugin->get_name() == "Script" && current_obj->get_class_name() != StringName("VisualScript") && (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")) || overrides_external_editor(current_obj))) { if (!changing_scene) main_plugin->edit(current_obj); } @@ -1579,7 +1581,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) { Node *scene = editor_data.get_edited_scene_root(); if (!scene) { - show_accept(TTR("There is no defined scene to run."), TTR("I see...")); + show_accept(TTR("There is no defined scene to run."), TTR("OK")); return; } @@ -1633,7 +1635,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) { if (scene->get_filename() == "") { - show_accept(TTR("Current scene was never saved, please save it prior to running."), TTR("I see...")); + show_accept(TTR("Current scene was never saved, please save it prior to running."), TTR("OK")); return; } @@ -1664,7 +1666,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) { if (error != OK) { - show_accept(TTR("Could not start subprocess!"), TTR("I see...")); + show_accept(TTR("Could not start subprocess!"), TTR("OK")); return; } @@ -1753,6 +1755,11 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } else { tab_closing = editor_data.get_edited_scene(); } + if (!editor_data.get_edited_scene_root(tab_closing)) { + // empty tab + _scene_tab_closed(tab_closing); + break; + } } // fallthrough case SCENE_TAB_CLOSE: @@ -1782,7 +1789,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { if (!scene) { - show_accept(TTR("This operation can't be done without a tree root."), TTR("I see...")); + show_accept(TTR("This operation can't be done without a tree root."), TTR("OK")); break; } @@ -1845,7 +1852,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { if (!editor_data.get_edited_scene_root()) { - show_accept(TTR("This operation can't be done without a scene."), TTR("I see...")); + show_accept(TTR("This operation can't be done without a scene."), TTR("OK")); break; } @@ -1865,7 +1872,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { //Make sure that the scene has a root before trying to convert to tileset if (!editor_data.get_edited_scene_root()) { - show_accept(TTR("This operation can't be done without a root node."), TTR("I see...")); + show_accept(TTR("This operation can't be done without a root node."), TTR("OK")); break; } @@ -1886,7 +1893,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { if (!editor_data.get_edited_scene_root()) { - show_accept(TTR("This operation can't be done without a selected node."), TTR("I see...")); + show_accept(TTR("This operation can't be done without a selected node."), TTR("OK")); break; } @@ -2047,6 +2054,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { project_settings->popup_project_settings(); } break; + case RUN_PROJECT_DATA_FOLDER: { + + OS::get_singleton()->shell_open(OS::get_singleton()->get_user_data_dir()); + } break; case FILE_QUIT: case RUN_PROJECT_MANAGER: { @@ -2159,7 +2170,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { OS::get_singleton()->set_low_processor_usage_mode(false); EditorSettings::get_singleton()->set_project_metadata("editor_options", "update_always", true); - show_accept(TTR("This option is deprecated. Situations where refresh must be forced are now considered a bug. Please report."), TTR("I see...")); + show_accept(TTR("This option is deprecated. Situations where refresh must be forced are now considered a bug. Please report."), TTR("OK")); } break; case SETTINGS_UPDATE_CHANGES: { @@ -2179,6 +2190,14 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { settings_config_dialog->popup_edit_settings(); } break; + case SETTINGS_EDITOR_DATA_FOLDER: { + + OS::get_singleton()->shell_open(EditorSettings::get_singleton()->get_data_dir()); + } break; + case SETTINGS_EDITOR_CONFIG_FOLDER: { + + OS::get_singleton()->shell_open(EditorSettings::get_singleton()->get_settings_dir()); + } break; case SETTINGS_MANAGE_EXPORT_TEMPLATES: { export_template_manager->popup_manager(); @@ -2765,7 +2784,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b if (!lpath.begins_with("res://")) { - show_accept(TTR("Error loading scene, it must be inside the project path. Use 'Import' to open the scene, then save it inside the project path."), TTR("Ugh")); + show_accept(TTR("Error loading scene, it must be inside the project path. Use 'Import' to open the scene, then save it inside the project path."), TTR("OK")); opening_prev = false; return ERR_FILE_NOT_FOUND; } @@ -3833,6 +3852,7 @@ void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) { Ref<InputEventMouseButton> mb = p_input; if (mb.is_valid()) { + if (scene_tabs->get_hovered_tab() >= 0) { if (mb->get_button_index() == BUTTON_MIDDLE && mb->is_pressed()) { _scene_tab_closed(scene_tabs->get_hovered_tab()); @@ -3842,6 +3862,26 @@ void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) { _menu_option_confirm(FILE_NEW_SCENE, true); } } + if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { + + // context menu + scene_tabs_context_menu->clear(); + scene_tabs_context_menu->set_size(Size2(1, 1)); + + scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/new_scene"), FILE_NEW_SCENE); + if (scene_tabs->get_hovered_tab() >= 0) { + scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_scene"), FILE_SAVE_SCENE); + scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_scene_as"), FILE_SAVE_AS_SCENE); + } + scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_all_scenes"), FILE_SAVE_ALL_SCENES); + if (scene_tabs->get_hovered_tab() >= 0) { + scene_tabs_context_menu->add_separator(); + scene_tabs_context_menu->add_item(TTR("Play This Scene"), RUN_PLAY_SCENE); + scene_tabs_context_menu->add_item(TTR("Close Tab"), FILE_CLOSE); + } + scene_tabs_context_menu->set_position(mb->get_global_position()); + scene_tabs_context_menu->popup(); + } } } @@ -3935,7 +3975,7 @@ void EditorNode::raise_bottom_panel_item(Control *p_item) { if (bottom_panel_items[i].control == p_item) { bottom_panel_items[i].button->raise(); - SWAP(bottom_panel_items[i], bottom_panel_items[bottom_panel_items.size() - 1]); + SWAP(bottom_panel_items.write[i], bottom_panel_items.write[bottom_panel_items.size() - 1]); break; } } @@ -4526,7 +4566,7 @@ static Node *_resource_get_edited_scene() { void EditorNode::_print_handler(void *p_this, const String &p_string, bool p_error) { EditorNode *en = (EditorNode *)p_this; - en->log->add_message(p_string, p_error); + en->log->add_message(p_string, p_error ? EditorLog::MSG_TYPE_ERROR : EditorLog::MSG_TYPE_STD); } EditorNode::EditorNode() { @@ -4627,6 +4667,20 @@ EditorNode::EditorNode() { import_texture.instance(); ResourceFormatImporter::get_singleton()->add_importer(import_texture); + Ref<ResourceImporterLayeredTexture> import_3d; + import_3d.instance(); + import_3d->set_3d(true); + ResourceFormatImporter::get_singleton()->add_importer(import_3d); + + Ref<ResourceImporterLayeredTexture> import_array; + import_array.instance(); + import_array->set_3d(false); + ResourceFormatImporter::get_singleton()->add_importer(import_array); + + Ref<ResourceImporterImage> import_image; + import_image.instance(); + ResourceFormatImporter::get_singleton()->add_importer(import_image); + Ref<ResourceImporterCSVTranslation> import_csv_translation; import_csv_translation.instance(); ResourceFormatImporter::get_singleton()->add_importer(import_csv_translation); @@ -4719,6 +4773,8 @@ EditorNode::EditorNode() { EDITOR_DEF_RST("interface/scene_tabs/show_thumbnail_on_hover", true); EDITOR_DEF_RST("interface/inspector/capitalize_properties", true); EDITOR_DEF_RST("interface/inspector/disable_folding", false); + EDITOR_DEF("interface/inspector/horizontal_vector2_editing", false); + EDITOR_DEF("interface/inspector/horizontal_vector3_editing", true); EDITOR_DEF("interface/inspector/open_resources_in_current_inspector", true); EDITOR_DEF("interface/inspector/resources_types_to_open_in_new_inspector", "SpatialMaterial"); EDITOR_DEF("run/auto_save/save_before_running", true); @@ -4897,6 +4953,7 @@ EditorNode::EditorNode() { scene_tabs = memnew(Tabs); scene_tabs->add_style_override("tab_fg", gui_base->get_stylebox("SceneTabFG", "EditorStyles")); scene_tabs->add_style_override("tab_bg", gui_base->get_stylebox("SceneTabBG", "EditorStyles")); + scene_tabs->set_select_with_rmb(true); scene_tabs->add_tab("unsaved"); scene_tabs->set_tab_align(Tabs::ALIGN_LEFT); scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/scene_tabs/always_show_close_button", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY)); @@ -4914,6 +4971,11 @@ EditorNode::EditorNode() { tabbar_container = memnew(HBoxContainer); scene_tabs->set_h_size_flags(Control::SIZE_EXPAND_FILL); + scene_tabs_context_menu = memnew(PopupMenu); + tabbar_container->add_child(scene_tabs_context_menu); + scene_tabs_context_menu->connect("id_pressed", this, "_menu_option"); + scene_tabs_context_menu->set_hide_on_window_lose_focus(true); + srt->add_child(tabbar_container); tabbar_container->add_child(scene_tabs); distraction_free = memnew(ToolButton); @@ -5020,6 +5082,7 @@ EditorNode::EditorNode() { file_menu->set_tooltip(TTR("Operations with scene files.")); p = file_menu->get_popup(); + p->set_hide_on_window_lose_focus(true); p->add_shortcut(ED_SHORTCUT("editor/new_scene", TTR("New Scene")), FILE_NEW_SCENE); p->add_shortcut(ED_SHORTCUT("editor/new_inherited_scene", TTR("New Inherited Scene...")), FILE_NEW_INHERITED_SCENE); p->add_shortcut(ED_SHORTCUT("editor/open_scene", TTR("Open Scene..."), KEY_MASK_CMD + KEY_O), FILE_OPEN_SCENE); @@ -5065,6 +5128,7 @@ EditorNode::EditorNode() { left_menu_hb->add_child(project_menu); p = project_menu->get_popup(); + p->set_hide_on_window_lose_focus(true); p->add_item(TTR("Project Settings"), RUN_SETTINGS); p->add_separator(); p->connect("id_pressed", this, "_menu_option"); @@ -5078,6 +5142,9 @@ EditorNode::EditorNode() { tool_menu->add_item(TTR("Orphan Resource Explorer"), TOOLS_ORPHAN_RESOURCES); p->add_separator(); + p->add_item(TTR("Open Project Data Folder"), RUN_PROJECT_DATA_FOLDER); + p->add_separator(); + #ifdef OSX_ENABLED p->add_item(TTR("Quit to Project List"), RUN_PROJECT_MANAGER, KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_Q); #else @@ -5097,6 +5164,7 @@ EditorNode::EditorNode() { left_menu_hb->add_child(debug_menu); p = debug_menu->get_popup(); + p->set_hide_on_window_lose_focus(true); p->set_hide_on_item_selection(false); p->add_check_item(TTR("Deploy with Remote Debug"), RUN_DEPLOY_REMOTE_DEBUG); p->set_item_tooltip(p->get_item_count() - 1, TTR("When exporting or deploying, the resulting executable will attempt to connect to the IP of this computer in order to be debugged.")); @@ -5121,10 +5189,12 @@ EditorNode::EditorNode() { settings_menu->set_text(TTR("Editor")); settings_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles")); left_menu_hb->add_child(settings_menu); - p = settings_menu->get_popup(); + p = settings_menu->get_popup(); + p->set_hide_on_window_lose_focus(true); p->add_item(TTR("Editor Settings"), SETTINGS_PREFERENCES); p->add_separator(); + editor_layouts = memnew(PopupMenu); editor_layouts->set_name("Layouts"); p->add_child(editor_layouts); @@ -5136,6 +5206,17 @@ EditorNode::EditorNode() { p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_SHIFT | KEY_F11), SETTINGS_TOGGLE_FULLSCREEN); #endif p->add_separator(); + + if (OS::get_singleton()->get_data_path() == OS::get_singleton()->get_config_path()) { + // Configuration and data folders are located in the same place (Windows/macOS) + p->add_item(TTR("Open Editor Data/Settings Folder"), SETTINGS_EDITOR_DATA_FOLDER); + } else { + // Separate configuration and data folders (Linux) + p->add_item(TTR("Open Editor Data Folder"), SETTINGS_EDITOR_DATA_FOLDER); + p->add_item(TTR("Open Editor Settings Folder"), SETTINGS_EDITOR_CONFIG_FOLDER); + } + p->add_separator(); + p->add_item(TTR("Manage Export Templates"), SETTINGS_MANAGE_EXPORT_TEMPLATES); // Help Menu @@ -5146,6 +5227,7 @@ EditorNode::EditorNode() { left_menu_hb->add_child(help_menu); p = help_menu->get_popup(); + p->set_hide_on_window_lose_focus(true); p->connect("id_pressed", this, "_menu_option"); p->add_icon_item(gui_base->get_icon("ClassList", "EditorIcons"), TTR("Classes"), HELP_CLASSES); p->add_icon_item(gui_base->get_icon("HelpSearch", "EditorIcons"), TTR("Search"), HELP_SEARCH); @@ -5366,6 +5448,7 @@ EditorNode::EditorNode() { bottom_panel->add_child(bottom_panel_vb); bottom_panel_hb = memnew(HBoxContainer); + bottom_panel_hb->set_custom_minimum_size(Size2(0, 24)); // Adjust for the height of the "Expand Bottom Dock" icon. bottom_panel_vb->add_child(bottom_panel_hb); bottom_panel_hb_editors = memnew(HBoxContainer); @@ -5528,6 +5611,7 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor))); add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor))); add_editor_plugin(memnew(SkeletonEditorPlugin(this))); + add_editor_plugin(memnew(SkeletonIKEditorPlugin(this))); add_editor_plugin(memnew(PhysicalBonePlugin(this))); // FIXME: Disabled as (according to reduz) users were complaining that it gets in the way diff --git a/editor/editor_node.h b/editor/editor_node.h index 38e68b2e09..85aa37ec7e 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -154,6 +154,7 @@ private: RUN_PLAY_CUSTOM_SCENE, RUN_SCENE_SETTINGS, RUN_SETTINGS, + RUN_PROJECT_DATA_FOLDER, RUN_PROJECT_MANAGER, RUN_FILE_SERVER, RUN_LIVE_DEBUG, @@ -168,6 +169,8 @@ private: SETTINGS_LAYOUT_SAVE, SETTINGS_LAYOUT_DELETE, SETTINGS_LAYOUT_DEFAULT, + SETTINGS_EDITOR_DATA_FOLDER, + SETTINGS_EDITOR_CONFIG_FOLDER, SETTINGS_MANAGE_EXPORT_TEMPLATES, SETTINGS_PICK_MAIN_SCENE, SETTINGS_TOGGLE_FULLSCREEN, @@ -220,6 +223,7 @@ private: //main tabs Tabs *scene_tabs; + PopupMenu *scene_tabs_context_menu; Panel *tab_preview_panel; TextureRect *tab_preview; int tab_closing; diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 843267d673..a926401558 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -479,15 +479,6 @@ void EditorPlugin::notify_resource_saved(const Ref<Resource> &p_resource) { emit_signal("resource_saved", p_resource); } -Ref<SpatialEditorGizmo> EditorPlugin::create_spatial_gizmo(Spatial *p_spatial) { - //?? - if (get_script_instance() && get_script_instance()->has_method("create_spatial_gizmo")) { - return get_script_instance()->call("create_spatial_gizmo", p_spatial); - } - - return Ref<SpatialEditorGizmo>(); -} - bool EditorPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { if (get_script_instance() && get_script_instance()->has_method("forward_canvas_gui_input")) { @@ -765,10 +756,6 @@ void EditorPlugin::_bind_methods() { ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_force_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "forward_spatial_gui_input", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); - MethodInfo gizmo = MethodInfo(Variant::OBJECT, "create_spatial_gizmo", PropertyInfo(Variant::OBJECT, "for_spatial", PROPERTY_HINT_RESOURCE_TYPE, "Spatial")); - gizmo.return_val.hint = PROPERTY_HINT_RESOURCE_TYPE; - gizmo.return_val.hint_string = "EditorSpatialGizmo"; - ClassDB::add_virtual_method(get_class_static(), gizmo); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_plugin_name")); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::OBJECT, "get_plugin_icon")); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "has_main_screen")); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 72e21b2f7f..c417f487dc 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -51,7 +51,6 @@ class Camera; class EditorSelection; class EditorExport; class EditorSettings; -class SpatialEditorGizmo; class EditorImportPlugin; class EditorExportPlugin; class EditorResourcePreview; @@ -171,7 +170,6 @@ public: void notify_scene_closed(const String &scene_filepath); void notify_resource_saved(const Ref<Resource> &p_resource); - virtual Ref<SpatialEditorGizmo> create_spatial_gizmo(Spatial *p_spatial); virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event); virtual void forward_draw_over_viewport(Control *p_overlay); virtual void forward_force_draw_over_viewport(Control *p_overlay); diff --git a/editor/editor_profiler.cpp b/editor/editor_profiler.cpp index d4a97b7095..67700b59de 100644 --- a/editor/editor_profiler.cpp +++ b/editor/editor_profiler.cpp @@ -37,9 +37,9 @@ void EditorProfiler::_make_metric_ptrs(Metric &m) { for (int i = 0; i < m.categories.size(); i++) { - m.category_ptrs[m.categories[i].signature] = &m.categories[i]; + m.category_ptrs[m.categories[i].signature] = &m.categories.write[i]; for (int j = 0; j < m.categories[i].items.size(); j++) { - m.item_ptrs[m.categories[i].items[j].signature] = &m.categories[i].items[j]; + m.item_ptrs[m.categories[i].items[j].signature] = &m.categories.write[i].items.write[j]; } } } @@ -50,8 +50,8 @@ void EditorProfiler::add_frame_metric(const Metric &p_metric, bool p_final) { if (last_metric >= frame_metrics.size()) last_metric = 0; - frame_metrics[last_metric] = p_metric; - _make_metric_ptrs(frame_metrics[last_metric]); + frame_metrics.write[last_metric] = p_metric; + _make_metric_ptrs(frame_metrics.write[last_metric]); updating_frame = true; cursor_metric_edit->set_max(frame_metrics[last_metric].frame_number); @@ -108,7 +108,7 @@ static String _get_percent_txt(float p_value, float p_total) { return String::num((p_value / p_total) * 100, 1) + "%"; } -String EditorProfiler::_get_time_as_text(Metric &m, float p_time, int p_calls) { +String EditorProfiler::_get_time_as_text(const Metric &m, float p_time, int p_calls) { int dmode = display_mode->get_selected(); @@ -192,18 +192,18 @@ void EditorProfiler::_update_plot() { float highest = 0; for (int i = 0; i < frame_metrics.size(); i++) { - Metric &m = frame_metrics[i]; + const Metric &m = frame_metrics[i]; if (!m.valid) continue; for (Set<StringName>::Element *E = plot_sigs.front(); E; E = E->next()) { - Map<StringName, Metric::Category *>::Element *F = m.category_ptrs.find(E->get()); + const Map<StringName, Metric::Category *>::Element *F = m.category_ptrs.find(E->get()); if (F) { highest = MAX(F->get()->total_time, highest); } - Map<StringName, Metric::Category::Item *>::Element *G = m.item_ptrs.find(E->get()); + const Map<StringName, Metric::Category::Item *>::Element *G = m.item_ptrs.find(E->get()); if (G) { if (use_self) { highest = MAX(G->get()->self, highest); @@ -256,18 +256,18 @@ void EditorProfiler::_update_plot() { } //get - Metric &m = frame_metrics[idx]; + const Metric &m = frame_metrics[idx]; if (m.valid == false) continue; //skip because invalid float value = 0; - Map<StringName, Metric::Category *>::Element *F = m.category_ptrs.find(E->get()); + const Map<StringName, Metric::Category *>::Element *F = m.category_ptrs.find(E->get()); if (F) { value = F->get()->total_time; } - Map<StringName, Metric::Category::Item *>::Element *G = m.item_ptrs.find(E->get()); + const Map<StringName, Metric::Category::Item *>::Element *G = m.item_ptrs.find(E->get()); if (G) { if (use_self) { value = G->get()->self; @@ -375,7 +375,7 @@ void EditorProfiler::_update_frame() { variables->clear(); TreeItem *root = variables->create_item(); - Metric &m = frame_metrics[cursor_metric]; + const Metric &m = frame_metrics[cursor_metric]; int dtime = display_time->get_selected(); @@ -394,7 +394,7 @@ void EditorProfiler::_update_frame() { } for (int j = 0; j < m.categories[i].items.size(); j++) { - Metric::Category::Item &it = m.categories[i].items[j]; + const Metric::Category::Item &it = m.categories[i].items[j]; TreeItem *item = variables->create_item(category); item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); diff --git a/editor/editor_profiler.h b/editor/editor_profiler.h index cb451475e7..d445ad58aa 100644 --- a/editor/editor_profiler.h +++ b/editor/editor_profiler.h @@ -136,7 +136,7 @@ private: void _activate_pressed(); void _clear_pressed(); - String _get_time_as_text(Metric &m, float p_time, int p_calls); + String _get_time_as_text(const Metric &m, float p_time, int p_calls); void _make_metric_ptrs(Metric &m); void _item_edited(); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 0b49b5a801..83a3662f21 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -258,6 +258,51 @@ EditorPropertyPath::EditorPropertyPath() { global = false; } +///////////////////// CLASS NAME ///////////////////////// + +void EditorPropertyClassName::setup(const String &p_base_type, const String &p_selected_type) { + + base_type = p_base_type; + dialog->set_base_type(base_type); + selected_type = p_selected_type; + property->set_text(selected_type); +} + +void EditorPropertyClassName::update_property() { + + String s = get_edited_object()->get(get_edited_property()); + property->set_text(s); + selected_type = s; +} + +void EditorPropertyClassName::_property_selected() { + dialog->popup_create(true); +} + +void EditorPropertyClassName::_dialog_created() { + selected_type = dialog->get_selected_type(); + emit_signal("property_changed", get_edited_property(), selected_type); + update_property(); +} + +void EditorPropertyClassName::_bind_methods() { + ClassDB::bind_method(D_METHOD("_dialog_created"), &EditorPropertyClassName::_dialog_created); + ClassDB::bind_method(D_METHOD("_property_selected"), &EditorPropertyClassName::_property_selected); +} + +EditorPropertyClassName::EditorPropertyClassName() { + property = memnew(Button); + property->set_clip_text(true); + add_child(property); + add_focusable(property); + property->set_text(selected_type); + property->connect("pressed", this, "_property_selected"); + dialog = memnew(CreateDialog); + dialog->set_base_type(base_type); + dialog->connect("create", this, "_dialog_created"); + add_child(dialog); +} + ///////////////////// MEMBER ///////////////////////// void EditorPropertyMember::_property_selected(const String &p_selected) { @@ -523,6 +568,7 @@ public: uint32_t value; Vector<Rect2> flag_rects; Vector<String> names; + Vector<String> tooltips; virtual Size2 get_minimum_size() const { Ref<Font> font = get_font("font", "Label"); @@ -531,8 +577,8 @@ public: virtual String get_tooltip(const Point2 &p_pos) const { for (int i = 0; i < flag_rects.size(); i++) { - if (i < names.size() && flag_rects[i].has_point(p_pos)) { - return names[i]; + if (i < tooltips.size() && flag_rects[i].has_point(p_pos)) { + return tooltips[i]; } } return String(); @@ -636,6 +682,7 @@ void EditorPropertyLayers::setup(LayerType p_layer_type) { } Vector<String> names; + Vector<String> tooltips; for (int i = 0; i < 20; i++) { String name; @@ -647,12 +694,12 @@ void EditorPropertyLayers::setup(LayerType p_layer_type) { name = TTR("Layer") + " " + itos(i + 1); } - name += "\n" + vformat(TTR("Bit %d, value %d"), i, 1 << i); - names.push_back(name); + tooltips.push_back(name + "\n" + vformat(TTR("Bit %d, value %d"), i, 1 << i)); } grid->names = names; + grid->tooltips = tooltips; } void EditorPropertyLayers::_button_pressed() { @@ -681,6 +728,7 @@ void EditorPropertyLayers::_menu_pressed(int p_menu) { grid->value |= (1 << p_menu); } grid->update(); + layers->set_item_checked(layers->get_item_index(p_menu), grid->value & (1 << p_menu)); _grid_changed(grid->value); } @@ -706,6 +754,7 @@ EditorPropertyLayers::EditorPropertyLayers() { set_bottom_editor(hb); layers = memnew(PopupMenu); add_child(layers); + layers->set_hide_on_checkable_item_selection(false); layers->connect("id_pressed", this, "_menu_pressed"); } ///////////////////// INT ///////////////////////// @@ -1020,18 +1069,35 @@ void EditorPropertyVector2::setup(double p_min, double p_max, double p_step, boo } EditorPropertyVector2::EditorPropertyVector2() { - VBoxContainer *vb = memnew(VBoxContainer); - add_child(vb); + bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector2_editing"); + + BoxContainer *bc; + + if (horizontal) { + bc = memnew(HBoxContainer); + add_child(bc); + set_bottom_editor(bc); + } else { + bc = memnew(VBoxContainer); + add_child(bc); + } + static const char *desc[2] = { "x", "y" }; for (int i = 0; i < 2; i++) { spin[i] = memnew(EditorSpinSlider); spin[i]->set_flat(true); spin[i]->set_label(desc[i]); - vb->add_child(spin[i]); + bc->add_child(spin[i]); add_focusable(spin[i]); spin[i]->connect("value_changed", this, "_value_changed"); + if (horizontal) { + spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); + } + } + + if (!horizontal) { + set_label_reference(spin[0]); //show text and buttons around this } - set_label_reference(spin[0]); //show text and buttons around this setting = false; } @@ -1146,19 +1212,35 @@ void EditorPropertyVector3::setup(double p_min, double p_max, double p_step, boo } EditorPropertyVector3::EditorPropertyVector3() { - VBoxContainer *vb = memnew(VBoxContainer); - add_child(vb); + bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector3_editing"); + + BoxContainer *bc; + + if (horizontal) { + bc = memnew(HBoxContainer); + add_child(bc); + set_bottom_editor(bc); + } else { + bc = memnew(VBoxContainer); + add_child(bc); + } + static const char *desc[3] = { "x", "y", "z" }; for (int i = 0; i < 3; i++) { spin[i] = memnew(EditorSpinSlider); - spin[i]->set_label(desc[i]); spin[i]->set_flat(true); - - vb->add_child(spin[i]); + spin[i]->set_label(desc[i]); + bc->add_child(spin[i]); add_focusable(spin[i]); spin[i]->connect("value_changed", this, "_value_changed"); + if (horizontal) { + spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); + } + } + + if (!horizontal) { + set_label_reference(spin[0]); //show text and buttons around this } - set_label_reference(spin[0]); //show text and buttons around this setting = false; } ///////////////////// PLANE ///////////////////////// @@ -1210,18 +1292,36 @@ void EditorPropertyPlane::setup(double p_min, double p_max, double p_step, bool } EditorPropertyPlane::EditorPropertyPlane() { - VBoxContainer *vb = memnew(VBoxContainer); - add_child(vb); + + bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector3_editing"); + + BoxContainer *bc; + + if (horizontal) { + bc = memnew(HBoxContainer); + add_child(bc); + set_bottom_editor(bc); + } else { + bc = memnew(VBoxContainer); + add_child(bc); + } + static const char *desc[4] = { "x", "y", "z", "d" }; for (int i = 0; i < 4; i++) { spin[i] = memnew(EditorSpinSlider); - spin[i]->set_label(desc[i]); spin[i]->set_flat(true); - vb->add_child(spin[i]); + spin[i]->set_label(desc[i]); + bc->add_child(spin[i]); add_focusable(spin[i]); spin[i]->connect("value_changed", this, "_value_changed"); + if (horizontal) { + spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); + } + } + + if (!horizontal) { + set_label_reference(spin[0]); //show text and buttons around this } - set_label_reference(spin[0]); //show text and buttons around this setting = false; } @@ -1274,19 +1374,35 @@ void EditorPropertyQuat::setup(double p_min, double p_max, double p_step, bool p } EditorPropertyQuat::EditorPropertyQuat() { - VBoxContainer *vb = memnew(VBoxContainer); - add_child(vb); + bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector3_editing"); + + BoxContainer *bc; + + if (horizontal) { + bc = memnew(HBoxContainer); + add_child(bc); + set_bottom_editor(bc); + } else { + bc = memnew(VBoxContainer); + add_child(bc); + } + static const char *desc[4] = { "x", "y", "z", "w" }; for (int i = 0; i < 4; i++) { spin[i] = memnew(EditorSpinSlider); - spin[i]->set_label(desc[i]); spin[i]->set_flat(true); - - vb->add_child(spin[i]); + spin[i]->set_label(desc[i]); + bc->add_child(spin[i]); add_focusable(spin[i]); spin[i]->connect("value_changed", this, "_value_changed"); + if (horizontal) { + spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); + } + } + + if (!horizontal) { + set_label_reference(spin[0]); //show text and buttons around this } - set_label_reference(spin[0]); //show text and buttons around this setting = false; } @@ -2607,6 +2723,10 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ } else if (p_hint == PROPERTY_HINT_MULTILINE_TEXT) { EditorPropertyMultilineText *editor = memnew(EditorPropertyMultilineText); add_property_editor(p_path, editor); + } else if (p_hint == PROPERTY_HINT_TYPE_STRING) { + EditorPropertyClassName *editor = memnew(EditorPropertyClassName); + editor->setup("Object", p_hint_text); + add_property_editor(p_path, editor); } else if (p_hint == PROPERTY_HINT_DIR || p_hint == PROPERTY_HINT_FILE || p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE) { Vector<String> extensions = p_hint_text.split(","); diff --git a/editor/editor_properties.h b/editor/editor_properties.h index 0afb1bf955..ccd73d2539 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -119,6 +119,25 @@ public: EditorPropertyPath(); }; +class EditorPropertyClassName : public EditorProperty { + GDCLASS(EditorPropertyClassName, EditorProperty) +private: + CreateDialog *dialog; + Button *property; + String selected_type; + String base_type; + void _property_selected(); + void _dialog_created(); + +protected: + static void _bind_methods(); + +public: + void setup(const String &p_base_type, const String &p_selected_type); + virtual void update_property(); + EditorPropertyClassName(); +}; + class EditorPropertyMember : public EditorProperty { GDCLASS(EditorPropertyMember, EditorProperty) public: diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index aa67ea03d7..a9eaad47b7 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -46,7 +46,7 @@ bool EditorResourcePreviewGenerator::handles(const String &p_type) const { ERR_EXPLAIN("EditorResourcePreviewGenerator::handles needs to be overridden"); ERR_FAIL_V(false); } -Ref<Texture> EditorResourcePreviewGenerator::generate(const RES &p_from) { +Ref<Texture> EditorResourcePreviewGenerator::generate(const RES &p_from) const { if (get_script_instance() && get_script_instance()->has_method("generate")) { return get_script_instance()->call("generate", p_from); @@ -55,7 +55,7 @@ Ref<Texture> EditorResourcePreviewGenerator::generate(const RES &p_from) { ERR_FAIL_V(Ref<Texture>()); } -Ref<Texture> EditorResourcePreviewGenerator::generate_from_path(const String &p_path) { +Ref<Texture> EditorResourcePreviewGenerator::generate_from_path(const String &p_path) const { if (get_script_instance() && get_script_instance()->has_method("generate_from_path")) { return get_script_instance()->call("generate_from_path", p_path); diff --git a/editor/editor_resource_preview.h b/editor/editor_resource_preview.h index e2276aa11d..74841b1a1e 100644 --- a/editor/editor_resource_preview.h +++ b/editor/editor_resource_preview.h @@ -63,8 +63,8 @@ protected: public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from); - virtual Ref<Texture> generate_from_path(const String &p_path); + virtual Ref<Texture> generate(const RES &p_from) const; + virtual Ref<Texture> generate_from_path(const String &p_path) const; EditorResourcePreviewGenerator(); }; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index c8e97b071f..8e079b1f67 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -396,7 +396,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("text_editor/cursor/block_caret", false); _initial_set("text_editor/cursor/caret_blink", true); - _initial_set("text_editor/cursor/caret_blink_speed", 0.65); + _initial_set("text_editor/cursor/caret_blink_speed", 0.5); hints["text_editor/cursor/caret_blink_speed"] = PropertyInfo(Variant::REAL, "text_editor/cursor/caret_blink_speed", PROPERTY_HINT_RANGE, "0.1, 10, 0.01"); _initial_set("text_editor/cursor/right_click_moves_caret", true); @@ -755,7 +755,7 @@ void EditorSettings::create() { } if (dir->change_dir(data_dir) != OK) { - dir->make_dir(data_dir); + dir->make_dir_recursive(data_dir); if (dir->change_dir(data_dir) != OK) { ERR_PRINT("Cannot create data directory!"); memdelete(dir); @@ -771,14 +771,8 @@ void EditorSettings::create() { // Validate/create cache dir - if (dir->change_dir(cache_path) != OK) { - ERR_PRINT("Cannot find path for cache directory!"); - memdelete(dir); - goto fail; - } - if (dir->change_dir(cache_dir) != OK) { - dir->make_dir(cache_dir); + dir->make_dir_recursive(cache_dir); if (dir->change_dir(cache_dir) != OK) { ERR_PRINT("Cannot create cache directory!"); memdelete(dir); @@ -788,14 +782,8 @@ void EditorSettings::create() { // Validate/create config dir and subdirectories - if (dir->change_dir(config_path) != OK) { - ERR_PRINT("Cannot find path for config directory!"); - memdelete(dir); - goto fail; - } - if (dir->change_dir(config_dir) != OK) { - dir->make_dir(config_dir); + dir->make_dir_recursive(config_dir); if (dir->change_dir(config_dir) != OK) { ERR_PRINT("Cannot create config directory!"); memdelete(dir); @@ -881,7 +869,7 @@ fail: Vector<String> list = extra_config->get_value("init_projects", "list"); for (int i = 0; i < list.size(); i++) { - list[i] = exe_path + "/" + list[i]; + list.write[i] = exe_path + "/" + list[i]; }; extra_config->set_value("init_projects", "list", list); }; diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index 0e6d81d13b..b2c9f9865a 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -30,7 +30,13 @@ #include "editor_spin_slider.h" #include "editor_scale.h" +#include "math/expression.h" #include "os/input.h" + +String EditorSpinSlider::get_tooltip(const Point2 &p_pos) const { + return rtos(get_value()); +} + String EditorSpinSlider::get_text_value() const { int zeros = Math::step_decimals(get_step()); return String::num(get_value(), zeros); @@ -270,10 +276,12 @@ void EditorSpinSlider::_notification(int p_what) { if (p_what == NOTIFICATION_FOCUS_ENTER) { /* Sorry, I dont like this, it makes navigating the different fields with arrows more difficult. * Just press enter to edit. - * if (!Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT) && !value_input_just_closed) { + * if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT) && !value_input_just_closed) { _focus_entered(); }*/ - + if ((Input::get_singleton()->is_action_pressed("ui_focus_next") || Input::get_singleton()->is_action_pressed("ui_focus_prev")) && !value_input_just_closed) { + _focus_entered(); + } value_input_just_closed = false; } } @@ -307,6 +315,21 @@ String EditorSpinSlider::get_label() const { return label; } +void EditorSpinSlider::_evaluate_input_text() { + String text = value_input->get_text(); + Ref<Expression> expr; + expr.instance(); + Error err = expr->parse(text); + if (err != OK) { + return; + } + + Variant v = expr->execute(Array(), NULL, false); + if (v.get_type() == Variant::NIL) + return; + set_value(v); +} + //text_entered signal void EditorSpinSlider::_value_input_entered(const String &p_text) { value_input_just_closed = true; @@ -315,13 +338,13 @@ void EditorSpinSlider::_value_input_entered(const String &p_text) { //modal_closed signal void EditorSpinSlider::_value_input_closed() { - set_value(value_input->get_text().to_double()); + _evaluate_input_text(); value_input_just_closed = true; } //focus_exited signal void EditorSpinSlider::_value_focus_exited() { - set_value(value_input->get_text().to_double()); + _evaluate_input_text(); // focus is not on the same element after the vlalue_input was exited // -> focus is on next element // -> TAB was pressed diff --git a/editor/editor_spin_slider.h b/editor/editor_spin_slider.h index fb32534ef4..e48eb171b8 100644 --- a/editor/editor_spin_slider.h +++ b/editor/editor_spin_slider.h @@ -73,6 +73,8 @@ class EditorSpinSlider : public Range { bool use_custom_label_color; Color custom_label_color; + void _evaluate_input_text(); + protected: void _notification(int p_what); void _gui_input(const Ref<InputEvent> &p_event); @@ -82,6 +84,8 @@ protected: void _focus_entered(); public: + String get_tooltip(const Point2 &p_pos) const; + String get_text_value() const; void set_label(const String &p_label); String get_label() const; diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 18cc52a5c6..3995eb3dd6 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -175,7 +175,7 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = const Color warning_color = p_theme->get_color("warning_color", "Editor"); dark_icon_color_dictionary[Color::html("#ff5d5d")] = error_color; dark_icon_color_dictionary[Color::html("#45ff8b")] = success_color; - dark_icon_color_dictionary[Color::html("#ffdd65")] = warning_color; + dark_icon_color_dictionary[Color::html("#dbab09")] = warning_color; List<String> exceptions; exceptions.push_back("EditorPivot"); @@ -365,11 +365,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("mono_color", "Editor", mono_color); Color success_color = accent_color.linear_interpolate(Color(0.2, 1, 0.2), 0.6) * 1.2; - Color warning_color = accent_color.linear_interpolate(Color(1, 1, 0), 0.7) * 1.2; + Color warning_color = accent_color.linear_interpolate(Color(1, 1, 0), 0.7) * 1.0; Color error_color = accent_color.linear_interpolate(Color(1, 0, 0), 0.8) * 1.7; + Color property_color = font_color.linear_interpolate(Color(0.5, 0.5, 0.5), 0.5); + if (!dark_theme) { // yellow on white themes is a P.I.T.A. - warning_color = accent_color.linear_interpolate(Color(1, 0.8, 0), 0.9); + warning_color = accent_color.linear_interpolate(Color(0.9, 0.7, 0), 0.9); warning_color = warning_color.linear_interpolate(mono_color, 0.2); success_color = success_color.linear_interpolate(mono_color, 0.2); error_color = error_color.linear_interpolate(mono_color, 0.2); @@ -377,6 +379,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("success_color", "Editor", success_color); theme->set_color("warning_color", "Editor", warning_color); theme->set_color("error_color", "Editor", error_color); + theme->set_color("property_color", "Editor", property_color); // 2d grid color const Color grid_minor_color = mono_color * Color(1.0, 1.0, 1.0, 0.07); @@ -825,6 +828,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("font_color", "LineEdit", font_color); theme->set_color("cursor_color", "LineEdit", font_color); theme->set_color("selection_color", "LineEdit", font_color_selection); + theme->set_color("clear_button_color", "LineEdit", font_color); + theme->set_color("clear_button_color_pressed", "LineEdit", accent_color); // TextEdit theme->set_stylebox("normal", "TextEdit", style_widget); diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp index 931785333f..6c9d1568fa 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export_template_manager.cpp @@ -178,7 +178,7 @@ void ExportTemplateManager::_uninstall_template_confirm() { _update_template_list(); } -void ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_progress) { +bool ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_progress) { FileAccess *fa = NULL; zlib_filefunc_def io = zipio_create_io_from_file(&fa); @@ -187,7 +187,7 @@ void ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_ if (!pkg) { EditorNode::get_singleton()->show_warning(TTR("Can't open export templates zip.")); - return; + return false; } int ret = unzGoToFirstFile(pkg); @@ -221,7 +221,7 @@ void ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_ if (data_str.get_slice_count(".") < 3) { EditorNode::get_singleton()->show_warning(vformat(TTR("Invalid version.txt format inside templates: %s."), data_str)); unzClose(pkg); - return; + return false; } version = data_str; @@ -237,7 +237,7 @@ void ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_ if (version == String()) { EditorNode::get_singleton()->show_warning(TTR("No version.txt found inside templates.")); unzClose(pkg); - return; + return false; } String template_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(version); @@ -247,7 +247,7 @@ void ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_ if (err != OK) { EditorNode::get_singleton()->show_warning(TTR("Error creating path for templates:") + "\n" + template_path); unzClose(pkg); - return; + return false; } memdelete(d); @@ -310,6 +310,8 @@ void ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_ unzClose(pkg); _update_template_list(); + + return true; } void ExportTemplateManager::popup_manager() { @@ -401,7 +403,15 @@ void ExportTemplateManager::_http_download_templates_completed(int p_status, int String path = download_templates->get_download_file(); template_list_state->set_text(TTR("Download Complete.")); template_downloader->hide(); - _install_from_file(path, false); + int ret = _install_from_file(path, false); + if (ret) { + Error err = OS::get_singleton()->move_to_trash(path); + if (err != OK) { + EditorNode::get_singleton()->add_io_error(TTR("Cannot remove:") + "\n" + path + "\n"); + } + } else { + WARN_PRINTS(vformat(TTR("Templates installation failed. The problematic templates archives can be found at '%s'."), path)); + } } } break; } diff --git a/editor/export_template_manager.h b/editor/export_template_manager.h index 54a645c69f..bd43fe5dc5 100644 --- a/editor/export_template_manager.h +++ b/editor/export_template_manager.h @@ -70,7 +70,7 @@ class ExportTemplateManager : public ConfirmationDialog { void _uninstall_template_confirm(); virtual void ok_pressed(); - void _install_from_file(const String &p_file, bool p_use_progress = true); + bool _install_from_file(const String &p_file, bool p_use_progress = true); 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); diff --git a/editor/fileserver/editor_file_server.cpp b/editor/fileserver/editor_file_server.cpp index a218070933..b9e0c7d0fa 100644 --- a/editor/fileserver/editor_file_server.cpp +++ b/editor/fileserver/editor_file_server.cpp @@ -78,7 +78,7 @@ void EditorFileServer::_subthread_start(void *s) { _close_client(cd); ERR_FAIL_COND(err != OK); } - passutf8[passlen] = 0; + passutf8.write[passlen] = 0; String s; s.parse_utf8(passutf8.ptr()); if (s != cd->efs->password) { @@ -145,7 +145,7 @@ void EditorFileServer::_subthread_start(void *s) { _close_client(cd); ERR_FAIL_COND(err != OK); } - fileutf8[namelen] = 0; + fileutf8.write[namelen] = 0; String s; s.parse_utf8(fileutf8.ptr()); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 37f86cc912..f2c8cde151 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -196,7 +196,8 @@ void FileSystemDock::_notification(int p_what) { files->connect("item_activated", this, "_select_file"); button_hist_next->connect("pressed", this, "_fw_history"); button_hist_prev->connect("pressed", this, "_bw_history"); - search_box->add_icon_override("right_icon", get_icon("Search", ei)); + search_box->set_right_icon(get_icon("Search", ei)); + search_box->set_clear_button_enabled(true); button_hist_next->set_icon(get_icon("Forward", ei)); button_hist_prev->set_icon(get_icon("Back", ei)); @@ -252,7 +253,8 @@ void FileSystemDock::_notification(int p_what) { button_hist_next->set_icon(get_icon("Forward", ei)); button_hist_prev->set_icon(get_icon("Back", ei)); - search_box->add_icon_override("right_icon", get_icon("Search", ei)); + search_box->set_right_icon(get_icon("Search", ei)); + search_box->set_clear_button_enabled(true); if (new_mode != display_mode) { set_display_mode(new_mode); @@ -1408,7 +1410,7 @@ void FileSystemDock::_resource_created() const { RES current_res = RES(r); - editor->save_resource_as(current_res); + editor->save_resource_as(current_res, path); } void FileSystemDock::_go_to_file_list() { @@ -1448,7 +1450,7 @@ void FileSystemDock::_dir_rmb_pressed(const Vector2 &p_pos) { } folder_options->add_separator(); folder_options->add_item(TTR("New Folder..."), FOLDER_NEW_FOLDER); - folder_options->add_item(TTR("Show In File Manager"), FOLDER_SHOW_IN_EXPLORER); + folder_options->add_item(TTR("Open In File Manager"), FOLDER_SHOW_IN_EXPLORER); } folder_options->set_position(tree->get_global_position() + p_pos); folder_options->popup(); @@ -1757,7 +1759,10 @@ void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) { file_options->add_item(TTR("New Folder..."), FILE_NEW_FOLDER); file_options->add_item(TTR("New Script..."), FILE_NEW_SCRIPT); file_options->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE); - file_options->add_item(TTR("Show In File Manager"), FILE_SHOW_IN_EXPLORER); + + String fpath = files->get_item_metadata(p_item); + String item_text = fpath.ends_with("/") ? TTR("Open In File Manager") : TTR("Show In File Manager"); + file_options->add_item(item_text, FILE_SHOW_IN_EXPLORER); file_options->set_position(files->get_global_position() + p_pos); file_options->popup(); @@ -1983,9 +1988,11 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { */ file_options = memnew(PopupMenu); + file_options->set_hide_on_window_lose_focus(true); add_child(file_options); folder_options = memnew(PopupMenu); + folder_options->set_hide_on_window_lose_focus(true); add_child(folder_options); split_box = memnew(VSplitContainer); diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index 004a49e2b4..2be1f1644e 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -143,7 +143,7 @@ void FindInFiles::_iterate() { // Scan folders first so we can build a list of files and have progress info later - PoolStringArray &folders_to_scan = _folders_stack[_folders_stack.size() - 1]; + PoolStringArray &folders_to_scan = _folders_stack.write[_folders_stack.size() - 1]; if (folders_to_scan.size() != 0) { // Scan one folder below diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp index 2bfd2eb5c3..0efd14e932 100644 --- a/editor/groups_editor.cpp +++ b/editor/groups_editor.cpp @@ -287,8 +287,10 @@ void GroupDialog::_notification(int p_what) { add_button->set_icon(get_icon("Forward", "EditorIcons")); remove_button->set_icon(get_icon("Back", "EditorIcons")); - add_filter->add_icon_override("right_icon", get_icon("Search", "EditorIcons")); - remove_filter->add_icon_override("right_icon", get_icon("Search", "EditorIcons")); + add_filter->set_right_icon(get_icon("Search", "EditorIcons")); + add_filter->set_clear_button_enabled(true); + remove_filter->set_right_icon(get_icon("Search", "EditorIcons")); + remove_filter->set_clear_button_enabled(true); } break; } } diff --git a/editor/icons/SCsub b/editor/icons/SCsub index 7f94073e01..31bf8f116a 100644 --- a/editor/icons/SCsub +++ b/editor/icons/SCsub @@ -1,96 +1,14 @@ #!/usr/bin/env python Import('env') -from compat import StringIO +from platform_methods import run_in_subprocess +import editor_icons_builders -def make_editor_icons_action(target, source, env): - import os - - dst = target[0].srcnode().abspath - svg_icons = source - - icons_string = StringIO() - - for f in svg_icons: - - fname = str(f) - - icons_string.write('\t"') - - with open(fname, 'rb') as svgf: - b = svgf.read(1) - while(len(b) == 1): - icons_string.write("\\" + str(hex(ord(b)))[1:]) - b = svgf.read(1) - - - icons_string.write('"') - if fname != svg_icons[-1]: - icons_string.write(",") - icons_string.write('\n') - - s = StringIO() - s.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") - s.write("#ifndef _EDITOR_ICONS_H\n") - s.write("#define _EDITOR_ICONS_H\n") - s.write("static const int editor_icons_count = {};\n".format(len(svg_icons))) - s.write("static const char *editor_icons_sources[] = {\n") - s.write(icons_string.getvalue()) - s.write('};\n\n') - s.write("static const char *editor_icons_names[] = {\n") - - # this is used to store the indices of thumbnail icons - thumb_medium_indices = []; - thumb_big_indices = []; - index = 0 - for f in svg_icons: - - fname = str(f) - - icon_name = os.path.basename(fname)[5:-4].title().replace("_", "") - # some special cases - if icon_name in ['Int', 'Bool', 'Float']: - icon_name = icon_name.lower() - if icon_name.endswith("MediumThumb"): # don't know a better way to handle this - thumb_medium_indices.append(str(index)) - if icon_name.endswith("BigThumb"): # don't know a better way to handle this - thumb_big_indices.append(str(index)) - - s.write('\t"{0}"'.format(icon_name)) - - if fname != svg_icons[-1]: - s.write(",") - s.write('\n') - - index += 1 - - s.write('};\n') - - if thumb_medium_indices: - s.write("\n\n") - s.write("static const int editor_md_thumbs_count = {};\n".format(len(thumb_medium_indices))) - s.write("static const int editor_md_thumbs_indices[] = {") - s.write(", ".join(thumb_medium_indices)) - s.write("};\n") - if thumb_big_indices: - s.write("\n\n") - s.write("static const int editor_bg_thumbs_count = {};\n".format(len(thumb_big_indices))) - s.write("static const int editor_bg_thumbs_indices[] = {") - s.write(", ".join(thumb_big_indices)) - s.write("};\n") - - s.write("#endif\n") - - with open(dst, "w") as f: - f.write(s.getvalue()) - - s.close() - icons_string.close() - -make_editor_icons_builder = Builder(action=make_editor_icons_action, +make_editor_icons_builder = Builder(action=run_in_subprocess(editor_icons_builders.make_editor_icons_action), suffix='.h', src_suffix='.svg') + env['BUILDERS']['MakeEditorIconsBuilder'] = make_editor_icons_builder env.Alias('editor_icons', [env.MakeEditorIconsBuilder('#editor/editor_icons.gen.h', Glob("*.svg"))]) diff --git a/editor/icons/editor_icons_builders.py b/editor/icons/editor_icons_builders.py new file mode 100644 index 0000000000..dfd0802ce9 --- /dev/null +++ b/editor/icons/editor_icons_builders.py @@ -0,0 +1,96 @@ +"""Functions used to generate source files during build time + +All such functions are invoked in a subprocess on Windows to prevent build flakiness. + +""" +import os +from platform_methods import subprocess_main +from compat import StringIO + + +def make_editor_icons_action(target, source, env): + + dst = target[0] + svg_icons = source + + icons_string = StringIO() + + for f in svg_icons: + + fname = str(f) + + icons_string.write('\t"') + + with open(fname, 'rb') as svgf: + b = svgf.read(1) + while(len(b) == 1): + icons_string.write("\\" + str(hex(ord(b)))[1:]) + b = svgf.read(1) + + + icons_string.write('"') + if fname != svg_icons[-1]: + icons_string.write(",") + icons_string.write('\n') + + s = StringIO() + s.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + s.write("#ifndef _EDITOR_ICONS_H\n") + s.write("#define _EDITOR_ICONS_H\n") + s.write("static const int editor_icons_count = {};\n".format(len(svg_icons))) + s.write("static const char *editor_icons_sources[] = {\n") + s.write(icons_string.getvalue()) + s.write('};\n\n') + s.write("static const char *editor_icons_names[] = {\n") + + # this is used to store the indices of thumbnail icons + thumb_medium_indices = []; + thumb_big_indices = []; + index = 0 + for f in svg_icons: + + fname = str(f) + + icon_name = os.path.basename(fname)[5:-4].title().replace("_", "") + # some special cases + if icon_name in ['Int', 'Bool', 'Float']: + icon_name = icon_name.lower() + if icon_name.endswith("MediumThumb"): # don't know a better way to handle this + thumb_medium_indices.append(str(index)) + if icon_name.endswith("BigThumb"): # don't know a better way to handle this + thumb_big_indices.append(str(index)) + + s.write('\t"{0}"'.format(icon_name)) + + if fname != svg_icons[-1]: + s.write(",") + s.write('\n') + + index += 1 + + s.write('};\n') + + if thumb_medium_indices: + s.write("\n\n") + s.write("static const int editor_md_thumbs_count = {};\n".format(len(thumb_medium_indices))) + s.write("static const int editor_md_thumbs_indices[] = {") + s.write(", ".join(thumb_medium_indices)) + s.write("};\n") + if thumb_big_indices: + s.write("\n\n") + s.write("static const int editor_bg_thumbs_count = {};\n".format(len(thumb_big_indices))) + s.write("static const int editor_bg_thumbs_indices[] = {") + s.write(", ".join(thumb_big_indices)) + s.write("};\n") + + s.write("#endif\n") + + with open(dst, "w") as f: + f.write(s.getvalue()) + + s.close() + icons_string.close() + + +if __name__ == '__main__': + subprocess_main(globals()) diff --git a/editor/icons/icon_add_atlas_tile.svg b/editor/icons/icon_add_atlas_tile.svg new file mode 100644 index 0000000000..912a0ce2c9 --- /dev/null +++ b/editor/icons/icon_add_atlas_tile.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m7 1v6h-6v2h6v6h2v-6h6v-2h-6v-6h-2z" fill="#c9cfd4"/> +</svg> diff --git a/editor/icons/icon_add_autotile.svg b/editor/icons/icon_add_autotile.svg new file mode 100644 index 0000000000..2cc34d53b1 --- /dev/null +++ b/editor/icons/icon_add_autotile.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m7 1v6h-6v2h6v6h2v-6h6v-2h-6v-6h-2z" fill="#4490fc"/> +</svg> diff --git a/editor/icons/icon_add_single_tile.svg b/editor/icons/icon_add_single_tile.svg new file mode 100644 index 0000000000..01af8e0649 --- /dev/null +++ b/editor/icons/icon_add_single_tile.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m7 1v6h-6v2h6v6h2v-6h6v-2h-6v-6h-2z" fill="#fce844"/> +</svg> diff --git a/editor/icons/icon_information_sign.svg b/editor/icons/icon_information_sign.svg new file mode 100644 index 0000000000..95002b6948 --- /dev/null +++ b/editor/icons/icon_information_sign.svg @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg8" + sodipodi:docname="icon_information_sign.svg" + inkscape:version="0.92.3 (2405546, 2018-03-11)"> + <metadata + id="metadata14"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs12" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1047" + inkscape:window-height="603" + id="namedview10" + showgrid="false" + inkscape:zoom="14.521571" + inkscape:cx="12.730205" + inkscape:cy="8.6526495" + inkscape:window-x="654" + inkscape:window-y="156" + inkscape:window-maximized="0" + inkscape:current-layer="svg8" /> + <path + style="fill:#ffb65d;fill-opacity:1;fill-rule:evenodd;stroke-width:0.57024062" + inkscape:connector-curvature="0" + id="path2" + d="m 4.5291945,14.892249 h 6.8428865 l 3.421444,-3.421444 V 4.6279186 L 11.372081,1.2064749 H 4.5291945 L 1.1077509,4.6279186 v 6.8428864 z" /> + <rect + style="fill:#ffffff;fill-opacity:1;stroke-width:0.57024062" + id="rect829" + width="2.6243541" + height="6.5062103" + x="6.6998501" + y="6.3477535" /> + <ellipse + style="fill:#ffffff;fill-opacity:1;stroke-width:0.57024062" + id="path831" + cx="8.0393629" + cy="4.2154655" + rx="1.3941878" + ry="1.3668507" /> +</svg> diff --git a/editor/icons/icon_texture_3_d.svg b/editor/icons/icon_texture_3_d.svg new file mode 100644 index 0000000000..dafdc8c68d --- /dev/null +++ b/editor/icons/icon_texture_3_d.svg @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg6" + sodipodi:docname="icon_texture_3_d.svg" + inkscape:version="0.92.3 (2405546, 2018-03-11)"> + <metadata + id="metadata12"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs10" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1853" + inkscape:window-height="1016" + id="namedview8" + showgrid="false" + inkscape:zoom="29.5" + inkscape:cx="15.226978" + inkscape:cy="9.4909723" + inkscape:window-x="67" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="svg6" /> + <g + id="g830" + transform="translate(0.35954582,-0.28763666)"> + <path + d="M 2,1 C 1.4477153,1 1,1.4477153 1,2 v 12 c 0,0.552285 0.4477153,1 1,1 h 12 c 0.552285,0 1,-0.447715 1,-1 V 2 C 15,1.4477153 14.552285,1 14,1 Z m 1,2 h 10 v 8 H 3 Z" + id="path2" + inkscape:connector-curvature="0" + style="fill:#e0e0e0;fill-opacity:0.99607999" + sodipodi:nodetypes="sssssssssccccc" /> + </g> + <g + aria-label="3D" + transform="scale(0.9167105,1.0908569)" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:8.12847996px;line-height:1.25;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';letter-spacing:0px;word-spacing:0px;fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:0.20321201" + id="text834"> + <path + d="m 5.8175194,8.9717502 q -0.2194689,0 -0.4633233,-0.032514 Q 5.1103417,8.9148508 4.8827442,8.86608 4.6551468,8.8173091 4.4681918,8.7604097 4.2812367,8.7035104 4.1755665,8.6547395 L 4.4112924,7.646808 q 0.2113405,0.089413 0.5364797,0.1950835 0.3332677,0.097542 0.8209765,0.097542 0.5608651,0 0.8209764,-0.2113404 0.2601114,-0.2113405 0.2601114,-0.5689936 0,-0.219469 -0.097542,-0.3657816 Q 6.6628814,6.6388764 6.5003118,6.5494632 6.3377422,6.4519214 6.1101447,6.4194075 5.8906758,6.3787651 5.6386929,6.3787651 H 5.167241 V 5.4033475 h 0.5364797 q 0.1788266,0 0.3413962,-0.032514 0.1706981,-0.032514 0.3007537,-0.1056703 0.1300557,-0.081285 0.203212,-0.2113404 0.081285,-0.1381842 0.081285,-0.3413962 0,-0.1544411 -0.065028,-0.2682398 Q 6.5003118,4.3303881 6.3946415,4.2572318 6.2970998,4.1840755 6.1589156,4.1515616 6.0288599,4.1109192 5.8906758,4.1109192 q -0.3495247,0 -0.6502784,0.1056702 Q 4.9477721,4.3222597 4.7039177,4.4767008 L 4.2731082,3.5906965 Q 4.4031639,3.5094117 4.573862,3.4199984 4.7526886,3.3305851 4.964029,3.2574288 5.1753695,3.1842725 5.4110954,3.1355016 q 0.2438544,-0.048771 0.5120943,-0.048771 0.4958373,0 0.8534904,0.1219272 0.3657816,0.1137987 0.6015075,0.3332677 0.2357259,0.2113405 0.3495246,0.5039657 0.1137987,0.2844968 0.1137987,0.625893 0,0.3332677 -0.186955,0.6502784 -0.186955,0.3088822 -0.5039657,0.4714518 0.4389379,0.1788266 0.6746638,0.5364797 0.2438544,0.3495246 0.2438544,0.8453619 0,0.3901671 -0.1300557,0.7234347 Q 7.808997,8.22393 7.5326287,8.4677844 7.2562604,8.7035104 6.825451,8.8416945 6.40277,8.9717502 5.8175194,8.9717502 Z" + style="fill:#e0e0e0;fill-opacity:0.99607843;stroke-width:0.20321201" + id="path836" /> + <path + d="m 10.502445,7.817506 q 0.08941,0.00813 0.203212,0.016257 0.121927,0 0.284497,0 0.951032,0 1.406227,-0.4795803 0.463323,-0.4795803 0.463323,-1.3249422 0,-0.8860044 -0.438938,-1.3411992 -0.438938,-0.4551949 -1.38997,-0.4551949 -0.130055,0 -0.26824,0.00813 -0.138184,0 -0.260111,0.016257 z M 14.16839,6.0292405 q 0,0.7315631 -0.227598,1.2761713 -0.227597,0.5446082 -0.650278,0.9022613 -0.414553,0.3576531 -1.01606,0.5364797 -0.601508,0.1788265 -1.349328,0.1788265 -0.341396,0 -0.796591,-0.032514 Q 9.6733402,8.86608 9.2344022,8.7766667 v -5.486724 q 0.438938,-0.081285 0.9103898,-0.1056702 0.47958,-0.032514 0.820976,-0.032514 0.723435,0 1.308686,0.1625696 0.593379,0.1625696 1.01606,0.5120943 0.422681,0.3495246 0.650278,0.8941328 0.227598,0.5446081 0.227598,1.3086853 z" + style="fill:#e0e0e0;fill-opacity:0.99607843;stroke-width:0.20321201" + id="path838" /> + </g> +</svg> diff --git a/editor/icons/icon_texture_array.svg b/editor/icons/icon_texture_array.svg new file mode 100644 index 0000000000..8297fc0f5d --- /dev/null +++ b/editor/icons/icon_texture_array.svg @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg6" + sodipodi:docname="icon_texture_array.svg" + inkscape:version="0.92.3 (2405546, 2018-03-11)"> + <metadata + id="metadata12"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs10" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1526" + inkscape:window-height="766" + id="namedview8" + showgrid="false" + inkscape:zoom="29.5" + inkscape:cx="8.3117238" + inkscape:cy="9.4909723" + inkscape:window-x="67" + inkscape:window-y="27" + inkscape:window-maximized="0" + inkscape:current-layer="svg6" /> + <g + id="g830" + transform="translate(0.35954582,-0.28763666)"> + <path + d="M 2,1 C 1.4477153,1 1,1.4477153 1,2 v 12 c 0,0.552285 0.4477153,1 1,1 h 12 c 0.552285,0 1,-0.447715 1,-1 V 2 C 15,1.4477153 14.552285,1 14,1 Z m 1,2 h 10 v 8 H 3 Z" + id="path2" + inkscape:connector-curvature="0" + style="fill:#e0e0e0;fill-opacity:0.99607999" + sodipodi:nodetypes="sssssssssccccc" /> + </g> + <g + aria-label="[]" + transform="matrix(1.6197742,0,0,0.750929,-3.7231532,1.8329569)" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:8.29580784px;line-height:1.25;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';letter-spacing:0px;word-spacing:0px;fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:0.2073952" + id="text834"> + <path + d="M 4.7302951,2.4553483 H 6.978459 V 3.4425495 H 5.9082998 V 9.4984892 H 6.978459 V 10.48569 H 4.7302951 Z" + style="fill:#e0e0e0;fill-opacity:0.99607843;stroke-width:0.2073952" + id="path862" + inkscape:connector-curvature="0" /> + <path + d="M 10.138643,10.48569 H 7.8904794 V 9.4984892 H 8.9606386 V 3.4425495 H 7.8904794 V 2.4553483 h 2.2481636 z" + style="fill:#e0e0e0;fill-opacity:0.99607843;stroke-width:0.2073952" + id="path864" + inkscape:connector-curvature="0" /> + </g> +</svg> diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index a13f741ee7..22ea5883e8 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -579,12 +579,12 @@ static void _generate_tangents_and_binormals(const PoolVector<int> &p_indices, c .normalized(); } - tangents[index_arrayr[idx * 3 + 0]] += tangent; - binormals[index_arrayr[idx * 3 + 0]] += binormal; - tangents[index_arrayr[idx * 3 + 1]] += tangent; - binormals[index_arrayr[idx * 3 + 1]] += binormal; - tangents[index_arrayr[idx * 3 + 2]] += tangent; - binormals[index_arrayr[idx * 3 + 2]] += binormal; + tangents.write[index_arrayr[idx * 3 + 0]] += tangent; + binormals.write[index_arrayr[idx * 3 + 0]] += binormal; + tangents.write[index_arrayr[idx * 3 + 1]] += tangent; + binormals.write[index_arrayr[idx * 3 + 1]] += binormal; + tangents.write[index_arrayr[idx * 3 + 2]] += tangent; + binormals.write[index_arrayr[idx * 3 + 2]] += binormal; //print_line(itos(idx)+" tangent: "+tangent); //print_line(itos(idx)+" binormal: "+binormal); @@ -800,7 +800,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me total += weights[i].weight; if (total) for (int i = 0; i < weights.size(); i++) - weights[i].weight /= total; + weights.write[i].weight /= total; if (weights.size() == 0 || total == 0) { //if nothing, add a weight to bone 0 //no weights assigned @@ -987,7 +987,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me vertex_array.resize(vertex_set.size()); for (Set<Collada::Vertex>::Element *F = vertex_set.front(); F; F = F->next()) { - vertex_array[F->get().idx] = F->get(); + vertex_array.write[F->get().idx] = F->get(); } if (has_weights) { @@ -996,9 +996,9 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me Transform local_xform = p_local_xform; for (int i = 0; i < vertex_array.size(); i++) { - vertex_array[i].vertex = local_xform.xform(vertex_array[i].vertex); - vertex_array[i].normal = local_xform.basis.xform(vertex_array[i].normal).normalized(); - vertex_array[i].tangent.normal = local_xform.basis.xform(vertex_array[i].tangent.normal).normalized(); + vertex_array.write[i].vertex = local_xform.xform(vertex_array[i].vertex); + vertex_array.write[i].normal = local_xform.basis.xform(vertex_array[i].normal).normalized(); + vertex_array.write[i].tangent.normal = local_xform.basis.xform(vertex_array[i].tangent.normal).normalized(); if (local_xform_mirror) { //i shouldn't do this? wtf? //vertex_array[i].normal*=-1.0; @@ -1061,13 +1061,13 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me //float sum=0.0; for (int l = 0; l < VS::ARRAY_WEIGHTS_SIZE; l++) { if (l < vertex_array[k].weights.size()) { - weights[l] = vertex_array[k].weights[l].weight; - bones[l] = vertex_array[k].weights[l].bone_idx; + weights.write[l] = vertex_array[k].weights[l].weight; + bones.write[l] = vertex_array[k].weights[l].bone_idx; //sum += vertex_array[k].weights[l].weight; } else { - weights[l] = 0; - bones[l] = 0; + weights.write[l] = 0; + bones.write[l] = 0; } } @@ -1286,7 +1286,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres String str = joint_src->sarray[i]; ERR_FAIL_COND_V(!bone_remap_map.has(str), ERR_INVALID_DATA); - bone_remap[i] = bone_remap_map[str]; + bone_remap.write[i] = bone_remap_map[str]; } } @@ -1506,7 +1506,7 @@ void ColladaImport::_fix_param_animation_tracks() { const Vector<int> &rt = collada.state.referenced_tracks[track_name]; for (int rti = 0; rti < rt.size(); rti++) { - Collada::AnimationTrack *at = &collada.state.animation_tracks[rt[rti]]; + Collada::AnimationTrack *at = &collada.state.animation_tracks.write[rt[rti]]; at->target = E->key(); at->param = "morph/" + collada.state.mesh_name_map[mesh_name]; @@ -1540,7 +1540,7 @@ void ColladaImport::create_animations(bool p_make_tracks_in_all_bones, bool p_im for (int i = 0; i < collada.state.animation_tracks.size(); i++) { - Collada::AnimationTrack &at = collada.state.animation_tracks[i]; + const Collada::AnimationTrack &at = collada.state.animation_tracks[i]; //print_line("CHANNEL: "+at.target+" PARAM: "+at.param); String node; @@ -1698,7 +1698,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones if (nm.anim_tracks.size() == 1) { //use snapshot keys from anim track instead, because this was most likely exported baked - Collada::AnimationTrack &at = collada.state.animation_tracks[nm.anim_tracks.front()->get()]; + const Collada::AnimationTrack &at = collada.state.animation_tracks[nm.anim_tracks.front()->get()]; snapshots.clear(); for (int i = 0; i < at.keys.size(); i++) snapshots.push_back(at.keys[i].time); @@ -1723,7 +1723,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones found_anim = true; - Collada::AnimationTrack &at = collada.state.animation_tracks[ET->get()]; + const Collada::AnimationTrack &at = collada.state.animation_tracks[ET->get()]; int xform_idx = -1; for (int j = 0; j < cn->xform_list.size(); j++) { @@ -1745,18 +1745,18 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones Vector<float> data = at.get_value_at_time(snapshots[i]); ERR_CONTINUE(data.empty()); - Collada::Node::XForm &xf = cn->xform_list[xform_idx]; + Collada::Node::XForm &xf = cn->xform_list.write[xform_idx]; if (at.component == "ANGLE") { ERR_CONTINUE(data.size() != 1); ERR_CONTINUE(xf.op != Collada::Node::XForm::OP_ROTATE); ERR_CONTINUE(xf.data.size() < 4); - xf.data[3] = data[0]; + xf.data.write[3] = data[0]; } else if (at.component == "X" || at.component == "Y" || at.component == "Z") { int cn = at.component[0] - 'X'; ERR_CONTINUE(cn >= xf.data.size()); ERR_CONTINUE(data.size() > 1); - xf.data[cn] = data[0]; + xf.data.write[cn] = data[0]; } else if (data.size() == xf.data.size()) { xf.data = data; @@ -1862,7 +1862,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones continue; } - Collada::AnimationTrack &at = collada.state.animation_tracks[ti]; + const Collada::AnimationTrack &at = collada.state.animation_tracks[ti]; // take snapshots if (!collada.state.scene_map.has(at.target)) @@ -1965,7 +1965,7 @@ Node *EditorSceneImporterCollada::import_scene(const String &p_path, uint32_t p_ if (p_flags & IMPORT_ANIMATION_DETECT_LOOP) { if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) { - state.animations[i]->set_loop(true); + state.animations.write[i]->set_loop(true); } } diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp index f2f4328cd2..906d902b4a 100644 --- a/editor/import/editor_scene_importer_gltf.cpp +++ b/editor/import/editor_scene_importer_gltf.cpp @@ -203,7 +203,6 @@ Error EditorSceneImporterGLTF::_parse_nodes(GLTFState &state) { GLTFNode *node = memnew(GLTFNode); Dictionary n = nodes[i]; - print_line("node " + itos(i) + ": " + String(Variant(n))); if (n.has("name")) { node->name = n["name"]; } @@ -651,7 +650,7 @@ Vector<double> EditorSceneImporterGLTF::_decode_accessor(GLTFState &state, int p } else { //fill with zeros, as bufferview is not defined. for (int i = 0; i < (a.count * component_count); i++) { - dst_buffer[i] = 0; + dst_buffer.write[i] = 0; } } @@ -794,7 +793,7 @@ Vector<Quat> EditorSceneImporterGLTF::_decode_accessor_as_quat(GLTFState &state, ret.resize(ret_size); { for (int i = 0; i < ret_size; i++) { - ret[i] = Quat(attribs_ptr[i * 4 + 0], attribs_ptr[i * 4 + 1], attribs_ptr[i * 4 + 2], attribs_ptr[i * 4 + 3]); + ret.write[i] = Quat(attribs_ptr[i * 4 + 0], attribs_ptr[i * 4 + 1], attribs_ptr[i * 4 + 2], attribs_ptr[i * 4 + 3]); } } return ret; @@ -808,8 +807,8 @@ Vector<Transform2D> EditorSceneImporterGLTF::_decode_accessor_as_xform2d(GLTFSta ERR_FAIL_COND_V(attribs.size() % 4 != 0, ret); ret.resize(attribs.size() / 4); for (int i = 0; i < ret.size(); i++) { - ret[i][0] = Vector2(attribs[i * 4 + 0], attribs[i * 4 + 1]); - ret[i][1] = Vector2(attribs[i * 4 + 2], attribs[i * 4 + 3]); + ret.write[i][0] = Vector2(attribs[i * 4 + 0], attribs[i * 4 + 1]); + ret.write[i][1] = Vector2(attribs[i * 4 + 2], attribs[i * 4 + 3]); } return ret; } @@ -823,9 +822,9 @@ Vector<Basis> EditorSceneImporterGLTF::_decode_accessor_as_basis(GLTFState &stat ERR_FAIL_COND_V(attribs.size() % 9 != 0, ret); ret.resize(attribs.size() / 9); for (int i = 0; i < ret.size(); i++) { - ret[i].set_axis(0, Vector3(attribs[i * 9 + 0], attribs[i * 9 + 1], attribs[i * 9 + 2])); - ret[i].set_axis(1, Vector3(attribs[i * 9 + 3], attribs[i * 9 + 4], attribs[i * 9 + 5])); - ret[i].set_axis(2, Vector3(attribs[i * 9 + 6], attribs[i * 9 + 7], attribs[i * 9 + 8])); + ret.write[i].set_axis(0, Vector3(attribs[i * 9 + 0], attribs[i * 9 + 1], attribs[i * 9 + 2])); + ret.write[i].set_axis(1, Vector3(attribs[i * 9 + 3], attribs[i * 9 + 4], attribs[i * 9 + 5])); + ret.write[i].set_axis(2, Vector3(attribs[i * 9 + 6], attribs[i * 9 + 7], attribs[i * 9 + 8])); } return ret; } @@ -838,10 +837,10 @@ Vector<Transform> EditorSceneImporterGLTF::_decode_accessor_as_xform(GLTFState & ERR_FAIL_COND_V(attribs.size() % 16 != 0, ret); ret.resize(attribs.size() / 16); for (int i = 0; i < ret.size(); i++) { - ret[i].basis.set_axis(0, Vector3(attribs[i * 16 + 0], attribs[i * 16 + 1], attribs[i * 16 + 2])); - ret[i].basis.set_axis(1, Vector3(attribs[i * 16 + 4], attribs[i * 16 + 5], attribs[i * 16 + 6])); - ret[i].basis.set_axis(2, Vector3(attribs[i * 16 + 8], attribs[i * 16 + 9], attribs[i * 16 + 10])); - ret[i].set_origin(Vector3(attribs[i * 16 + 12], attribs[i * 16 + 13], attribs[i * 16 + 14])); + ret.write[i].basis.set_axis(0, Vector3(attribs[i * 16 + 0], attribs[i * 16 + 1], attribs[i * 16 + 2])); + ret.write[i].basis.set_axis(1, Vector3(attribs[i * 16 + 4], attribs[i * 16 + 5], attribs[i * 16 + 6])); + ret.write[i].basis.set_axis(2, Vector3(attribs[i * 16 + 8], attribs[i * 16 + 9], attribs[i * 16 + 10])); + ret.write[i].set_origin(Vector3(attribs[i * 16 + 12], attribs[i * 16 + 13], attribs[i * 16 + 14])); } return ret; } @@ -1085,7 +1084,7 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) { ERR_FAIL_COND_V(mesh.mesh->get_blend_shape_count() != weights.size(), ERR_PARSE_ERROR); mesh.blend_weights.resize(weights.size()); for (int j = 0; j < weights.size(); j++) { - mesh.blend_weights[j] = weights[j]; + mesh.blend_weights.write[j] = weights[j]; } } @@ -1139,7 +1138,7 @@ Error EditorSceneImporterGLTF::_parse_images(GLTFState &state, const String &p_b ERR_FAIL_INDEX_V(bvi, state.buffer_views.size(), ERR_PARAMETER_RANGE_ERROR); - GLTFBufferView &bv = state.buffer_views[bvi]; + const GLTFBufferView &bv = state.buffer_views[bvi]; int bi = bv.buffer; ERR_FAIL_INDEX_V(bi, state.buffers.size(), ERR_PARAMETER_RANGE_ERROR); @@ -1596,7 +1595,7 @@ Error EditorSceneImporterGLTF::_parse_animations(GLTFState &state) { PoolVector<float> weights = _decode_accessor_as_floats(state, output, false); ERR_FAIL_INDEX_V(state.nodes[node]->mesh, state.meshes.size(), ERR_PARSE_ERROR); - GLTFMesh *mesh = &state.meshes[state.nodes[node]->mesh]; + const GLTFMesh *mesh = &state.meshes[state.nodes[node]->mesh]; ERR_FAIL_COND_V(mesh->blend_weights.size() == 0, ERR_PARSE_ERROR); int wc = mesh->blend_weights.size(); @@ -1611,11 +1610,11 @@ Error EditorSceneImporterGLTF::_parse_animations(GLTFState &state) { Vector<float> wdata; wdata.resize(wlen); for (int l = 0; l < wlen; l++) { - wdata[l] = r[l * wc + k]; + wdata.write[l] = r[l * wc + k]; } cf.values = wdata; - track->weight_tracks[k] = cf; + track->weight_tracks.write[k] = cf; } } else { WARN_PRINTS("Invalid path: " + path); @@ -1657,7 +1656,8 @@ void EditorSceneImporterGLTF::_generate_node(GLTFState &state, int p_node, Node if (n->mesh >= 0) { ERR_FAIL_INDEX(n->mesh, state.meshes.size()); MeshInstance *mi = memnew(MeshInstance); - GLTFMesh &mesh = state.meshes[n->mesh]; + print_line("**creating mesh for: " + n->name); + GLTFMesh &mesh = state.meshes.write[n->mesh]; mi->set_mesh(mesh.mesh); if (mesh.mesh->get_name() == "") { mesh.mesh->set_name(n->name); @@ -1686,20 +1686,22 @@ void EditorSceneImporterGLTF::_generate_node(GLTFState &state, int p_node, Node node->set_name(n->name); - p_parent->add_child(node); - node->set_owner(p_owner); - node->set_transform(n->xform); - n->godot_nodes.push_back(node); if (n->skin >= 0 && Object::cast_to<MeshInstance>(node)) { MeshInstance *mi = Object::cast_to<MeshInstance>(node); - //move skeleton around and place it on node, as the node _is_ a skeleton. + Skeleton *s = skeletons[n->skin]; - state.paths_to_skeleton[mi] = s; - //move it later, as skeleton may be moved around first + s->add_child(node); //According to spec, mesh should actually act as a child of the skeleton, as it inherits its transform + mi->set_skeleton_path(String("..")); + + } else { + p_parent->add_child(node); + node->set_transform(n->xform); } + node->set_owner(p_owner); + #if 0 for (int i = 0; i < n->skeleton_children.size(); i++) { @@ -1729,6 +1731,10 @@ void EditorSceneImporterGLTF::_generate_bone(GLTFState &state, int p_node, Vecto skeletons[i]->get_parent()->remove_child(skeletons[i]); p_parent_node->add_child(skeletons[i]); skeletons[i]->set_owner(owner); + //may have meshes as children, set owner in them too + for (int j = 0; j < skeletons[i]->get_child_count(); j++) { + skeletons[i]->get_child(j)->set_owner(owner); + } } } @@ -1744,13 +1750,11 @@ void EditorSceneImporterGLTF::_generate_bone(GLTFState &state, int p_node, Vecto const int parent = gltf_bone_node->parent; const int parent_index = s->find_bone(state.nodes[parent]->name); - s->add_bone(bone_name); const int bone_index = s->find_bone(bone_name); s->set_bone_parent(bone_index, parent_index); - s->set_bone_rest(bone_index, state.skins[skin].bones[n->joints[i].bone].inverse_bind.affine_inverse()); n->godot_nodes.push_back(s); - n->joints[i].godot_bone_index = bone_index; + n->joints.write[i].godot_bone_index = bone_index; } for (int i = 0; i < n->children.size(); i++) { @@ -1979,8 +1983,9 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye if (node->joints.size()) { Transform xform; - xform.basis = Basis(rot); - xform.basis.scale(scale); + //xform.basis = Basis(rot); + //xform.basis.scale(scale); + xform.basis.set_quat_scale(rot, scale); xform.origin = pos; Skeleton *skeleton = skeletons[node->joints[i].skin]; @@ -2061,6 +2066,10 @@ Spatial *EditorSceneImporterGLTF::_generate_scene(GLTFState &state, int p_bake_f if (name == "") { name = _gen_unique_name(state, "Skeleton"); } + for (int j = 0; j < state.skins[i].bones.size(); j++) { + s->add_bone(state.nodes[state.skins[i].bones[j].node]->name); + s->set_bone_rest(j, state.skins[i].bones[j].inverse_bind.affine_inverse()); + } s->set_name(name); root->add_child(s); s->set_owner(root); @@ -2074,12 +2083,6 @@ Spatial *EditorSceneImporterGLTF::_generate_scene(GLTFState &state, int p_bake_f } } - for (Map<Node *, Skeleton *>::Element *E = state.paths_to_skeleton.front(); E; E = E->next()) { - MeshInstance *mi = Object::cast_to<MeshInstance>(E->key()); - ERR_CONTINUE(!mi); - mi->set_skeleton_path(mi->get_path_to(E->get())); - } - for (int i = 0; i < skeletons.size(); i++) { skeletons[i]->localize_rests(); } diff --git a/editor/import/editor_scene_importer_gltf.h b/editor/import/editor_scene_importer_gltf.h index e8f3bdff62..8258ec41fd 100644 --- a/editor/import/editor_scene_importer_gltf.h +++ b/editor/import/editor_scene_importer_gltf.h @@ -275,7 +275,6 @@ class EditorSceneImporterGLTF : public EditorSceneImporter { Vector<GLTFAnimation> animations; Map<int, Vector<int> > skeleton_nodes; - Map<Node *, Skeleton *> paths_to_skeleton; //Map<int, Vector<int> > skin_users; //cache skin users diff --git a/editor/import/resource_importer_csv_translation.cpp b/editor/import/resource_importer_csv_translation.cpp index ec0500361d..cf850eef03 100644 --- a/editor/import/resource_importer_csv_translation.cpp +++ b/editor/import/resource_importer_csv_translation.cpp @@ -119,7 +119,7 @@ Error ResourceImporterCSVTranslation::import(const String &p_source_file, const if (key != "") { for (int i = 1; i < line.size(); i++) { - translations[i - 1]->add_message(key, line[i]); + translations.write[i - 1]->add_message(key, line[i]); } } diff --git a/editor/import/resource_importer_image.cpp b/editor/import/resource_importer_image.cpp new file mode 100644 index 0000000000..b6a67c0cd3 --- /dev/null +++ b/editor/import/resource_importer_image.cpp @@ -0,0 +1,79 @@ +#include "resource_importer_image.h" + +#include "io/image_loader.h" +#include "io/resource_saver.h" +#include "os/file_access.h" +#include "scene/resources/texture.h" + +String ResourceImporterImage::get_importer_name() const { + + return "image"; +} + +String ResourceImporterImage::get_visible_name() const { + + return "Image"; +} +void ResourceImporterImage::get_recognized_extensions(List<String> *p_extensions) const { + + ImageLoader::get_recognized_extensions(p_extensions); +} + +String ResourceImporterImage::get_save_extension() const { + return "image"; +} + +String ResourceImporterImage::get_resource_type() const { + + return "Image"; +} + +bool ResourceImporterImage::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { + + return true; +} + +int ResourceImporterImage::get_preset_count() const { + return 0; +} +String ResourceImporterImage::get_preset_name(int p_idx) const { + + return String(); +} + +void ResourceImporterImage::get_import_options(List<ImportOption> *r_options, int p_preset) const { +} + +Error ResourceImporterImage::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files) { + + FileAccess *f = FileAccess::open(p_source_file, FileAccess::READ); + if (!f) { + ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); + } + + size_t len = f->get_len(); + + Vector<uint8_t> data; + data.resize(len); + + f->get_buffer(data.ptrw(), len); + + memdelete(f); + + f = FileAccess::open(p_save_path + ".image", FileAccess::WRITE); + + //save the header GDIM + const uint8_t header[4] = { 'G', 'D', 'I', 'M' }; + f->store_buffer(header, 4); + //SAVE the extension (so it can be recognized by the loader later + f->store_pascal_string(p_source_file.get_extension().to_lower()); + //SAVE the actual image + f->store_buffer(data.ptr(), len); + + memdelete(f); + + return OK; +} + +ResourceImporterImage::ResourceImporterImage() { +} diff --git a/editor/import/resource_importer_image.h b/editor/import/resource_importer_image.h new file mode 100644 index 0000000000..5aadd00a35 --- /dev/null +++ b/editor/import/resource_importer_image.h @@ -0,0 +1,27 @@ +#ifndef RESOURCE_IMPORTER_IMAGE_H +#define RESOURCE_IMPORTER_IMAGE_H + +#include "image.h" +#include "io/resource_import.h" + +class ResourceImporterImage : public ResourceImporter { + GDCLASS(ResourceImporterImage, ResourceImporter) +public: + virtual String get_importer_name() const; + virtual String get_visible_name() const; + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual String get_save_extension() const; + virtual String get_resource_type() const; + + virtual int get_preset_count() const; + virtual String get_preset_name(int p_idx) const; + + virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const; + virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const; + + virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL); + + ResourceImporterImage(); +}; + +#endif // RESOURCE_IMPORTER_IMAGE_H diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp new file mode 100644 index 0000000000..2f958a6fdd --- /dev/null +++ b/editor/import/resource_importer_layered_texture.cpp @@ -0,0 +1,274 @@ +#include "resource_importer_layered_texture.h" + +#include "resource_importer_texture.h" + +#include "editor/editor_file_system.h" +#include "editor/editor_node.h" +#include "io/config_file.h" +#include "io/image_loader.h" +#include "scene/resources/texture.h" + +String ResourceImporterLayeredTexture::get_importer_name() const { + + return is_3d ? "texture_3d" : "texture_array"; +} + +String ResourceImporterLayeredTexture::get_visible_name() const { + + return is_3d ? "Texture3D" : "TextureArray"; +} +void ResourceImporterLayeredTexture::get_recognized_extensions(List<String> *p_extensions) const { + + ImageLoader::get_recognized_extensions(p_extensions); +} +String ResourceImporterLayeredTexture::get_save_extension() const { + return is_3d ? "tex3d" : "texarr"; +} + +String ResourceImporterLayeredTexture::get_resource_type() const { + + return is_3d ? "Texture3D" : "TextureArray"; +} + +bool ResourceImporterLayeredTexture::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { + + return true; +} + +int ResourceImporterLayeredTexture::get_preset_count() const { + return 3; +} +String ResourceImporterLayeredTexture::get_preset_name(int p_idx) const { + + static const char *preset_names[] = { + "3D", + "2D", + "ColorCorrect" + }; + + return preset_names[p_idx]; +} + +void ResourceImporterLayeredTexture::get_import_options(List<ImportOption> *r_options, int p_preset) const { + + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "Lossless,Video RAM,Uncompressed", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), p_preset == PRESET_3D ? 1 : 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "flags/repeat", PROPERTY_HINT_ENUM, "Disabled,Enabled,Mirrored"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "flags/filter"), true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "flags/mipmaps"), p_preset == PRESET_COLOR_CORRECT ? 0 : 1)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "flags/srgb", PROPERTY_HINT_ENUM, "Disable,Enable"), p_preset == PRESET_3D ? 1 : 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slices/horizontal", PROPERTY_HINT_RANGE, "1,256,1"), p_preset == PRESET_COLOR_CORRECT ? 16 : 8)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slices/vertical", PROPERTY_HINT_RANGE, "1,256,1"), p_preset == PRESET_COLOR_CORRECT ? 1 : 8)); +} + +void ResourceImporterLayeredTexture::_save_tex(const Vector<Ref<Image> > &p_images, const String &p_to_path, int p_compress_mode, Image::CompressMode p_vram_compression, bool p_mipmaps, int p_texture_flags) { + + FileAccess *f = FileAccess::open(p_to_path, FileAccess::WRITE); + f->store_8('G'); + f->store_8('D'); + if (is_3d) { + f->store_8('3'); + } else { + f->store_8('A'); + } + f->store_8('T'); //godot streamable texture + + f->store_32(p_images[0]->get_width()); + f->store_32(p_images[0]->get_height()); + f->store_32(p_images.size()); //depth + f->store_32(p_texture_flags); + if (p_compress_mode != COMPRESS_VIDEO_RAM) { + //vram needs to do a first compression to tell what the format is, for the rest its ok + f->store_32(p_images[0]->get_format()); + f->store_32(p_compress_mode); // 0 - lossless (PNG), 1 - vram, 2 - uncompressed + } + + if ((p_compress_mode == COMPRESS_LOSSLESS) && p_images[0]->get_format() > Image::FORMAT_RGBA8) { + p_compress_mode = COMPRESS_UNCOMPRESSED; //these can't go as lossy + } + + for (int i = 0; i < p_images.size(); i++) { + + switch (p_compress_mode) { + case COMPRESS_LOSSLESS: { + + Ref<Image> image = p_images[i]->duplicate(); + if (p_mipmaps) { + image->generate_mipmaps(); + } else { + image->clear_mipmaps(); + } + + int mmc = image->get_mipmap_count() + 1; + f->store_32(mmc); + + for (int i = 0; i < mmc; i++) { + + if (i > 0) { + image->shrink_x2(); + } + + PoolVector<uint8_t> data = Image::lossless_packer(image); + int data_len = data.size(); + f->store_32(data_len); + + PoolVector<uint8_t>::Read r = data.read(); + f->store_buffer(r.ptr(), data_len); + } + + } break; + case COMPRESS_VIDEO_RAM: { + + Ref<Image> image = p_images[i]->duplicate(); + image->generate_mipmaps(false); + + Image::CompressSource csource = Image::COMPRESS_SOURCE_LAYERED; + image->compress(p_vram_compression, csource, 0.7); + + if (i == 0) { + //hack so we can properly tell the format + f->store_32(image->get_format()); + f->store_32(p_compress_mode); // 0 - lossless (PNG), 1 - vram, 2 - uncompressed + } + + PoolVector<uint8_t> data = image->get_data(); + int dl = data.size(); + + PoolVector<uint8_t>::Read r = data.read(); + f->store_buffer(r.ptr(), dl); + } break; + case COMPRESS_UNCOMPRESSED: { + + Ref<Image> image = p_images[i]->duplicate(); + + if (p_mipmaps) { + image->generate_mipmaps(); + } else { + image->clear_mipmaps(); + } + + PoolVector<uint8_t> data = image->get_data(); + int dl = data.size(); + + PoolVector<uint8_t>::Read r = data.read(); + + f->store_buffer(r.ptr(), dl); + + } break; + } + } + + memdelete(f); +} + +Error ResourceImporterLayeredTexture::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files) { + + int compress_mode = p_options["compress/mode"]; + int repeat = p_options["flags/repeat"]; + bool filter = p_options["flags/filter"]; + bool mipmaps = p_options["flags/mipmaps"]; + int srgb = p_options["flags/srgb"]; + int hslices = p_options["slices/horizontal"]; + int vslices = p_options["slices/vertical"]; + + Ref<Image> image; + image.instance(); + Error err = ImageLoader::load_image(p_source_file, image, NULL, false, 1.0); + if (err != OK) + return err; + + int tex_flags = 0; + if (repeat > 0) + tex_flags |= Texture::FLAG_REPEAT; + if (repeat == 2) + tex_flags |= Texture::FLAG_MIRRORED_REPEAT; + if (filter) + tex_flags |= Texture::FLAG_FILTER; + if (mipmaps || compress_mode == COMPRESS_VIDEO_RAM) + tex_flags |= Texture::FLAG_MIPMAPS; + if (srgb == 1) + tex_flags |= Texture::FLAG_CONVERT_TO_LINEAR; + + Vector<Ref<Image> > slices; + + int slice_w = image->get_width() / hslices; + int slice_h = image->get_height() / vslices; + + //optimize + if (compress_mode == COMPRESS_VIDEO_RAM) { + //if using video ram, optimize + if (srgb) { + //remove alpha if not needed, so compression is more efficient + if (image->get_format() == Image::FORMAT_RGBA8 && !image->detect_alpha()) { + image->convert(Image::FORMAT_RGB8); + } + } else { + image->optimize_channels(); + } + } + + for (int i = 0; i < vslices; i++) { + for (int j = 0; j < hslices; j++) { + int x = slice_w * j; + int y = slice_h * i; + Ref<Image> slice = image->get_rect(Rect2(x, y, slice_w, slice_h)); + ERR_CONTINUE(slice.is_null() || slice->empty()); + if (slice->get_width() != slice_w || slice->get_height() != slice_h) { + slice->resize(slice_w, slice_h); + } + slices.push_back(slice); + } + } + + String extension = get_save_extension(); + + if (compress_mode == COMPRESS_VIDEO_RAM) { + //must import in all formats, in order of priority (so platform choses the best supported one. IE, etc2 over etc). + //Android, GLES 2.x + + bool ok_on_pc = false; + + if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_s3tc")) { + + _save_tex(slices, p_save_path + ".s3tc." + extension, compress_mode, Image::COMPRESS_S3TC, mipmaps, tex_flags); + r_platform_variants->push_back("s3tc"); + ok_on_pc = true; + } + + if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc2")) { + + _save_tex(slices, p_save_path + ".etc2." + extension, compress_mode, Image::COMPRESS_ETC2, mipmaps, tex_flags); + r_platform_variants->push_back("etc2"); + } + + if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc")) { + _save_tex(slices, p_save_path + ".etc." + extension, compress_mode, Image::COMPRESS_ETC, mipmaps, tex_flags); + r_platform_variants->push_back("etc"); + } + + if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_pvrtc")) { + + _save_tex(slices, p_save_path + ".pvrtc." + extension, compress_mode, Image::COMPRESS_PVRTC4, mipmaps, tex_flags); + r_platform_variants->push_back("pvrtc"); + } + + if (!ok_on_pc) { + EditorNode::add_io_error("Warning, no suitable PC VRAM compression enabled in Project Settings. This texture will not display correcly on PC."); + } + } else { + //import normally + _save_tex(slices, p_save_path + "." + extension, compress_mode, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, tex_flags); + } + + return OK; +} + +ResourceImporterLayeredTexture *ResourceImporterLayeredTexture::singleton = NULL; + +ResourceImporterLayeredTexture::ResourceImporterLayeredTexture() { + + singleton = this; + is_3d = true; +} + +ResourceImporterLayeredTexture::~ResourceImporterLayeredTexture() { +} diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h new file mode 100644 index 0000000000..ec73b2624d --- /dev/null +++ b/editor/import/resource_importer_layered_texture.h @@ -0,0 +1,57 @@ +#ifndef RESOURCE_IMPORTER_LAYERED_TEXTURE_H +#define RESOURCE_IMPORTER_LAYERED_TEXTURE_H + +#include "image.h" +#include "io/resource_import.h" + +class StreamTexture; + +class ResourceImporterLayeredTexture : public ResourceImporter { + GDCLASS(ResourceImporterLayeredTexture, ResourceImporter) + + bool is_3d; + +protected: + static void _texture_reimport_srgb(const Ref<StreamTexture> &p_tex); + static void _texture_reimport_3d(const Ref<StreamTexture> &p_tex); + static void _texture_reimport_normal(const Ref<StreamTexture> &p_tex); + + static ResourceImporterLayeredTexture *singleton; + +public: + static ResourceImporterLayeredTexture *get_singleton() { return singleton; } + virtual String get_importer_name() const; + virtual String get_visible_name() const; + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual String get_save_extension() const; + virtual String get_resource_type() const; + + enum Preset { + PRESET_3D, + PRESET_2D, + PRESET_COLOR_CORRECT, + }; + + enum CompressMode { + COMPRESS_LOSSLESS, + COMPRESS_VIDEO_RAM, + COMPRESS_UNCOMPRESSED + }; + + virtual int get_preset_count() const; + virtual String get_preset_name(int p_idx) const; + + virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const; + virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const; + + void _save_tex(const Vector<Ref<Image> > &p_images, const String &p_to_path, int p_compress_mode, Image::CompressMode p_vram_compression, bool p_mipmaps, int p_texture_flags); + + virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL); + + void update_imports(); + + void set_3d(bool p_3d) { is_3d = p_3d; } + ResourceImporterLayeredTexture(); + ~ResourceImporterLayeredTexture(); +}; +#endif // RESOURCE_IMPORTER_LAYERED_TEXTURE_H diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp index b8dd4a87b7..5babf6419c 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/resource_importer_obj.cpp @@ -224,6 +224,13 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh> > &r_meshes, bool p while (true) { String l = f->get_line().strip_edges(); + while (l.length() && l[l.length() - 1] == '\\') { + String add = f->get_line().strip_edges(); + l += add; + if (add == String()) { + break; + } + } if (l.begins_with("v ")) { //vertex @@ -264,10 +271,12 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh> > &r_meshes, bool p face[0] = v[1].split("/"); face[1] = v[2].split("/"); ERR_FAIL_COND_V(face[0].size() == 0, ERR_FILE_CORRUPT); + ERR_FAIL_COND_V(face[0].size() != face[1].size(), ERR_FILE_CORRUPT); for (int i = 2; i < v.size() - 1; i++) { face[2] = v[i + 1].split("/"); + ERR_FAIL_COND_V(face[0].size() != face[2].size(), ERR_FILE_CORRUPT); for (int j = 0; j < 3; j++) { diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index a5ad34f377..b5e3466b12 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -750,7 +750,7 @@ void ResourceImporterScene::_filter_tracks(Node *scene, const String &p_text) { Vector<String> strings = p_text.split("\n"); for (int i = 0; i < strings.size(); i++) { - strings[i] = strings[i].strip_edges(); + strings.write[i] = strings[i].strip_edges(); } List<StringName> anim_names; diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp index debdeb1c4a..41f5a892eb 100644 --- a/editor/import/resource_importer_wav.cpp +++ b/editor/import/resource_importer_wav.cpp @@ -215,19 +215,19 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s for (int i = 0; i < frames * format_channels; i++) { // 8 bit samples are UNSIGNED - data[i] = int8_t(file->get_8() - 128) / 128.f; + data.write[i] = int8_t(file->get_8() - 128) / 128.f; } } else if (format_bits == 32 && compression_code == 3) { for (int i = 0; i < frames * format_channels; i++) { //32 bit IEEE Float - data[i] = file->get_float(); + data.write[i] = file->get_float(); } } else if (format_bits == 16) { for (int i = 0; i < frames * format_channels; i++) { //16 bit SIGNED - data[i] = int16_t(file->get_16()) / 32768.f; + data.write[i] = int16_t(file->get_16()) / 32768.f; } } else { for (int i = 0; i < frames * format_channels; i++) { @@ -241,7 +241,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s } s <<= (32 - format_bits); - data[i] = (int32_t(s) >> 16) / 32768.f; + data.write[i] = (int32_t(s) >> 16) / 32768.f; } } @@ -335,7 +335,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s float res = (a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3); - new_data[i * format_channels + c] = res; + new_data.write[i * format_channels + c] = res; // update position and always keep fractional part within ]0...1] // in order to avoid 32bit floating point precision errors @@ -374,7 +374,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s float mult = 1.0 / max; for (int i = 0; i < data.size(); i++) { - data[i] *= mult; + data.write[i] *= mult; } } } @@ -408,7 +408,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s Vector<float> new_data; new_data.resize((last - first + 1) * format_channels); for (int i = first * format_channels; i < (last + 1) * format_channels; i++) { - new_data[i - first * format_channels] = data[i]; + new_data.write[i - first * format_channels] = data[i]; } data = new_data; @@ -433,7 +433,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s Vector<float> new_data; new_data.resize(data.size() / 2); for (int i = 0; i < frames; i++) { - new_data[i] = (data[i * 2 + 0] + data[i * 2 + 1]) / 2.0; + new_data.write[i] = (data[i * 2 + 0] + data[i * 2 + 1]) / 2.0; } data = new_data; @@ -465,8 +465,8 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s right.resize(tframes); for (int i = 0; i < tframes; i++) { - left[i] = data[i * 2 + 0]; - right[i] = data[i * 2 + 1]; + left.write[i] = data[i * 2 + 0]; + right.write[i] = data[i * 2 + 1]; } PoolVector<uint8_t> bleft; @@ -526,119 +526,5 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s return OK; } -void ResourceImporterWAV::_compress_ima_adpcm(const Vector<float> &p_data, PoolVector<uint8_t> &dst_data) { - - /*p_sample_data->data = (void*)malloc(len); - xm_s8 *dataptr=(xm_s8*)p_sample_data->data;*/ - - static const int16_t _ima_adpcm_step_table[89] = { - 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, - 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, - 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, - 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, - 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, - 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, - 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, - 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, - 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 - }; - - static const int8_t _ima_adpcm_index_table[16] = { - -1, -1, -1, -1, 2, 4, 6, 8, - -1, -1, -1, -1, 2, 4, 6, 8 - }; - - int datalen = p_data.size(); - int datamax = datalen; - if (datalen & 1) - datalen++; - - dst_data.resize(datalen / 2 + 4); - PoolVector<uint8_t>::Write w = dst_data.write(); - - int i, step_idx = 0, prev = 0; - uint8_t *out = w.ptr(); - //int16_t xm_prev=0; - const float *in = p_data.ptr(); - - /* initial value is zero */ - *(out++) = 0; - *(out++) = 0; - /* Table index initial value */ - *(out++) = 0; - /* unused */ - *(out++) = 0; - - for (i = 0; i < datalen; i++) { - int step, diff, vpdiff, mask; - uint8_t nibble; - int16_t xm_sample; - - if (i >= datamax) - xm_sample = 0; - else { - - xm_sample = CLAMP(in[i] * 32767.0, -32768, 32767); - /* - if (xm_sample==32767 || xm_sample==-32768) - printf("clippy!\n",xm_sample); - */ - } - - //xm_sample=xm_sample+xm_prev; - //xm_prev=xm_sample; - - diff = (int)xm_sample - prev; - - nibble = 0; - step = _ima_adpcm_step_table[step_idx]; - vpdiff = step >> 3; - if (diff < 0) { - nibble = 8; - diff = -diff; - } - mask = 4; - while (mask) { - - if (diff >= step) { - - nibble |= mask; - diff -= step; - vpdiff += step; - } - - step >>= 1; - mask >>= 1; - }; - - if (nibble & 8) - prev -= vpdiff; - else - prev += vpdiff; - - if (prev > 32767) { - //printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip up %i\n",i,xm_sample,prev,diff,vpdiff,prev); - prev = 32767; - } else if (prev < -32768) { - //printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip down %i\n",i,xm_sample,prev,diff,vpdiff,prev); - prev = -32768; - } - - step_idx += _ima_adpcm_index_table[nibble]; - if (step_idx < 0) - step_idx = 0; - else if (step_idx > 88) - step_idx = 88; - - if (i & 1) { - *out |= nibble << 4; - out++; - } else { - *out = nibble; - } - /*dataptr[i]=prev>>8;*/ - } -} - ResourceImporterWAV::ResourceImporterWAV() { } diff --git a/editor/import/resource_importer_wav.h b/editor/import/resource_importer_wav.h index cfce5a31ee..f78ab09e9b 100644 --- a/editor/import/resource_importer_wav.h +++ b/editor/import/resource_importer_wav.h @@ -48,7 +48,118 @@ public: virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const; virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const; - void _compress_ima_adpcm(const Vector<float> &p_data, PoolVector<uint8_t> &dst_data); + static void _compress_ima_adpcm(const Vector<float> &p_data, PoolVector<uint8_t> &dst_data) { + /*p_sample_data->data = (void*)malloc(len); + xm_s8 *dataptr=(xm_s8*)p_sample_data->data;*/ + + static const int16_t _ima_adpcm_step_table[89] = { + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, + 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, + 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, + 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, + 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, + 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, + 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 + }; + + static const int8_t _ima_adpcm_index_table[16] = { + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8 + }; + + int datalen = p_data.size(); + int datamax = datalen; + if (datalen & 1) + datalen++; + + dst_data.resize(datalen / 2 + 4); + PoolVector<uint8_t>::Write w = dst_data.write(); + + int i, step_idx = 0, prev = 0; + uint8_t *out = w.ptr(); + //int16_t xm_prev=0; + const float *in = p_data.ptr(); + + /* initial value is zero */ + *(out++) = 0; + *(out++) = 0; + /* Table index initial value */ + *(out++) = 0; + /* unused */ + *(out++) = 0; + + for (i = 0; i < datalen; i++) { + int step, diff, vpdiff, mask; + uint8_t nibble; + int16_t xm_sample; + + if (i >= datamax) + xm_sample = 0; + else { + + xm_sample = CLAMP(in[i] * 32767.0, -32768, 32767); + /* + if (xm_sample==32767 || xm_sample==-32768) + printf("clippy!\n",xm_sample); + */ + } + + //xm_sample=xm_sample+xm_prev; + //xm_prev=xm_sample; + + diff = (int)xm_sample - prev; + + nibble = 0; + step = _ima_adpcm_step_table[step_idx]; + vpdiff = step >> 3; + if (diff < 0) { + nibble = 8; + diff = -diff; + } + mask = 4; + while (mask) { + + if (diff >= step) { + + nibble |= mask; + diff -= step; + vpdiff += step; + } + + step >>= 1; + mask >>= 1; + }; + + if (nibble & 8) + prev -= vpdiff; + else + prev += vpdiff; + + if (prev > 32767) { + //printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip up %i\n",i,xm_sample,prev,diff,vpdiff,prev); + prev = 32767; + } else if (prev < -32768) { + //printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip down %i\n",i,xm_sample,prev,diff,vpdiff,prev); + prev = -32768; + } + + step_idx += _ima_adpcm_index_table[nibble]; + if (step_idx < 0) + step_idx = 0; + else if (step_idx > 88) + step_idx = 88; + + if (i & 1) { + *out |= nibble << 4; + out++; + } else { + *out = nibble; + } + /*dataptr[i]=prev>>8;*/ + } + } virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL); diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index 43baabe2f5..615e9df043 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -142,7 +142,7 @@ void InspectorDock::_resource_file_selected(String p_file) { RES res = ResourceLoader::load(p_file); if (res.is_null()) { - warning_dialog->get_ok()->set_text("Ugh"); + warning_dialog->get_ok()->set_text(TTR("OK")); warning_dialog->set_text(TTR("Failed to load resource.")); return; }; @@ -529,7 +529,8 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { search = memnew(LineEdit); search->set_h_size_flags(Control::SIZE_EXPAND_FILL); search->set_placeholder(TTR("Filter properties")); - search->add_icon_override("right_icon", get_icon("Search", "EditorIcons")); + search->set_right_icon(get_icon("Search", "EditorIcons")); + search->set_clear_button_enabled(true); add_child(search); warning = memnew(Button); diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 5052b69e24..2d341cdd93 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -345,7 +345,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) 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); + vertices.write[edited_point.vertex] = edited_point.pos - _get_offset(edited_point.polygon); undo_redo->create_action(TTR("Edit Poly")); _action_set_polygon(edited_point.polygon, pre_move_edit, vertices); @@ -445,7 +445,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) 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); + vertices.write[edited_point.vertex] = cpoint - _get_offset(edited_point.polygon); _set_polygon(edited_point.polygon, vertices); } diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp index 8d17062248..27df60f87a 100644 --- a/editor/plugins/animation_blend_space_2d_editor.cpp +++ b/editor/plugins/animation_blend_space_2d_editor.cpp @@ -414,7 +414,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() { point = (point - blend_space->get_min_space()) / (blend_space->get_max_space() - blend_space->get_min_space()); point *= s; point.y = s.height - point.y; - points[j] = point; + points.write[j] = point; } for (int j = 0; j < 3; j++) { diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 23eeef9f20..9ab5436de8 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -1333,7 +1333,7 @@ void AnimationPlayerEditor::_allocate_onion_layers() { bool is_present = onion.differences_only && i == captures - 1; // Each capture is a viewport with a canvas item attached that renders a full-size rect with the contents of the main viewport - onion.captures[i] = VS::get_singleton()->viewport_create(); + onion.captures.write[i] = VS::get_singleton()->viewport_create(); VS::get_singleton()->viewport_set_usage(onion.captures[i], VS::VIEWPORT_USAGE_2D); VS::get_singleton()->viewport_set_size(onion.captures[i], capture_size.width, capture_size.height); VS::get_singleton()->viewport_set_update_mode(onion.captures[i], VS::VIEWPORT_UPDATE_ALWAYS); @@ -1473,7 +1473,7 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() { float pos = cpos + step_off * anim->get_step(); bool valid = anim->has_loop() || (pos >= 0 && pos <= anim->get_length()); - onion.captures_valid[cidx] = valid; + onion.captures_valid.write[cidx] = valid; if (valid) { player->seek(pos, true); get_tree()->flush_transform_notifications(); // Needed for transforms of Spatials diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index 04bd5f0cec..ee450333c8 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -679,7 +679,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() { Ref<StyleBox> sb = name == selected_node ? style_selected : style; int strsize = font->get_string_size(name).width; - NodeRect &nr = node_rects[i]; + NodeRect &nr = node_rects.write[i]; Vector2 offset = nr.node.position; int h = nr.node.size.height; @@ -771,7 +771,7 @@ void AnimationNodeStateMachineEditor::_state_machine_pos_draw() { if (idx == -1) return; - NodeRect &nr = node_rects[idx]; + const NodeRect &nr = node_rects[idx]; Vector2 from; from.x = nr.play.position.x; diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 505dd4ab76..4ed2b051aa 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -197,7 +197,7 @@ void EditorAssetLibraryItemDescription::set_image(int p_type, int p_index, const for (int i = 0; i < preview_images.size(); i++) { if (preview_images[i].id == p_index) { - preview_images[i].image = p_image; + preview_images.write[i].image = p_image; if (preview_images[i].button->is_pressed()) { _preview_click(p_index); } @@ -384,14 +384,11 @@ void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int return; } - progress->set_max(download->get_body_size()); - progress->set_value(download->get_downloaded_bytes()); - install->set_disabled(false); + status->set_text(TTR("Success!")); + // Make the progress bar invisible but don't reflow other Controls around it + progress->set_modulate(Color(0, 0, 0, 0)); - progress->set_value(download->get_downloaded_bytes()); - - status->set_text(TTR("Success!") + " (" + String::humanize_size(download->get_downloaded_bytes()) + ")"); set_process(false); } @@ -413,25 +410,37 @@ void EditorAssetLibraryItemDownload::_notification(int p_what) { if (p_what == NOTIFICATION_PROCESS) { - progress->set_max(download->get_body_size()); - progress->set_value(download->get_downloaded_bytes()); + // Make the progress bar visible again when retrying the download + progress->set_modulate(Color(1, 1, 1, 1)); + + if (download->get_downloaded_bytes() > 0) { + progress->set_max(download->get_body_size()); + progress->set_value(download->get_downloaded_bytes()); + } int cstatus = download->get_http_client_status(); - if (cstatus == HTTPClient::STATUS_BODY) - status->set_text(TTR("Fetching:") + " " + String::humanize_size(download->get_downloaded_bytes())); + if (cstatus == HTTPClient::STATUS_BODY) { + status->set_text(vformat(TTR("Downloading (%s / %s)..."), String::humanize_size(download->get_downloaded_bytes()), String::humanize_size(download->get_body_size()))); + } if (cstatus != prev_status) { switch (cstatus) { case HTTPClient::STATUS_RESOLVING: { status->set_text(TTR("Resolving...")); + progress->set_max(1); + progress->set_value(0); } break; case HTTPClient::STATUS_CONNECTING: { status->set_text(TTR("Connecting...")); + progress->set_max(1); + progress->set_value(0); } break; case HTTPClient::STATUS_REQUESTING: { status->set_text(TTR("Requesting...")); + progress->set_max(1); + progress->set_value(0); } break; default: {} } @@ -527,7 +536,7 @@ EditorAssetLibraryItemDownload::EditorAssetLibraryItemDownload() { hb2->add_child(retry); hb2->add_child(install); - set_custom_minimum_size(Size2(250, 0)); + set_custom_minimum_size(Size2(310, 0)); download = memnew(HTTPRequest); add_child(download); @@ -554,6 +563,8 @@ void EditorAssetLibrary::_notification(int p_what) { error_tr->set_texture(get_icon("Error", "EditorIcons")); reverse->set_icon(get_icon("Sort", "EditorIcons")); + filter->set_right_icon(get_icon("Search", "EditorIcons")); + filter->set_clear_button_enabled(true); error_label->raise(); } break; @@ -604,6 +615,8 @@ void EditorAssetLibrary::_notification(int p_what) { library_scroll_bg->add_style_override("panel", get_stylebox("bg", "Tree")); error_tr->set_texture(get_icon("Error", "EditorIcons")); reverse->set_icon(get_icon("Sort", "EditorIcons")); + filter->set_right_icon(get_icon("Search", "EditorIcons")); + filter->set_clear_button_enabled(true); } break; } } diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp index ddb03d0250..454a5d72f2 100644 --- a/editor/plugins/audio_stream_editor_plugin.cpp +++ b/editor/plugins/audio_stream_editor_plugin.cpp @@ -81,8 +81,8 @@ void AudioStreamEditor::_draw_preview() { float min = preview->get_min(ofs, ofs_n) * 0.5 + 0.5; int idx = i; - lines[idx * 2 + 0] = Vector2(i + 1, rect.position.y + min * rect.size.y); - lines[idx * 2 + 1] = Vector2(i + 1, rect.position.y + max * rect.size.y); + lines.write[idx * 2 + 0] = Vector2(i + 1, rect.position.y + min * rect.size.y); + lines.write[idx * 2 + 1] = Vector2(i + 1, rect.position.y + max * rect.size.y); } Vector<Color> color; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 1d20c63969..145a2ef9bb 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -375,33 +375,24 @@ Rect2 CanvasItemEditor::_get_encompassing_rect_from_list(List<CanvasItem *> p_li // Handles the first element CanvasItem *canvas_item = p_list.front()->get(); - Rect2 rect; - if (canvas_item->_edit_use_rect()) { - rect = Rect2(canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_rect().position + canvas_item->_edit_get_rect().size / 2), Size2()); - } else { - rect = Rect2(canvas_item->get_global_transform_with_canvas().xform(Point2()), Size2()); - } + Rect2 rect = Rect2(canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_rect().position + canvas_item->_edit_get_rect().size / 2), Size2()); // Expand with the other ones for (List<CanvasItem *>::Element *E = p_list.front(); E; E = E->next()) { CanvasItem *canvas_item = E->get(); Transform2D xform = canvas_item->get_global_transform_with_canvas(); - if (canvas_item->_edit_use_rect()) { - Rect2 current_rect = canvas_item->_edit_get_rect(); - rect.expand_to(xform.xform(current_rect.position)); - rect.expand_to(xform.xform(current_rect.position + Vector2(current_rect.size.x, 0))); - rect.expand_to(xform.xform(current_rect.position + current_rect.size)); - rect.expand_to(xform.xform(current_rect.position + Vector2(0, current_rect.size.y))); - } else { - rect.expand_to(xform.xform(Point2())); - } + Rect2 current_rect = canvas_item->_edit_get_rect(); + rect.expand_to(xform.xform(current_rect.position)); + rect.expand_to(xform.xform(current_rect.position + Vector2(current_rect.size.x, 0))); + rect.expand_to(xform.xform(current_rect.position + current_rect.size)); + rect.expand_to(xform.xform(current_rect.position + Vector2(0, current_rect.size.y))); } return rect; } -void CanvasItemEditor::_expand_encompassing_rect_using_children(Rect2 &r_rect, const Node *p_node, bool &r_first, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { +void CanvasItemEditor::_expand_encompassing_rect_using_children(Rect2 &r_rect, const Node *p_node, bool &r_first, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform, bool include_locked_nodes) { if (!p_node) return; if (Object::cast_to<Viewport>(p_node)) @@ -409,12 +400,6 @@ void CanvasItemEditor::_expand_encompassing_rect_using_children(Rect2 &r_rect, c const CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); - /*bool inherited = p_node != get_tree()->get_edited_scene_root() && p_node->get_filename() != ""; - bool editable = !inherited || EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node); - bool lock_children = p_node->has_meta("_edit_group_") && p_node->get_meta("_edit_group_"); - - if (!lock_children && editable) {}*/ - for (int i = p_node->get_child_count() - 1; i >= 0; i--) { if (canvas_item && !canvas_item->is_set_as_toplevel()) { _expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); @@ -424,28 +409,17 @@ void CanvasItemEditor::_expand_encompassing_rect_using_children(Rect2 &r_rect, c } } - if (canvas_item && canvas_item->is_visible_in_tree() && !canvas_item->has_meta("_edit_lock_")) { + if (canvas_item && canvas_item->is_visible_in_tree() && (include_locked_nodes || !canvas_item->has_meta("_edit_lock_"))) { Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform(); - if (canvas_item->_edit_use_rect()) { - Rect2 rect = canvas_item->_edit_get_rect(); - if (r_first) { - r_rect = Rect2(xform.xform(rect.position + rect.size / 2), Size2()); - r_first = false; - } - if (r_rect.size != Size2()) { - r_rect.expand_to(xform.xform(rect.position)); - r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0))); - r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y))); - r_rect.expand_to(xform.xform(rect.position + rect.size)); - } - } else { - if (r_first) { - r_rect = Rect2(xform.xform(Point2()), Size2()); - r_first = false; - } else { - r_rect.expand_to(xform.xform(Point2())); - } + Rect2 rect = canvas_item->_edit_get_rect(); + if (r_first) { + r_rect = Rect2(xform.xform(rect.position + rect.size / 2), Size2()); + r_first = false; } + r_rect.expand_to(xform.xform(rect.position)); + r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0))); + r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y))); + r_rect.expand_to(xform.xform(rect.position + rect.size)); } } @@ -533,7 +507,7 @@ void CanvasItemEditor::_get_canvas_items_at_pos(const Point2 &p_pos, Vector<_Sel r_items.remove(i); i--; } else { - r_items[i].item = canvas_item; + r_items.write[i].item = canvas_item; } } } @@ -4879,7 +4853,7 @@ void CanvasItemEditorViewport::_perform_drop_data() { files_str += error_files[i].get_file().get_basename() + ","; } files_str = files_str.substr(0, files_str.length() - 1); - accept->get_ok()->set_text(TTR("Ugh")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.c_str())); accept->popup_centered_minsize(); } diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index adc4010f39..2c943385ad 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -390,7 +390,7 @@ class CanvasItemEditor : public VBoxContainer { List<CanvasItem *> _get_edited_canvas_items(bool retreive_locked = false, bool remove_canvas_item_if_parent_in_selection = true); Rect2 _get_encompassing_rect_from_list(List<CanvasItem *> p_list); - void _expand_encompassing_rect_using_children(Rect2 &p_rect, const Node *p_node, bool &r_first, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); + void _expand_encompassing_rect_using_children(Rect2 &p_rect, const Node *p_node, bool &r_first, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D(), bool include_locked_nodes = true); Rect2 _get_encompassing_rect(const Node *p_node); Object *_get_editor_data(Object *p_what); diff --git a/editor/plugins/collision_polygon_editor_plugin.cpp b/editor/plugins/collision_polygon_editor_plugin.cpp index e837359d0c..5109379add 100644 --- a/editor/plugins/collision_polygon_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_editor_plugin.cpp @@ -276,7 +276,7 @@ bool Polygon3DEditor::forward_spatial_gui_input(Camera *p_camera, const Ref<Inpu //apply ERR_FAIL_INDEX_V(edited_point, poly.size(), false); - poly[edited_point] = edited_point_pos; + poly.write[edited_point] = edited_point_pos; undo_redo->create_action(TTR("Edit Poly")); undo_redo->add_do_method(node, "set_polygon", poly); undo_redo->add_undo_method(node, "set_polygon", pre_move_edit); diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index b003664dca..9e052bb027 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -446,8 +446,8 @@ void CollisionShape2DEditor::forward_draw_over_viewport(Control *p_overlay) { float radius = shape->get_radius(); float height = shape->get_height() / 2; - handles[0] = Point2(radius, -height); - handles[1] = Point2(0, -(height + radius)); + handles.write[0] = Point2(radius, -height); + handles.write[1] = Point2(0, -(height + radius)); p_overlay->draw_texture(h, gt.xform(handles[0]) - size); p_overlay->draw_texture(h, gt.xform(handles[1]) - size); @@ -458,7 +458,7 @@ void CollisionShape2DEditor::forward_draw_over_viewport(Control *p_overlay) { Ref<CircleShape2D> shape = node->get_shape(); handles.resize(1); - handles[0] = Point2(shape->get_radius(), 0); + handles.write[0] = Point2(shape->get_radius(), 0); p_overlay->draw_texture(h, gt.xform(handles[0]) - size); @@ -476,8 +476,8 @@ void CollisionShape2DEditor::forward_draw_over_viewport(Control *p_overlay) { Ref<LineShape2D> shape = node->get_shape(); handles.resize(2); - handles[0] = shape->get_normal() * shape->get_d(); - handles[1] = shape->get_normal() * (shape->get_d() + 30.0); + handles.write[0] = shape->get_normal() * shape->get_d(); + handles.write[1] = shape->get_normal() * (shape->get_d() + 30.0); p_overlay->draw_texture(h, gt.xform(handles[0]) - size); p_overlay->draw_texture(h, gt.xform(handles[1]) - size); @@ -488,7 +488,7 @@ void CollisionShape2DEditor::forward_draw_over_viewport(Control *p_overlay) { Ref<RayShape2D> shape = node->get_shape(); handles.resize(1); - handles[0] = Point2(0, shape->get_length()); + handles.write[0] = Point2(0, shape->get_length()); p_overlay->draw_texture(h, gt.xform(handles[0]) - size); @@ -499,8 +499,8 @@ void CollisionShape2DEditor::forward_draw_over_viewport(Control *p_overlay) { handles.resize(2); Vector2 ext = shape->get_extents(); - handles[0] = Point2(ext.x, 0); - handles[1] = Point2(0, -ext.y); + handles.write[0] = Point2(ext.x, 0); + handles.write[1] = Point2(0, -ext.y); p_overlay->draw_texture(h, gt.xform(handles[0]) - size); p_overlay->draw_texture(h, gt.xform(handles[1]) - size); @@ -511,8 +511,8 @@ void CollisionShape2DEditor::forward_draw_over_viewport(Control *p_overlay) { Ref<SegmentShape2D> shape = node->get_shape(); handles.resize(2); - handles[0] = shape->get_a(); - handles[1] = shape->get_b(); + handles.write[0] = shape->get_a(); + handles.write[1] = shape->get_b(); p_overlay->draw_texture(h, gt.xform(handles[0]) - size); p_overlay->draw_texture(h, gt.xform(handles[1]) - size); diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 0d25b3685a..9acbceec92 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -78,7 +78,7 @@ bool EditorTexturePreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "Texture"); } -Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from) { +Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from) const { Ref<Image> img; Ref<AtlasTexture> atex = p_from; @@ -138,12 +138,66 @@ EditorTexturePreviewPlugin::EditorTexturePreviewPlugin() { //////////////////////////////////////////////////////////////////////////// +bool EditorImagePreviewPlugin::handles(const String &p_type) const { + + return p_type == "Image"; +} + +Ref<Texture> EditorImagePreviewPlugin::generate(const RES &p_from) const { + + Ref<Image> img = p_from; + + if (img.is_null() || img->empty()) + return Ref<Image>(); + + img = img->duplicate(); + img->clear_mipmaps(); + + int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); + thumbnail_size *= EDSCALE; + if (img->is_compressed()) { + if (img->decompress() != OK) + return Ref<Image>(); + } else if (img->get_format() != Image::FORMAT_RGB8 && img->get_format() != Image::FORMAT_RGBA8) { + img->convert(Image::FORMAT_RGBA8); + } + + int width, height; + if (img->get_width() > thumbnail_size && img->get_width() >= img->get_height()) { + + width = thumbnail_size; + height = img->get_height() * thumbnail_size / img->get_width(); + } else if (img->get_height() > thumbnail_size && img->get_height() >= img->get_width()) { + + height = thumbnail_size; + width = img->get_width() * thumbnail_size / img->get_height(); + } else { + + width = img->get_width(); + height = img->get_height(); + } + + img->resize(width, height); + post_process_preview(img); + + Ref<ImageTexture> ptex; + ptex.instance(); + + ptex->create_from_image(img, 0); + return ptex; +} + +EditorImagePreviewPlugin::EditorImagePreviewPlugin() { +} + +//////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////// bool EditorBitmapPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "BitMap"); } -Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) { +Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) const { Ref<BitMap> bm = p_from; @@ -215,12 +269,12 @@ bool EditorPackedScenePreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "PackedScene"); } -Ref<Texture> EditorPackedScenePreviewPlugin::generate(const RES &p_from) { +Ref<Texture> EditorPackedScenePreviewPlugin::generate(const RES &p_from) const { return generate_from_path(p_from->get_path()); } -Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String &p_path) { +Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String &p_path) const { String temp_path = EditorSettings::get_singleton()->get_cache_dir(); String cache_base = ProjectSettings::get_singleton()->globalize_path(p_path).md5_text(); @@ -269,7 +323,7 @@ bool EditorMaterialPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "Material"); //any material } -Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES &p_from) { +Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES &p_from) const { Ref<Material> material = p_from; ERR_FAIL_COND_V(material.is_null(), Ref<Texture>()); @@ -281,7 +335,7 @@ Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES &p_from) { VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_ONCE); //once used for capture preview_done = false; - VS::get_singleton()->request_frame_drawn_callback(this, "_preview_done", Variant()); + VS::get_singleton()->request_frame_drawn_callback(const_cast<EditorMaterialPreviewPlugin *>(this), "_preview_done", Variant()); while (!preview_done) { OS::get_singleton()->delay_usec(10); @@ -436,7 +490,7 @@ bool EditorScriptPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "Script"); } -Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) { +Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) const { Ref<Script> scr = p_from; if (scr.is_null()) @@ -559,7 +613,7 @@ bool EditorAudioStreamPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "AudioStream"); } -Ref<Texture> EditorAudioStreamPreviewPlugin::generate(const RES &p_from) { +Ref<Texture> EditorAudioStreamPreviewPlugin::generate(const RES &p_from) const { Ref<AudioStream> stream = p_from; ERR_FAIL_COND_V(stream.is_null(), Ref<Texture>()); @@ -657,7 +711,7 @@ bool EditorMeshPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "Mesh"); //any Mesh } -Ref<Texture> EditorMeshPreviewPlugin::generate(const RES &p_from) { +Ref<Texture> EditorMeshPreviewPlugin::generate(const RES &p_from) const { Ref<Mesh> mesh = p_from; ERR_FAIL_COND_V(mesh.is_null(), Ref<Texture>()); @@ -684,7 +738,7 @@ Ref<Texture> EditorMeshPreviewPlugin::generate(const RES &p_from) { VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_ONCE); //once used for capture preview_done = false; - VS::get_singleton()->request_frame_drawn_callback(this, "_preview_done", Variant()); + VS::get_singleton()->request_frame_drawn_callback(const_cast<EditorMeshPreviewPlugin *>(this), "_preview_done", Variant()); while (!preview_done) { OS::get_singleton()->delay_usec(10); @@ -771,16 +825,7 @@ bool EditorFontPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "DynamicFontData"); } -Ref<Texture> EditorFontPreviewPlugin::generate_from_path(const String &p_path) { - if (canvas.is_valid()) { - VS::get_singleton()->viewport_remove_canvas(viewport, canvas); - } - - canvas = VS::get_singleton()->canvas_create(); - canvas_item = VS::get_singleton()->canvas_item_create(); - - VS::get_singleton()->viewport_attach_canvas(viewport, canvas); - VS::get_singleton()->canvas_item_set_parent(canvas_item, canvas); +Ref<Texture> EditorFontPreviewPlugin::generate_from_path(const String &p_path) const { Ref<DynamicFontData> SampledFont; SampledFont.instance(); @@ -809,7 +854,7 @@ Ref<Texture> EditorFontPreviewPlugin::generate_from_path(const String &p_path) { VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_ONCE); //once used for capture preview_done = false; - VS::get_singleton()->request_frame_drawn_callback(this, "_preview_done", Variant()); + VS::get_singleton()->request_frame_drawn_callback(const_cast<EditorFontPreviewPlugin *>(this), "_preview_done", Variant()); while (!preview_done) { OS::get_singleton()->delay_usec(10); @@ -829,7 +874,7 @@ Ref<Texture> EditorFontPreviewPlugin::generate_from_path(const String &p_path) { return ptex; } -Ref<Texture> EditorFontPreviewPlugin::generate(const RES &p_from) { +Ref<Texture> EditorFontPreviewPlugin::generate(const RES &p_from) const { return generate_from_path(p_from->get_path()); } @@ -842,6 +887,12 @@ EditorFontPreviewPlugin::EditorFontPreviewPlugin() { VS::get_singleton()->viewport_set_size(viewport, 128, 128); VS::get_singleton()->viewport_set_active(viewport, true); viewport_texture = VS::get_singleton()->viewport_get_texture(viewport); + + canvas = VS::get_singleton()->canvas_create(); + canvas_item = VS::get_singleton()->canvas_item_create(); + + VS::get_singleton()->viewport_attach_canvas(viewport, canvas); + VS::get_singleton()->canvas_item_set_parent(canvas_item, canvas); } EditorFontPreviewPlugin::~EditorFontPreviewPlugin() { diff --git a/editor/plugins/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h index 140d9f849f..8bd7943383 100644 --- a/editor/plugins/editor_preview_plugins.h +++ b/editor/plugins/editor_preview_plugins.h @@ -39,16 +39,25 @@ class EditorTexturePreviewPlugin : public EditorResourcePreviewGenerator { GDCLASS(EditorTexturePreviewPlugin, EditorResourcePreviewGenerator) public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from); + virtual Ref<Texture> generate(const RES &p_from) const; EditorTexturePreviewPlugin(); }; +class EditorImagePreviewPlugin : public EditorResourcePreviewGenerator { + GDCLASS(EditorImagePreviewPlugin, EditorResourcePreviewGenerator) +public: + virtual bool handles(const String &p_type) const; + virtual Ref<Texture> generate(const RES &p_from) const; + + EditorImagePreviewPlugin(); +}; + class EditorBitmapPreviewPlugin : public EditorResourcePreviewGenerator { GDCLASS(EditorBitmapPreviewPlugin, EditorResourcePreviewGenerator) public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from); + virtual Ref<Texture> generate(const RES &p_from) const; EditorBitmapPreviewPlugin(); }; @@ -57,8 +66,8 @@ class EditorPackedScenePreviewPlugin : public EditorResourcePreviewGenerator { public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from); - virtual Ref<Texture> generate_from_path(const String &p_path); + virtual Ref<Texture> generate(const RES &p_from) const; + virtual Ref<Texture> generate_from_path(const String &p_path) const; EditorPackedScenePreviewPlugin(); }; @@ -77,7 +86,7 @@ class EditorMaterialPreviewPlugin : public EditorResourcePreviewGenerator { RID light2; RID light_instance2; RID camera; - volatile bool preview_done; + mutable volatile bool preview_done; void _preview_done(const Variant &p_udata); @@ -86,7 +95,7 @@ protected: public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from); + virtual Ref<Texture> generate(const RES &p_from) const; EditorMaterialPreviewPlugin(); ~EditorMaterialPreviewPlugin(); @@ -95,7 +104,7 @@ public: class EditorScriptPreviewPlugin : public EditorResourcePreviewGenerator { public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from); + virtual Ref<Texture> generate(const RES &p_from) const; EditorScriptPreviewPlugin(); }; @@ -103,7 +112,7 @@ public: class EditorAudioStreamPreviewPlugin : public EditorResourcePreviewGenerator { public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from); + virtual Ref<Texture> generate(const RES &p_from) const; EditorAudioStreamPreviewPlugin(); }; @@ -121,7 +130,7 @@ class EditorMeshPreviewPlugin : public EditorResourcePreviewGenerator { RID light2; RID light_instance2; RID camera; - volatile bool preview_done; + mutable volatile bool preview_done; void _preview_done(const Variant &p_udata); @@ -130,7 +139,7 @@ protected: public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from); + virtual Ref<Texture> generate(const RES &p_from) const; EditorMeshPreviewPlugin(); ~EditorMeshPreviewPlugin(); @@ -144,7 +153,7 @@ class EditorFontPreviewPlugin : public EditorResourcePreviewGenerator { RID viewport_texture; RID canvas; RID canvas_item; - volatile bool preview_done; + mutable volatile bool preview_done; void _preview_done(const Variant &p_udata); @@ -153,8 +162,8 @@ protected: public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from); - virtual Ref<Texture> generate_from_path(const String &p_path); + virtual Ref<Texture> generate(const RES &p_from) const; + virtual Ref<Texture> generate_from_path(const String &p_path) const; EditorFontPreviewPlugin(); ~EditorFontPreviewPlugin(); diff --git a/editor/plugins/light_occluder_2d_editor_plugin.cpp b/editor/plugins/light_occluder_2d_editor_plugin.cpp index a3be10dc33..3351e5918f 100644 --- a/editor/plugins/light_occluder_2d_editor_plugin.cpp +++ b/editor/plugins/light_occluder_2d_editor_plugin.cpp @@ -255,7 +255,7 @@ bool LightOccluder2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { //apply ERR_FAIL_INDEX_V(edited_point, poly.size(), false); - poly[edited_point] = edited_point_pos; + poly.write[edited_point] = edited_point_pos; undo_redo->create_action(TTR("Edit Poly")); undo_redo->add_do_method(node->get_occluder_polygon().ptr(), "set_polygon", poly); undo_redo->add_undo_method(node->get_occluder_polygon().ptr(), "set_polygon", pre_move_edit); diff --git a/editor/plugins/particles_2d_editor_plugin.cpp b/editor/plugins/particles_2d_editor_plugin.cpp index 6d11079759..c2b17189ef 100644 --- a/editor/plugins/particles_2d_editor_plugin.cpp +++ b/editor/plugins/particles_2d_editor_plugin.cpp @@ -165,12 +165,12 @@ void Particles2DEditorPlugin::_generate_emission_mask() { if (emode == EMISSION_MODE_SOLID) { if (capture_colors) { - valid_colors[vpc * 4 + 0] = r[(j * s.width + i) * 4 + 0]; - valid_colors[vpc * 4 + 1] = r[(j * s.width + i) * 4 + 1]; - valid_colors[vpc * 4 + 2] = r[(j * s.width + i) * 4 + 2]; - valid_colors[vpc * 4 + 3] = r[(j * s.width + i) * 4 + 3]; + valid_colors.write[vpc * 4 + 0] = r[(j * s.width + i) * 4 + 0]; + valid_colors.write[vpc * 4 + 1] = r[(j * s.width + i) * 4 + 1]; + valid_colors.write[vpc * 4 + 2] = r[(j * s.width + i) * 4 + 2]; + valid_colors.write[vpc * 4 + 3] = r[(j * s.width + i) * 4 + 3]; } - valid_positions[vpc++] = Point2(i, j); + valid_positions.write[vpc++] = Point2(i, j); } else { @@ -189,7 +189,7 @@ void Particles2DEditorPlugin::_generate_emission_mask() { } if (on_border) { - valid_positions[vpc] = Point2(i, j); + valid_positions.write[vpc] = Point2(i, j); if (emode == EMISSION_MODE_BORDER_DIRECTED) { Vector2 normal; @@ -206,14 +206,14 @@ void Particles2DEditorPlugin::_generate_emission_mask() { } normal.normalize(); - valid_normals[vpc] = normal; + valid_normals.write[vpc] = normal; } if (capture_colors) { - valid_colors[vpc * 4 + 0] = r[(j * s.width + i) * 4 + 0]; - valid_colors[vpc * 4 + 1] = r[(j * s.width + i) * 4 + 1]; - valid_colors[vpc * 4 + 2] = r[(j * s.width + i) * 4 + 2]; - valid_colors[vpc * 4 + 3] = r[(j * s.width + i) * 4 + 3]; + valid_colors.write[vpc * 4 + 0] = r[(j * s.width + i) * 4 + 0]; + valid_colors.write[vpc * 4 + 1] = r[(j * s.width + i) * 4 + 1]; + valid_colors.write[vpc * 4 + 2] = r[(j * s.width + i) * 4 + 2]; + valid_colors.write[vpc * 4 + 3] = r[(j * s.width + i) * 4 + 3]; } vpc++; diff --git a/editor/plugins/path_editor_plugin.cpp b/editor/plugins/path_editor_plugin.cpp index 72a8b55a52..618c70d1a1 100644 --- a/editor/plugins/path_editor_plugin.cpp +++ b/editor/plugins/path_editor_plugin.cpp @@ -215,6 +215,10 @@ void PathSpatialGizmo::redraw() { clear(); + Ref<SpatialMaterial> path_material = gizmo_plugin->get_material("path_material"); + Ref<SpatialMaterial> path_thin_material = gizmo_plugin->get_material("path_thin_material"); + Ref<SpatialMaterial> handles_material = gizmo_plugin->get_material("handles"); + Ref<Curve3D> c = path->get_curve(); if (c.is_null()) return; @@ -238,7 +242,7 @@ void PathSpatialGizmo::redraw() { } if (v3p.size() > 1) { - add_lines(v3p, PathEditorPlugin::singleton->path_material); + add_lines(v3p, path_material); add_collision_segments(v3p); } @@ -265,13 +269,13 @@ void PathSpatialGizmo::redraw() { } if (v3p.size() > 1) { - add_lines(v3p, PathEditorPlugin::singleton->path_thin_material); + add_lines(v3p, path_thin_material); } if (handles.size()) { - add_handles(handles); + add_handles(handles, handles_material); } if (sec_handles.size()) { - add_handles(sec_handles, false, true); + add_handles(sec_handles, handles_material, false, true); } } } @@ -282,16 +286,6 @@ PathSpatialGizmo::PathSpatialGizmo(Path *p_path) { set_spatial_node(p_path); } -Ref<SpatialEditorGizmo> PathEditorPlugin::create_spatial_gizmo(Spatial *p_spatial) { - - if (Object::cast_to<Path>(p_spatial)) { - - return memnew(PathSpatialGizmo(Object::cast_to<Path>(p_spatial))); - } - - return Ref<SpatialEditorGizmo>(); -} - bool PathEditorPlugin::forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event) { if (!path) @@ -567,21 +561,9 @@ PathEditorPlugin::PathEditorPlugin(EditorNode *p_node) { mirror_handle_angle = true; mirror_handle_length = true; - path_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); - path_material->set_albedo(Color(0.5, 0.5, 1.0, 0.8)); - path_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - path_material->set_line_width(3); - path_material->set_cull_mode(SpatialMaterial::CULL_DISABLED); - path_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - - path_thin_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); - path_thin_material->set_albedo(Color(0.5, 0.5, 1.0, 0.4)); - path_thin_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - path_thin_material->set_line_width(1); - path_thin_material->set_cull_mode(SpatialMaterial::CULL_DISABLED); - path_thin_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - - //SpatialEditor::get_singleton()->add_gizmo_plugin(this); + Ref<PathSpatialGizmoPlugin> gizmo_plugin; + gizmo_plugin.instance(); + SpatialEditor::get_singleton()->register_gizmo_plugin(gizmo_plugin); sep = memnew(VSeparator); sep->hide(); @@ -630,18 +612,53 @@ PathEditorPlugin::PathEditorPlugin(EditorNode *p_node) { curve_edit->set_pressed(true); /* - collision_polygon_editor = memnew( PathEditor(p_node) ); - editor->get_viewport()->add_child(collision_polygon_editor); + collision_polygon_editor = memnew( PathEditor(p_node) ); + editor->get_viewport()->add_child(collision_polygon_editor); + collision_polygon_editor->set_margin(MARGIN_LEFT,200); + collision_polygon_editor->set_margin(MARGIN_RIGHT,230); + collision_polygon_editor->set_margin(MARGIN_TOP,0); + collision_polygon_editor->set_margin(MARGIN_BOTTOM,10); + collision_polygon_editor->hide(); + */ +} - collision_polygon_editor->set_margin(MARGIN_LEFT,200); - collision_polygon_editor->set_margin(MARGIN_RIGHT,230); - collision_polygon_editor->set_margin(MARGIN_TOP,0); - collision_polygon_editor->set_margin(MARGIN_BOTTOM,10); +PathEditorPlugin::~PathEditorPlugin() { +} + +Ref<EditorSpatialGizmo> PathSpatialGizmoPlugin::create_gizmo(Spatial *p_spatial) { + Ref<PathSpatialGizmo> ref; + Path *path = Object::cast_to<Path>(p_spatial); + if (path) ref = Ref<PathSpatialGizmo>(memnew(PathSpatialGizmo(path))); - collision_polygon_editor->hide(); - */ + return ref; } -PathEditorPlugin::~PathEditorPlugin() { +String PathSpatialGizmoPlugin::get_name() const { + return "Path"; +} + +PathSpatialGizmoPlugin::PathSpatialGizmoPlugin() { + + Color path_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/path", Color(0.5, 0.5, 1.0, 0.8)); + + Ref<SpatialMaterial> path_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + path_color.a = 0.8; + path_material->set_albedo(path_color); + path_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + path_material->set_line_width(3); + path_material->set_cull_mode(SpatialMaterial::CULL_DISABLED); + path_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + + Ref<SpatialMaterial> path_thin_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + path_color.a = 0.4; + path_thin_material->set_albedo(path_color); + path_thin_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + path_thin_material->set_line_width(1); + path_thin_material->set_cull_mode(SpatialMaterial::CULL_DISABLED); + path_thin_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + + add_material("path_material", path_material); + add_material("path_thin_material", path_thin_material); + create_handle_material("handles"); } diff --git a/editor/plugins/path_editor_plugin.h b/editor/plugins/path_editor_plugin.h index 52dfb78b61..61f309e794 100644 --- a/editor/plugins/path_editor_plugin.h +++ b/editor/plugins/path_editor_plugin.h @@ -49,10 +49,22 @@ public: virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); - void redraw(); + virtual void redraw(); PathSpatialGizmo(Path *p_path = NULL); }; +class PathSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { + + GDCLASS(PathSpatialGizmoPlugin, EditorSpatialGizmoPlugin); + +protected: + Ref<EditorSpatialGizmo> create_gizmo(Spatial *p_spatial); + +public: + String get_name() const; + PathSpatialGizmoPlugin(); +}; + class PathEditorPlugin : public EditorPlugin { GDCLASS(PathEditorPlugin, EditorPlugin); @@ -88,12 +100,10 @@ public: Path *get_edited_path() { return path; } static PathEditorPlugin *singleton; - Ref<SpatialMaterial> path_material; - Ref<SpatialMaterial> path_thin_material; virtual bool forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event); //virtual bool forward_gui_input(const InputEvent& p_event) { return collision_polygon_editor->forward_gui_input(p_event); } - virtual Ref<SpatialEditorGizmo> create_spatial_gizmo(Spatial *p_spatial); + //virtual Ref<SpatialEditorGizmo> create_spatial_gizmo(Spatial *p_spatial); virtual String get_name() const { return "Path"; } bool has_main_screen() const { return false; } virtual void edit(Object *p_object); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index a1dc746702..7d72537e32 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -219,6 +219,9 @@ void ScriptEditorQuickOpen::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { connect("confirmed", this, "_confirmed"); + + search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_clear_button_enabled(true); } break; } } @@ -342,11 +345,11 @@ void ScriptEditor::_save_history() { if (Object::cast_to<ScriptEditorBase>(n)) { - history[history_pos].state = Object::cast_to<ScriptEditorBase>(n)->get_edit_state(); + history.write[history_pos].state = Object::cast_to<ScriptEditorBase>(n)->get_edit_state(); } if (Object::cast_to<EditorHelp>(n)) { - history[history_pos].state = Object::cast_to<EditorHelp>(n)->get_scroll(); + history.write[history_pos].state = Object::cast_to<EditorHelp>(n)->get_scroll(); } } @@ -373,11 +376,11 @@ void ScriptEditor::_go_to_tab(int p_idx) { if (Object::cast_to<ScriptEditorBase>(n)) { - history[history_pos].state = Object::cast_to<ScriptEditorBase>(n)->get_edit_state(); + history.write[history_pos].state = Object::cast_to<ScriptEditorBase>(n)->get_edit_state(); } if (Object::cast_to<EditorHelp>(n)) { - history[history_pos].state = Object::cast_to<EditorHelp>(n)->get_scroll(); + history.write[history_pos].state = Object::cast_to<EditorHelp>(n)->get_scroll(); } } @@ -1876,6 +1879,7 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra if ((debugger->get_dump_stack_script() != p_resource || debugger->get_debug_with_external_editor()) && p_resource->get_path().is_resource_file() && + p_resource->get_class_name() != StringName("VisualScript") && bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor"))) { String path = EditorSettings::get_singleton()->get("text_editor/external/exec_path"); @@ -2401,26 +2405,25 @@ void ScriptEditor::_make_script_list_context_menu() { if (se) { context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/save"), FILE_SAVE); context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/save_as"), FILE_SAVE_AS); - context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/close_file"), FILE_CLOSE); - context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/close_all"), CLOSE_ALL); - context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/close_other_tabs"), CLOSE_OTHER_TABS); - context_menu->add_separator(); - context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/copy_path"), FILE_COPY_PATH); - context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/show_in_file_system"), SHOW_IN_FILE_SYSTEM); } - - Ref<Script> scr = se->get_edited_resource(); - if (scr != NULL) { - context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/reload_script_soft"), FILE_TOOL_RELOAD_SOFT); - if (!scr.is_null() && scr->is_tool()) { - context_menu->add_separator(); - context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/run_file"), FILE_RUN); + context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/close_file"), FILE_CLOSE); + context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/close_all"), CLOSE_ALL); + context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/close_other_tabs"), CLOSE_OTHER_TABS); + context_menu->add_separator(); + if (se) { + Ref<Script> scr = se->get_edited_resource(); + if (scr != NULL) { + context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/reload_script_soft"), FILE_TOOL_RELOAD_SOFT); + if (!scr.is_null() && scr->is_tool()) { + context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/run_file"), FILE_RUN); + context_menu->add_separator(); + } } - } else { - context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/close_file"), FILE_CLOSE); + context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/copy_path"), FILE_COPY_PATH); + context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/show_in_file_system"), SHOW_IN_FILE_SYSTEM); + context_menu->add_separator(); } - context_menu->add_separator(); context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/window_move_up"), WINDOW_MOVE_UP); context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/window_move_down"), WINDOW_MOVE_DOWN); context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/window_sort"), WINDOW_SORT); @@ -2612,11 +2615,11 @@ void ScriptEditor::_update_history_pos(int p_new_pos) { if (Object::cast_to<ScriptEditorBase>(n)) { - history[history_pos].state = Object::cast_to<ScriptEditorBase>(n)->get_edit_state(); + history.write[history_pos].state = Object::cast_to<ScriptEditorBase>(n)->get_edit_state(); } if (Object::cast_to<EditorHelp>(n)) { - history[history_pos].state = Object::cast_to<EditorHelp>(n)->get_scroll(); + history.write[history_pos].state = Object::cast_to<EditorHelp>(n)->get_scroll(); } history_pos = p_new_pos; @@ -2894,13 +2897,14 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { script_list->set_v_size_flags(SIZE_EXPAND_FILL); script_split->set_split_offset(140); _sort_list_on_update = true; - script_list->connect("gui_input", this, "_script_list_gui_input"); + script_list->connect("gui_input", this, "_script_list_gui_input", varray(), CONNECT_DEFERRED); script_list->set_allow_rmb_select(true); script_list->set_drag_forwarding(this); context_menu = memnew(PopupMenu); add_child(context_menu); context_menu->connect("id_pressed", this, "_menu_option"); + context_menu->set_hide_on_window_lose_focus(true); overview_vbox = memnew(VBoxContainer); overview_vbox->set_custom_minimum_size(Size2(0, 90)); @@ -2955,6 +2959,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { file_menu = memnew(MenuButton); menu_hb->add_child(file_menu); file_menu->set_text(TTR("File")); + file_menu->get_popup()->set_hide_on_window_lose_focus(true); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new", TTR("New")), FILE_NEW); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/open", TTR("Open")), FILE_OPEN); file_menu->get_popup()->add_submenu_item(TTR("Open Recent"), "RecentScripts", FILE_OPEN_RECENT); @@ -3004,6 +3009,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { script_search_menu = memnew(MenuButton); menu_hb->add_child(script_search_menu); script_search_menu->set_text(TTR("Search")); + script_search_menu->get_popup()->set_hide_on_window_lose_focus(true); script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find", TTR("Find..."), KEY_MASK_CMD | KEY_F), HELP_SEARCH_FIND); script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_next", TTR("Find Next"), KEY_F3), HELP_SEARCH_FIND_NEXT); script_search_menu->get_popup()->connect("id_pressed", this, "_menu_option"); @@ -3012,6 +3018,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { debug_menu = memnew(MenuButton); menu_hb->add_child(debug_menu); debug_menu->set_text(TTR("Debug")); + debug_menu->get_popup()->set_hide_on_window_lose_focus(true); debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/step_over", TTR("Step Over"), KEY_F10), DEBUG_NEXT); debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/step_into", TTR("Step Into"), KEY_F11), DEBUG_STEP); debug_menu->get_popup()->add_separator(); @@ -3093,7 +3100,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { error_dialog = memnew(AcceptDialog); add_child(error_dialog); - error_dialog->get_ok()->set_text(TTR("I see...")); + error_dialog->get_ok()->set_text(TTR("OK")); debugger = memnew(ScriptEditorDebugger(editor)); debugger->connect("goto_script_line", this, "_goto_script_line"); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 165d7e32b9..522ce52234 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -274,6 +274,23 @@ void ScriptTextEditor::_set_theme_for_script() { } } +void ScriptTextEditor::_toggle_warning_pannel(const Ref<InputEvent> &p_event) { + Ref<InputEventMouseButton> mb = p_event; + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + warnings_panel->set_visible(!warnings_panel->is_visible()); + } +} + +void ScriptTextEditor::_warning_clicked(Variant p_line) { + if (p_line.get_type() == Variant::INT) { + code_editor->get_text_edit()->cursor_set_line(p_line.operator int64_t()); + } else if (p_line.get_type() == Variant::DICTIONARY) { + Dictionary meta = p_line.operator Dictionary(); + code_editor->get_text_edit()->insert_at("#warning-ignore:" + meta["code"].operator String(), meta["line"].operator int64_t() - 1); + _validate_script(); + } +} + void ScriptTextEditor::reload_text() { ERR_FAIL_COND(script.is_null()); @@ -421,8 +438,9 @@ void ScriptTextEditor::_validate_script() { String text = te->get_text(); List<String> fnc; Set<int> safe_lines; + List<ScriptLanguage::Warning> warnings; - if (!script->get_language()->validate(text, line, col, errortxt, script->get_path(), &fnc, &safe_lines)) { + if (!script->get_language()->validate(text, line, col, errortxt, script->get_path(), &fnc, &warnings, &safe_lines)) { String error_text = "error(" + itos(line) + "," + itos(col) + "): " + errortxt; code_editor->set_error(error_text); } else { @@ -442,6 +460,37 @@ void ScriptTextEditor::_validate_script() { } } + code_editor->get_warning_count_label()->set_text(itos(warnings.size())); + warnings_panel->clear(); + warnings_panel->push_table(3); + for (List<ScriptLanguage::Warning>::Element *E = warnings.front(); E; E = E->next()) { + ScriptLanguage::Warning w = E->get(); + + warnings_panel->push_cell(); + warnings_panel->push_meta(w.line - 1); + warnings_panel->push_color(warnings_panel->get_color("warning_color", "Editor")); + warnings_panel->add_text(TTR("Line") + " " + itos(w.line)); + warnings_panel->add_text(" (" + w.string_code + "):"); + warnings_panel->pop(); // Color + warnings_panel->pop(); // Meta goto + warnings_panel->pop(); // Cell + + warnings_panel->push_cell(); + warnings_panel->add_text(w.message); + warnings_panel->pop(); // Cell + + Dictionary ignore_meta; + ignore_meta["line"] = w.line; + ignore_meta["code"] = w.string_code.to_lower(); + warnings_panel->push_cell(); + warnings_panel->push_meta(ignore_meta); + warnings_panel->add_text(TTR("(ignore)")); + warnings_panel->pop(); // Meta ignore + warnings_panel->pop(); // Cell + //warnings_panel->add_newline(); + } + warnings_panel->pop(); // Table + line--; bool highlight_safe = EDITOR_DEF("text_editor/highlighting/highlight_type_safe_lines", true); bool last_is_safe = false; @@ -967,7 +1016,6 @@ void ScriptTextEditor::_edit_option(int p_op) { } } break; - case HELP_CONTEXTUAL: { String text = tx->get_selection_text(); @@ -977,6 +1025,15 @@ void ScriptTextEditor::_edit_option(int p_op) { emit_signal("request_help_search", text); } } break; + case LOOKUP_SYMBOL: { + + String text = tx->get_word_under_cursor(); + if (text == "") + text = tx->get_selection_text(); + if (text != "") { + _lookup_symbol(text, tx->cursor_get_line(), tx->cursor_get_column()); + } + } break; } } @@ -1014,6 +1071,8 @@ void ScriptTextEditor::_bind_methods() { ClassDB::bind_method("_goto_line", &ScriptTextEditor::_goto_line); ClassDB::bind_method("_lookup_symbol", &ScriptTextEditor::_lookup_symbol); ClassDB::bind_method("_text_edit_gui_input", &ScriptTextEditor::_text_edit_gui_input); + ClassDB::bind_method("_toggle_warning_pannel", &ScriptTextEditor::_toggle_warning_pannel); + ClassDB::bind_method("_warning_clicked", &ScriptTextEditor::_warning_clicked); ClassDB::bind_method("_color_changed", &ScriptTextEditor::_color_changed); ClassDB::bind_method("get_drag_data_fw", &ScriptTextEditor::get_drag_data_fw); @@ -1182,19 +1241,13 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { if (mb.is_valid()) { - if (mb->get_button_index() == BUTTON_RIGHT) { - + if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { int col, row; TextEdit *tx = code_editor->get_text_edit(); tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col); Vector2 mpos = mb->get_global_position() - tx->get_global_position(); tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret")); - bool has_color = (tx->get_word_at_pos(mpos) == "Color"); - int fold_state = 0; - bool can_fold = tx->can_fold(row); - bool is_folded = tx->is_folded(row); - if (tx->is_right_click_moving_caret()) { if (tx->is_selection_active()) { @@ -1214,38 +1267,62 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { } } - if (!mb->is_pressed()) { - if (has_color) { - String line = tx->get_line(row); - color_line = row; - int begin = 0; - int end = 0; - bool valid = false; - for (int i = col; i < line.length(); i++) { - if (line[i] == '(') { - begin = i; - continue; - } else if (line[i] == ')') { - end = i + 1; - valid = true; - break; - } + String word_at_mouse = tx->get_word_at_pos(mpos); + if (word_at_mouse == "") + word_at_mouse = tx->get_word_under_cursor(); + if (word_at_mouse == "") + word_at_mouse = tx->get_selection_text(); + + bool has_color = (word_at_mouse == "Color"); + int fold_state = 0; + bool foldable = tx->can_fold(row) || tx->is_folded(row); + bool open_docs = false; + bool goto_definition = false; + + if (word_at_mouse.is_resource_file()) { + open_docs = true; + } else { + + Node *base = get_tree()->get_edited_scene_root(); + if (base) { + base = _find_node_for_script(base, base, script); + } + ScriptLanguage::LookupResult result; + if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), word_at_mouse, script->get_path().get_base_dir(), base, result) == OK) { + open_docs = true; + } + } + + if (has_color) { + String line = tx->get_line(row); + color_line = row; + int begin = 0; + int end = 0; + bool valid = false; + for (int i = col; i < line.length(); i++) { + if (line[i] == '(') { + begin = i; + continue; + } else if (line[i] == ')') { + end = i + 1; + valid = true; + break; } - if (valid) { - color_args = line.substr(begin, end - begin); - String stripped = color_args.replace(" ", "").replace("(", "").replace(")", ""); - Vector<float> color = stripped.split_floats(","); - if (color.size() > 2) { - float alpha = color.size() > 3 ? color[3] : 1.0f; - color_picker->set_pick_color(Color(color[0], color[1], color[2], alpha)); - } - color_panel->set_position(get_global_transform().xform(get_local_mouse_position())); - } else { - has_color = false; + } + if (valid) { + color_args = line.substr(begin, end - begin); + String stripped = color_args.replace(" ", "").replace("(", "").replace(")", ""); + Vector<float> color = stripped.split_floats(","); + if (color.size() > 2) { + float alpha = color.size() > 3 ? color[3] : 1.0f; + color_picker->set_pick_color(Color(color[0], color[1], color[2], alpha)); } + color_panel->set_position(get_global_transform().xform(get_local_mouse_position())); + } else { + has_color = false; } - _make_context_menu(tx->is_selection_active(), has_color, can_fold, is_folded); } + _make_context_menu(tx->is_selection_active(), has_color, foldable, open_docs, goto_definition); } } } @@ -1264,7 +1341,7 @@ void ScriptTextEditor::_color_changed(const Color &p_color) { code_editor->get_text_edit()->set_line(color_line, new_line); } -void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p_can_fold, bool p_is_folded) { +void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition) { context_menu->clear(); if (p_selection) { @@ -1287,13 +1364,17 @@ void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/convert_to_uppercase"), EDIT_TO_UPPERCASE); context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/convert_to_lowercase"), EDIT_TO_LOWERCASE); } - if (p_can_fold || p_is_folded) + if (p_foldable) context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_fold_line"), EDIT_TOGGLE_FOLD_LINE); - if (p_color) { + if (p_color || p_open_docs || p_goto_definition) { context_menu->add_separator(); - context_menu->add_item(TTR("Pick Color"), EDIT_PICK_COLOR); + if (p_open_docs) + context_menu->add_item(TTR("Lookup Symbol"), LOOKUP_SYMBOL); + if (p_color) + context_menu->add_item(TTR("Pick Color"), EDIT_PICK_COLOR); } + context_menu->set_position(get_global_transform().xform(get_local_mouse_position())); context_menu->set_size(Vector2(1, 1)); context_menu->popup(); @@ -1303,8 +1384,13 @@ ScriptTextEditor::ScriptTextEditor() { theme_loaded = false; + VSplitContainer *editor_box = memnew(VSplitContainer); + add_child(editor_box); + editor_box->set_anchors_and_margins_preset(Control::PRESET_WIDE); + editor_box->set_v_size_flags(SIZE_EXPAND_FILL); + code_editor = memnew(CodeTextEditor); - add_child(code_editor); + editor_box->add_child(code_editor); code_editor->add_constant_override("separation", 0); code_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE); code_editor->connect("validate_script", this, "_validate_script"); @@ -1312,7 +1398,20 @@ ScriptTextEditor::ScriptTextEditor() { code_editor->set_code_complete_func(_code_complete_scripts, this); code_editor->get_text_edit()->connect("breakpoint_toggled", this, "_breakpoint_toggled"); code_editor->get_text_edit()->connect("symbol_lookup", this, "_lookup_symbol"); - code_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); + code_editor->set_v_size_flags(SIZE_EXPAND_FILL); + + warnings_panel = memnew(RichTextLabel); + editor_box->add_child(warnings_panel); + warnings_panel->set_custom_minimum_size(Size2(0, 100 * EDSCALE)); + warnings_panel->set_h_size_flags(SIZE_EXPAND_FILL); + warnings_panel->set_meta_underline(true); + warnings_panel->set_selection_enabled(true); + warnings_panel->set_focus_mode(FOCUS_CLICK); + warnings_panel->hide(); + + code_editor->get_warning_label()->connect("gui_input", this, "_toggle_warning_pannel"); + code_editor->get_warning_count_label()->connect("gui_input", this, "_toggle_warning_pannel"); + warnings_panel->connect("meta_clicked", this, "_warning_clicked"); update_settings(); @@ -1327,6 +1426,7 @@ ScriptTextEditor::ScriptTextEditor() { context_menu = memnew(PopupMenu); add_child(context_menu); context_menu->connect("id_pressed", this, "_edit_option"); + context_menu->set_hide_on_window_lose_focus(true); color_panel = memnew(PopupPanel); add_child(color_panel); @@ -1338,6 +1438,7 @@ ScriptTextEditor::ScriptTextEditor() { edit_menu = memnew(MenuButton); edit_menu->set_text(TTR("Edit")); + edit_menu->get_popup()->set_hide_on_window_lose_focus(true); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO); edit_menu->get_popup()->add_separator(); @@ -1391,6 +1492,7 @@ ScriptTextEditor::ScriptTextEditor() { search_menu = memnew(MenuButton); edit_hb->add_child(search_menu); search_menu->set_text(TTR("Search")); + search_menu->get_popup()->set_hide_on_window_lose_focus(true); search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find"), SEARCH_FIND); search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_next"), SEARCH_FIND_NEXT); search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_previous"), SEARCH_FIND_PREV); diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index f0b00a9117..837201a947 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -39,6 +39,7 @@ class ScriptTextEditor : public ScriptEditorBase { GDCLASS(ScriptTextEditor, ScriptEditorBase); CodeTextEditor *code_editor; + RichTextLabel *warnings_panel; Ref<Script> script; @@ -112,6 +113,7 @@ class ScriptTextEditor : public ScriptEditorBase { DEBUG_GOTO_NEXT_BREAKPOINT, DEBUG_GOTO_PREV_BREAKPOINT, HELP_CONTEXTUAL, + LOOKUP_SYMBOL, }; protected: @@ -123,6 +125,8 @@ protected: void _code_complete_script(const String &p_code, List<String> *r_options, bool &r_force); void _load_theme_settings(); void _set_theme_for_script(); + void _toggle_warning_pannel(const Ref<InputEvent> &p_event); + void _warning_clicked(Variant p_line); void _notification(int p_what); static void _bind_methods(); @@ -131,7 +135,7 @@ protected: void _change_syntax_highlighter(int p_idx); void _edit_option(int p_op); - void _make_context_menu(bool p_selection, bool p_color, bool p_can_fold, bool p_is_folded); + void _make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition); void _text_edit_gui_input(const Ref<InputEvent> &ev); void _color_changed(const Color &p_color); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 7650cd6ae7..ea1876c27a 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -465,7 +465,7 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { if (mb.is_valid()) { - if (mb->get_button_index() == BUTTON_RIGHT) { + if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { int col, row; TextEdit *tx = shader_editor->get_text_edit(); @@ -491,10 +491,7 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { tx->cursor_set_column(col); } } - - if (!mb->is_pressed()) { - _make_context_menu(tx->is_selection_active()); - } + _make_context_menu(tx->is_selection_active()); } } } @@ -546,6 +543,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) { context_menu = memnew(PopupMenu); add_child(context_menu); context_menu->connect("id_pressed", this, "_menu_option"); + context_menu->set_hide_on_window_lose_focus(true); VBoxContainer *main_container = memnew(VBoxContainer); HBoxContainer *hbc = memnew(HBoxContainer); @@ -554,6 +552,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) { //edit_menu->set_position(Point2(5, -1)); edit_menu->set_text(TTR("Edit")); + edit_menu->get_popup()->set_hide_on_window_lose_focus(true); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO); edit_menu->get_popup()->add_separator(); @@ -578,7 +577,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) { search_menu = memnew(MenuButton); //search_menu->set_position(Point2(38, -1)); search_menu->set_text(TTR("Search")); - + search_menu->get_popup()->set_hide_on_window_lose_focus(true); search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find"), SEARCH_FIND); search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_next"), SEARCH_FIND_NEXT); search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_previous"), SEARCH_FIND_PREV); diff --git a/editor/plugins/skeleton_editor_plugin.cpp b/editor/plugins/skeleton_editor_plugin.cpp index 40a696119e..fe7d1df50c 100644 --- a/editor/plugins/skeleton_editor_plugin.cpp +++ b/editor/plugins/skeleton_editor_plugin.cpp @@ -68,16 +68,16 @@ void SkeletonEditor::create_physical_skeleton() { if (parent < 0) { - bones_infos[bone_id].relative_rest = skeleton->get_bone_rest(bone_id); + bones_infos.write[bone_id].relative_rest = skeleton->get_bone_rest(bone_id); } else { - bones_infos[bone_id].relative_rest = bones_infos[parent].relative_rest * skeleton->get_bone_rest(bone_id); + bones_infos.write[bone_id].relative_rest = bones_infos[parent].relative_rest * skeleton->get_bone_rest(bone_id); /// create physical bone on parent if (!bones_infos[parent].physical_bone) { - bones_infos[parent].physical_bone = create_physical_bone(parent, bone_id, bones_infos); + bones_infos.write[parent].physical_bone = create_physical_bone(parent, bone_id, bones_infos); ur->create_action(TTR("Create physical bones")); ur->add_do_method(skeleton, "add_child", bones_infos[parent].physical_bone); diff --git a/editor/plugins/skeleton_ik_editor_plugin.cpp b/editor/plugins/skeleton_ik_editor_plugin.cpp new file mode 100644 index 0000000000..2d343d3edd --- /dev/null +++ b/editor/plugins/skeleton_ik_editor_plugin.cpp @@ -0,0 +1,110 @@ +/*************************************************************************/ +/* skeleton_ik_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "skeleton_ik_editor_plugin.h" + +#include "scene/animation/skeleton_ik.h" + +void SkeletonIKEditorPlugin::_play() { + + if (!skeleton_ik) + return; + + if (!skeleton_ik->get_parent_skeleton()) + return; + + if (play_btn->is_pressed()) { + + initial_bone_poses.resize(skeleton_ik->get_parent_skeleton()->get_bone_count()); + for (int i = 0; i < skeleton_ik->get_parent_skeleton()->get_bone_count(); ++i) { + initial_bone_poses.write[i] = skeleton_ik->get_parent_skeleton()->get_bone_pose(i); + } + + skeleton_ik->start(); + } else { + skeleton_ik->stop(); + + if (initial_bone_poses.size() != skeleton_ik->get_parent_skeleton()->get_bone_count()) + return; + + for (int i = 0; i < skeleton_ik->get_parent_skeleton()->get_bone_count(); ++i) { + skeleton_ik->get_parent_skeleton()->set_bone_pose(i, initial_bone_poses[i]); + } + } +} + +void SkeletonIKEditorPlugin::edit(Object *p_object) { + + if (p_object != skeleton_ik) { + if (skeleton_ik) { + play_btn->set_pressed(false); + _play(); + } + } + + SkeletonIK *s = Object::cast_to<SkeletonIK>(p_object); + if (!s) + return; + + skeleton_ik = s; +} + +bool SkeletonIKEditorPlugin::handles(Object *p_object) const { + + return p_object->is_class("SkeletonIK"); +} + +void SkeletonIKEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) + play_btn->show(); + else + play_btn->hide(); +} + +void SkeletonIKEditorPlugin::_bind_methods() { + + ClassDB::bind_method("_play", &SkeletonIKEditorPlugin::_play); +} + +SkeletonIKEditorPlugin::SkeletonIKEditorPlugin(EditorNode *p_node) { + + editor = p_node; + play_btn = memnew(Button); + play_btn->set_icon(editor->get_gui_base()->get_icon("Play", "EditorIcons")); + play_btn->set_text(TTR("Play IK")); + play_btn->set_toggle_mode(true); + play_btn->hide(); + play_btn->connect("pressed", this, "_play"); + add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, play_btn); + skeleton_ik = NULL; +} + +SkeletonIKEditorPlugin::~SkeletonIKEditorPlugin() {} diff --git a/editor/plugins/skeleton_ik_editor_plugin.h b/editor/plugins/skeleton_ik_editor_plugin.h new file mode 100644 index 0000000000..e645bea39a --- /dev/null +++ b/editor/plugins/skeleton_ik_editor_plugin.h @@ -0,0 +1,65 @@ +/*************************************************************************/ +/* skeleton_ik_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SKELETON_IK_EDITOR_PLUGIN_H +#define SKELETON_IK_EDITOR_PLUGIN_H + +#include "editor/editor_node.h" +#include "editor/editor_plugin.h" + +class SkeletonIK; + +class SkeletonIKEditorPlugin : public EditorPlugin { + + GDCLASS(SkeletonIKEditorPlugin, EditorPlugin); + + SkeletonIK *skeleton_ik; + + Button *play_btn; + EditorNode *editor; + Vector<Transform> initial_bone_poses; + + void _play(); + +protected: + static void _bind_methods(); + +public: + virtual String get_name() const { return "SkeletonIK"; } + bool has_main_screen() const { return false; } + virtual void edit(Object *p_object); + virtual bool handles(Object *p_object) const; + virtual void make_visible(bool p_visible); + + SkeletonIKEditorPlugin(EditorNode *p_node); + ~SkeletonIKEditorPlugin(); +}; + +#endif // SKELETON_IK_EDITOR_PLUGIN_H diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index f0c874a150..c3d48d498c 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -184,49 +184,6 @@ Transform SpatialEditorViewport::to_camera_transform(const Cursor &p_cursor) con return camera_transform; } -String SpatialEditorGizmo::get_handle_name(int p_idx) const { - - if (get_script_instance() && get_script_instance()->has_method("get_handle_name")) - return get_script_instance()->call("get_handle_name", p_idx); - - return ""; -} - -Variant SpatialEditorGizmo::get_handle_value(int p_idx) const { - - if (get_script_instance() && get_script_instance()->has_method("get_handle_value")) - return get_script_instance()->call("get_handle_value", p_idx); - - return Variant(); -} - -void SpatialEditorGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) { - - if (get_script_instance() && get_script_instance()->has_method("set_handle")) - get_script_instance()->call("set_handle", p_idx, p_camera, p_point); -} - -void SpatialEditorGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { - - if (get_script_instance() && get_script_instance()->has_method("commit_handle")) - get_script_instance()->call("commit_handle", p_idx, p_restore, p_cancel); -} - -bool SpatialEditorGizmo::intersect_frustum(const Camera *p_camera, const Vector<Plane> &p_frustum) { - - return false; -} - -bool SpatialEditorGizmo::intersect_ray(Camera *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle, bool p_sec_first) { - - return false; -} - -SpatialEditorGizmo::SpatialEditorGizmo() { - - selected = false; -} - int SpatialEditorViewport::get_selected_count() const { Map<Node *, Object *> &selection = editor_selection->get_selection(); @@ -346,7 +303,7 @@ ObjectID SpatialEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, Vector3 pos = _get_ray_pos(p_pos); Vector<ObjectID> instances = VisualServer::get_singleton()->instances_cull_ray(pos, ray, get_tree()->get_root()->get_world()->get_scenario()); - Set<Ref<SpatialEditorGizmo> > found_gizmos; + Set<Ref<EditorSpatialGizmo> > found_gizmos; Node *edited_scene = get_tree()->get_edited_scene_root(); ObjectID closest = 0; @@ -361,7 +318,7 @@ ObjectID SpatialEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, if (!spat) continue; - Ref<SpatialEditorGizmo> seg = spat->get_gizmo(); + Ref<EditorSpatialGizmo> seg = spat->get_gizmo(); if ((!seg.is_valid()) || found_gizmos.has(seg)) { continue; @@ -418,7 +375,7 @@ void SpatialEditorViewport::_find_items_at_pos(const Point2 &p_pos, bool &r_incl Vector3 pos = _get_ray_pos(p_pos); Vector<ObjectID> instances = VisualServer::get_singleton()->instances_cull_ray(pos, ray, get_tree()->get_root()->get_world()->get_scenario()); - Set<Ref<SpatialEditorGizmo> > found_gizmos; + Set<Ref<EditorSpatialGizmo> > found_gizmos; r_includes_current = false; @@ -429,7 +386,7 @@ void SpatialEditorViewport::_find_items_at_pos(const Point2 &p_pos, bool &r_incl if (!spat) continue; - Ref<SpatialEditorGizmo> seg = spat->get_gizmo(); + Ref<EditorSpatialGizmo> seg = spat->get_gizmo(); if (!seg.is_valid()) continue; @@ -559,7 +516,7 @@ void SpatialEditorViewport::_select_region() { if (selected.find(root_sp) != -1) continue; - Ref<SpatialEditorGizmo> seg = sp->get_gizmo(); + Ref<EditorSpatialGizmo> seg = sp->get_gizmo(); if (!seg.is_valid()) continue; @@ -963,7 +920,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (b->is_pressed() && _edit.gizmo.is_valid()) { //restore _edit.gizmo->commit_handle(_edit.gizmo_handle, _edit.gizmo_initial_value, true); - _edit.gizmo = Ref<SpatialEditorGizmo>(); + _edit.gizmo = Ref<EditorSpatialGizmo>(); } if (_edit.mode == TRANSFORM_NONE && b->is_pressed()) { @@ -1079,7 +1036,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (can_select_gizmos && spatial_editor->get_selected()) { - Ref<SpatialEditorGizmo> seg = spatial_editor->get_selected()->get_gizmo(); + Ref<EditorSpatialGizmo> seg = spatial_editor->get_selected()->get_gizmo(); if (seg.is_valid()) { int handle = -1; Vector3 point; @@ -1158,7 +1115,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { Spatial *spa = Object::cast_to<Spatial>(ObjectDB::get_instance(clicked)); if (spa) { - Ref<SpatialEditorGizmo> seg = spa->get_gizmo(); + Ref<EditorSpatialGizmo> seg = spa->get_gizmo(); if (seg.is_valid()) { _edit.gizmo = seg; @@ -1175,7 +1132,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (_edit.gizmo.is_valid()) { _edit.gizmo->commit_handle(_edit.gizmo_handle, _edit.gizmo_initial_value, false); - _edit.gizmo = Ref<SpatialEditorGizmo>(); + _edit.gizmo = Ref<EditorSpatialGizmo>(); break; } if (clicked) { @@ -1233,7 +1190,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (spatial_editor->get_selected()) { - Ref<SpatialEditorGizmo> seg = spatial_editor->get_selected()->get_gizmo(); + Ref<EditorSpatialGizmo> seg = spatial_editor->get_selected()->get_gizmo(); if (seg.is_valid()) { int selected_handle = -1; @@ -1928,6 +1885,11 @@ void SpatialEditorViewport::_nav_zoom(Ref<InputEventWithModifiers> p_event, cons void SpatialEditorViewport::_nav_orbit(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative) { + if (lock_rotation) { + _nav_pan(p_event, p_relative); + return; + } + real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity"); real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel); bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y-axis"); @@ -2151,6 +2113,21 @@ void SpatialEditorViewport::_notification(int p_what) { _update_freelook(delta); + Node *scene_root = editor->get_scene_tree_dock()->get_editor_data()->get_edited_scene_root(); + if (previewing_cinema == true && scene_root != NULL) { + Camera *cam = scene_root->get_viewport()->get_camera(); + if (cam != NULL && cam != previewing) { + //then switch the viewport's camera to the scene's viewport camera + if (previewing != NULL) { + previewing->disconnect("tree_exited", this, "_preview_exited_scene"); + } + previewing = cam; + previewing->connect("tree_exited", this, "_preview_exited_scene"); + VS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), cam->get_camera()); + surface->update(); + } + } + _update_camera(delta); Map<Node *, Object *> &selection = editor_selection->get_selection(); @@ -2256,6 +2233,13 @@ void SpatialEditorViewport::_notification(int p_what) { text += TTR("FPS") + ": " + itos(temp_fps) + " (" + String::num(1000.0f / temp_fps, 2) + " ms)"; fps_label->set_text(text); } + + bool show_cinema = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_CINEMATIC_PREVIEW)); + cinema_label->set_visible(show_cinema); + if (show_cinema) { + float cinema_half_width = cinema_label->get_size().width / 2.0f; + cinema_label->set_anchor_and_margin(MARGIN_LEFT, 0.5f, -cinema_half_width); + } } if (p_what == NOTIFICATION_ENTER_TREE) { @@ -2268,6 +2252,7 @@ void SpatialEditorViewport::_notification(int p_what) { surface->connect("focus_exited", this, "_surface_focus_exit"); info_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); fps_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + cinema_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); preview_camera->set_icon(get_icon("Camera", "EditorIcons")); _init_gizmo_instance(index); } @@ -2563,6 +2548,19 @@ void SpatialEditorViewport::_menu_option(int p_option) { _update_name(); } break; + case VIEW_LOCK_ROTATION: { + + int idx = view_menu->get_popup()->get_item_index(VIEW_LOCK_ROTATION); + bool current = view_menu->get_popup()->is_item_checked(idx); + lock_rotation = !current; + view_menu->get_popup()->set_item_checked(idx, !current); + if (lock_rotation) { + view_menu->set_icon(get_icon("Lock", "EditorIcons")); + } else { + view_menu->set_icon(Ref<Texture>()); + } + + } break; case VIEW_AUDIO_LISTENER: { int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER); @@ -2581,6 +2579,22 @@ void SpatialEditorViewport::_menu_option(int p_option) { view_menu->get_popup()->set_item_checked(idx, current); } break; + case VIEW_CINEMATIC_PREVIEW: { + + int idx = view_menu->get_popup()->get_item_index(VIEW_CINEMATIC_PREVIEW); + bool current = view_menu->get_popup()->is_item_checked(idx); + current = !current; + view_menu->get_popup()->set_item_checked(idx, current); + previewing_cinema = true; + _toggle_cinema_preview(current); + + if (current) { + preview_camera->hide(); + } else { + if (previewing != NULL) + preview_camera->show(); + } + } break; case VIEW_GIZMOS: { int idx = view_menu->get_popup()->get_item_index(VIEW_GIZMOS); @@ -2744,6 +2758,25 @@ void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) { } } +void SpatialEditorViewport::_toggle_cinema_preview(bool p_activate) { + previewing_cinema = p_activate; + if (!previewing_cinema) { + if (previewing != NULL) + previewing->disconnect("tree_exited", this, "_preview_exited_scene"); + + previewing = NULL; + VS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), camera->get_camera()); //restore + preview_camera->set_pressed(false); + if (!preview) { + preview_camera->hide(); + } else { + preview_camera->show(); + } + view_menu->show(); + surface->update(); + } +} + void SpatialEditorViewport::_selection_result_pressed(int p_result) { if (selection_results.size() <= p_result) @@ -2768,7 +2801,7 @@ void SpatialEditorViewport::set_can_preview(Camera *p_preview) { preview = p_preview; - if (!preview_camera->is_pressed()) + if (!preview_camera->is_pressed() && !previewing_cinema) preview_camera->set_visible(p_preview); } @@ -2791,7 +2824,7 @@ void SpatialEditorViewport::update_transform_gizmo_view() { dd = 0.0001; float gsize = EditorSettings::get_singleton()->get("editors/3d/manipulator_gizmo_size"); - gizmo_scale = (gsize / Math::abs(dd)); + gizmo_scale = (gsize / Math::abs(dd)) * MAX(1, EDSCALE) / viewport_container->get_stretch_shrink(); Vector3 scale = Vector3(1, 1, 1) * gizmo_scale; xform.basis.scale(scale); @@ -2836,6 +2869,12 @@ void SpatialEditorViewport::set_state(const Dictionary &p_state) { if (!view_menu->get_popup()->is_item_checked(idx)) _menu_option(display); } + if (p_state.has("lock_rotation")) { + lock_rotation = p_state["lock_rotation"]; + + int idx = view_menu->get_popup()->get_item_index(VIEW_LOCK_ROTATION); + view_menu->get_popup()->set_item_checked(idx, lock_rotation); + } if (p_state.has("use_environment")) { bool env = p_state["use_environment"]; @@ -2883,6 +2922,12 @@ void SpatialEditorViewport::set_state(const Dictionary &p_state) { int idx = view_menu->get_popup()->get_item_index(VIEW_HALF_RESOLUTION); view_menu->get_popup()->set_item_checked(idx, half_res); } + if (p_state.has("cinematic_preview")) { + previewing_cinema = p_state["cinematic_preview"]; + + int idx = view_menu->get_popup()->get_item_index(VIEW_CINEMATIC_PREVIEW); + view_menu->get_popup()->set_item_checked(idx, previewing_cinema); + } if (p_state.has("previewing")) { Node *pv = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["previewing"]); @@ -2921,8 +2966,11 @@ Dictionary SpatialEditorViewport::get_state() const { d["information"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_INFORMATION)); d["fps"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_FPS)); d["half_res"] = viewport_container->get_stretch_shrink() > 1; + d["cinematic_preview"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_CINEMATIC_PREVIEW)); if (previewing) d["previewing"] = EditorNode::get_singleton()->get_edited_scene()->get_path_to(previewing); + if (lock_rotation) + d["lock_rotation"] = lock_rotation; return d; } @@ -2951,6 +2999,7 @@ void SpatialEditorViewport::_bind_methods() { void SpatialEditorViewport::reset() { orthogonal = false; + lock_rotation = false; message_time = 0; message = ""; last_message = ""; @@ -3007,7 +3056,7 @@ Vector3 SpatialEditorViewport::_get_instance_position(const Point2 &p_pos) const Vector3 world_pos = _get_ray_pos(p_pos); Vector<ObjectID> instances = VisualServer::get_singleton()->instances_cull_ray(world_pos, world_ray, get_tree()->get_root()->get_world()->get_scenario()); - Set<Ref<SpatialEditorGizmo> > found_gizmos; + Set<Ref<EditorSpatialGizmo> > found_gizmos; float closest_dist = MAX_DISTANCE; @@ -3021,7 +3070,7 @@ Vector3 SpatialEditorViewport::_get_instance_position(const Point2 &p_pos) const if (!mesh_instance) continue; - Ref<SpatialEditorGizmo> seg = mesh_instance->get_gizmo(); + Ref<EditorSpatialGizmo> seg = mesh_instance->get_gizmo(); if ((!seg.is_valid()) || found_gizmos.has(seg)) { continue; @@ -3216,7 +3265,7 @@ void SpatialEditorViewport::_perform_drop_data() { files_str += error_files[i].get_file().get_basename() + ","; } files_str = files_str.substr(0, files_str.length() - 1); - accept->get_ok()->set_text(TTR("Ugh")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.c_str())); accept->popup_centered_minsize(); } @@ -3297,7 +3346,7 @@ void SpatialEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p if (root_node) { list.push_back(root_node); } else { - accept->get_ok()->set_text(TTR("OK :(")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("No parent to instance a child at.")); accept->popup_centered_minsize(); _remove_preview(); @@ -3305,7 +3354,7 @@ void SpatialEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p } } if (list.size() != 1) { - accept->get_ok()->set_text(TTR("I see...")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("This operation requires a single selected node.")); accept->popup_centered_minsize(); _remove_preview(); @@ -3337,6 +3386,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed clicked = 0; clicked_includes_current = false; orthogonal = false; + lock_rotation = false; message_time = 0; zoom_indicator_delay = 0.0; @@ -3377,6 +3427,8 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed view_menu->get_popup()->add_radio_check_item(TTR("Orthogonal") + " (" + ED_GET_SHORTCUT("spatial_editor/switch_perspective_orthogonal")->get_as_text() + ")", VIEW_ORTHOGONAL); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_PERSPECTIVE), true); view_menu->get_popup()->add_separator(); + view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_lock_rotation", TTR("Lock View Rotation")), VIEW_LOCK_ROTATION); + view_menu->get_popup()->add_separator(); view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_normal", TTR("Display Normal")), VIEW_DISPLAY_NORMAL); view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_wireframe", TTR("Display Wireframe")), VIEW_DISPLAY_WIREFRAME); view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_overdraw", TTR("Display Overdraw")), VIEW_DISPLAY_OVERDRAW); @@ -3396,6 +3448,9 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_GIZMOS), true); view_menu->get_popup()->add_separator(); + view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_cinematic_preview", TTR("Cinematic Preview")), VIEW_CINEMATIC_PREVIEW); + + view_menu->get_popup()->add_separator(); view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/focus_origin"), VIEW_CENTER_TO_ORIGIN); view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/focus_selection"), VIEW_CENTER_TO_SELECTION); view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/align_selection_with_view"), VIEW_ALIGN_SELECTION_WITH_VIEW); @@ -3445,6 +3500,15 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed surface->add_child(fps_label); fps_label->hide(); + cinema_label = memnew(Label); + cinema_label->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 10 * EDSCALE); + cinema_label->set_h_grow_direction(GROW_DIRECTION_END); + cinema_label->set_align(Label::ALIGN_CENTER); + surface->add_child(cinema_label); + cinema_label->set_text(TTR("Cinematic Preview")); + cinema_label->hide(); + previewing_cinema = false; + accept = NULL; freelook_active = false; @@ -3786,10 +3850,6 @@ void SpatialEditor::select_gizmo_highlight_axis(int p_axis) { } } -int SpatialEditor::get_skeleton_visibility_state() const { - return view_menu->get_popup()->get_item_state(view_menu->get_popup()->get_item_index(MENU_VISIBILITY_SKELETON)); -} - void SpatialEditor::update_transform_gizmo() { List<Node *> &selection = editor_selection->get_selected_node_list(); @@ -3942,6 +4002,16 @@ Dictionary SpatialEditor::get_state() const { d["znear"] = get_znear(); d["zfar"] = get_zfar(); + Dictionary gizmos_status; + for (int i = 0; i < gizmo_plugins.size(); i++) { + if (!gizmo_plugins[i]->can_be_hidden()) continue; + int state = gizmos_menu->get_item_state(gizmos_menu->get_item_index(i)); + String name = gizmo_plugins[i]->get_name(); + gizmos_status[name] = state; + } + + d["gizmos_status"] = gizmos_status; + return d; } void SpatialEditor::set_state(const Dictionary &p_state) { @@ -4015,6 +4085,39 @@ void SpatialEditor::set_state(const Dictionary &p_state) { VisualServer::get_singleton()->instance_set_visible(origin_instance, use); } } + + if (d.has("gizmos_status")) { + Dictionary gizmos_status = d["gizmos_status"]; + List<Variant> keys; + gizmos_status.get_key_list(&keys); + + for (int j = 0; j < gizmo_plugins.size(); ++j) { + if (!gizmo_plugins[j]->can_be_hidden()) continue; + int state = EditorSpatialGizmoPlugin::ON_TOP; + for (uint32_t i = 0; i < keys.size(); i++) { + if (gizmo_plugins.write[j]->get_name() == keys[i]) { + state = gizmos_status[keys[i]]; + } + } + + const int idx = gizmos_menu->get_item_index(j); + + gizmos_menu->set_item_multistate(idx, state); + gizmo_plugins.write[j]->set_state(state); + + switch (state) { + case EditorSpatialGizmoPlugin::ON_TOP: + gizmos_menu->set_item_icon(idx, gizmos_menu->get_icon("visibility_visible")); + break; + case EditorSpatialGizmoPlugin::VISIBLE: + gizmos_menu->set_item_icon(idx, gizmos_menu->get_icon("visibility_xray")); + break; + case EditorSpatialGizmoPlugin::HIDDEN: + gizmos_menu->set_item_icon(idx, gizmos_menu->get_icon("visibility_hidden")); + break; + } + } + } } void SpatialEditor::edit(Spatial *p_spatial) { @@ -4022,7 +4125,7 @@ void SpatialEditor::edit(Spatial *p_spatial) { if (p_spatial != selected) { if (selected) { - Ref<SpatialEditorGizmo> seg = selected->get_gizmo(); + Ref<EditorSpatialGizmo> seg = selected->get_gizmo(); if (seg.is_valid()) { seg->set_selected(false); selected->update_gizmo(); @@ -4034,7 +4137,7 @@ void SpatialEditor::edit(Spatial *p_spatial) { if (selected) { - Ref<SpatialEditorGizmo> seg = selected->get_gizmo(); + Ref<EditorSpatialGizmo> seg = selected->get_gizmo(); if (seg.is_valid()) { seg->set_selected(true); selected->update_gizmo(); @@ -4108,6 +4211,30 @@ void SpatialEditor::_menu_item_toggled(bool pressed, int p_option) { } } +void SpatialEditor::_menu_gizmo_toggled(int p_option) { + + const int idx = gizmos_menu->get_item_index(p_option); + gizmos_menu->toggle_item_multistate(idx); + + // Change icon + const int state = gizmos_menu->get_item_state(idx); + switch (state) { + case EditorSpatialGizmoPlugin::ON_TOP: + gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_visible")); + break; + case EditorSpatialGizmoPlugin::VISIBLE: + gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_xray")); + break; + case EditorSpatialGizmoPlugin::HIDDEN: + gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_hidden")); + break; + } + + gizmo_plugins.write[p_option]->set_state(state); + + update_all_gizmos(); +} + void SpatialEditor::_menu_item_pressed(int p_option) { switch (p_option) { @@ -4241,6 +4368,9 @@ void SpatialEditor::_menu_item_pressed(int p_option) { settings_dialog->popup_centered(settings_vbc->get_combined_minimum_size() + Size2(50, 50)); } break; + case MENU_SNAP_TO_FLOOR: { + snap_selected_nodes_to_floor(); + } break; case MENU_LOCK_SELECTED: { List<Node *> &selection = editor_selection->get_selected_node_list(); @@ -4279,28 +4409,6 @@ void SpatialEditor::_menu_item_pressed(int p_option) { _refresh_menu_icons(); } break; - case MENU_VISIBILITY_SKELETON: { - - const int idx = view_menu->get_popup()->get_item_index(MENU_VISIBILITY_SKELETON); - view_menu->get_popup()->toggle_item_multistate(idx); - - // Change icon - const int state = view_menu->get_popup()->get_item_state(idx); - switch (state) { - case 0: - view_menu->get_popup()->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_hidden")); - break; - case 1: - view_menu->get_popup()->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_visible")); - break; - case 2: - view_menu->get_popup()->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_xray")); - break; - } - - update_all_gizmos(); - - } break; } } @@ -4410,9 +4518,9 @@ void SpatialEditor::_init_indicators() { nivec * 0.0 + ivec * (GIZMO_ARROW_OFFSET + GIZMO_ARROW_SIZE), }; - int arrow_sides = 6; + int arrow_sides = 16; - for (int k = 0; k < 6; k++) { + for (int k = 0; k < arrow_sides; k++) { Basis ma(ivec, Math_PI * 2 * float(k) / arrow_sides); Basis mb(ivec, Math_PI * 2 * float(k + 1) / arrow_sides); @@ -4496,10 +4604,10 @@ void SpatialEditor::_init_indicators() { ivec * 0.02 + ivec2 * 0.02 + ivec2 * GIZMO_CIRCLE_SIZE, }; - for (int k = 0; k < 32; k++) { + for (int k = 0; k < 64; k++) { - Basis ma(ivec, Math_PI * 2 * float(k) / 32); - Basis mb(ivec, Math_PI * 2 * float(k + 1) / 32); + Basis ma(ivec, Math_PI * 2 * float(k) / 64); + Basis mb(ivec, Math_PI * 2 * float(k + 1) / 64); for (int j = 0; j < 4; j++) { @@ -4616,6 +4724,26 @@ void SpatialEditor::_init_indicators() { _generate_selection_box(); } +struct _GizmoPluginComparator { + + bool operator()(const Ref<EditorSpatialGizmoPlugin> &p_a, const Ref<EditorSpatialGizmoPlugin> &p_b) const { + return p_a->get_name() < p_b->get_name(); + } +}; + +void SpatialEditor::_init_gizmos_menu() { + _register_all_gizmos(); + + gizmo_plugins.sort_custom<_GizmoPluginComparator>(); + + for (int i = 0; i < gizmo_plugins.size(); ++i) { + if (!gizmo_plugins[i]->can_be_hidden()) continue; + String plugin_name = gizmo_plugins[i]->get_name(); + gizmos_menu->add_multistate_item(TTR(plugin_name), 3, EditorSpatialGizmoPlugin::ON_TOP, i); + gizmos_menu->set_item_icon(gizmos_menu->get_item_index(i), gizmos_menu->get_icon("visibility_visible")); + } +} + void SpatialEditor::_init_grid() { PoolVector<Color> grid_colors[3]; @@ -4716,6 +4844,119 @@ void SpatialEditor::_refresh_menu_icons() { tool_button[TOOL_UNLOCK_SELECTED]->set_visible(all_locked); } +template <typename T> +Set<T *> _get_child_nodes(Node *parent_node) { + Set<T *> nodes = Set<T *>(); + T *node = Node::cast_to<T>(parent_node); + if (node) { + nodes.insert(node); + } + + for (int i = 0; i < parent_node->get_child_count(); i++) { + Node *child_node = parent_node->get_child(i); + Set<T *> child_nodes = _get_child_nodes<T>(child_node); + for (typename Set<T *>::Element *I = child_nodes.front(); I; I = I->next()) { + nodes.insert(I->get()); + } + } + + return nodes; +} + +Set<RID> _get_physics_bodies_rid(Node *node) { + Set<RID> rids = Set<RID>(); + PhysicsBody *pb = Node::cast_to<PhysicsBody>(node); + if (pb) { + rids.insert(pb->get_rid()); + } + Set<PhysicsBody *> child_nodes = _get_child_nodes<PhysicsBody>(node); + for (Set<PhysicsBody *>::Element *I = child_nodes.front(); I; I = I->next()) { + rids.insert(I->get()->get_rid()); + } + + return rids; +} + +void SpatialEditor::snap_selected_nodes_to_floor() { + List<Node *> &selection = editor_selection->get_selected_node_list(); + Dictionary snap_data; + + for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { + Spatial *sp = Object::cast_to<Spatial>(E->get()); + if (sp) { + Vector3 from = Vector3(); + Vector3 position_offset = Vector3(); + + // Priorities for snapping to floor are CollisionShapes, VisualInstances and then origin + Set<VisualInstance *> vi = _get_child_nodes<VisualInstance>(sp); + Set<CollisionShape *> cs = _get_child_nodes<CollisionShape>(sp); + + if (cs.size()) { + AABB aabb = sp->get_global_transform().xform(cs.front()->get()->get_shape()->get_debug_mesh()->get_aabb()); + for (Set<CollisionShape *>::Element *I = cs.front(); I; I = I->next()) { + aabb.merge_with(sp->get_global_transform().xform(I->get()->get_shape()->get_debug_mesh()->get_aabb())); + } + Vector3 size = aabb.size * Vector3(0.5, 0.0, 0.5); + from = aabb.position + size; + position_offset.y = from.y - sp->get_global_transform().origin.y; + } else if (vi.size()) { + AABB aabb = vi.front()->get()->get_transformed_aabb(); + for (Set<VisualInstance *>::Element *I = vi.front(); I; I = I->next()) { + aabb.merge_with(I->get()->get_transformed_aabb()); + } + Vector3 size = aabb.size * Vector3(0.5, 0.0, 0.5); + from = aabb.position + size; + position_offset.y = from.y - sp->get_global_transform().origin.y; + } else { + from = sp->get_global_transform().origin; + } + + // We add a bit of margin to the from position to avoid it from snapping + // when the spatial is already on a floor and there's another floor under + // it + from = from + Vector3(0.0, 0.1, 0.0); + + Dictionary d; + + d["from"] = from; + d["position_offset"] = position_offset; + snap_data[sp] = d; + } + } + + PhysicsDirectSpaceState *ss = get_tree()->get_root()->get_world()->get_direct_space_state(); + PhysicsDirectSpaceState::RayResult result; + + Array keys = snap_data.keys(); + + if (keys.size()) { + undo_redo->create_action("Snap Nodes To Floor"); + + for (int i = 0; i < keys.size(); i++) { + Node *node = keys[i]; + Spatial *sp = Object::cast_to<Spatial>(node); + + Dictionary d = snap_data[node]; + Vector3 from = d["from"]; + Vector3 position_offset = d["position_offset"]; + + Vector3 to = from - Vector3(0.0, 10.0, 0.0); + Set<RID> excluded = _get_physics_bodies_rid(sp); + + if (ss->intersect_ray(from, to, result, excluded)) { + Transform new_transform = sp->get_global_transform(); + new_transform.origin.y = result.position.y; + new_transform.origin = new_transform.origin - position_offset; + + undo_redo->add_do_method(sp, "set_global_transform", new_transform); + undo_redo->add_undo_method(sp, "set_global_transform", sp->get_global_transform()); + } + } + + undo_redo->commit_action(); + } +} + void SpatialEditor::_unhandled_key_input(Ref<InputEvent> p_event) { if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack()) @@ -4744,6 +4985,8 @@ void SpatialEditor::_unhandled_key_input(Ref<InputEvent> p_event) { else if (ED_IS_SHORTCUT("spatial_editor/tool_scale", p_event)) _menu_item_pressed(MENU_TOOL_SCALE); + else if (ED_IS_SHORTCUT("spatial_editor/snap_to_floor", p_event)) + snap_selected_nodes_to_floor(); else if (ED_IS_SHORTCUT("spatial_editor/local_coords", p_event)) if (are_local_coords_enabled()) { @@ -4781,7 +5024,6 @@ void SpatialEditor::_notification(int p_what) { view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), get_icon("Panels3", "EditorIcons")); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_icon("Panels3Alt", "EditorIcons")); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_icon("Panels4", "EditorIcons")); - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VISIBILITY_SKELETON), view_menu->get_popup()->get_icon("visibility_visible")); _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT); @@ -4794,14 +5036,13 @@ void SpatialEditor::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { - gizmos = memnew(SpatialEditorGizmos); + _init_gizmos_menu(); _init_indicators(); } if (p_what == NOTIFICATION_EXIT_TREE) { _finish_indicators(); - memdelete(gizmos); } if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { tool_button[SpatialEditor::TOOL_MODE_SELECT]->set_icon(get_icon("ToolSelect", "EditorIcons")); @@ -4860,25 +5101,21 @@ void SpatialEditor::_request_gizmo(Object *p_obj) { return; if (editor->get_edited_scene() && (sp == editor->get_edited_scene() || (sp->get_owner() && editor->get_edited_scene()->is_a_parent_of(sp)))) { - Ref<SpatialEditorGizmo> seg; + Ref<EditorSpatialGizmo> seg; - for (int i = 0; i < EditorNode::get_singleton()->get_editor_data().get_editor_plugin_count(); i++) { + for (int i = 0; i < gizmo_plugins.size(); ++i) { + seg = gizmo_plugins.write[i]->get_gizmo(sp); - seg = EditorNode::get_singleton()->get_editor_data().get_editor_plugin(i)->create_spatial_gizmo(sp); - if (seg.is_valid()) - break; - } + if (seg.is_valid()) { + sp->set_gizmo(seg); - if (!seg.is_valid()) { - seg = gizmos->get_gizmo(sp); - } - if (seg.is_valid()) { - sp->set_gizmo(seg); - } + if (sp == selected) { + seg->set_selected(true); + selected->update_gizmo(); + } - if (seg.is_valid() && sp == selected) { - seg->set_selected(true); - selected->update_gizmo(); + break; + } } } } @@ -4934,11 +5171,35 @@ void SpatialEditor::_node_removed(Node *p_node) { selected = NULL; } +void SpatialEditor::_register_all_gizmos() { + register_gizmo_plugin(Ref<CameraSpatialGizmoPlugin>(memnew(CameraSpatialGizmoPlugin))); + register_gizmo_plugin(Ref<LightSpatialGizmoPlugin>(memnew(LightSpatialGizmoPlugin))); + register_gizmo_plugin(Ref<AudioStreamPlayer3DSpatialGizmoPlugin>(memnew(AudioStreamPlayer3DSpatialGizmoPlugin))); + register_gizmo_plugin(Ref<MeshInstanceSpatialGizmoPlugin>(memnew(MeshInstanceSpatialGizmoPlugin))); + register_gizmo_plugin(Ref<SoftBodySpatialGizmoPlugin>(memnew(SoftBodySpatialGizmoPlugin))); + register_gizmo_plugin(Ref<Sprite3DSpatialGizmoPlugin>(memnew(Sprite3DSpatialGizmoPlugin))); + register_gizmo_plugin(Ref<Position3DSpatialGizmoPlugin>(memnew(Position3DSpatialGizmoPlugin))); + register_gizmo_plugin(Ref<SkeletonSpatialGizmoPlugin>(memnew(SkeletonSpatialGizmoPlugin))); + register_gizmo_plugin(Ref<RayCastSpatialGizmoPlugin>(memnew(RayCastSpatialGizmoPlugin))); + register_gizmo_plugin(Ref<VehicleWheelSpatialGizmoPlugin>(memnew(VehicleWheelSpatialGizmoPlugin))); + register_gizmo_plugin(Ref<VisibilityNotifierGizmoPlugin>(memnew(VisibilityNotifierGizmoPlugin))); + register_gizmo_plugin(Ref<ParticlesGizmoPlugin>(memnew(ParticlesGizmoPlugin))); + register_gizmo_plugin(Ref<ReflectionProbeGizmoPlugin>(memnew(ReflectionProbeGizmoPlugin))); + register_gizmo_plugin(Ref<GIProbeGizmoPlugin>(memnew(GIProbeGizmoPlugin))); + register_gizmo_plugin(Ref<BakedIndirectLightGizmoPlugin>(memnew(BakedIndirectLightGizmoPlugin))); + register_gizmo_plugin(Ref<CollisionShapeSpatialGizmoPlugin>(memnew(CollisionShapeSpatialGizmoPlugin))); + register_gizmo_plugin(Ref<CollisionPolygonSpatialGizmoPlugin>(memnew(CollisionPolygonSpatialGizmoPlugin))); + register_gizmo_plugin(Ref<NavigationMeshSpatialGizmoPlugin>(memnew(NavigationMeshSpatialGizmoPlugin))); + register_gizmo_plugin(Ref<JointSpatialGizmoPlugin>(memnew(JointSpatialGizmoPlugin))); + register_gizmo_plugin(Ref<PhysicalBoneSpatialGizmoPlugin>(memnew(PhysicalBoneSpatialGizmoPlugin))); +} + void SpatialEditor::_bind_methods() { ClassDB::bind_method("_unhandled_key_input", &SpatialEditor::_unhandled_key_input); ClassDB::bind_method("_node_removed", &SpatialEditor::_node_removed); ClassDB::bind_method("_menu_item_pressed", &SpatialEditor::_menu_item_pressed); + ClassDB::bind_method("_menu_gizmo_toggled", &SpatialEditor::_menu_gizmo_toggled); ClassDB::bind_method("_menu_item_toggled", &SpatialEditor::_menu_item_toggled); ClassDB::bind_method("_xform_dialog_action", &SpatialEditor::_xform_dialog_action); ClassDB::bind_method("_get_editor_data", &SpatialEditor::_get_editor_data); @@ -5009,7 +5270,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_SELECT]->set_toggle_mode(true); tool_button[TOOL_MODE_SELECT]->set_flat(true); tool_button[TOOL_MODE_SELECT]->set_pressed(true); - button_binds[0] = MENU_TOOL_SELECT; + button_binds.write[0] = MENU_TOOL_SELECT; tool_button[TOOL_MODE_SELECT]->connect("pressed", this, "_menu_item_pressed", button_binds); tool_button[TOOL_MODE_SELECT]->set_tooltip(TTR("Select Mode (Q)") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate\nAlt+Drag: Move\nAlt+RMB: Depth list selection")); @@ -5017,7 +5278,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { hbc_menu->add_child(tool_button[TOOL_MODE_MOVE]); tool_button[TOOL_MODE_MOVE]->set_toggle_mode(true); tool_button[TOOL_MODE_MOVE]->set_flat(true); - button_binds[0] = MENU_TOOL_MOVE; + button_binds.write[0] = MENU_TOOL_MOVE; tool_button[TOOL_MODE_MOVE]->connect("pressed", this, "_menu_item_pressed", button_binds); tool_button[TOOL_MODE_MOVE]->set_tooltip(TTR("Move Mode (W)")); @@ -5025,7 +5286,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { hbc_menu->add_child(tool_button[TOOL_MODE_ROTATE]); tool_button[TOOL_MODE_ROTATE]->set_toggle_mode(true); tool_button[TOOL_MODE_ROTATE]->set_flat(true); - button_binds[0] = MENU_TOOL_ROTATE; + button_binds.write[0] = MENU_TOOL_ROTATE; tool_button[TOOL_MODE_ROTATE]->connect("pressed", this, "_menu_item_pressed", button_binds); tool_button[TOOL_MODE_ROTATE]->set_tooltip(TTR("Rotate Mode (E)")); @@ -5033,7 +5294,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { hbc_menu->add_child(tool_button[TOOL_MODE_SCALE]); tool_button[TOOL_MODE_SCALE]->set_toggle_mode(true); tool_button[TOOL_MODE_SCALE]->set_flat(true); - button_binds[0] = MENU_TOOL_SCALE; + button_binds.write[0] = MENU_TOOL_SCALE; tool_button[TOOL_MODE_SCALE]->connect("pressed", this, "_menu_item_pressed", button_binds); tool_button[TOOL_MODE_SCALE]->set_tooltip(TTR("Scale Mode (R)")); @@ -5041,19 +5302,19 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { hbc_menu->add_child(tool_button[TOOL_MODE_LIST_SELECT]); tool_button[TOOL_MODE_LIST_SELECT]->set_toggle_mode(true); tool_button[TOOL_MODE_LIST_SELECT]->set_flat(true); - button_binds[0] = MENU_TOOL_LIST_SELECT; + button_binds.write[0] = MENU_TOOL_LIST_SELECT; tool_button[TOOL_MODE_LIST_SELECT]->connect("pressed", this, "_menu_item_pressed", button_binds); tool_button[TOOL_MODE_LIST_SELECT]->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode).")); tool_button[TOOL_LOCK_SELECTED] = memnew(ToolButton); hbc_menu->add_child(tool_button[TOOL_LOCK_SELECTED]); - button_binds[0] = MENU_LOCK_SELECTED; + button_binds.write[0] = MENU_LOCK_SELECTED; tool_button[TOOL_LOCK_SELECTED]->connect("pressed", this, "_menu_item_pressed", button_binds); tool_button[TOOL_LOCK_SELECTED]->set_tooltip(TTR("Lock the selected object in place (can't be moved).")); tool_button[TOOL_UNLOCK_SELECTED] = memnew(ToolButton); hbc_menu->add_child(tool_button[TOOL_UNLOCK_SELECTED]); - button_binds[0] = MENU_UNLOCK_SELECTED; + button_binds.write[0] = MENU_UNLOCK_SELECTED; tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", this, "_menu_item_pressed", button_binds); tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip(TTR("Unlock the selected object (can be moved).")); @@ -5064,7 +5325,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { hbc_menu->add_child(tool_option_button[TOOL_OPT_LOCAL_COORDS]); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_toggle_mode(true); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_flat(true); - button_binds[0] = MENU_TOOL_LOCAL_COORDS; + button_binds.write[0] = MENU_TOOL_LOCAL_COORDS; tool_option_button[TOOL_OPT_LOCAL_COORDS]->connect("toggled", this, "_menu_item_toggled", button_binds); ED_SHORTCUT("spatial_editor/local_coords", TTR("Local Coords"), KEY_T); sct = ED_GET_SHORTCUT("spatial_editor/local_coords").ptr()->get_as_text(); @@ -5074,7 +5335,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { hbc_menu->add_child(tool_option_button[TOOL_OPT_USE_SNAP]); tool_option_button[TOOL_OPT_USE_SNAP]->set_toggle_mode(true); tool_option_button[TOOL_OPT_USE_SNAP]->set_flat(true); - button_binds[0] = MENU_TOOL_USE_SNAP; + button_binds.write[0] = MENU_TOOL_USE_SNAP; tool_option_button[TOOL_OPT_USE_SNAP]->connect("toggled", this, "_menu_item_toggled", button_binds); ED_SHORTCUT("spatial_editor/snap", TTR("Snap"), KEY_Y); sct = ED_GET_SHORTCUT("spatial_editor/snap").ptr()->get_as_text(); @@ -5103,6 +5364,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { ED_SHORTCUT("spatial_editor/tool_move", TTR("Tool Move"), KEY_W); ED_SHORTCUT("spatial_editor/tool_rotate", TTR("Tool Rotate"), KEY_E); ED_SHORTCUT("spatial_editor/tool_scale", TTR("Tool Scale"), KEY_R); + ED_SHORTCUT("spatial_editor/snap_to_floor", TTR("Snap To Floor"), KEY_PAGEDOWN); ED_SHORTCUT("spatial_editor/freelook_toggle", TTR("Toggle Freelook"), KEY_MASK_SHIFT + KEY_F); @@ -5113,6 +5375,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { hbc_menu->add_child(transform_menu); p = transform_menu->get_popup(); + p->add_shortcut(ED_SHORTCUT("spatial_editor/snap_to_floor", TTR("Snap object to floor")), MENU_SNAP_TO_FLOOR); p->add_shortcut(ED_SHORTCUT("spatial_editor/configure_snap", TTR("Configure Snap...")), MENU_TRANSFORM_CONFIGURE_SNAP); p->add_separator(); p->add_shortcut(ED_SHORTCUT("spatial_editor/transform_dialog", TTR("Transform Dialog...")), MENU_TRANSFORM_DIALOG); @@ -5137,19 +5400,26 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/4_viewports", TTR("4 Viewports"), KEY_MASK_CMD + KEY_4), MENU_VIEW_USE_4_VIEWPORTS); p->add_separator(); + p->add_submenu_item(TTR("Gizmos"), "GizmosMenu"); + + p->add_separator(); + p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_origin", TTR("View Origin")), MENU_VIEW_ORIGIN); p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_grid", TTR("View Grid")), MENU_VIEW_GRID); p->add_separator(); p->add_shortcut(ED_SHORTCUT("spatial_editor/settings", TTR("Settings")), MENU_VIEW_CAMERA_SETTINGS); - p->add_separator(); - p->add_multistate_item(TTR("Skeleton Gizmo visibility"), 3, 1, MENU_VISIBILITY_SKELETON); - p->set_item_checked(p->get_item_index(MENU_VIEW_ORIGIN), true); p->set_item_checked(p->get_item_index(MENU_VIEW_GRID), true); p->connect("id_pressed", this, "_menu_item_pressed"); + gizmos_menu = memnew(PopupMenu); + p->add_child(gizmos_menu); + gizmos_menu->set_name("GizmosMenu"); + gizmos_menu->set_hide_on_checkable_item_selection(false); + gizmos_menu->connect("id_pressed", this, "_menu_gizmo_toggled"); + /* REST OF MENU */ palette_split = memnew(HSplitContainer); @@ -5357,6 +5627,10 @@ void SpatialEditorPlugin::snap_cursor_to_plane(const Plane &p_plane) { spatial_editor->snap_cursor_to_plane(p_plane); } +void SpatialEditor::register_gizmo_plugin(Ref<EditorSpatialGizmoPlugin> ref) { + gizmo_plugins.push_back(ref); +} + SpatialEditorPlugin::SpatialEditorPlugin(EditorNode *p_node) { editor = p_node; @@ -5370,3 +5644,182 @@ SpatialEditorPlugin::SpatialEditorPlugin(EditorNode *p_node) { SpatialEditorPlugin::~SpatialEditorPlugin() { } + +void EditorSpatialGizmoPlugin::create_material(const String &p_name, const Color &p_color, bool p_billboard, bool p_on_top, bool p_use_vertex_color) { + + Color instanced_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/instanced"); + + Vector<Ref<SpatialMaterial> > mats; + + for (int i = 0; i < 4; i++) { + bool selected = i % 2 == 1; + bool instanced = i < 2; + + Ref<SpatialMaterial> material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + + Color color = instanced ? instanced_color : p_color; + + if (!selected) { + color.a *= 0.3; + } + + material->set_albedo(color); + material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + material->set_render_priority(SpatialMaterial::RENDER_PRIORITY_MIN + 1); + + if (p_use_vertex_color) { + material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + } + + if (p_billboard) { + material->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); + } + + if (p_on_top && selected) { + material->set_on_top_of_alpha(); + } + + mats.push_back(material); + } + + materials[p_name] = mats; +} + +void EditorSpatialGizmoPlugin::create_icon_material(const String &p_name, const Ref<Texture> &p_texture, bool p_on_top, const Color &p_albedo) { + + Color instanced_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/instanced"); + + Vector<Ref<SpatialMaterial> > icons; + + for (int i = 0; i < 4; i++) { + bool selected = i % 2 == 1; + bool instanced = i < 2; + + Ref<SpatialMaterial> icon = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + + Color color = instanced ? instanced_color : p_albedo; + + if (!selected) { + color.a *= 0.3; + } + + icon->set_albedo(color); + + icon->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + icon->set_cull_mode(SpatialMaterial::CULL_DISABLED); + icon->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_DISABLED); + icon->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + icon->set_texture(SpatialMaterial::TEXTURE_ALBEDO, p_texture); + icon->set_flag(SpatialMaterial::FLAG_FIXED_SIZE, true); + icon->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); + icon->set_render_priority(SpatialMaterial::RENDER_PRIORITY_MIN); + + if (p_on_top && selected) { + icon->set_on_top_of_alpha(); + } + + icons.push_back(icon); + } + + materials[p_name] = icons; +} + +void EditorSpatialGizmoPlugin::create_handle_material(const String &p_name, bool p_billboard) { + Ref<SpatialMaterial> handle_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + + handle_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + handle_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + handle_material->set_flag(SpatialMaterial::FLAG_USE_POINT_SIZE, true); + Ref<Texture> handle_t = SpatialEditor::get_singleton()->get_icon("Editor3DHandle", "EditorIcons"); + handle_material->set_point_size(handle_t->get_width()); + handle_material->set_texture(SpatialMaterial::TEXTURE_ALBEDO, handle_t); + handle_material->set_albedo(Color(1, 1, 1)); + handle_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + handle_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + handle_material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + handle_material->set_on_top_of_alpha(); + if (p_billboard) { + handle_material->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); + handle_material->set_on_top_of_alpha(); + } + + materials[p_name] = Vector<Ref<SpatialMaterial> >(); + materials[p_name].push_back(handle_material); +} + +void EditorSpatialGizmoPlugin::add_material(const String &p_name, Ref<SpatialMaterial> p_material) { + materials[p_name] = Vector<Ref<SpatialMaterial> >(); + materials[p_name].push_back(p_material); +} + +Ref<SpatialMaterial> EditorSpatialGizmoPlugin::get_material(const String &p_name, EditorSpatialGizmo *p_gizmo) { + ERR_FAIL_COND_V(!materials.has(p_name), Ref<SpatialMaterial>()); + ERR_FAIL_COND_V(materials[p_name].size() == 0, Ref<SpatialMaterial>()); + + if (p_gizmo == NULL) return materials[p_name][0]; + + int index = (p_gizmo->is_selected() ? 1 : 0) + (p_gizmo->is_editable() ? 2 : 0); + + Ref<SpatialMaterial> mat = materials[p_name][index]; + + if (current_state == ON_TOP && p_gizmo->is_selected()) { + mat->set_flag(SpatialMaterial::FLAG_DISABLE_DEPTH_TEST, true); + } else { + mat->set_flag(SpatialMaterial::FLAG_DISABLE_DEPTH_TEST, false); + } + + return mat; +} + +Ref<EditorSpatialGizmo> EditorSpatialGizmoPlugin::get_gizmo(Spatial *p_spatial) { + + Ref<EditorSpatialGizmo> ref = create_gizmo(p_spatial); + + if (ref.is_null()) return ref; + + ref->set_plugin(this); + ref->set_spatial_node(p_spatial); + ref->set_hidden(current_state == HIDDEN); + + current_gizmos.push_back(ref.ptr()); + return ref; +} + +bool EditorSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return false; +} + +Ref<EditorSpatialGizmo> EditorSpatialGizmoPlugin::create_gizmo(Spatial *p_spatial) { + + Ref<EditorSpatialGizmo> ref; + if (has_gizmo(p_spatial)) ref.instance(); + return ref; +} + +bool EditorSpatialGizmoPlugin::can_be_hidden() const { + return true; +} + +bool EditorSpatialGizmoPlugin::is_selectable_when_hidden() const { + return false; +} + +void EditorSpatialGizmoPlugin::set_state(int p_state) { + current_state = p_state; + for (int i = 0; i < current_gizmos.size(); ++i) { + current_gizmos[i]->set_hidden(current_state == HIDDEN); + } +} + +void EditorSpatialGizmoPlugin::unregister_gizmo(EditorSpatialGizmo *p_gizmo) { + current_gizmos.erase(p_gizmo); +} + +EditorSpatialGizmoPlugin::EditorSpatialGizmoPlugin() { + current_state = ON_TOP; +} + +EditorSpatialGizmoPlugin::~EditorSpatialGizmoPlugin() { +} diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index af882f6e05..0ebc11e5df 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -43,11 +43,11 @@ class Camera; class SpatialEditor; -class SpatialEditorGizmos; +class EditorSpatialGizmoPlugin; -class SpatialEditorGizmo : public SpatialGizmo { +class EditorSpatialGizmo : public SpatialGizmo { - GDCLASS(SpatialEditorGizmo, SpatialGizmo); + GDCLASS(EditorSpatialGizmo, SpatialGizmo); bool selected; bool instanced; @@ -56,15 +56,86 @@ public: void set_selected(bool p_selected) { selected = p_selected; } bool is_selected() const { return selected; } + struct Instance { + + RID instance; + Ref<ArrayMesh> mesh; + RID skeleton; + bool billboard; + bool unscaled; + bool can_intersect; + bool extra_margin; + Instance() { + + billboard = false; + unscaled = false; + can_intersect = false; + extra_margin = false; + } + + void create_instance(Spatial *p_base, bool p_hidden = false); + }; + + Vector<Vector3> collision_segments; + Ref<TriangleMesh> collision_mesh; + + struct Handle { + Vector3 pos; + bool billboard; + }; + + Vector<Vector3> handles; + Vector<Vector3> secondary_handles; + float selectable_icon_size = -1.0f; + bool billboard_handle; + + bool valid; + bool hidden; + Spatial *base; + Vector<Instance> instances; + Spatial *spatial_node; + EditorSpatialGizmoPlugin *gizmo_plugin; + + void _set_spatial_node(Node *p_node) { set_spatial_node(Object::cast_to<Spatial>(p_node)); } + +protected: + static void _bind_methods(); + +public: + void add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard = false); + void add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard = false, const RID &p_skeleton = RID()); + void add_collision_segments(const Vector<Vector3> &p_lines); + void add_collision_triangles(const Ref<TriangleMesh> &p_tmesh); + void add_unscaled_billboard(const Ref<Material> &p_material, float p_scale = 1); + void add_handles(const Vector<Vector3> &p_handles, const Ref<Material> &p_material, bool p_billboard = false, bool p_secondary = false); + void add_solid_box(Ref<Material> &p_material, Vector3 p_size, Vector3 p_position = Vector3()); + virtual String get_handle_name(int p_idx) const; - virtual Variant get_handle_value(int p_idx) const; + virtual Variant get_handle_value(int p_idx); virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); - virtual bool is_gizmo_handle_highlighted(int idx) const { return false; } - virtual bool intersect_frustum(const Camera *p_camera, const Vector<Plane> &p_frustum); - virtual bool intersect_ray(Camera *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle = NULL, bool p_sec_first = false); - SpatialEditorGizmo(); + void set_spatial_node(Spatial *p_node); + Spatial *get_spatial_node() const { return spatial_node; } + Vector3 get_handle_pos(int p_idx) const; + bool intersect_frustum(const Camera *p_camera, const Vector<Plane> &p_frustum); + bool intersect_ray(Camera *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle = NULL, bool p_sec_first = false); + + virtual void clear(); + virtual void create(); + virtual void transform(); + virtual void redraw(); + virtual void free(); + + //TODO remove (?) + virtual bool is_editable() const; + virtual bool can_draw() const; + + void set_hidden(bool p_hidden); + void set_plugin(EditorSpatialGizmoPlugin *p_gizmo); + + EditorSpatialGizmo(); + ~EditorSpatialGizmo(); }; class SpatialEditorViewport : public Control { @@ -94,7 +165,9 @@ class SpatialEditorViewport : public Control { VIEW_DISPLAY_NORMAL, VIEW_DISPLAY_WIREFRAME, VIEW_DISPLAY_OVERDRAW, - VIEW_DISPLAY_SHADELESS + VIEW_DISPLAY_SHADELESS, + VIEW_LOCK_ROTATION, + VIEW_CINEMATIC_PREVIEW }; public: @@ -108,7 +181,6 @@ private: int index; String name; void _menu_option(int p_option); - Spatial *preview_node; AABB *preview_bounds; Vector<String> selected_files; @@ -132,6 +204,7 @@ private: Camera *camera; bool transforming; bool orthogonal; + bool lock_rotation; float gizmo_scale; bool freelook_active; @@ -139,6 +212,7 @@ private: Label *info_label; Label *fps_label; + Label *cinema_label; struct _RayResult { @@ -230,7 +304,7 @@ private: int edited_gizmo; Point2 mouse_pos; bool snap; - Ref<SpatialEditorGizmo> gizmo; + Ref<EditorSpatialGizmo> gizmo; int gizmo_handle; Variant gizmo_initial_value; Vector3 gizmo_initial_pos; @@ -287,8 +361,11 @@ private: Camera *previewing; Camera *preview; + bool previewing_cinema; + void _preview_exited_scene(); void _toggle_camera_preview(bool); + void _toggle_cinema_preview(bool); void _init_gizmo_instance(int p_idx); void _finish_gizmo_instances(); void _selection_result_pressed(int); @@ -403,7 +480,6 @@ public: TOOL_LOCK_SELECTED, TOOL_UNLOCK_SELECTED, TOOL_MAX - }; enum ToolOptions { @@ -484,16 +560,18 @@ private: MENU_VIEW_USE_4_VIEWPORTS, MENU_VIEW_ORIGIN, MENU_VIEW_GRID, + MENU_VIEW_GIZMOS_3D_ICONS, MENU_VIEW_CAMERA_SETTINGS, MENU_LOCK_SELECTED, MENU_UNLOCK_SELECTED, - MENU_VISIBILITY_SKELETON + MENU_SNAP_TO_FLOOR }; Button *tool_button[TOOL_MAX]; Button *tool_option_button[TOOL_OPT_MAX]; MenuButton *transform_menu; + PopupMenu *gizmos_menu; MenuButton *view_menu; ToolButton *lock_button; @@ -525,6 +603,7 @@ private: void _xform_dialog_action(); void _menu_item_pressed(int p_option); void _menu_item_toggled(bool pressed, int p_option); + void _menu_gizmo_toggled(int p_option); HBoxContainer *hbc_menu; @@ -533,6 +612,7 @@ private: void _instance_scene(); void _init_indicators(); + void _init_gizmos_menu(); void _init_grid(); void _finish_indicators(); void _finish_grid(); @@ -552,7 +632,10 @@ private: static SpatialEditor *singleton; void _node_removed(Node *p_node); - SpatialEditorGizmos *gizmos; + Vector<Ref<EditorSpatialGizmoPlugin> > gizmo_plugins; + + void _register_all_gizmos(); + SpatialEditor(); bool is_any_freelook_active() const; @@ -592,11 +675,9 @@ public: Ref<ArrayMesh> get_scale_gizmo(int idx) const { return scale_gizmo[idx]; } Ref<ArrayMesh> get_scale_plane_gizmo(int idx) const { return scale_plane_gizmo[idx]; } - int get_skeleton_visibility_state() const; - void update_transform_gizmo(); void update_all_gizmos(); - + void snap_selected_nodes_to_floor(); void select_gizmo_highlight_axis(int p_axis); void set_custom_camera(Node *p_camera) { custom_camera = p_camera; } @@ -626,6 +707,8 @@ public: return viewports[p_idx]; } + void register_gizmo_plugin(Ref<EditorSpatialGizmoPlugin> ref); + Camera *get_camera() { return NULL; } void edit(Spatial *p_spatial); void clear(); @@ -662,4 +745,49 @@ public: ~SpatialEditorPlugin(); }; +class EditorSpatialGizmoPlugin : public Resource { + + GDCLASS(EditorSpatialGizmoPlugin, Resource); + +public: + static const int ON_TOP = 0; + static const int VISIBLE = 1; + static const int HIDDEN = 2; + +private: + int current_state; + List<EditorSpatialGizmo *> current_gizmos; + HashMap<String, Vector<Ref<SpatialMaterial> > > materials; + +protected: + virtual bool has_gizmo(Spatial *p_spatial); + virtual Ref<EditorSpatialGizmo> create_gizmo(Spatial *p_spatial); + +public: + void create_material(const String &p_name, const Color &p_color, bool p_billboard = false, bool p_on_top = false, bool p_use_vertex_color = false); + void create_icon_material(const String &p_name, const Ref<Texture> &p_texture, bool p_on_top = false, const Color &p_albedo = Color(1, 1, 1, 1)); + void create_handle_material(const String &p_name, bool p_billboard = false); + void add_material(const String &p_name, Ref<SpatialMaterial> p_material); + + Ref<SpatialMaterial> get_material(const String &p_name, EditorSpatialGizmo *p_gizmo = NULL); + + virtual String get_name() const = 0; + virtual bool can_be_hidden() const; + virtual bool is_selectable_when_hidden() const; + + virtual void redraw(EditorSpatialGizmo *p_gizmo) {} + virtual String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { return ""; } + virtual Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { return Variant(); } + virtual void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) {} + virtual void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) {} + virtual bool is_gizmo_handle_highlighted(const EditorSpatialGizmo *p_gizmo, int idx) const { return false; } + + Ref<EditorSpatialGizmo> get_gizmo(Spatial *p_spatial); + void set_state(int p_state); + void unregister_gizmo(EditorSpatialGizmo *p_gizmo); + + EditorSpatialGizmoPlugin(); + virtual ~EditorSpatialGizmoPlugin(); +}; + #endif diff --git a/editor/plugins/sprite_editor_plugin.cpp b/editor/plugins/sprite_editor_plugin.cpp index 66673cca00..9bf1178b58 100644 --- a/editor/plugins/sprite_editor_plugin.cpp +++ b/editor/plugins/sprite_editor_plugin.cpp @@ -169,7 +169,7 @@ void SpriteEditor::_update_mesh_data() { Size2 img_size = Vector2(image->get_width(), image->get_height()); for (int j = 0; j < lines.size(); j++) { - lines[j] = expand(lines[j], rect, epsilon); + lines.write[j] = expand(lines[j], rect, epsilon); int index_ofs = computed_vertices.size(); diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index e4fdd1f251..0419c3d4b1 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -57,8 +57,6 @@ void TextureRegionEditor::_region_draw() { base_tex = obj_styleBox->get_texture(); else if (atlas_tex.is_valid()) base_tex = atlas_tex->get_atlas(); - else if (tile_set.is_valid() && selected_tile != -1 && tile_set->has_tile(selected_tile)) - base_tex = tile_set->tile_get_texture(selected_tile); if (base_tex.is_null()) return; @@ -284,8 +282,6 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { r = obj_styleBox->get_region_rect(); else if (atlas_tex.is_valid()) r = atlas_tex->get_region(); - else if (tile_set.is_valid() && selected_tile != -1) - r = tile_set->tile_get_region(selected_tile); rect.expand_to(r.position); rect.expand_to(r.position + r.size); } @@ -302,9 +298,6 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { } else if (atlas_tex.is_valid()) { undo_redo->add_do_method(atlas_tex.ptr(), "set_region", rect); undo_redo->add_undo_method(atlas_tex.ptr(), "set_region", atlas_tex->get_region()); - } else if (tile_set.is_valid() && selected_tile != -1) { - undo_redo->add_do_method(tile_set.ptr(), "tile_set_region", selected_tile, rect); - undo_redo->add_undo_method(tile_set.ptr(), "tile_set_region", selected_tile, tile_set->tile_get_region(selected_tile)); } undo_redo->add_do_method(edit_draw, "update"); undo_redo->add_undo_method(edit_draw, "update"); @@ -327,8 +320,6 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { rect_prev = obj_styleBox->get_region_rect(); else if (atlas_tex.is_valid()) rect_prev = atlas_tex->get_region(); - else if (tile_set.is_valid() && selected_tile != -1) - rect_prev = tile_set->tile_get_region(selected_tile); for (int i = 0; i < 8; i++) { Vector2 tuv = endpoints[i]; @@ -372,9 +363,6 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { } else if (obj_styleBox.is_valid()) { undo_redo->add_do_method(obj_styleBox.ptr(), "set_region_rect", obj_styleBox->get_region_rect()); undo_redo->add_undo_method(obj_styleBox.ptr(), "set_region_rect", rect_prev); - } else if (tile_set.is_valid()) { - undo_redo->add_do_method(tile_set.ptr(), "tile_set_region", selected_tile, tile_set->tile_get_region(selected_tile)); - undo_redo->add_undo_method(tile_set.ptr(), "tile_set_region", selected_tile, rect_prev); } drag_index = -1; } @@ -595,8 +583,6 @@ void TextureRegionEditor::apply_rect(const Rect2 &rect) { obj_styleBox->set_region_rect(rect); else if (atlas_tex.is_valid()) atlas_tex->set_region(rect); - else if (tile_set.is_valid() && selected_tile != -1) - tile_set->tile_set_region(selected_tile, rect); } void TextureRegionEditor::_notification(int p_what) { @@ -623,12 +609,11 @@ void TextureRegionEditor::_notification(int p_what) { } void TextureRegionEditor::_node_removed(Object *p_obj) { - if (p_obj == node_sprite || p_obj == node_ninepatch || p_obj == obj_styleBox.ptr() || p_obj == atlas_tex.ptr() || p_obj == tile_set.ptr()) { + if (p_obj == node_sprite || p_obj == node_ninepatch || p_obj == obj_styleBox.ptr() || p_obj == atlas_tex.ptr()) { node_ninepatch = NULL; node_sprite = NULL; obj_styleBox = Ref<StyleBox>(NULL); atlas_tex = Ref<AtlasTexture>(NULL); - tile_set = Ref<TileSet>(NULL); hide(); } } @@ -677,8 +662,6 @@ void TextureRegionEditor::edit(Object *p_obj) { obj_styleBox->remove_change_receptor(this); if (atlas_tex.is_valid()) atlas_tex->remove_change_receptor(this); - if (tile_set.is_valid()) - tile_set->remove_change_receptor(this); if (p_obj) { node_sprite = Object::cast_to<Sprite>(p_obj); node_ninepatch = Object::cast_to<NinePatchRect>(p_obj); @@ -686,8 +669,6 @@ void TextureRegionEditor::edit(Object *p_obj) { obj_styleBox = Ref<StyleBoxTexture>(Object::cast_to<StyleBoxTexture>(p_obj)); if (Object::cast_to<AtlasTexture>(p_obj)) atlas_tex = Ref<AtlasTexture>(Object::cast_to<AtlasTexture>(p_obj)); - if (Object::cast_to<TileSet>(p_obj)) - tile_set = Ref<TileSet>(Object::cast_to<TileSet>(p_obj)); p_obj->add_change_receptor(this); _edit_region(); } else { @@ -695,7 +676,6 @@ void TextureRegionEditor::edit(Object *p_obj) { node_ninepatch = NULL; obj_styleBox = Ref<StyleBoxTexture>(NULL); atlas_tex = Ref<AtlasTexture>(NULL); - tile_set = Ref<TileSet>(NULL); } edit_draw->update(); if (node_sprite && !node_sprite->is_region()) { @@ -724,8 +704,6 @@ void TextureRegionEditor::_edit_region() { texture = obj_styleBox->get_texture(); else if (atlas_tex.is_valid()) texture = atlas_tex->get_atlas(); - else if (tile_set.is_valid() && selected_tile != -1 && tile_set->has_tile(selected_tile)) - texture = tile_set->tile_get_texture(selected_tile); if (texture.is_null()) { edit_draw->update(); @@ -794,8 +772,6 @@ void TextureRegionEditor::_edit_region() { rect = obj_styleBox->get_region_rect(); else if (atlas_tex.is_valid()) rect = atlas_tex->get_region(); - else if (tile_set.is_valid() && selected_tile != -1) - rect = tile_set->tile_get_region(selected_tile); edit_draw->update(); } @@ -814,10 +790,8 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) { node_ninepatch = NULL; obj_styleBox = Ref<StyleBoxTexture>(NULL); atlas_tex = Ref<AtlasTexture>(NULL); - tile_set = Ref<TileSet>(NULL); editor = p_editor; undo_redo = editor->get_undo_redo(); - selected_tile = -1; snap_step = Vector2(10, 10); snap_separation = Vector2(0, 0); diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h index eeba1987a6..bd93be9267 100644 --- a/editor/plugins/texture_region_editor_plugin.h +++ b/editor/plugins/texture_region_editor_plugin.h @@ -38,7 +38,6 @@ #include "scene/gui/nine_patch_rect.h" #include "scene/resources/style_box.h" #include "scene/resources/texture.h" -#include "scene/resources/tile_set.h" /** @author Mariano Suligoy @@ -56,8 +55,6 @@ class TextureRegionEditor : public Control { }; friend class TextureRegionEditorPlugin; - friend class TileSetEditor; - friend class TileSetEditorPlugin; MenuButton *snap_mode_button; TextureRect *icon_zoom; ToolButton *zoom_in; @@ -91,14 +88,12 @@ class TextureRegionEditor : public Control { Sprite *node_sprite; Ref<StyleBoxTexture> obj_styleBox; Ref<AtlasTexture> atlas_tex; - Ref<TileSet> tile_set; Rect2 rect; Rect2 rect_prev; float prev_margin; int edited_margin; List<Rect2> autoslice_cache; - int selected_tile; bool drag; bool creating; diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 484da3b4f3..101dc3037f 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -73,7 +73,8 @@ void TileMapEditor::_notification(int p_what) { rotate_180->set_icon(get_icon("Rotate180", "EditorIcons")); rotate_270->set_icon(get_icon("Rotate270", "EditorIcons")); - search_box->add_icon_override("right_icon", get_icon("Search", "EditorIcons")); + search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_clear_button_enabled(true); PopupMenu *p = options->get_popup(); p->set_item_icon(p->get_item_index(OPTION_PAINTING), get_icon("Edit", "EditorIcons")); @@ -168,10 +169,11 @@ void TileMapEditor::_menu_option(int p_option) { } void TileMapEditor::_palette_selected(int index) { + _update_palette(); +} - if (manual_autotile) { - _update_palette(); - } +void TileMapEditor::_palette_multi_selected(int index, bool selected) { + _update_palette(); } void TileMapEditor::_canvas_mouse_enter() { @@ -196,7 +198,7 @@ Vector<int> TileMapEditor::get_selected_tiles() const { } for (int i = items.size() - 1; i >= 0; i--) { - items[i] = palette->get_item_metadata(items[i]); + items.write[i] = palette->get_item_metadata(items[i]); } return items; } @@ -296,7 +298,7 @@ void TileMapEditor::_set_cell(const Point2i &p_pos, Vector<int> p_values, bool p } node->set_cell(p_pos.x, p_pos.y, p_value, p_flip_h, p_flip_v, p_transpose); - if (manual_autotile) { + if (manual_autotile || node->get_tileset()->tile_get_tile_mode(p_value) == TileSet::ATLAS_TILE) { if (current != -1) { node->set_cell_autotile_coord(p_pos.x, p_pos.y, position); } @@ -317,7 +319,6 @@ void TileMapEditor::_text_entered(const String &p_text) { } void TileMapEditor::_text_changed(const String &p_text) { - _update_palette(); } @@ -427,7 +428,7 @@ void TileMapEditor::_update_palette() { if (tex.is_valid()) { Rect2 region = tileset->tile_get_region(entries[i].id); - if (tileset->tile_get_tile_mode(entries[i].id) == TileSet::AUTO_TILE) { + if (tileset->tile_get_tile_mode(entries[i].id) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(entries[i].id) == TileSet::ATLAS_TILE) { int spacing = tileset->autotile_get_spacing(entries[i].id); region.size = tileset->autotile_get_size(entries[i].id); region.position += (region.size + Vector2(spacing, spacing)) * tileset->autotile_get_icon_coordinate(entries[i].id); @@ -450,7 +451,7 @@ void TileMapEditor::_update_palette() { palette->select(0); } - if (manual_autotile && tileset->tile_get_tile_mode(sel_tile) == TileSet::AUTO_TILE) { + if ((manual_autotile && tileset->tile_get_tile_mode(sel_tile) == TileSet::AUTO_TILE) || tileset->tile_get_tile_mode(sel_tile) == TileSet::ATLAS_TILE) { const Map<Vector2, uint16_t> &tiles = tileset->autotile_get_bitmask_map(sel_tile); @@ -676,10 +677,10 @@ void TileMapEditor::_draw_cell(int p_cell, const Point2i &p_point, bool p_flip_h Vector2 tile_ofs = node->get_tileset()->tile_get_texture_offset(p_cell); Rect2 r = node->get_tileset()->tile_get_region(p_cell); - if (node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::AUTO_TILE) { + if (node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::AUTO_TILE || node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::ATLAS_TILE) { Vector2 offset; int selected = manual_palette->get_current(); - if (manual_autotile && selected != -1) { + if ((manual_autotile || node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::ATLAS_TILE) && selected != -1) { offset = manual_palette->get_item_metadata(selected); } else { offset = node->get_tileset()->autotile_get_icon_coordinate(p_cell); @@ -983,7 +984,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { ids.push_back(0); for (List<TileData>::Element *E = copydata.front(); E; E = E->next()) { - ids[0] = E->get().cell; + ids.write[0] = E->get().cell; _set_cell(E->get().pos + ofs, ids, E->get().flip_h, E->get().flip_v, E->get().transpose); } _finish_undo(); @@ -1006,7 +1007,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } for (List<TileData>::Element *E = copydata.front(); E; E = E->next()) { - ids[0] = E->get().cell; + ids.write[0] = E->get().cell; _set_cell(E->get().pos + ofs, ids, E->get().flip_h, E->get().flip_v, E->get().transpose); } _finish_undo(); @@ -1228,7 +1229,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) { - tmp_cell[0] = E->get().idx; + tmp_cell.write[0] = E->get().idx; _set_cell(E->key(), tmp_cell, E->get().xf, E->get().yf, E->get().tr); } } @@ -1265,7 +1266,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) { - tmp_cell[0] = E->get().idx; + tmp_cell.write[0] = E->get().idx; _set_cell(E->key(), tmp_cell, E->get().xf, E->get().yf, E->get().tr); } } @@ -1673,6 +1674,7 @@ void TileMapEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_tileset_settings_changed"), &TileMapEditor::_tileset_settings_changed); ClassDB::bind_method(D_METHOD("_update_transform_buttons"), &TileMapEditor::_update_transform_buttons); ClassDB::bind_method(D_METHOD("_palette_selected"), &TileMapEditor::_palette_selected); + ClassDB::bind_method(D_METHOD("_palette_multi_selected"), &TileMapEditor::_palette_multi_selected); ClassDB::bind_method(D_METHOD("_fill_points"), &TileMapEditor::_fill_points); ClassDB::bind_method(D_METHOD("_erase_points"), &TileMapEditor::_erase_points); @@ -1750,7 +1752,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { bucket_cache_visited = 0; invalid_cell.resize(1); - invalid_cell[0] = TileMap::INVALID_CELL; + invalid_cell.write[0] = TileMap::INVALID_CELL; ED_SHORTCUT("tile_map_editor/erase_selection", TTR("Erase Selection"), KEY_DELETE); ED_SHORTCUT("tile_map_editor/find_tile", TTR("Find Tile"), KEY_MASK_CMD + KEY_F); @@ -1800,6 +1802,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { palette->set_max_text_lines(2); palette->set_select_mode(ItemList::SELECT_MULTI); palette->connect("item_selected", this, "_palette_selected"); + palette->connect("multi_selected", this, "_palette_multi_selected"); palette_container->add_child(palette); // Add autotile override palette diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h index b8443ca962..bb76879b02 100644 --- a/editor/plugins/tile_map_editor_plugin.h +++ b/editor/plugins/tile_map_editor_plugin.h @@ -184,6 +184,7 @@ class TileMapEditor : public VBoxContainer { void _update_palette(); void _menu_option(int p_option); void _palette_selected(int index); + void _palette_multi_selected(int index, bool selected); void _start_undo(const String &p_action); void _finish_undo(); diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index 087c4293f1..8d1db5de8f 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -30,6 +30,8 @@ #include "tile_set_editor_plugin.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "scene/2d/physics_body_2d.h" #include "scene/2d/sprite.h" @@ -39,7 +41,9 @@ void TileSetEditor::edit(const Ref<TileSet> &p_tileset) { tileset = p_tileset; tileset->add_change_receptor(this); - update_tile_list(); + texture_list->clear(); + texture_map.clear(); + update_texture_list(); } void TileSetEditor::_import_node(Node *p_node, Ref<TileSet> p_library) { @@ -161,75 +165,6 @@ void TileSetEditor::_import_scene(Node *p_scene, Ref<TileSet> p_library, bool p_ _import_node(p_scene, p_library); } -void TileSetEditor::_menu_confirm() { - - switch (option) { - - case MENU_OPTION_MERGE_FROM_SCENE: - case MENU_OPTION_CREATE_FROM_SCENE: { - - EditorNode *en = editor; - Node *scene = en->get_edited_scene(); - if (!scene) - break; - - _import_scene(scene, tileset, option == MENU_OPTION_MERGE_FROM_SCENE); - - } break; - } -} - -void TileSetEditor::_name_dialog_confirm(const String &name) { - - switch (option) { - - case MENU_OPTION_REMOVE_ITEM: { - - int id = tileset->find_tile_by_name(name); - - if (id < 0 && name.is_valid_integer()) - id = name.to_int(); - - if (tileset->has_tile(id)) { - tileset->remove_tile(id); - update_tile_list(); - } else { - err_dialog->set_text(TTR("Could not find tile:") + " " + name); - err_dialog->popup_centered(Size2(300, 60)); - } - } break; - } -} - -void TileSetEditor::_menu_cbk(int p_option) { - - option = p_option; - switch (p_option) { - - case MENU_OPTION_ADD_ITEM: { - tileset->create_tile(tileset->get_last_unused_tile_id()); - tileset->tile_set_name(tileset->get_last_unused_tile_id() - 1, itos(tileset->get_last_unused_tile_id() - 1)); - update_tile_list(); - } break; - case MENU_OPTION_REMOVE_ITEM: { - - nd->set_title(TTR("Remove Item")); - nd->set_text(TTR("Item name or ID:")); - nd->popup_centered(Size2(300, 95)); - } break; - case MENU_OPTION_CREATE_FROM_SCENE: { - - cd->set_text(TTR("Create from scene?")); - cd->popup_centered(Size2(300, 60)); - } break; - case MENU_OPTION_MERGE_FROM_SCENE: { - - cd->set_text(TTR("Merge from scene?")); - cd->popup_centered(Size2(300, 60)); - } break; - } -} - Error TileSetEditor::update_library_file(Node *p_base_scene, Ref<TileSet> ml, bool p_merge) { _import_scene(p_base_scene, ml, p_merge); @@ -237,28 +172,36 @@ Error TileSetEditor::update_library_file(Node *p_base_scene, Ref<TileSet> ml, bo } void TileSetEditor::_bind_methods() { - - ClassDB::bind_method("_menu_cbk", &TileSetEditor::_menu_cbk); - ClassDB::bind_method("_menu_confirm", &TileSetEditor::_menu_confirm); - ClassDB::bind_method("_name_dialog_confirm", &TileSetEditor::_name_dialog_confirm); - ClassDB::bind_method("_on_tile_list_selected", &TileSetEditor::_on_tile_list_selected); + ClassDB::bind_method("_on_tileset_toolbar_button_pressed", &TileSetEditor::_on_tileset_toolbar_button_pressed); + ClassDB::bind_method("_on_textures_added", &TileSetEditor::_on_textures_added); + ClassDB::bind_method("_on_tileset_toolbar_confirm", &TileSetEditor::_on_tileset_toolbar_confirm); + ClassDB::bind_method("_on_texture_list_selected", &TileSetEditor::_on_texture_list_selected); ClassDB::bind_method("_on_edit_mode_changed", &TileSetEditor::_on_edit_mode_changed); + ClassDB::bind_method("_on_workspace_mode_changed", &TileSetEditor::_on_workspace_mode_changed); ClassDB::bind_method("_on_workspace_overlay_draw", &TileSetEditor::_on_workspace_overlay_draw); + ClassDB::bind_method("_on_workspace_process", &TileSetEditor::_on_workspace_process); ClassDB::bind_method("_on_workspace_draw", &TileSetEditor::_on_workspace_draw); ClassDB::bind_method("_on_workspace_input", &TileSetEditor::_on_workspace_input); ClassDB::bind_method("_on_tool_clicked", &TileSetEditor::_on_tool_clicked); ClassDB::bind_method("_on_priority_changed", &TileSetEditor::_on_priority_changed); ClassDB::bind_method("_on_grid_snap_toggled", &TileSetEditor::_on_grid_snap_toggled); - ClassDB::bind_method("_set_snap_step_x", &TileSetEditor::_set_snap_step_x); - ClassDB::bind_method("_set_snap_step_y", &TileSetEditor::_set_snap_step_y); - ClassDB::bind_method("_set_snap_off_x", &TileSetEditor::_set_snap_off_x); - ClassDB::bind_method("_set_snap_off_y", &TileSetEditor::_set_snap_off_y); - ClassDB::bind_method("_set_snap_sep_x", &TileSetEditor::_set_snap_sep_x); - ClassDB::bind_method("_set_snap_sep_y", &TileSetEditor::_set_snap_sep_y); + ClassDB::bind_method("_set_snap_step", &TileSetEditor::_set_snap_step); + ClassDB::bind_method("_set_snap_off", &TileSetEditor::_set_snap_off); + ClassDB::bind_method("_set_snap_sep", &TileSetEditor::_set_snap_sep); } void TileSetEditor::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { + + tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]->set_icon(get_icon("ToolAddNode", "EditorIcons")); + tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]->set_icon(get_icon("Remove", "EditorIcons")); + tileset_toolbar_tools->set_icon(get_icon("Tools", "EditorIcons")); + + tool_workspacemode[WORKSPACE_EDIT]->set_icon(get_icon("Edit", "EditorIcons")); + tool_workspacemode[WORKSPACE_CREATE_SINGLE]->set_icon(get_icon("AddSingleTile", "EditorIcons")); + tool_workspacemode[WORKSPACE_CREATE_AUTOTILE]->set_icon(get_icon("AddAutotile", "EditorIcons")); + tool_workspacemode[WORKSPACE_CREATE_ATLAS]->set_icon(get_icon("AddAtlasTile", "EditorIcons")); + tools[TOOL_SELECT]->set_icon(get_icon("ToolSelect", "EditorIcons")); tools[BITMASK_COPY]->set_icon(get_icon("Duplicate", "EditorIcons")); tools[BITMASK_PASTE]->set_icon(get_icon("Override", "EditorIcons")); @@ -266,91 +209,126 @@ void TileSetEditor::_notification(int p_what) { tools[SHAPE_NEW_POLYGON]->set_icon(get_icon("CollisionPolygon2D", "EditorIcons")); tools[SHAPE_DELETE]->set_icon(get_icon("Remove", "EditorIcons")); tools[SHAPE_KEEP_INSIDE_TILE]->set_icon(get_icon("Snap", "EditorIcons")); - tools[SHAPE_GRID_SNAP]->set_icon(get_icon("SnapGrid", "EditorIcons")); + tools[TOOL_GRID_SNAP]->set_icon(get_icon("SnapGrid", "EditorIcons")); tools[ZOOM_OUT]->set_icon(get_icon("ZoomLess", "EditorIcons")); tools[ZOOM_1]->set_icon(get_icon("ZoomReset", "EditorIcons")); tools[ZOOM_IN]->set_icon(get_icon("ZoomMore", "EditorIcons")); + tools[VISIBLE_INFO]->set_icon(get_icon("InformationSign", "EditorIcons")); + + tool_editmode[EDITMODE_REGION]->set_icon(get_icon("RegionEdit", "EditorIcons")); + tool_editmode[EDITMODE_COLLISION]->set_icon(get_icon("StaticBody2D", "EditorIcons")); + tool_editmode[EDITMODE_OCCLUSION]->set_icon(get_icon("LightOccluder2D", "EditorIcons")); + tool_editmode[EDITMODE_NAVIGATION]->set_icon(get_icon("Navigation2D", "EditorIcons")); + tool_editmode[EDITMODE_BITMASK]->set_icon(get_icon("PackedDataContainer", "EditorIcons")); + tool_editmode[EDITMODE_PRIORITY]->set_icon(get_icon("MaterialPreviewLight1", "EditorIcons")); + tool_editmode[EDITMODE_ICON]->set_icon(get_icon("LargeTexture", "EditorIcons")); } } -void TileSetEditor::_changed_callback(Object *p_changed, const char *p_prop) { - if (p_prop == StringName("region")) { - update_tile_list_icon(); - preview->set_region_rect(tileset->tile_get_region(get_current_tile())); - } else if (p_prop == StringName("name")) { - update_tile_list_icon(); - } else if (p_prop == StringName("texture") || p_prop == StringName("modulate") || p_prop == StringName("tile_mode")) { - _on_tile_list_selected(get_current_tile()); - workspace->update(); - preview->set_texture(tileset->tile_get_texture(get_current_tile())); - preview->set_modulate(tileset->tile_get_modulate(get_current_tile())); - preview->set_region_rect(tileset->tile_get_region(get_current_tile())); - if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) - property_editor->show(); - else - property_editor->hide(); - texture_region_editor->_edit_region(); - update_tile_list_icon(); - } else if (p_prop == StringName("autotile")) { - workspace->update(); - } -} +TileSetEditor::TileSetEditor(EditorNode *p_editor) { -void TileSetEditor::initialize_bottom_editor() { + editor = p_editor; + set_name("Tile Set Bottom Editor"); - //Side Panel - side_panel = memnew(Control); - side_panel->set_name("Tile Set"); + HSplitContainer *split = memnew(HSplitContainer); + split->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_MINSIZE, 10); + add_child(split); - VSplitContainer *split = memnew(VSplitContainer); - side_panel->add_child(split); - split->set_anchors_and_margins_preset(Control::PRESET_WIDE); + VBoxContainer *left_container = memnew(VBoxContainer); + split->add_child(left_container); - tile_list = memnew(ItemList); - tile_list->set_v_size_flags(SIZE_EXPAND_FILL); - tile_list->set_h_size_flags(SIZE_EXPAND_FILL); - tile_list->set_custom_minimum_size(Size2(10, 200)); - tile_list->connect("item_selected", this, "_on_tile_list_selected"); - split->add_child(tile_list); + texture_list = memnew(ItemList); + left_container->add_child(texture_list); + texture_list->set_v_size_flags(SIZE_EXPAND_FILL); + texture_list->set_custom_minimum_size(Size2(200, 0)); + texture_list->connect("item_selected", this, "_on_texture_list_selected"); - property_editor = memnew(PropertyEditor); - property_editor->set_v_size_flags(SIZE_EXPAND_FILL); - property_editor->set_h_size_flags(SIZE_EXPAND_FILL); - property_editor->set_custom_minimum_size(Size2(10, 70)); - split->add_child(property_editor); + HBoxContainer *tileset_toolbar_container = memnew(HBoxContainer); + left_container->add_child(tileset_toolbar_container); - helper = memnew(TileSetEditorHelper(this)); - property_editor->call_deferred("edit", helper); - helper->add_change_receptor(this); + tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE] = memnew(ToolButton); + Vector<Variant> p; + p.push_back((int)TOOL_TILESET_ADD_TEXTURE); + tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]->connect("pressed", this, "_on_tileset_toolbar_button_pressed", p); + tileset_toolbar_container->add_child(tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]); + tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]->set_tooltip(TTR("Add Texture(s) to TileSet")); + + tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE] = memnew(ToolButton); + p = Vector<Variant>(); + p.push_back((int)TOOL_TILESET_REMOVE_TEXTURE); + tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]->connect("pressed", this, "_on_tileset_toolbar_button_pressed", p); + tileset_toolbar_container->add_child(tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]); + tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]->set_tooltip(TTR("Remove current Texture from TileSet")); + + Control *toolbar_separator = memnew(Control); + toolbar_separator->set_h_size_flags(Control::SIZE_EXPAND_FILL); + tileset_toolbar_container->add_child(toolbar_separator); + + tileset_toolbar_tools = memnew(MenuButton); + tileset_toolbar_tools->set_text("Tools"); + p = Vector<Variant>(); + p.push_back((int)TOOL_TILESET_CREATE_SCENE); + tileset_toolbar_tools->get_popup()->add_item(TTR("Create from Scene"), TOOL_TILESET_CREATE_SCENE); + p = Vector<Variant>(); + p.push_back((int)TOOL_TILESET_MERGE_SCENE); + tileset_toolbar_tools->get_popup()->add_item(TTR("Merge from Scene"), TOOL_TILESET_MERGE_SCENE); - //Editor - //Bottom Panel - bottom_panel = memnew(Control); - bottom_panel->set_name("Tile Set Bottom Editor"); + tileset_toolbar_tools->get_popup()->connect("id_pressed", this, "_on_tileset_toolbar_button_pressed"); + tileset_toolbar_container->add_child(tileset_toolbar_tools); + + //--------------- + VBoxContainer *right_container = memnew(VBoxContainer); + right_container->set_v_size_flags(SIZE_EXPAND_FILL); + split->add_child(right_container); dragging_point = -1; creating_shape = false; snap_step = Vector2(32, 32); + snap_offset = WORKSPACE_MARGIN; - bottom_panel->set_custom_minimum_size(Size2(0, 150)); + set_custom_minimum_size(Size2(0, 150)); VBoxContainer *main_vb = memnew(VBoxContainer); - bottom_panel->add_child(main_vb); - main_vb->set_anchors_and_margins_preset(Control::PRESET_WIDE); + right_container->add_child(main_vb); + main_vb->set_v_size_flags(SIZE_EXPAND_FILL); HBoxContainer *tool_hb = memnew(HBoxContainer); Ref<ButtonGroup> g(memnew(ButtonGroup)); - String label[EDITMODE_MAX] = { "Collision", "Occlusion", "Navigation", "Bitmask", "Priority", "Icon" }; + String workspace_label[WORKSPACE_MODE_MAX] = { "Edit", "New Single Tile", "New Autotile", "New Atlas" }; + + for (int i = 0; i < (int)WORKSPACE_MODE_MAX; i++) { + tool_workspacemode[i] = memnew(Button); + tool_workspacemode[i]->set_text(workspace_label[i]); + tool_workspacemode[i]->set_toggle_mode(true); + tool_workspacemode[i]->set_button_group(g); + Vector<Variant> p; + p.push_back(i); + tool_workspacemode[i]->connect("pressed", this, "_on_workspace_mode_changed", p); + tool_hb->add_child(tool_workspacemode[i]); + } + tool_workspacemode[WORKSPACE_EDIT]->set_pressed(true); + workspace_mode = WORKSPACE_EDIT; + + main_vb->add_child(tool_hb); + main_vb->add_child(memnew(HSeparator)); + + tool_hb = memnew(HBoxContainer); + Control *spacer = memnew(Control); + spacer->set_custom_minimum_size(Size2(30, 0)); + tool_hb->add_child(spacer); + + g = Ref<ButtonGroup>(memnew(ButtonGroup)); + String label[EDITMODE_MAX] = { "Region", "Collision", "Occlusion", "Navigation", "Bitmask", "Priority", "Icon" }; for (int i = 0; i < (int)EDITMODE_MAX; i++) { tool_editmode[i] = memnew(Button); tool_editmode[i]->set_text(label[i]); tool_editmode[i]->set_toggle_mode(true); tool_editmode[i]->set_button_group(g); - Vector<Variant> args; - args.push_back(i); - tool_editmode[i]->connect("pressed", this, "_on_edit_mode_changed", args); + Vector<Variant> p; + p.push_back(i); + tool_editmode[i]->connect("pressed", this, "_on_edit_mode_changed", p); tool_hb->add_child(tool_editmode[i]); } tool_editmode[EDITMODE_COLLISION]->set_pressed(true); @@ -360,127 +338,52 @@ void TileSetEditor::initialize_bottom_editor() { main_vb->add_child(memnew(HSeparator)); toolbar = memnew(HBoxContainer); - for (int i = 0; i < (int)TOOLBAR_MAX; i++) { - tool_containers[i] = memnew(HBoxContainer); - toolbar->add_child(tool_containers[i]); - tool_containers[i]->hide(); - } - Ref<ButtonGroup> tg(memnew(ButtonGroup)); - Vector<Variant> p; + p = Vector<Variant>(); tools[TOOL_SELECT] = memnew(ToolButton); - tool_containers[TOOLBAR_DUMMY]->add_child(tools[TOOL_SELECT]); + toolbar->add_child(tools[TOOL_SELECT]); tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to use as icon, this will be also used on invalid autotile bindings.")); tools[TOOL_SELECT]->set_toggle_mode(true); tools[TOOL_SELECT]->set_button_group(tg); tools[TOOL_SELECT]->set_pressed(true); p.push_back((int)TOOL_SELECT); tools[TOOL_SELECT]->connect("pressed", this, "_on_tool_clicked", p); - tool_containers[TOOLBAR_DUMMY]->show(); tools[BITMASK_COPY] = memnew(ToolButton); p.push_back((int)BITMASK_COPY); tools[BITMASK_COPY]->connect("pressed", this, "_on_tool_clicked", p); - tool_containers[TOOLBAR_BITMASK]->add_child(tools[BITMASK_COPY]); + toolbar->add_child(tools[BITMASK_COPY]); tools[BITMASK_PASTE] = memnew(ToolButton); p = Vector<Variant>(); p.push_back((int)BITMASK_PASTE); tools[BITMASK_PASTE]->connect("pressed", this, "_on_tool_clicked", p); - tool_containers[TOOLBAR_BITMASK]->add_child(tools[BITMASK_PASTE]); + toolbar->add_child(tools[BITMASK_PASTE]); tools[BITMASK_CLEAR] = memnew(ToolButton); p = Vector<Variant>(); p.push_back((int)BITMASK_CLEAR); tools[BITMASK_CLEAR]->connect("pressed", this, "_on_tool_clicked", p); - tool_containers[TOOLBAR_BITMASK]->add_child(tools[BITMASK_CLEAR]); + toolbar->add_child(tools[BITMASK_CLEAR]); tools[SHAPE_NEW_POLYGON] = memnew(ToolButton); - tool_containers[TOOLBAR_SHAPE]->add_child(tools[SHAPE_NEW_POLYGON]); + toolbar->add_child(tools[SHAPE_NEW_POLYGON]); tools[SHAPE_NEW_POLYGON]->set_toggle_mode(true); tools[SHAPE_NEW_POLYGON]->set_button_group(tg); - tool_containers[TOOLBAR_SHAPE]->add_child(memnew(VSeparator)); + toolbar->add_child(memnew(VSeparator)); tools[SHAPE_DELETE] = memnew(ToolButton); p = Vector<Variant>(); p.push_back((int)SHAPE_DELETE); tools[SHAPE_DELETE]->connect("pressed", this, "_on_tool_clicked", p); - tool_containers[TOOLBAR_SHAPE]->add_child(tools[SHAPE_DELETE]); - tool_containers[TOOLBAR_SHAPE]->add_child(memnew(VSeparator)); + toolbar->add_child(tools[SHAPE_DELETE]); + toolbar->add_child(memnew(VSeparator)); tools[SHAPE_KEEP_INSIDE_TILE] = memnew(ToolButton); tools[SHAPE_KEEP_INSIDE_TILE]->set_toggle_mode(true); tools[SHAPE_KEEP_INSIDE_TILE]->set_pressed(true); - tool_containers[TOOLBAR_SHAPE]->add_child(tools[SHAPE_KEEP_INSIDE_TILE]); - tools[SHAPE_GRID_SNAP] = memnew(ToolButton); - tools[SHAPE_GRID_SNAP]->set_toggle_mode(true); - tools[SHAPE_GRID_SNAP]->connect("toggled", this, "_on_grid_snap_toggled"); - tool_containers[TOOLBAR_SHAPE]->add_child(tools[SHAPE_GRID_SNAP]); - - hb_grid = memnew(HBoxContainer); - tool_containers[TOOLBAR_SHAPE]->add_child(hb_grid); - - hb_grid->add_child(memnew(VSeparator)); - hb_grid->add_child(memnew(Label(TTR("Offset:")))); - - sb_off_x = memnew(SpinBox); - sb_off_x->set_min(-256); - sb_off_x->set_max(256); - sb_off_x->set_step(1); - sb_off_x->set_value(snap_offset.x); - sb_off_x->set_suffix("px"); - sb_off_x->connect("value_changed", this, "_set_snap_off_x"); - hb_grid->add_child(sb_off_x); - - sb_off_y = memnew(SpinBox); - sb_off_y->set_min(-256); - sb_off_y->set_max(256); - sb_off_y->set_step(1); - sb_off_y->set_value(snap_offset.y); - sb_off_y->set_suffix("px"); - sb_off_y->connect("value_changed", this, "_set_snap_off_y"); - hb_grid->add_child(sb_off_y); - - hb_grid->add_child(memnew(VSeparator)); - hb_grid->add_child(memnew(Label(TTR("Step:")))); - - sb_step_x = memnew(SpinBox); - sb_step_x->set_min(-256); - sb_step_x->set_max(256); - sb_step_x->set_step(1); - sb_step_x->set_value(snap_step.x); - sb_step_x->set_suffix("px"); - sb_step_x->connect("value_changed", this, "_set_snap_step_x"); - hb_grid->add_child(sb_step_x); - - sb_step_y = memnew(SpinBox); - sb_step_y->set_min(-256); - sb_step_y->set_max(256); - sb_step_y->set_step(1); - sb_step_y->set_value(snap_step.y); - sb_step_y->set_suffix("px"); - sb_step_y->connect("value_changed", this, "_set_snap_step_y"); - hb_grid->add_child(sb_step_y); - - hb_grid->add_child(memnew(VSeparator)); - hb_grid->add_child(memnew(Label(TTR("Separation:")))); - - sb_sep_x = memnew(SpinBox); - sb_sep_x->set_min(0); - sb_sep_x->set_max(256); - sb_sep_x->set_step(1); - sb_sep_x->set_value(snap_separation.x); - sb_sep_x->set_suffix("px"); - sb_sep_x->connect("value_changed", this, "_set_snap_sep_x"); - hb_grid->add_child(sb_sep_x); - - sb_sep_y = memnew(SpinBox); - sb_sep_y->set_min(0); - sb_sep_y->set_max(256); - sb_sep_y->set_step(1); - sb_sep_y->set_value(snap_separation.y); - sb_sep_y->set_suffix("px"); - sb_sep_y->connect("value_changed", this, "_set_snap_sep_y"); - hb_grid->add_child(sb_sep_y); - - hb_grid->hide(); + toolbar->add_child(tools[SHAPE_KEEP_INSIDE_TILE]); + tools[TOOL_GRID_SNAP] = memnew(ToolButton); + tools[TOOL_GRID_SNAP]->set_toggle_mode(true); + tools[TOOL_GRID_SNAP]->connect("toggled", this, "_on_grid_snap_toggled"); + toolbar->add_child(tools[TOOL_GRID_SNAP]); spin_priority = memnew(SpinBox); spin_priority->set_min(1); @@ -491,8 +394,6 @@ void TileSetEditor::initialize_bottom_editor() { spin_priority->hide(); toolbar->add_child(spin_priority); - tool_containers[TOOLBAR_SHAPE]->show(); - Control *separator = memnew(Control); separator->set_h_size_flags(SIZE_EXPAND_FILL); toolbar->add_child(separator); @@ -502,22 +403,31 @@ void TileSetEditor::initialize_bottom_editor() { p.push_back((int)ZOOM_OUT); tools[ZOOM_OUT]->connect("pressed", this, "_on_tool_clicked", p); toolbar->add_child(tools[ZOOM_OUT]); + tools[ZOOM_OUT]->set_tooltip(TTR("Zoom Out")); tools[ZOOM_1] = memnew(ToolButton); p = Vector<Variant>(); p.push_back((int)ZOOM_1); tools[ZOOM_1]->connect("pressed", this, "_on_tool_clicked", p); toolbar->add_child(tools[ZOOM_1]); + tools[ZOOM_1]->set_tooltip(TTR("Reset Zoom")); tools[ZOOM_IN] = memnew(ToolButton); p = Vector<Variant>(); p.push_back((int)ZOOM_IN); tools[ZOOM_IN]->connect("pressed", this, "_on_tool_clicked", p); toolbar->add_child(tools[ZOOM_IN]); + tools[ZOOM_IN]->set_tooltip(TTR("Zoom In")); + + tools[VISIBLE_INFO] = memnew(ToolButton); + tools[VISIBLE_INFO]->set_toggle_mode(true); + tools[VISIBLE_INFO]->set_tooltip(TTR("Display tile's names (hold Alt Key)")); + toolbar->add_child(tools[VISIBLE_INFO]); main_vb->add_child(toolbar); scroll = memnew(ScrollContainer); main_vb->add_child(scroll); scroll->set_v_size_flags(SIZE_EXPAND_FILL); + scroll->set_clip_contents(true); workspace_container = memnew(Control); scroll->add_child(workspace_container); @@ -527,6 +437,7 @@ void TileSetEditor::initialize_bottom_editor() { workspace_container->add_child(workspace_overlay); workspace = memnew(Control); + workspace->set_focus_mode(FOCUS_ALL); workspace->connect("draw", this, "_on_workspace_draw"); workspace->connect("gui_input", this, "_on_workspace_input"); workspace->set_draw_behind_parent(true); @@ -536,39 +447,35 @@ void TileSetEditor::initialize_bottom_editor() { workspace->add_child(preview); preview->set_centered(false); preview->set_draw_behind_parent(true); - preview->set_region(true); -} + preview->set_position(WORKSPACE_MARGIN); -TileSetEditor::TileSetEditor(EditorNode *p_editor) { - - menu = memnew(MenuButton); - CanvasItemEditor::get_singleton()->add_control_to_menu_panel(menu); - menu->hide(); - menu->set_text(TTR("Tile Set")); - menu->get_popup()->add_item(TTR("Add Item"), MENU_OPTION_ADD_ITEM); - menu->get_popup()->add_item(TTR("Remove Item"), MENU_OPTION_REMOVE_ITEM); - menu->get_popup()->add_separator(); - menu->get_popup()->add_item(TTR("Create from Scene"), MENU_OPTION_CREATE_FROM_SCENE); - menu->get_popup()->add_item(TTR("Merge from Scene"), MENU_OPTION_MERGE_FROM_SCENE); - menu->get_popup()->connect("id_pressed", this, "_menu_cbk"); - editor = p_editor; + //--------------- cd = memnew(ConfirmationDialog); add_child(cd); - cd->get_ok()->connect("pressed", this, "_menu_confirm"); - - nd = memnew(EditorNameDialog); - add_child(nd); - nd->set_hide_on_ok(true); - nd->get_line_edit()->set_margin(MARGIN_TOP, 28); - nd->connect("name_confirmed", this, "_name_dialog_confirm"); + cd->connect("confirmed", this, "_on_tileset_toolbar_confirm"); + //--------------- err_dialog = memnew(AcceptDialog); add_child(err_dialog); - err_dialog->set_title(TTR("Error")); - draw_handles = false; + //--------------- + texture_dialog = memnew(EditorFileDialog); + texture_dialog->set_access(EditorFileDialog::ACCESS_RESOURCES); + texture_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILES); + texture_dialog->clear_filters(); + List<String> extensions; + + ResourceLoader::get_recognized_extensions_for_type("Texture", &extensions); + for (List<String>::Element *E = extensions.front(); E; E = E->next()) { - initialize_bottom_editor(); + texture_dialog->add_filter("*." + E->get() + " ; " + E->get().to_upper()); + } + add_child(texture_dialog); + texture_dialog->connect("files_selected", this, "_on_textures_added"); + + //--------------- + helper = memnew(TilesetEditorContext(this)); + tile_names_opacity = 0; } TileSetEditor::~TileSetEditor() { @@ -576,57 +483,166 @@ TileSetEditor::~TileSetEditor() { memdelete(helper); } -void TileSetEditor::_on_tile_list_selected(int p_index) { - if (get_current_tile() >= 0) { +void TileSetEditor::_on_tileset_toolbar_button_pressed(int p_index) { + option = p_index; + switch (option) { + case TOOL_TILESET_ADD_TEXTURE: { + texture_dialog->popup_centered_ratio(); + } break; + case TOOL_TILESET_REMOVE_TEXTURE: { + if (get_current_texture().is_valid()) { + cd->set_text(TTR("Remove Selected Textue and ALL TILES wich uses it?")); + cd->popup_centered(Size2(300, 60)); + } else { + err_dialog->set_text(TTR("You haven't selected a texture to remove.")); + err_dialog->popup_centered(Size2(300, 60)); + } + } break; + case TOOL_TILESET_CREATE_SCENE: { + + cd->set_text(TTR("Create from scene?")); + cd->popup_centered(Size2(300, 60)); + } break; + case TOOL_TILESET_MERGE_SCENE: { + + cd->set_text(TTR("Merge from scene?")); + cd->popup_centered(Size2(300, 60)); + } break; + } +} + +void TileSetEditor::_on_tileset_toolbar_confirm() { + switch (option) { + case TOOL_TILESET_REMOVE_TEXTURE: { + RID current_rid = get_current_texture()->get_rid(); + List<int> ids; + tileset->get_tile_list(&ids); + for (List<int>::Element *E = ids.front(); E; E = E->next()) { + if (tileset->tile_get_texture(E->get())->get_rid() == current_rid) { + tileset->remove_tile(E->get()); + } + } + texture_list->remove_item(texture_list->find_metadata(current_rid)); + texture_map.erase(current_rid); + _on_texture_list_selected(-1); + } break; + case TOOL_TILESET_MERGE_SCENE: + case TOOL_TILESET_CREATE_SCENE: { + + EditorNode *en = editor; + Node *scene = en->get_edited_scene(); + if (!scene) + break; + _import_scene(scene, tileset, option == TOOL_TILESET_MERGE_SCENE); + + edit(tileset); + } break; + } +} + +void TileSetEditor::_on_texture_list_selected(int p_index) { + if (get_current_texture().is_valid()) { current_item_index = p_index; - preview->set_texture(tileset->tile_get_texture(get_current_tile())); - preview->set_modulate(tileset->tile_get_modulate(get_current_tile())); - preview->set_region_rect(tileset->tile_get_region(get_current_tile())); - workspace->set_custom_minimum_size(tileset->tile_get_region(get_current_tile()).size); + preview->set_texture(get_current_texture()); + workspace->set_custom_minimum_size(get_current_texture()->get_size() + WORKSPACE_MARGIN * 2); + workspace_container->set_custom_minimum_size(get_current_texture()->get_size() + WORKSPACE_MARGIN * 2); + workspace_overlay->set_custom_minimum_size(get_current_texture()->get_size() + WORKSPACE_MARGIN * 2); update_workspace_tile_mode(); } else { current_item_index = -1; preview->set_texture(NULL); workspace->set_custom_minimum_size(Size2i()); + update_workspace_tile_mode(); } - texture_region_editor->selected_tile = get_current_tile(); - texture_region_editor->_edit_region(); - helper->selected_tile = get_current_tile(); - helper->_change_notify(""); + set_current_tile(-1); workspace->update(); } +void TileSetEditor::_on_textures_added(const PoolStringArray &p_paths) { + int invalid_count = 0; + for (int i = 0; i < p_paths.size(); i++) { + Ref<Texture> t = Ref<Texture>(ResourceLoader::load(p_paths[i])); + if (texture_map.has(t->get_rid())) { + invalid_count++; + } else { + texture_list->add_item(t->get_path().get_file()); + texture_map.insert(t->get_rid(), t); + texture_list->set_item_metadata(texture_list->get_item_count() - 1, t->get_rid()); + } + } + update_texture_list_icon(); + texture_list->select(texture_list->get_item_count() - 1); + _on_texture_list_selected(texture_list->get_item_count() - 1); + if (invalid_count > 0) { + err_dialog->set_text(String::num(invalid_count, 0) + TTR(" file(s) was not added because was already on the list.")); + err_dialog->popup_centered(Size2(300, 60)); + } +} + void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { edit_mode = (EditMode)p_edit_mode; switch (edit_mode) { + case EDITMODE_REGION: { + tools[TOOL_SELECT]->show(); + tools[BITMASK_COPY]->hide(); + tools[BITMASK_PASTE]->hide(); + tools[BITMASK_CLEAR]->hide(); + tools[SHAPE_NEW_POLYGON]->hide(); + if (workspace_mode == WORKSPACE_EDIT) + tools[SHAPE_DELETE]->show(); + else + tools[SHAPE_DELETE]->hide(); + tools[SHAPE_KEEP_INSIDE_TILE]->hide(); + tools[TOOL_GRID_SNAP]->show(); + + tools[TOOL_SELECT]->set_pressed(true); + tools[TOOL_SELECT]->set_tooltip(TTR("Drag handles to edit Rect.\nClick on another Tile to edit it.")); + spin_priority->hide(); + } break; case EDITMODE_BITMASK: { - tool_containers[TOOLBAR_DUMMY]->show(); - tool_containers[TOOLBAR_BITMASK]->show(); - tool_containers[TOOLBAR_SHAPE]->hide(); + tools[TOOL_SELECT]->show(); + tools[BITMASK_COPY]->show(); + tools[BITMASK_PASTE]->show(); + tools[BITMASK_CLEAR]->show(); + tools[SHAPE_NEW_POLYGON]->hide(); + tools[SHAPE_DELETE]->hide(); + tools[SHAPE_KEEP_INSIDE_TILE]->hide(); + tools[TOOL_GRID_SNAP]->hide(); + tools[TOOL_SELECT]->set_pressed(true); - tools[TOOL_SELECT]->set_tooltip(TTR("LMB: set bit on.\nRMB: set bit off.")); + tools[TOOL_SELECT]->set_tooltip(TTR("LMB: set bit on.\nRMB: set bit off.\nClick on another Tile to edit it.")); spin_priority->hide(); } break; case EDITMODE_COLLISION: case EDITMODE_NAVIGATION: case EDITMODE_OCCLUSION: { - tool_containers[TOOLBAR_DUMMY]->show(); - tool_containers[TOOLBAR_BITMASK]->hide(); - tool_containers[TOOLBAR_SHAPE]->show(); - tools[TOOL_SELECT]->set_tooltip(TTR("Select current edited sub-tile.")); + tools[TOOL_SELECT]->show(); + tools[BITMASK_COPY]->hide(); + tools[BITMASK_PASTE]->hide(); + tools[BITMASK_CLEAR]->hide(); + tools[SHAPE_NEW_POLYGON]->show(); + tools[SHAPE_DELETE]->show(); + tools[SHAPE_KEEP_INSIDE_TILE]->show(); + tools[TOOL_GRID_SNAP]->show(); + + tools[TOOL_SELECT]->set_tooltip(TTR("Select current edited sub-tile.\nClick on another Tile to edit it.")); spin_priority->hide(); - select_coord(edited_shape_coord); } break; default: { - tool_containers[TOOLBAR_DUMMY]->show(); - tool_containers[TOOLBAR_BITMASK]->hide(); - tool_containers[TOOLBAR_SHAPE]->hide(); + tools[TOOL_SELECT]->show(); + tools[BITMASK_COPY]->hide(); + tools[BITMASK_PASTE]->hide(); + tools[BITMASK_CLEAR]->hide(); + tools[SHAPE_NEW_POLYGON]->hide(); + tools[SHAPE_DELETE]->hide(); + tools[SHAPE_KEEP_INSIDE_TILE]->hide(); + tools[TOOL_GRID_SNAP]->show(); if (edit_mode == EDITMODE_ICON) { - tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to use as icon, this will be also used on invalid autotile bindings.")); + tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to use as icon, this will be also used on invalid autotile bindings.\nClick on another Tile to edit it.")); spin_priority->hide(); } else { - tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to change its priority.")); + tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to change its priority.\nClick on another Tile to edit it.")); spin_priority->show(); } } break; @@ -634,25 +650,52 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { workspace->update(); } +void TileSetEditor::_on_workspace_mode_changed(int p_workspace_mode) { + workspace_mode = (WorkspaceMode)p_workspace_mode; + if (p_workspace_mode == WORKSPACE_EDIT) { + update_workspace_tile_mode(); + } else { + for (int i = 0; i < EDITMODE_MAX; i++) { + tool_editmode[i]->hide(); + } + tool_editmode[EDITMODE_REGION]->show(); + tool_editmode[EDITMODE_REGION]->set_pressed(true); + _on_edit_mode_changed(EDITMODE_REGION); + } +} + void TileSetEditor::_on_workspace_draw() { - if (get_current_tile() >= 0 && !tileset.is_null()) { + const Color COLOR_AUTOTILE = Color(0.266373, 0.565288, 0.988281); + const Color COLOR_SINGLE = Color(0.988281, 0.909323, 0.266373); + const Color COLOR_ATLAS = Color(0.78653, 0.812835, 0.832031); + + if (tileset.is_null()) + return; + if (!get_current_texture().is_valid()) + return; + + draw_highlight_current_tile(); + + draw_grid_snap(); + if (get_current_tile() >= 0) { int spacing = tileset->autotile_get_spacing(get_current_tile()); Vector2 size = tileset->autotile_get_size(get_current_tile()); Rect2i region = tileset->tile_get_region(get_current_tile()); - Color c(0.347214, 0.722656, 0.617063); switch (edit_mode) { case EDITMODE_ICON: { Vector2 coord = tileset->autotile_get_icon_coordinate(get_current_tile()); - draw_highlight_tile(coord); + draw_highlight_subtile(coord); } break; case EDITMODE_BITMASK: { - c = Color(1, 0, 0, 0.5); + Color c(1, 0, 0, 0.5); for (float x = 0; x < region.size.x / (spacing + size.x); x++) { for (float y = 0; y < region.size.y / (spacing + size.y); y++) { Vector2 coord(x, y); Point2 anchor(coord.x * (spacing + size.x), coord.y * (spacing + size.y)); + anchor += WORKSPACE_MARGIN; + anchor += region.position; uint16_t mask = tileset->autotile_get_bitmask(get_current_tile(), coord); if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_2X2) { if (mask & TileSet::BIND_TOPLEFT) { @@ -702,9 +745,9 @@ void TileSetEditor::_on_workspace_draw() { case EDITMODE_COLLISION: case EDITMODE_OCCLUSION: case EDITMODE_NAVIGATION: { - if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) { + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(get_current_tile()) == TileSet::ATLAS_TILE) { Vector2 coord = edited_shape_coord; - draw_highlight_tile(coord); + draw_highlight_subtile(coord); } draw_polygon_shapes(); draw_grid_snap(); @@ -723,89 +766,334 @@ void TileSetEditor::_on_workspace_draw() { } } spin_priority->set_suffix(" / " + String::num(total, 0)); - draw_highlight_tile(edited_shape_coord, queue_others); + draw_highlight_subtile(edited_shape_coord, queue_others); } break; } - if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) { - float j = -size.x; //make sure to draw at 0 - while (j < region.size.x) { - j += size.x; - if (spacing <= 0) { - workspace->draw_line(Point2(j, 0), Point2(j, region.size.y), c); - } else { - workspace->draw_rect(Rect2(Point2(j, 0), Size2(spacing, region.size.y)), c); - } - j += spacing; - } - j = -size.y; //make sure to draw at 0 - while (j < region.size.y) { - j += size.y; - if (spacing <= 0) { - workspace->draw_line(Point2(0, j), Point2(region.size.x, j), c); - } else { - workspace->draw_rect(Rect2(Point2(0, j), Size2(region.size.x, spacing)), c); - } - j += spacing; + draw_tile_subdivision(get_current_tile(), Color(0.347214, 0.722656, 0.617063)); + } + + RID current_texture_rid = get_current_texture()->get_rid(); + List<int> *tiles = new List<int>(); + tileset->get_tile_list(tiles); + for (List<int>::Element *E = tiles->front(); E; E = E->next()) { + int t_id = E->get(); + if (tileset->tile_get_texture(t_id)->get_rid() == current_texture_rid && (t_id != get_current_tile() || edit_mode != EDITMODE_REGION)) { + Rect2i region = tileset->tile_get_region(t_id); + region.position += WORKSPACE_MARGIN; + Color c; + if (tileset->tile_get_tile_mode(t_id) == TileSet::SINGLE_TILE) + c = COLOR_SINGLE; + else if (tileset->tile_get_tile_mode(t_id) == TileSet::AUTO_TILE) + c = COLOR_AUTOTILE; + else if (tileset->tile_get_tile_mode(t_id) == TileSet::ATLAS_TILE) + c = COLOR_ATLAS; + draw_tile_subdivision(t_id, Color(0.347214, 0.722656, 0.617063, 0.5)); + workspace->draw_rect(region, c, false); + } + } + if (edit_mode == EDITMODE_REGION) { + if (workspace_mode != WORKSPACE_EDIT) { + Rect2i region = edited_region; + Color c; + if (workspace_mode == WORKSPACE_CREATE_SINGLE) + c = COLOR_SINGLE; + else if (workspace_mode == WORKSPACE_CREATE_AUTOTILE) + c = COLOR_AUTOTILE; + else if (workspace_mode == WORKSPACE_CREATE_ATLAS) + c = COLOR_ATLAS; + workspace->draw_rect(region, c, false); + draw_edited_region_subdivision(); + } else { + int t_id = get_current_tile(); + Rect2i region; + if (draw_edited_region) + region = edited_region; + else { + region = tileset->tile_get_region(t_id); + region.position += WORKSPACE_MARGIN; } + Color c; + if (tileset->tile_get_tile_mode(t_id) == TileSet::SINGLE_TILE) + c = COLOR_SINGLE; + else if (tileset->tile_get_tile_mode(t_id) == TileSet::AUTO_TILE) + c = COLOR_AUTOTILE; + else if (tileset->tile_get_tile_mode(t_id) == TileSet::ATLAS_TILE) + c = COLOR_ATLAS; + if (draw_edited_region) + draw_edited_region_subdivision(); + else + draw_tile_subdivision(t_id, Color(0.347214, 0.722656, 0.617063, 1)); + workspace->draw_rect(region, c, false); } } workspace_overlay->update(); } +void TileSetEditor::_on_workspace_process() { + float a = tile_names_opacity; + if (Input::get_singleton()->is_key_pressed(KEY_ALT) || tools[VISIBLE_INFO]->is_pressed()) { + a += get_tree()->get_idle_process_time() * 2; + } else { + a -= get_tree()->get_idle_process_time() * 2; + } + + a = CLAMP(a, 0, 1); + if (a != tile_names_opacity) + workspace_overlay->update(); + tile_names_opacity = a; +} + void TileSetEditor::_on_workspace_overlay_draw() { + if (!tileset.is_valid()) + return; + if (!get_current_texture().is_valid()) + return; + + const Color COLOR_AUTOTILE = Color(0.266373, 0.565288, 0.988281); + const Color COLOR_SINGLE = Color(0.988281, 0.909323, 0.266373); + const Color COLOR_ATLAS = Color(0.78653, 0.812835, 0.832031); + + if (tile_names_opacity > 0) { + RID current_texture_rid = get_current_texture()->get_rid(); + List<int> *tiles = new List<int>(); + tileset->get_tile_list(tiles); + for (List<int>::Element *E = tiles->front(); E; E = E->next()) { + int t_id = E->get(); + if (tileset->tile_get_texture(t_id)->get_rid() == current_texture_rid) { + Rect2i region = tileset->tile_get_region(t_id); + region.position += WORKSPACE_MARGIN; + region.position *= workspace->get_scale().x; + Color c; + if (tileset->tile_get_tile_mode(t_id) == TileSet::SINGLE_TILE) + c = COLOR_SINGLE; + else if (tileset->tile_get_tile_mode(t_id) == TileSet::AUTO_TILE) + c = COLOR_AUTOTILE; + else if (tileset->tile_get_tile_mode(t_id) == TileSet::ATLAS_TILE) + c = COLOR_ATLAS; + c.a = tile_names_opacity; + Ref<Font> font = get_font("font", "Label"); + region.set_size(font->get_string_size(tileset->tile_get_name(t_id))); + workspace_overlay->draw_rect(region, c); + region.position.y += region.size.y - 2; + c = Color(0.1, 0.1, 0.1, tile_names_opacity); + workspace_overlay->draw_string(font, region.position, tileset->tile_get_name(t_id), c); + } + } + } + int t_id = get_current_tile(); - if (t_id < 0 || !draw_handles) + if (t_id < 0) return; Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons"); - - for (int i = 0; i < current_shape.size(); i++) { - workspace_overlay->draw_texture(handle, current_shape[i] * workspace->get_scale().x - handle->get_size() * 0.5); + if (draw_handles) { + for (int i = 0; i < current_shape.size(); i++) { + workspace_overlay->draw_texture(handle, current_shape[i] * workspace->get_scale().x - handle->get_size() * 0.5); + } } } #define MIN_DISTANCE_SQUARED 6 void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { + if (tileset.is_null()) + return; + if (!get_current_texture().is_valid()) + return; - if (get_current_tile() >= 0 && !tileset.is_null()) { - Ref<InputEventMouseButton> mb = p_ie; - Ref<InputEventMouseMotion> mm = p_ie; + static bool dragging; + static bool erasing; + draw_edited_region = false; - static bool dragging; - static bool erasing; + Rect2 current_tile_region = Rect2(); + if (get_current_tile() >= 0) { + current_tile_region = tileset->tile_get_region(get_current_tile()); + } + current_tile_region.position += WORKSPACE_MARGIN; + + Ref<InputEventMouseButton> mb = p_ie; + Ref<InputEventMouseMotion> mm = p_ie; + + if (mb.is_valid()) { + if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (!current_tile_region.has_point(mb->get_position())) { + List<int> *tiles = new List<int>(); + tileset->get_tile_list(tiles); + for (List<int>::Element *E = tiles->front(); E; E = E->next()) { + int t_id = E->get(); + if (get_current_texture()->get_rid() == tileset->tile_get_texture(t_id)->get_rid()) { + Rect2 r = tileset->tile_get_region(t_id); + r.position += WORKSPACE_MARGIN; + if (r.has_point(mb->get_position())) { + set_current_tile(t_id); + workspace->update(); + workspace_overlay->update(); + return; + } + } + } + } + } + } + // Drag Middle Mouse + if (mm.is_valid()) { + if (mm->get_button_mask() & BUTTON_MASK_MIDDLE) { + Vector2 dragged(mm->get_relative().x, mm->get_relative().y); + scroll->set_h_scroll(scroll->get_h_scroll() - dragged.x * workspace->get_scale().x); + scroll->set_v_scroll(scroll->get_v_scroll() - dragged.y * workspace->get_scale().x); + } + } - int spacing = tileset->autotile_get_spacing(get_current_tile()); - Vector2 size = tileset->autotile_get_size(get_current_tile()); - switch (edit_mode) { - case EDITMODE_ICON: { - if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - Vector2 coord((int)(mb->get_position().x / (spacing + size.x)), (int)(mb->get_position().y / (spacing + size.y))); - tileset->autotile_set_icon_coordinate(get_current_tile(), coord); - Rect2 region = tileset->tile_get_region(get_current_tile()); - region.size = size; - coord.x *= (spacing + size.x); - coord.y *= (spacing + size.y); - region.position += coord; - tile_list->set_item_icon_region(current_item_index, region); - workspace->update(); + if (edit_mode == EDITMODE_REGION) { + if (mb.is_valid()) { + if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (get_current_tile() >= 0 || workspace_mode != WORKSPACE_EDIT) { + dragging = true; + region_from = mb->get_position(); + edited_region = Rect2(region_from, Size2()); + workspace->update(); + workspace_overlay->update(); + return; + } + } else if (dragging && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) { + dragging = false; + edited_region = Rect2(); + workspace->update(); + workspace_overlay->update(); + return; + } else if (dragging && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + dragging = false; + update_edited_region(mb->get_position()); + edited_region.position -= WORKSPACE_MARGIN; + if (!edited_region.has_no_area()) { + if (get_current_tile() >= 0 && workspace_mode == WORKSPACE_EDIT) { + tileset->tile_set_region(get_current_tile(), edited_region); + } else { + int t_id = tileset->get_last_unused_tile_id(); + tileset->create_tile(t_id); + tileset->tile_set_texture(t_id, get_current_texture()); + tileset->tile_set_region(t_id, edited_region); + tileset->tile_set_name(t_id, get_current_texture()->get_path().get_file() + " " + String::num(t_id, 0)); + if (workspace_mode != WORKSPACE_CREATE_SINGLE) { + tileset->autotile_set_size(t_id, snap_step); + tileset->autotile_set_spacing(t_id, snap_separation.x); + tileset->tile_set_tile_mode(t_id, workspace_mode == WORKSPACE_CREATE_AUTOTILE ? TileSet::AUTO_TILE : TileSet::ATLAS_TILE); + } + set_current_tile(t_id); + tool_workspacemode[WORKSPACE_EDIT]->set_pressed(true); + _on_workspace_mode_changed(WORKSPACE_EDIT); } } - } break; - case EDITMODE_BITMASK: { - if (mb.is_valid()) { - if (mb->is_pressed()) { - if (dragging) { - return; + workspace->update(); + workspace_overlay->update(); + return; + } + } else if (mm.is_valid()) { + if (dragging) { + update_edited_region(mm->get_position()); + draw_edited_region = true; + workspace->update(); + workspace_overlay->update(); + return; + } + } + } + if (workspace_mode == WORKSPACE_EDIT) { + + if (get_current_tile() >= 0) { + int spacing = tileset->autotile_get_spacing(get_current_tile()); + Vector2 size = tileset->autotile_get_size(get_current_tile()); + switch (edit_mode) { + case EDITMODE_ICON: { + if (mb.is_valid()) { + if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && current_tile_region.has_point(mb->get_position())) { + Vector2 coord((int)((mb->get_position().x - current_tile_region.position.x) / (spacing + size.x)), (int)((mb->get_position().y - current_tile_region.position.y) / (spacing + size.y))); + tileset->autotile_set_icon_coordinate(get_current_tile(), coord); + Rect2 region = tileset->tile_get_region(get_current_tile()); + region.size = size; + coord.x *= (spacing + size.x); + coord.y *= (spacing + size.y); + region.position += coord; + workspace->update(); + } + } + } break; + case EDITMODE_BITMASK: { + if (mb.is_valid()) { + if (mb->is_pressed()) { + if (dragging) { + return; + } + if ((mb->get_button_index() == BUTTON_RIGHT || mb->get_button_index() == BUTTON_LEFT) && current_tile_region.has_point(mb->get_position())) { + dragging = true; + erasing = (mb->get_button_index() == BUTTON_RIGHT); + Vector2 coord((int)((mb->get_position().x - current_tile_region.position.x) / (spacing + size.x)), (int)((mb->get_position().y - current_tile_region.position.y) / (spacing + size.y))); + Vector2 pos(coord.x * (spacing + size.x), coord.y * (spacing + size.y)); + pos = mb->get_position() - (pos + current_tile_region.position); + uint16_t bit = 0; + if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_2X2) { + if (pos.x < size.x / 2) { + if (pos.y < size.y / 2) { + bit = TileSet::BIND_TOPLEFT; + } else { + bit = TileSet::BIND_BOTTOMLEFT; + } + } else { + if (pos.y < size.y / 2) { + bit = TileSet::BIND_TOPRIGHT; + } else { + bit = TileSet::BIND_BOTTOMRIGHT; + } + } + } else { + if (pos.x < size.x / 3) { + if (pos.y < size.y / 3) { + bit = TileSet::BIND_TOPLEFT; + } else if (pos.y > (size.y / 3) * 2) { + bit = TileSet::BIND_BOTTOMLEFT; + } else { + bit = TileSet::BIND_LEFT; + } + } else if (pos.x > (size.x / 3) * 2) { + if (pos.y < size.y / 3) { + bit = TileSet::BIND_TOPRIGHT; + } else if (pos.y > (size.y / 3) * 2) { + bit = TileSet::BIND_BOTTOMRIGHT; + } else { + bit = TileSet::BIND_RIGHT; + } + } else { + if (pos.y < size.y / 3) { + bit = TileSet::BIND_TOP; + } else if (pos.y > (size.y / 3) * 2) { + bit = TileSet::BIND_BOTTOM; + } else { + bit = TileSet::BIND_CENTER; + } + } + } + uint16_t mask = tileset->autotile_get_bitmask(get_current_tile(), coord); + if (erasing) { + mask &= ~bit; + } else { + mask |= bit; + } + tileset->autotile_set_bitmask(get_current_tile(), coord, mask); + workspace->update(); + } + } else { + if ((erasing && mb->get_button_index() == BUTTON_RIGHT) || (!erasing && mb->get_button_index() == BUTTON_LEFT)) { + dragging = false; + erasing = false; + } } - if (mb->get_button_index() == BUTTON_RIGHT || mb->get_button_index() == BUTTON_LEFT) { - dragging = true; - erasing = (mb->get_button_index() == BUTTON_RIGHT); - Vector2 coord((int)(mb->get_position().x / (spacing + size.x)), (int)(mb->get_position().y / (spacing + size.y))); + } + if (mm.is_valid()) { + if (dragging && current_tile_region.has_point(mm->get_position())) { + Vector2 coord((int)((mm->get_position().x - current_tile_region.position.x) / (spacing + size.x)), (int)((mm->get_position().y - current_tile_region.position.y) / (spacing + size.y))); Vector2 pos(coord.x * (spacing + size.x), coord.y * (spacing + size.y)); - pos = mb->get_position() - pos; + pos = mm->get_position() - (pos + current_tile_region.position); uint16_t bit = 0; if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_2X2) { if (pos.x < size.x / 2) { @@ -857,269 +1145,198 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { tileset->autotile_set_bitmask(get_current_tile(), coord, mask); workspace->update(); } - } else { - if ((erasing && mb->get_button_index() == BUTTON_RIGHT) || (!erasing && mb->get_button_index() == BUTTON_LEFT)) { - dragging = false; - erasing = false; - } } - } - if (mm.is_valid()) { - if (dragging) { - Vector2 coord((int)(mm->get_position().x / (spacing + size.x)), (int)(mm->get_position().y / (spacing + size.y))); - Vector2 pos(coord.x * (spacing + size.x), coord.y * (spacing + size.y)); - pos = mm->get_position() - pos; - uint16_t bit = 0; - if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_2X2) { - if (pos.x < size.x / 2) { - if (pos.y < size.y / 2) { - bit = TileSet::BIND_TOPLEFT; - } else { - bit = TileSet::BIND_BOTTOMLEFT; - } - } else { - if (pos.y < size.y / 2) { - bit = TileSet::BIND_TOPRIGHT; - } else { - bit = TileSet::BIND_BOTTOMRIGHT; - } - } - } else { - if (pos.x < size.x / 3) { - if (pos.y < size.y / 3) { - bit = TileSet::BIND_TOPLEFT; - } else if (pos.y > (size.y / 3) * 2) { - bit = TileSet::BIND_BOTTOMLEFT; - } else { - bit = TileSet::BIND_LEFT; - } - } else if (pos.x > (size.x / 3) * 2) { - if (pos.y < size.y / 3) { - bit = TileSet::BIND_TOPRIGHT; - } else if (pos.y > (size.y / 3) * 2) { - bit = TileSet::BIND_BOTTOMRIGHT; - } else { - bit = TileSet::BIND_RIGHT; - } - } else { - if (pos.y < size.y / 3) { - bit = TileSet::BIND_TOP; - } else if (pos.y > (size.y / 3) * 2) { - bit = TileSet::BIND_BOTTOM; - } else { - bit = TileSet::BIND_CENTER; - } - } - } - uint16_t mask = tileset->autotile_get_bitmask(get_current_tile(), coord); - if (erasing) { - mask &= ~bit; - } else { - mask |= bit; - } - tileset->autotile_set_bitmask(get_current_tile(), coord, mask); - workspace->update(); + } break; + case EDITMODE_COLLISION: + case EDITMODE_OCCLUSION: + case EDITMODE_NAVIGATION: + case EDITMODE_PRIORITY: { + Vector2 shape_anchor = Vector2(0, 0); + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(get_current_tile()) == TileSet::ATLAS_TILE) { + shape_anchor = edited_shape_coord; + shape_anchor.x *= (size.x + spacing); + shape_anchor.y *= (size.y + spacing); } - } - } break; - case EDITMODE_COLLISION: - case EDITMODE_OCCLUSION: - case EDITMODE_NAVIGATION: - case EDITMODE_PRIORITY: { - Vector2 shape_anchor = Vector2(0, 0); - if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) { - shape_anchor = edited_shape_coord; - shape_anchor.x *= (size.x + spacing); - shape_anchor.y *= (size.y + spacing); - } - if (tools[TOOL_SELECT]->is_pressed()) { - if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - if (edit_mode != EDITMODE_PRIORITY && current_shape.size() > 0) { - for (int i = 0; i < current_shape.size(); i++) { - if ((current_shape[i] - mb->get_position()).length_squared() <= MIN_DISTANCE_SQUARED) { - dragging_point = i; - workspace->update(); - return; + shape_anchor += current_tile_region.position; + if (tools[TOOL_SELECT]->is_pressed()) { + if (mb.is_valid()) { + if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (edit_mode != EDITMODE_PRIORITY && current_shape.size() > 0) { + for (int i = 0; i < current_shape.size(); i++) { + if ((current_shape[i] - mb->get_position()).length_squared() <= MIN_DISTANCE_SQUARED) { + dragging_point = i; + workspace->update(); + return; + } } } - } - if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) { - Vector2 coord((int)(mb->get_position().x / (spacing + size.x)), (int)(mb->get_position().y / (spacing + size.y))); - if (edited_shape_coord != coord) { - edited_shape_coord = coord; - edited_occlusion_shape = tileset->autotile_get_light_occluder(get_current_tile(), edited_shape_coord); - edited_navigation_shape = tileset->autotile_get_navigation_polygon(get_current_tile(), edited_shape_coord); - Vector<TileSet::ShapeData> sd = tileset->tile_get_shapes(get_current_tile()); - bool found_collision_shape = false; - for (int i = 0; i < sd.size(); i++) { - if (sd[i].autotile_coord == coord) { - edited_collision_shape = sd[i].shape; - found_collision_shape = true; - break; + if ((tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(get_current_tile()) == TileSet::ATLAS_TILE) && current_tile_region.has_point(mb->get_position())) { + Vector2 coord((int)((mb->get_position().x - current_tile_region.position.x) / (spacing + size.x)), (int)((mb->get_position().y - current_tile_region.position.y) / (spacing + size.y))); + if (edited_shape_coord != coord) { + edited_shape_coord = coord; + edited_occlusion_shape = tileset->autotile_get_light_occluder(get_current_tile(), edited_shape_coord); + edited_navigation_shape = tileset->autotile_get_navigation_polygon(get_current_tile(), edited_shape_coord); + Vector<TileSet::ShapeData> sd = tileset->tile_get_shapes(get_current_tile()); + bool found_collision_shape = false; + for (int i = 0; i < sd.size(); i++) { + if (sd[i].autotile_coord == coord) { + edited_collision_shape = sd[i].shape; + found_collision_shape = true; + break; + } } + if (!found_collision_shape) + edited_collision_shape = Ref<ConvexPolygonShape2D>(NULL); + select_coord(edited_shape_coord); } - if (!found_collision_shape) - edited_collision_shape = Ref<ConvexPolygonShape2D>(NULL); - select_coord(edited_shape_coord); } - } - workspace->update(); - } else if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - if (edit_mode == EDITMODE_COLLISION) { - if (dragging_point >= 0) { - dragging_point = -1; + workspace->update(); + } else if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (edit_mode == EDITMODE_COLLISION) { + if (dragging_point >= 0) { + dragging_point = -1; - Vector<Vector2> points; + Vector<Vector2> points; - for (int i = 0; i < current_shape.size(); i++) { - Vector2 p = current_shape[i]; - if (tools[SHAPE_GRID_SNAP]->is_pressed() || tools[SHAPE_KEEP_INSIDE_TILE]->is_pressed()) { - p = snap_point(p); + for (int i = 0; i < current_shape.size(); i++) { + Vector2 p = current_shape[i]; + if (tools[TOOL_GRID_SNAP]->is_pressed() || tools[SHAPE_KEEP_INSIDE_TILE]->is_pressed()) { + p = snap_point(p); + } + points.push_back(p - shape_anchor); } - points.push_back(p - shape_anchor); - } - edited_collision_shape->set_points(points); + edited_collision_shape->set_points(points); - workspace->update(); - } - } else if (edit_mode == EDITMODE_OCCLUSION) { - if (dragging_point >= 0) { - dragging_point = -1; - - PoolVector<Vector2> polygon; - polygon.resize(current_shape.size()); - PoolVector<Vector2>::Write w = polygon.write(); - - for (int i = 0; i < current_shape.size(); i++) { - w[i] = current_shape[i] - shape_anchor; + workspace->update(); } + } else if (edit_mode == EDITMODE_OCCLUSION) { + if (dragging_point >= 0) { + dragging_point = -1; - w = PoolVector<Vector2>::Write(); - edited_occlusion_shape->set_polygon(polygon); + PoolVector<Vector2> polygon; + polygon.resize(current_shape.size()); + PoolVector<Vector2>::Write w = polygon.write(); - workspace->update(); - } - } else if (edit_mode == EDITMODE_NAVIGATION) { - if (dragging_point >= 0) { - dragging_point = -1; + for (int i = 0; i < current_shape.size(); i++) { + w[i] = current_shape[i] - shape_anchor; + } - PoolVector<Vector2> polygon; - Vector<int> indices; - polygon.resize(current_shape.size()); - PoolVector<Vector2>::Write w = polygon.write(); + w = PoolVector<Vector2>::Write(); + edited_occlusion_shape->set_polygon(polygon); - for (int i = 0; i < current_shape.size(); i++) { - w[i] = current_shape[i] - shape_anchor; - indices.push_back(i); + workspace->update(); } + } else if (edit_mode == EDITMODE_NAVIGATION) { + if (dragging_point >= 0) { + dragging_point = -1; + + PoolVector<Vector2> polygon; + Vector<int> indices; + polygon.resize(current_shape.size()); + PoolVector<Vector2>::Write w = polygon.write(); + + for (int i = 0; i < current_shape.size(); i++) { + w[i] = current_shape[i] - shape_anchor; + indices.push_back(i); + } - w = PoolVector<Vector2>::Write(); - edited_navigation_shape->set_vertices(polygon); - edited_navigation_shape->add_polygon(indices); - - workspace->update(); - } - } - } - } else if (mm.is_valid()) { - if (dragging_point >= 0) { - current_shape.set(dragging_point, snap_point(mm->get_position())); - workspace->update(); - } - } - } else if (tools[SHAPE_NEW_POLYGON]->is_pressed()) { + w = PoolVector<Vector2>::Write(); + edited_navigation_shape->set_vertices(polygon); + edited_navigation_shape->add_polygon(indices); - if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - Vector2 pos = mb->get_position(); - pos = snap_point(pos); - if (creating_shape) { - if (current_shape.size() > 0) { - if ((pos - current_shape[0]).length_squared() <= MIN_DISTANCE_SQUARED) { - if (current_shape.size() > 2) { - close_shape(shape_anchor); - workspace->update(); - return; - } + workspace->update(); } } - current_shape.push_back(pos); + } + } else if (mm.is_valid()) { + if (dragging_point >= 0) { + current_shape.set(dragging_point, snap_point(mm->get_position())); workspace->update(); - } else { - int t_id = get_current_tile(); - if (t_id >= 0) { - if (edit_mode == EDITMODE_COLLISION) { - Vector<TileSet::ShapeData> sd = tileset->tile_get_shapes(t_id); - for (int i = 0; i < sd.size(); i++) { - if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE || sd[i].autotile_coord == edited_shape_coord) { - Ref<ConvexPolygonShape2D> shape = sd[i].shape; - - if (!shape.is_null()) { - sd.remove(i); - tileset->tile_set_shapes(get_current_tile(), sd); - edited_collision_shape = Ref<Shape2D>(); - workspace->update(); - } - break; + } + } + } else if (tools[SHAPE_NEW_POLYGON]->is_pressed()) { + + if (mb.is_valid()) { + if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + Vector2 pos = mb->get_position(); + pos = snap_point(pos); + if (creating_shape) { + if (current_shape.size() > 0) { + if ((pos - current_shape[0]).length_squared() <= MIN_DISTANCE_SQUARED) { + if (current_shape.size() > 2) { + close_shape(shape_anchor); + workspace->update(); + return; } } - } else if (edit_mode == EDITMODE_OCCLUSION) { - if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) { - Map<Vector2, Ref<OccluderPolygon2D> > map = tileset->autotile_get_light_oclusion_map(t_id); - for (Map<Vector2, Ref<OccluderPolygon2D> >::Element *E = map.front(); E; E = E->next()) { - if (E->key() == edited_shape_coord) { - tileset->autotile_set_light_occluder(get_current_tile(), Ref<OccluderPolygon2D>(), edited_shape_coord); + } + current_shape.push_back(pos); + workspace->update(); + } else { + int t_id = get_current_tile(); + if (t_id >= 0) { + if (edit_mode == EDITMODE_COLLISION) { + Vector<TileSet::ShapeData> sd = tileset->tile_get_shapes(t_id); + for (int i = 0; i < sd.size(); i++) { + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE || sd[i].autotile_coord == edited_shape_coord) { + Ref<ConvexPolygonShape2D> shape = sd[i].shape; + + if (!shape.is_null()) { + sd.remove(i); + tileset->tile_set_shapes(get_current_tile(), sd); + edited_collision_shape = Ref<Shape2D>(); + workspace->update(); + } break; } } - } else - tileset->tile_set_light_occluder(t_id, Ref<OccluderPolygon2D>()); + } else if (edit_mode == EDITMODE_OCCLUSION) { + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(get_current_tile()) == TileSet::ATLAS_TILE) { + Map<Vector2, Ref<OccluderPolygon2D> > map = tileset->autotile_get_light_oclusion_map(t_id); + for (Map<Vector2, Ref<OccluderPolygon2D> >::Element *E = map.front(); E; E = E->next()) { + if (E->key() == edited_shape_coord) { + tileset->autotile_set_light_occluder(get_current_tile(), Ref<OccluderPolygon2D>(), edited_shape_coord); + break; + } + } + } else + tileset->tile_set_light_occluder(t_id, Ref<OccluderPolygon2D>()); - edited_occlusion_shape = Ref<OccluderPolygon2D>(); - workspace->update(); - } else if (edit_mode == EDITMODE_NAVIGATION) { - if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) { - Map<Vector2, Ref<NavigationPolygon> > map = tileset->autotile_get_navigation_map(t_id); - for (Map<Vector2, Ref<NavigationPolygon> >::Element *E = map.front(); E; E = E->next()) { - if (E->key() == edited_shape_coord) { - tileset->autotile_set_navigation_polygon(t_id, Ref<NavigationPolygon>(), edited_shape_coord); - break; + edited_occlusion_shape = Ref<OccluderPolygon2D>(); + workspace->update(); + } else if (edit_mode == EDITMODE_NAVIGATION) { + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(get_current_tile()) == TileSet::ATLAS_TILE) { + Map<Vector2, Ref<NavigationPolygon> > map = tileset->autotile_get_navigation_map(t_id); + for (Map<Vector2, Ref<NavigationPolygon> >::Element *E = map.front(); E; E = E->next()) { + if (E->key() == edited_shape_coord) { + tileset->autotile_set_navigation_polygon(t_id, Ref<NavigationPolygon>(), edited_shape_coord); + break; + } } - } - } else - tileset->tile_set_navigation_polygon(t_id, Ref<NavigationPolygon>()); - edited_navigation_shape = Ref<NavigationPolygon>(); - workspace->update(); + } else + tileset->tile_set_navigation_polygon(t_id, Ref<NavigationPolygon>()); + edited_navigation_shape = Ref<NavigationPolygon>(); + workspace->update(); + } } - } - creating_shape = true; - current_shape.resize(0); - current_shape.push_back(snap_point(pos)); + creating_shape = true; + current_shape.resize(0); + current_shape.push_back(snap_point(pos)); + } + } else if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT && current_shape.size() > 2) { + if (creating_shape) { + close_shape(shape_anchor); + } } - } else if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT && current_shape.size() > 2) { + } else if (mm.is_valid()) { if (creating_shape) { - close_shape(shape_anchor); + workspace->update(); } } - } else if (mm.is_valid()) { - if (creating_shape) { - workspace->update(); - } } - } - } break; - } - - //Drag Middle Mouse - if (mm.is_valid()) { - if (mm->get_button_mask() & BUTTON_MASK_MIDDLE) { - - Vector2 dragged(mm->get_relative().x, mm->get_relative().y); - scroll->set_h_scroll(scroll->get_h_scroll() - dragged.x * workspace->get_scale().x); - scroll->set_v_scroll(scroll->get_v_scroll() - dragged.y * workspace->get_scale().x); + } break; } } } @@ -1144,6 +1361,16 @@ void TileSetEditor::_on_tool_clicked(int p_tool) { workspace->update(); } else { switch (edit_mode) { + case EDITMODE_REGION: { + if (workspace_mode == WORKSPACE_EDIT && get_current_tile() >= 0) { + tileset->remove_tile(get_current_tile()); + workspace->update(); + workspace_overlay->update(); + } + tool_workspacemode[WORKSPACE_EDIT]->set_pressed(true); + workspace_mode = WORKSPACE_EDIT; + update_workspace_tile_mode(); + } break; case EDITMODE_COLLISION: { if (!edited_collision_shape.is_null()) { Vector<TileSet::ShapeData> sd = tileset->tile_get_shapes(get_current_tile()); @@ -1186,22 +1413,22 @@ void TileSetEditor::_on_tool_clicked(int p_tool) { if (scale > 0.1) { scale /= 2; workspace->set_scale(Vector2(scale, scale)); - workspace_container->set_custom_minimum_size(preview->get_region_rect().size * scale); - workspace_overlay->set_custom_minimum_size(preview->get_region_rect().size * scale); + workspace_container->set_custom_minimum_size(workspace->get_rect().size * scale); + workspace_overlay->set_custom_minimum_size(workspace->get_rect().size * scale); } } else if (p_tool == ZOOM_1) { workspace->set_scale(Vector2(1, 1)); - workspace_container->set_custom_minimum_size(preview->get_region_rect().size); - workspace_overlay->set_custom_minimum_size(preview->get_region_rect().size); + workspace_container->set_custom_minimum_size(workspace->get_rect().size); + workspace_overlay->set_custom_minimum_size(workspace->get_rect().size); } else if (p_tool == ZOOM_IN) { float scale = workspace->get_scale().x; scale *= 2; workspace->set_scale(Vector2(scale, scale)); - workspace_container->set_custom_minimum_size(preview->get_region_rect().size * scale); - workspace_overlay->set_custom_minimum_size(preview->get_region_rect().size * scale); + workspace_container->set_custom_minimum_size(workspace->get_rect().size * scale); + workspace_overlay->set_custom_minimum_size(workspace->get_rect().size * scale); } else if (p_tool == TOOL_SELECT) { if (creating_shape) { - //Cancel Creation + // Cancel Creation creating_shape = false; current_shape.resize(0); workspace->update(); @@ -1215,66 +1442,140 @@ void TileSetEditor::_on_priority_changed(float val) { } void TileSetEditor::_on_grid_snap_toggled(bool p_val) { - if (p_val) - hb_grid->show(); - else - hb_grid->hide(); + helper->set_snap_options_visible(p_val); workspace->update(); } -void TileSetEditor::_set_snap_step_x(float p_val) { - snap_step.x = p_val; +void TileSetEditor::_set_snap_step(Vector2 p_val) { + snap_step.x = CLAMP(p_val.x, 0, 256); + snap_step.y = CLAMP(p_val.y, 0, 256); workspace->update(); } -void TileSetEditor::_set_snap_step_y(float p_val) { - snap_step.y = p_val; +void TileSetEditor::_set_snap_off(Vector2 p_val) { + snap_offset.x = CLAMP(p_val.x, 0, 256 + WORKSPACE_MARGIN.x); + snap_offset.y = CLAMP(p_val.y, 0, 256 + WORKSPACE_MARGIN.y); workspace->update(); } -void TileSetEditor::_set_snap_off_x(float p_val) { - snap_offset.x = p_val; +void TileSetEditor::_set_snap_sep(Vector2 p_val) { + snap_separation.x = CLAMP(p_val.x, 0, 256); + snap_separation.y = CLAMP(p_val.y, 0, 256); workspace->update(); } -void TileSetEditor::_set_snap_off_y(float p_val) { - snap_offset.y = p_val; - workspace->update(); -} -void TileSetEditor::_set_snap_sep_x(float p_val) { - snap_separation.x = p_val; - workspace->update(); -} +void TileSetEditor::draw_highlight_current_tile() { -void TileSetEditor::_set_snap_sep_y(float p_val) { - snap_separation.y = p_val; - workspace->update(); + if (get_current_tile() >= 0) { + Rect2 region = tileset->tile_get_region(get_current_tile()); + region.position += WORKSPACE_MARGIN; + workspace->draw_rect(Rect2(0, 0, workspace->get_rect().size.x, region.position.y), Color(0.3, 0.3, 0.3, 0.3)); + workspace->draw_rect(Rect2(0, region.position.y, region.position.x, region.size.y), Color(0.3, 0.3, 0.3, 0.3)); + workspace->draw_rect(Rect2(region.position.x + region.size.x, region.position.y, workspace->get_rect().size.x - region.position.x - region.size.x, region.size.y), Color(0.3, 0.3, 0.3, 0.3)); + workspace->draw_rect(Rect2(0, region.position.y + region.size.y, workspace->get_rect().size.x, workspace->get_rect().size.y - region.size.y - region.position.y), Color(0.3, 0.3, 0.3, 0.3)); + } else { + workspace->draw_rect(Rect2(Point2(0, 0), workspace->get_rect().size), Color(0.3, 0.3, 0.3, 0.3)); + } } -void TileSetEditor::draw_highlight_tile(Vector2 coord, const Vector<Vector2> &other_highlighted) { +void TileSetEditor::draw_highlight_subtile(Vector2 coord, const Vector<Vector2> &other_highlighted) { Vector2 size = tileset->autotile_get_size(get_current_tile()); int spacing = tileset->autotile_get_spacing(get_current_tile()); Rect2 region = tileset->tile_get_region(get_current_tile()); coord.x *= (size.x + spacing); coord.y *= (size.y + spacing); - workspace->draw_rect(Rect2(0, 0, region.size.x, coord.y), Color(0.5, 0.5, 0.5, 0.5)); - workspace->draw_rect(Rect2(0, coord.y, coord.x, size.y), Color(0.5, 0.5, 0.5, 0.5)); - workspace->draw_rect(Rect2(coord.x + size.x, coord.y, region.size.x - coord.x - size.x, size.y), Color(0.5, 0.5, 0.5, 0.5)); - workspace->draw_rect(Rect2(0, coord.y + size.y, region.size.x, region.size.y - size.y - coord.y), Color(0.5, 0.5, 0.5, 0.5)); + coord += region.position; + coord += WORKSPACE_MARGIN; + workspace->draw_rect(Rect2(0, 0, workspace->get_rect().size.x, coord.y), Color(0.3, 0.3, 0.3, 0.3)); + workspace->draw_rect(Rect2(0, coord.y, coord.x, size.y), Color(0.3, 0.3, 0.3, 0.3)); + workspace->draw_rect(Rect2(coord.x + size.x, coord.y, workspace->get_rect().size.x - coord.x - size.x, size.y), Color(0.3, 0.3, 0.3, 0.3)); + workspace->draw_rect(Rect2(0, coord.y + size.y, workspace->get_rect().size.x, workspace->get_rect().size.y - size.y - coord.y), Color(0.3, 0.3, 0.3, 0.3)); coord += Vector2(1, 1) / workspace->get_scale().x; workspace->draw_rect(Rect2(coord, size - Vector2(2, 2) / workspace->get_scale().x), Color(1, 0, 0), false); for (int i = 0; i < other_highlighted.size(); i++) { coord = other_highlighted[i]; coord.x *= (size.x + spacing); coord.y *= (size.y + spacing); + coord += region.position; + coord += WORKSPACE_MARGIN; coord += Vector2(1, 1) / workspace->get_scale().x; - workspace->draw_rect(Rect2(coord, size - Vector2(2, 2) / workspace->get_scale().x), Color(1, 0, 0), false); + workspace->draw_rect(Rect2(coord, size - Vector2(2, 2) / workspace->get_scale().x), Color(1, 0.5, 0.5), false); + } +} + +void TileSetEditor::draw_tile_subdivision(int p_id, Color p_color) const { + Color c = p_color; + if (tileset->tile_get_tile_mode(p_id) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(p_id) == TileSet::ATLAS_TILE) { + Rect2 region = tileset->tile_get_region(p_id); + Size2 size = tileset->autotile_get_size(p_id); + int spacing = tileset->autotile_get_spacing(p_id); + float j = 0; + while (j < region.size.x) { + j += size.x; + if (spacing <= 0) { + workspace->draw_line(region.position + WORKSPACE_MARGIN + Point2(j, 0), region.position + WORKSPACE_MARGIN + Point2(j, region.size.y), c); + } else { + workspace->draw_rect(Rect2(region.position + WORKSPACE_MARGIN + Point2(j, 0), Size2(spacing, region.size.y)), c); + } + j += spacing; + } + j = 0; + while (j < region.size.y) { + j += size.y; + if (spacing <= 0) { + workspace->draw_line(region.position + WORKSPACE_MARGIN + Point2(0, j), region.position + WORKSPACE_MARGIN + Point2(region.size.x, j), c); + } else { + workspace->draw_rect(Rect2(region.position + WORKSPACE_MARGIN + Point2(0, j), Size2(region.size.x, spacing)), c); + } + j += spacing; + } + } +} + +void TileSetEditor::draw_edited_region_subdivision() const { + Color c = Color(0.347214, 0.722656, 0.617063, 1); + Rect2 region = edited_region; + Size2 size; + int spacing; + bool draw; + if (workspace_mode == WORKSPACE_EDIT) { + int p_id = get_current_tile(); + size = tileset->autotile_get_size(p_id); + spacing = tileset->autotile_get_spacing(p_id); + draw = tileset->tile_get_tile_mode(p_id) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(p_id) == TileSet::ATLAS_TILE; + } else { + size = snap_step; + spacing = snap_separation.x; + draw = workspace_mode != WORKSPACE_CREATE_SINGLE; + } + if (draw) { + + float j = 0; + while (j < region.size.x) { + j += size.x; + if (spacing <= 0) { + workspace->draw_line(region.position + Point2(j, 0), region.position + Point2(j, region.size.y), c); + } else { + workspace->draw_rect(Rect2(region.position + Point2(j, 0), Size2(spacing, region.size.y)), c); + } + j += spacing; + } + j = 0; + while (j < region.size.y) { + j += size.y; + if (spacing <= 0) { + workspace->draw_line(region.position + Point2(0, j), region.position + Point2(region.size.x, j), c); + } else { + workspace->draw_rect(Rect2(region.position + Point2(0, j), Size2(region.size.x, spacing)), c); + } + j += spacing; + } } } void TileSetEditor::draw_grid_snap() { - if (tools[SHAPE_GRID_SNAP]->is_pressed()) { + if (tools[TOOL_GRID_SNAP]->is_pressed()) { Color grid_color = Color(0.39, 0, 1, 0.2f); Size2 s = workspace->get_size(); @@ -1328,7 +1629,7 @@ void TileSetEditor::draw_polygon_shapes() { for (int i = 0; i < sd.size(); i++) { Vector2 coord = Vector2(0, 0); Vector2 anchor = Vector2(0, 0); - if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) { + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(get_current_tile()) == TileSet::ATLAS_TILE) { coord = sd[i].autotile_coord; anchor = tileset->autotile_get_size(t_id); anchor.x += tileset->autotile_get_spacing(t_id); @@ -1336,6 +1637,8 @@ void TileSetEditor::draw_polygon_shapes() { anchor.x *= coord.x; anchor.y *= coord.y; } + anchor += WORKSPACE_MARGIN; + anchor += tileset->tile_get_region(t_id).position; Ref<ConvexPolygonShape2D> shape = sd[i].shape; if (shape.is_valid()) { Color c_bg; @@ -1407,6 +1710,8 @@ void TileSetEditor::draw_polygon_shapes() { anchor.y += tileset->autotile_get_spacing(t_id); anchor.x *= coord.x; anchor.y *= coord.y; + anchor += WORKSPACE_MARGIN; + anchor += tileset->tile_get_region(t_id).position; Ref<OccluderPolygon2D> shape = E->value(); if (shape.is_valid()) { Color c_bg; @@ -1483,6 +1788,8 @@ void TileSetEditor::draw_polygon_shapes() { anchor.y += tileset->autotile_get_spacing(t_id); anchor.x *= coord.x; anchor.y *= coord.y; + anchor += WORKSPACE_MARGIN; + anchor += tileset->tile_get_region(t_id).position; Ref<NavigationPolygon> shape = E->value(); if (shape.is_valid()) { Color c_bg; @@ -1558,10 +1865,10 @@ void TileSetEditor::close_shape(const Vector2 &shape_anchor) { shape->set_points(segments); - if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(get_current_tile()) == TileSet::ATLAS_TILE) tileset->tile_add_shape(get_current_tile(), shape, Transform2D(), false, edited_shape_coord); else - tileset->tile_set_shape(get_current_tile(), 0, shape); + tileset->tile_add_shape(get_current_tile(), shape, Transform2D()); edited_collision_shape = shape; } @@ -1582,7 +1889,7 @@ void TileSetEditor::close_shape(const Vector2 &shape_anchor) { w = PoolVector<Vector2>::Write(); shape->set_polygon(polygon); - if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(get_current_tile()) == TileSet::ATLAS_TILE) tileset->autotile_set_light_occluder(get_current_tile(), shape, edited_shape_coord); else tileset->tile_set_light_occluder(get_current_tile(), shape); @@ -1606,7 +1913,7 @@ void TileSetEditor::close_shape(const Vector2 &shape_anchor) { shape->set_vertices(polygon); shape->add_polygon(indices); - if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(get_current_tile()) == TileSet::ATLAS_TILE) tileset->autotile_set_navigation_polygon(get_current_tile(), shape, edited_shape_coord); else tileset->tile_set_navigation_polygon(get_current_tile(), shape); @@ -1619,6 +1926,8 @@ void TileSetEditor::close_shape(const Vector2 &shape_anchor) { void TileSetEditor::select_coord(const Vector2 &coord) { current_shape = PoolVector2Array(); + Rect2 current_tile_region = tileset->tile_get_region(get_current_tile()); + current_tile_region.position += WORKSPACE_MARGIN; if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) { if (edited_collision_shape != tileset->tile_get_shape(get_current_tile(), 0)) edited_collision_shape = tileset->tile_get_shape(get_current_tile(), 0); @@ -1631,14 +1940,14 @@ void TileSetEditor::select_coord(const Vector2 &coord) { current_shape.resize(0); if (edited_collision_shape.is_valid()) { for (int i = 0; i < edited_collision_shape->get_points().size(); i++) { - current_shape.push_back(edited_collision_shape->get_points()[i]); + current_shape.push_back(edited_collision_shape->get_points()[i] + current_tile_region.position); } } } else if (edit_mode == EDITMODE_OCCLUSION) { current_shape.resize(0); if (edited_occlusion_shape.is_valid()) { for (int i = 0; i < edited_occlusion_shape->get_polygon().size(); i++) { - current_shape.push_back(edited_occlusion_shape->get_polygon()[i]); + current_shape.push_back(edited_occlusion_shape->get_polygon()[i] + current_tile_region.position); } } } else if (edit_mode == EDITMODE_NAVIGATION) { @@ -1647,7 +1956,7 @@ void TileSetEditor::select_coord(const Vector2 &coord) { if (edited_navigation_shape->get_polygon_count() > 0) { PoolVector<Vector2> vertices = edited_navigation_shape->get_vertices(); for (int i = 0; i < edited_navigation_shape->get_polygon(0).size(); i++) { - current_shape.push_back(vertices[edited_navigation_shape->get_polygon(0)[i]]); + current_shape.push_back(vertices[edited_navigation_shape->get_polygon(0)[i]] + current_tile_region.position); } } } @@ -1658,6 +1967,7 @@ void TileSetEditor::select_coord(const Vector2 &coord) { Vector2 shape_anchor = coord; shape_anchor.x *= (size.x + spacing); shape_anchor.y *= (size.y + spacing); + shape_anchor += current_tile_region.position; if (edit_mode == EDITMODE_COLLISION) { current_shape.resize(0); if (edited_collision_shape.is_valid()) { @@ -1684,6 +1994,9 @@ void TileSetEditor::select_coord(const Vector2 &coord) { } } } + workspace->update(); + workspace_container->update(); + helper->_change_notify(""); } Vector2 TileSetEditor::snap_point(const Vector2 &point) { @@ -1694,11 +2007,13 @@ Vector2 TileSetEditor::snap_point(const Vector2 &point) { Vector2 anchor = coord; anchor.x *= (tile_size.x + spacing); anchor.y *= (tile_size.y + spacing); + anchor += tileset->tile_get_region(get_current_tile()).position; + anchor += WORKSPACE_MARGIN; Rect2 region(anchor, tile_size); if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) - region.position = Point2(0, 0); + region.position = tileset->tile_get_region(get_current_tile()).position + WORKSPACE_MARGIN; - if (tools[SHAPE_GRID_SNAP]->is_pressed()) { + if (tools[TOOL_GRID_SNAP]->is_pressed()) { p.x = Math::snap_scalar_seperation(snap_offset.x, snap_step.x, p.x, snap_separation.x); p.y = Math::snap_scalar_seperation(snap_offset.y, snap_step.y, p.y, snap_separation.y); } @@ -1715,211 +2030,332 @@ Vector2 TileSetEditor::snap_point(const Vector2 &point) { return p; } -void TileSetEditor::update_tile_list() { - int selected_tile = get_current_tile(); - - if (selected_tile < 0) - selected_tile = 0; +void TileSetEditor::update_texture_list() { + Ref<Texture> selected_texture = get_current_texture(); helper->set_tileset(tileset); - tile_list->clear(); List<int> ids; tileset->get_tile_list(&ids); for (List<int>::Element *E = ids.front(); E; E = E->next()) { - tile_list->add_item(tileset->tile_get_name(E->get())); - tile_list->set_item_metadata(tile_list->get_item_count() - 1, E->get()); - tile_list->set_item_icon(tile_list->get_item_count() - 1, tileset->tile_get_texture(E->get())); - Rect2 region = tileset->tile_get_region(E->get()); - if (tileset->tile_get_tile_mode(E->get()) == TileSet::AUTO_TILE) { - region.size = tileset->autotile_get_size(E->get()); - Vector2 pos = tileset->autotile_get_icon_coordinate(E->get()); - pos.x *= (tileset->autotile_get_spacing(E->get()) + region.size.x); - pos.y *= (tileset->autotile_get_spacing(E->get()) + region.size.y); - region.position += pos; + if (!texture_map.has(tileset->tile_get_texture(E->get())->get_rid())) { + texture_list->add_item(tileset->tile_get_texture(E->get())->get_path().get_file()); + texture_map.insert(tileset->tile_get_texture(E->get())->get_rid(), tileset->tile_get_texture(E->get())); + texture_list->set_item_metadata(texture_list->get_item_count() - 1, tileset->tile_get_texture(E->get())->get_rid()); } - tile_list->set_item_icon_region(tile_list->get_item_count() - 1, region); - tile_list->set_item_icon_modulate(tile_list->get_item_count() - 1, tileset->tile_get_modulate(E->get())); } - if (tile_list->get_item_count() > 0 && selected_tile < tile_list->get_item_count()) { - tile_list->select(selected_tile); - _on_tile_list_selected(selected_tile); + if (texture_list->get_item_count() > 0 && selected_texture.is_valid()) { + texture_list->select(texture_list->find_metadata(selected_texture->get_rid())); + if (texture_list->get_selected_items().size() > 0) + _on_texture_list_selected(texture_list->get_selected_items()[0]); + } else if (get_current_texture().is_valid()) { + _on_texture_list_selected(texture_list->find_metadata(get_current_texture()->get_rid())); + } else { + _on_texture_list_selected(-1); } + update_texture_list_icon(); helper->_change_notify(""); } -void TileSetEditor::update_tile_list_icon() { - List<int> ids; - tileset->get_tile_list(&ids); - int current_idx = 0; - for (List<int>::Element *E = ids.front(); E; E = E->next()) { - if (current_idx >= tile_list->get_item_count()) - break; - - Rect2 region = tileset->tile_get_region(E->get()); - if (tileset->tile_get_tile_mode(E->get()) == TileSet::AUTO_TILE) { - region.size = tileset->autotile_get_size(E->get()); - Vector2 pos = tileset->autotile_get_icon_coordinate(E->get()); - pos.x *= (tileset->autotile_get_spacing(E->get()) + region.size.x); - pos.y *= (tileset->autotile_get_spacing(E->get()) + region.size.y); - region.position += pos; - } - tile_list->set_item_metadata(current_idx, E->get()); - tile_list->set_item_icon(current_idx, tileset->tile_get_texture(E->get())); - tile_list->set_item_icon_region(current_idx, region); - tile_list->set_item_icon_modulate(current_idx, tileset->tile_get_modulate(E->get())); - tile_list->set_item_text(current_idx, tileset->tile_get_name(E->get())); - current_idx += 1; +void TileSetEditor::update_texture_list_icon() { + + for (int current_idx = 0; current_idx < texture_list->get_item_count(); current_idx++) { + RID rid = texture_list->get_item_metadata(current_idx); + texture_list->set_item_icon(current_idx, texture_map[rid]); + texture_list->set_item_icon_region(current_idx, Rect2(0, 0, 150, 100)); } - tile_list->update(); + texture_list->update(); } void TileSetEditor::update_workspace_tile_mode() { - if (get_current_tile() < 0) + + if (workspace_mode != WORKSPACE_EDIT) { + for (int i = 0; i < EDITMODE_MAX; i++) { + tool_editmode[i]->hide(); + } + tool_editmode[EDITMODE_REGION]->show(); + tool_editmode[EDITMODE_REGION]->set_pressed(true); + _on_edit_mode_changed(EDITMODE_REGION); + return; + } + + if (get_current_tile() < 0) { + for (int i = 0; i < EDITMODE_MAX; i++) { + tool_editmode[i]->hide(); + } + for (int i = 0; i < ZOOM_OUT; i++) { + tools[i]->hide(); + } return; + } + + for (int i = 0; i < EDITMODE_MAX; i++) { + tool_editmode[i]->show(); + } + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) { if (tool_editmode[EDITMODE_ICON]->is_pressed() || tool_editmode[EDITMODE_PRIORITY]->is_pressed() || tool_editmode[EDITMODE_BITMASK]->is_pressed()) { tool_editmode[EDITMODE_COLLISION]->set_pressed(true); - _on_edit_mode_changed(EDITMODE_COLLISION); - } else { - select_coord(Vector2(0, 0)); + edit_mode = EDITMODE_COLLISION; } + select_coord(Vector2(0, 0)); tool_editmode[EDITMODE_ICON]->hide(); tool_editmode[EDITMODE_BITMASK]->hide(); tool_editmode[EDITMODE_PRIORITY]->hide(); - property_editor->hide(); + } else if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(get_current_tile()) == TileSet::ATLAS_TILE) { + if (edit_mode == EDITMODE_ICON) + select_coord(tileset->autotile_get_icon_coordinate(get_current_tile())); + else + select_coord(edited_shape_coord); + } else if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::ATLAS_TILE) { + if (tool_editmode[EDITMODE_PRIORITY]->is_pressed() || tool_editmode[EDITMODE_BITMASK]->is_pressed()) { + tool_editmode[EDITMODE_COLLISION]->set_pressed(true); + edit_mode = EDITMODE_COLLISION; + } + if (edit_mode == EDITMODE_ICON) + select_coord(tileset->autotile_get_icon_coordinate(get_current_tile())); + else + select_coord(edited_shape_coord); + + tool_editmode[EDITMODE_BITMASK]->hide(); + tool_editmode[EDITMODE_PRIORITY]->hide(); + } + _on_edit_mode_changed(edit_mode); +} + +void TileSetEditor::update_edited_region(const Vector2 &end_point) { + edited_region = Rect2(region_from, Size2()); + if (tools[TOOL_GRID_SNAP]->is_pressed()) { + Vector2 grid_coord; + grid_coord.x = Math::floor((region_from.x - snap_offset.x) / (snap_step.x + snap_separation.x)); + grid_coord.y = Math::floor((region_from.y - snap_offset.y) / (snap_step.y + snap_separation.y)); + grid_coord.x *= (snap_step.x + snap_separation.x); + grid_coord.y *= (snap_step.y + snap_separation.y); + grid_coord += snap_offset; + edited_region.expand_to(grid_coord); + grid_coord += snap_step; + edited_region.expand_to(grid_coord); + grid_coord.x = Math::floor((end_point.x - snap_offset.x) / (snap_step.x + snap_separation.x)); + grid_coord.y = Math::floor((end_point.y - snap_offset.y) / (snap_step.y + snap_separation.y)); + grid_coord.x *= (snap_step.x + snap_separation.x); + grid_coord.y *= (snap_step.y + snap_separation.y); + grid_coord += snap_offset; + edited_region.expand_to(grid_coord); + grid_coord += snap_step; + if (grid_coord.x < end_point.x) + grid_coord.x += snap_separation.x; + if (grid_coord.y < end_point.y) + grid_coord.y += snap_separation.y; + edited_region.expand_to(grid_coord); } else { - tool_editmode[EDITMODE_ICON]->show(); - tool_editmode[EDITMODE_BITMASK]->show(); - tool_editmode[EDITMODE_PRIORITY]->show(); - property_editor->show(); + edited_region.expand_to(end_point); } } -int TileSetEditor::get_current_tile() { - if (tile_list->get_selected_items().size() == 0) - return -1; +int TileSetEditor::get_current_tile() const { + return current_tile; +} + +void TileSetEditor::set_current_tile(int p_id) { + if (current_tile != p_id) { + current_tile = p_id; + helper->_change_notify(""); + select_coord(Vector2(0, 0)); + update_workspace_tile_mode(); + } +} + +Ref<Texture> TileSetEditor::get_current_texture() { + if (texture_list->get_selected_items().size() == 0) + return Ref<Texture>(); else - return tile_list->get_item_metadata(tile_list->get_selected_items()[0]); + return texture_map[texture_list->get_item_metadata(texture_list->get_selected_items()[0])]; } -void TileSetEditorHelper::set_tileset(const Ref<TileSet> &p_tileset) { +void TilesetEditorContext::set_tileset(const Ref<TileSet> &p_tileset) { tileset = p_tileset; } -bool TileSetEditorHelper::_set(const StringName &p_name, const Variant &p_value) { +void TilesetEditorContext::set_snap_options_visible(bool p_visible) { + snap_options_visible = p_visible; + _change_notify(""); +} - if (selected_tile < 0 || tileset.is_null()) - return false; +bool TilesetEditorContext::_set(const StringName &p_name, const Variant &p_value) { String name = p_name.operator String(); - bool v = false; - if (name == "bitmask_mode") { - tileset->set(String::num(selected_tile, 0) + "/autotile/bitmask_mode", p_value, &v); - } else if (name.left(7) == "layout/") { - tileset->set(String::num(selected_tile, 0) + "/autotile" + name.right(6), p_value, &v); - } - if (v) { - tileset->_change_notify("autotile"); + + if (name == "options_offset") { + Vector2 snap = p_value; + tileset_editor->_set_snap_off(snap + WORKSPACE_MARGIN); + return true; + } else if (name == "options_step") { + Vector2 snap = p_value; + tileset_editor->_set_snap_step(snap); + return true; + } else if (name == "options_separation") { + Vector2 snap = p_value; + tileset_editor->_set_snap_sep(snap); + return true; + } else if (p_name.operator String().left(5) == "tile_") { + String name = p_name.operator String().right(5); + bool v = false; + + if (tileset_editor->get_current_tile() < 0 || tileset.is_null()) + return false; + + if (name == "autotile_bitmask_mode") { + tileset->set(String::num(tileset_editor->get_current_tile(), 0) + "/autotile/bitmask_mode", p_value, &v); + } else if (name == "subtile_size") { + tileset->set(String::num(tileset_editor->get_current_tile(), 0) + "/autotile/tile_size", p_value, &v); + } else if (name == "subtile_spacing") { + tileset->set(String::num(tileset_editor->get_current_tile(), 0) + "/autotile/spacing", p_value, &v); + } else { + tileset->set(String::num(tileset_editor->get_current_tile(), 0) + "/" + name, p_value, &v); + } + if (v) { + tileset->_change_notify(""); + tileset_editor->workspace->update(); + tileset_editor->workspace_overlay->update(); + } + return v; } - return v; -} -bool TileSetEditorHelper::_get(const StringName &p_name, Variant &r_ret) const { + tileset_editor->err_dialog->set_text(TTR("This property can't be changed.")); + tileset_editor->err_dialog->popup_centered(Size2(300, 60)); + return false; +} - if (selected_tile < 0 || tileset.is_null()) - return false; - if (!tileset->has_tile(selected_tile)) - return false; +bool TilesetEditorContext::_get(const StringName &p_name, Variant &r_ret) const { String name = p_name.operator String(); bool v = false; - if (name == "bitmask_mode") { - r_ret = tileset->get(String::num(selected_tile, 0) + "/autotile/bitmask_mode", &v); - } else if (name.left(7) == "layout/") { - r_ret = tileset->get(String::num(selected_tile, 0) + "/autotile" + name.right(6), &v); + + if (name == "options_offset") { + r_ret = tileset_editor->snap_offset - WORKSPACE_MARGIN; + v = true; + } else if (name == "options_step") { + r_ret = tileset_editor->snap_step; + v = true; + } else if (name == "options_separation") { + r_ret = tileset_editor->snap_separation; + v = true; + } else if (name.left(5) == "tile_") { + name = name.right(5); + + if (tileset_editor->get_current_tile() < 0 || tileset.is_null()) + return false; + if (!tileset->has_tile(tileset_editor->get_current_tile())) + return false; + + if (name == "autotile_bitmask_mode") { + r_ret = tileset->get(String::num(tileset_editor->get_current_tile(), 0) + "/autotile/bitmask_mode", &v); + } else if (name == "subtile_size") { + r_ret = tileset->get(String::num(tileset_editor->get_current_tile(), 0) + "/autotile/tile_size", &v); + } else if (name == "subtile_spacing") { + r_ret = tileset->get(String::num(tileset_editor->get_current_tile(), 0) + "/autotile/spacing", &v); + } else { + r_ret = tileset->get(String::num(tileset_editor->get_current_tile(), 0) + "/" + name, &v); + } + return v; + } else if (name == "selected_collision") { + r_ret = tileset_editor->edited_collision_shape; + v = true; + } else if (name == "selected_navigation") { + r_ret = tileset_editor->edited_navigation_shape; + v = true; + } else if (name == "selected_occlusion") { + r_ret = tileset_editor->edited_occlusion_shape; + v = true; } return v; } -void TileSetEditorHelper::_get_property_list(List<PropertyInfo> *p_list) const { - - if (selected_tile < 0 || tileset.is_null()) - return; +void TilesetEditorContext::_get_property_list(List<PropertyInfo> *p_list) const { - p_list->push_back(PropertyInfo(Variant::INT, "bitmask_mode", PROPERTY_HINT_ENUM, "2x2,3x3 (minimal),3x3")); - p_list->push_back(PropertyInfo(Variant::VECTOR2, "layout/tile_size")); - p_list->push_back(PropertyInfo(Variant::INT, "layout/spacing", PROPERTY_HINT_RANGE, "0,256,1")); + if (snap_options_visible) { + p_list->push_back(PropertyInfo(Variant::NIL, "Snap Options", PROPERTY_HINT_NONE, "options_", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, "options_offset")); + p_list->push_back(PropertyInfo(Variant::VECTOR2, "options_step")); + p_list->push_back(PropertyInfo(Variant::VECTOR2, "options_separation")); + } + if (tileset_editor->get_current_tile() >= 0 && !tileset.is_null()) { + int id = tileset_editor->get_current_tile(); + p_list->push_back(PropertyInfo(Variant::NIL, "Selected Tile", PROPERTY_HINT_NONE, "tile_", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::STRING, "tile_name")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "tile_normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture")); + p_list->push_back(PropertyInfo(Variant::VECTOR2, "tile_tex_offset")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "tile_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial")); + p_list->push_back(PropertyInfo(Variant::COLOR, "tile_modulate")); + p_list->push_back(PropertyInfo(Variant::INT, "tile_tile_mode", PROPERTY_HINT_ENUM, "SINGLE_TILE,AUTO_TILE,ATLAS_TILE")); + if (tileset->tile_get_tile_mode(id) == TileSet::AUTO_TILE) { + p_list->push_back(PropertyInfo(Variant::INT, "tile_autotile_bitmask_mode", PROPERTY_HINT_ENUM, "2X2,3X3 (minimal),3X3")); + p_list->push_back(PropertyInfo(Variant::VECTOR2, "tile_subtile_size")); + p_list->push_back(PropertyInfo(Variant::INT, "tile_subtile_spacing", PROPERTY_HINT_RANGE, "0, 256, 1")); + } else if (tileset->tile_get_tile_mode(id) == TileSet::ATLAS_TILE) { + p_list->push_back(PropertyInfo(Variant::VECTOR2, "tile_subtile_size")); + p_list->push_back(PropertyInfo(Variant::INT, "tile_subtile_spacing", PROPERTY_HINT_RANGE, "0, 256, 1")); + } + p_list->push_back(PropertyInfo(Variant::VECTOR2, "tile_occluder_offset")); + p_list->push_back(PropertyInfo(Variant::VECTOR2, "tile_navigation_offset")); + p_list->push_back(PropertyInfo(Variant::VECTOR2, "tile_shape_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, "tile_shape_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::INT, "tile_z_index", PROPERTY_HINT_RANGE, itos(VS::CANVAS_ITEM_Z_MIN) + "," + itos(VS::CANVAS_ITEM_Z_MAX) + ",1")); + } + if (tileset_editor->edit_mode == TileSetEditor::EDITMODE_COLLISION && tileset_editor->edited_collision_shape.is_valid()) { + p_list->push_back(PropertyInfo(Variant::OBJECT, "selected_collision", PROPERTY_HINT_RESOURCE_TYPE, tileset_editor->edited_collision_shape->get_class())); + } + if (tileset_editor->edit_mode == TileSetEditor::EDITMODE_NAVIGATION && tileset_editor->edited_navigation_shape.is_valid()) { + p_list->push_back(PropertyInfo(Variant::OBJECT, "selected_navigation", PROPERTY_HINT_RESOURCE_TYPE, tileset_editor->edited_navigation_shape->get_class())); + } + if (tileset_editor->edit_mode == TileSetEditor::EDITMODE_OCCLUSION && tileset_editor->edited_occlusion_shape.is_valid()) { + p_list->push_back(PropertyInfo(Variant::OBJECT, "selected_occlusion", PROPERTY_HINT_RESOURCE_TYPE, tileset_editor->edited_occlusion_shape->get_class())); + } } -TileSetEditorHelper::TileSetEditorHelper(TileSetEditor *p_tileset_editor) { - +TilesetEditorContext::TilesetEditorContext(TileSetEditor *p_tileset_editor) { tileset_editor = p_tileset_editor; - selected_tile = -1; } void TileSetEditorPlugin::edit(Object *p_node) { if (Object::cast_to<TileSet>(p_node)) { tileset_editor->edit(Object::cast_to<TileSet>(p_node)); - tileset_editor->show(); - tileset_editor->texture_region_editor->edit(p_node); - } else - tileset_editor->hide(); + editor->get_inspector()->edit(tileset_editor->helper); + } } bool TileSetEditorPlugin::handles(Object *p_node) const { - return p_node->is_class("TileSet"); + return p_node->is_class("TileSet") || + p_node->is_class("TilesetEditorContext"); } void TileSetEditorPlugin::make_visible(bool p_visible) { - if (p_visible) { - tileset_editor->show(); - tileset_editor->menu->show(); tileset_editor_button->show(); - tileset_editor->side_panel->show(); if (tileset_editor_button->is_pressed()) { - tileset_editor->bottom_panel->show(); + tileset_editor->show(); } - texture_region_button->show(); - if (texture_region_button->is_pressed()) - tileset_editor->texture_region_editor->show(); + get_tree()->connect("idle_frame", tileset_editor, "_on_workspace_process"); } else { tileset_editor->hide(); - tileset_editor->menu->hide(); - tileset_editor->side_panel->hide(); - tileset_editor->bottom_panel->hide(); tileset_editor_button->hide(); - texture_region_button->hide(); - tileset_editor->texture_region_editor->hide(); + get_tree()->disconnect("idle_frame", tileset_editor, "_on_workspace_process"); } } TileSetEditorPlugin::TileSetEditorPlugin(EditorNode *p_node) { - + editor = p_node; tileset_editor = memnew(TileSetEditor(p_node)); - add_control_to_container(CONTAINER_CANVAS_EDITOR_MENU, tileset_editor); - tileset_editor->set_anchors_and_margins_preset(Control::PRESET_TOP_WIDE); - tileset_editor->set_end(Point2(0, 22)); - tileset_editor->hide(); - - tileset_editor->texture_region_editor = memnew(TextureRegionEditor(p_node)); - texture_region_button = p_node->add_bottom_panel_item(TTR("Texture Region"), tileset_editor->texture_region_editor); - texture_region_button->set_tooltip(TTR("Texture Region Editor")); - - tileset_editor->texture_region_editor->set_custom_minimum_size(Size2(0, 200)); - tileset_editor->texture_region_editor->hide(); - texture_region_button->hide(); + tileset_editor_button = + p_node->add_bottom_panel_item(TTR("Tile Set"), tileset_editor); + tileset_editor_button->set_tooltip(TTR("Tile Set Editor")); - add_control_to_container(CONTAINER_CANVAS_EDITOR_SIDE, tileset_editor->side_panel); - tileset_editor->side_panel->set_anchors_and_margins_preset(Control::PRESET_WIDE); - tileset_editor->side_panel->set_custom_minimum_size(Size2(200, 0)); - tileset_editor->side_panel->hide(); - tileset_editor_button = p_node->add_bottom_panel_item(TTR("Tile Set"), tileset_editor->bottom_panel); + tileset_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE); + tileset_editor->hide(); tileset_editor_button->hide(); } diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h index 4894d641a3..0c175e718c 100644 --- a/editor/plugins/tile_set_editor_plugin.h +++ b/editor/plugins/tile_set_editor_plugin.h @@ -33,21 +33,38 @@ #include "editor/editor_name_dialog.h" #include "editor/editor_node.h" -#include "editor/plugins/texture_region_editor_plugin.h" #include "scene/2d/sprite.h" #include "scene/resources/convex_polygon_shape_2d.h" #include "scene/resources/tile_set.h" -class TileSetEditorHelper; +#define WORKSPACE_MARGIN Vector2(10, 10) +class TilesetEditorContext; -class TileSetEditor : public Control { +class TileSetEditor : public Panel { friend class TileSetEditorPlugin; - friend class TextureRegionEditor; + friend class TilesetEditorContext; - GDCLASS(TileSetEditor, Control); + GDCLASS(TileSetEditor, Panel) + + enum TextureToolButtons { + TOOL_TILESET_ADD_TEXTURE, + TOOL_TILESET_REMOVE_TEXTURE, + TOOL_TILESET_CREATE_SCENE, + TOOL_TILESET_MERGE_SCENE, + TOOL_TILESET_MAX + }; + + enum WorkspaceMode { + WORKSPACE_EDIT, + WORKSPACE_CREATE_SINGLE, + WORKSPACE_CREATE_AUTOTILE, + WORKSPACE_CREATE_ATLAS, + WORKSPACE_MODE_MAX + }; enum EditMode { + EDITMODE_REGION, EDITMODE_COLLISION, EDITMODE_OCCLUSION, EDITMODE_NAVIGATION, @@ -57,13 +74,6 @@ class TileSetEditor : public Control { EDITMODE_MAX }; - enum TileSetToolbar { - TOOLBAR_DUMMY, - TOOLBAR_BITMASK, - TOOLBAR_SHAPE, - TOOLBAR_MAX - }; - enum TileSetTools { TOOL_SELECT, BITMASK_COPY, @@ -71,17 +81,42 @@ class TileSetEditor : public Control { BITMASK_CLEAR, SHAPE_NEW_POLYGON, SHAPE_DELETE, - SHAPE_CREATE_FROM_BITMASK, - SHAPE_CREATE_FROM_NOT_BITMASK, SHAPE_KEEP_INSIDE_TILE, - SHAPE_GRID_SNAP, + TOOL_GRID_SNAP, ZOOM_OUT, ZOOM_1, ZOOM_IN, + VISIBLE_INFO, TOOL_MAX }; Ref<TileSet> tileset; + TilesetEditorContext *helper; + EditorNode *editor; + + ConfirmationDialog *cd; + AcceptDialog *err_dialog; + EditorFileDialog *texture_dialog; + + ItemList *texture_list; + int option; + ToolButton *tileset_toolbar_buttons[TOOL_TILESET_MAX]; + MenuButton *tileset_toolbar_tools; + Map<RID, Ref<Texture> > texture_map; + + bool creating_shape; + int dragging_point; + float tile_names_opacity; + Vector2 region_from; + Rect2 edited_region; + bool draw_edited_region; + Vector2 edited_shape_coord; + PoolVector2Array current_shape; + Map<Vector2, uint16_t> bitmask_map_copy; + + Vector2 snap_step; + Vector2 snap_offset; + Vector2 snap_separation; Ref<ConvexPolygonShape2D> edited_collision_shape; Ref<OccluderPolygon2D> edited_occlusion_shape; @@ -94,55 +129,19 @@ class TileSetEditor : public Control { bool draw_handles; Control *workspace_overlay; Control *workspace; + Button *tool_workspacemode[WORKSPACE_MODE_MAX]; Button *tool_editmode[EDITMODE_MAX]; - HBoxContainer *tool_containers[TOOLBAR_MAX]; HBoxContainer *toolbar; - HBoxContainer *hb_grid; ToolButton *tools[TOOL_MAX]; SpinBox *spin_priority; - SpinBox *sb_step_y; - SpinBox *sb_step_x; - SpinBox *sb_off_y; - SpinBox *sb_off_x; - SpinBox *sb_sep_y; - SpinBox *sb_sep_x; + WorkspaceMode workspace_mode; EditMode edit_mode; + int current_tile; - Vector2 snap_step; - Vector2 snap_offset; - Vector2 snap_separation; + void update_texture_list(); + void update_texture_list_icon(); - bool creating_shape; - int dragging_point; - Vector2 edited_shape_coord; - PoolVector2Array current_shape; - Map<Vector2, uint16_t> bitmask_map_copy; - - EditorNode *editor; - TextureRegionEditor *texture_region_editor; - Control *bottom_panel; - Control *side_panel; - ItemList *tile_list; - PropertyEditor *property_editor; - TileSetEditorHelper *helper; - - MenuButton *menu; - ConfirmationDialog *cd; - EditorNameDialog *nd; - AcceptDialog *err_dialog; - - enum { - - MENU_OPTION_ADD_ITEM, - MENU_OPTION_REMOVE_ITEM, - MENU_OPTION_CREATE_FROM_SCENE, - MENU_OPTION_MERGE_FROM_SCENE - }; - - int option; - void _menu_cbk(int p_option); - void _menu_confirm(); - void _name_dialog_confirm(const String &name); + Ref<Texture> get_current_texture(); static void _import_node(Node *p_node, Ref<TileSet> p_library); static void _import_scene(Node *p_scene, Ref<TileSet> p_library, bool p_merge); @@ -150,7 +149,6 @@ class TileSetEditor : public Control { protected: static void _bind_methods(); void _notification(int p_what); - virtual void _changed_callback(Object *p_changed, const char *p_prop); public: void edit(const Ref<TileSet> &p_tileset); @@ -160,53 +158,61 @@ public: ~TileSetEditor(); private: - void _on_tile_list_selected(int p_index); + void _on_tileset_toolbar_button_pressed(int p_index); + void _on_tileset_toolbar_confirm(); + void _on_texture_list_selected(int p_index); + void _on_textures_added(const PoolStringArray &p_paths); void _on_edit_mode_changed(int p_edit_mode); + void _on_workspace_mode_changed(int p_workspace_mode); void _on_workspace_overlay_draw(); void _on_workspace_draw(); + void _on_workspace_process(); void _on_workspace_input(const Ref<InputEvent> &p_ie); void _on_tool_clicked(int p_tool); void _on_priority_changed(float val); void _on_grid_snap_toggled(bool p_val); - void _set_snap_step_x(float p_val); - void _set_snap_step_y(float p_val); - void _set_snap_off_x(float p_val); - void _set_snap_off_y(float p_val); - void _set_snap_sep_x(float p_val); - void _set_snap_sep_y(float p_val); - - void initialize_bottom_editor(); - void draw_highlight_tile(Vector2 coord, const Vector<Vector2> &other_highlighted = Vector<Vector2>()); + void _set_snap_step(Vector2 p_val); + void _set_snap_off(Vector2 p_val); + void _set_snap_sep(Vector2 p_val); + + void draw_highlight_current_tile(); + void draw_highlight_subtile(Vector2 coord, const Vector<Vector2> &other_highlighted = Vector<Vector2>()); + void draw_tile_subdivision(int p_id, Color p_color) const; + void draw_edited_region_subdivision() const; void draw_grid_snap(); void draw_polygon_shapes(); void close_shape(const Vector2 &shape_anchor); void select_coord(const Vector2 &coord); Vector2 snap_point(const Vector2 &point); - void update_tile_list(); - void update_tile_list_icon(); void update_workspace_tile_mode(); + void update_edited_region(const Vector2 &end_point); - int get_current_tile(); + int get_current_tile() const; + void set_current_tile(int p_id); }; -class TileSetEditorHelper : public Object { +class TilesetEditorContext : public Object { friend class TileSetEditor; - GDCLASS(TileSetEditorHelper, Object); + GDCLASS(TilesetEditorContext, Object); Ref<TileSet> tileset; TileSetEditor *tileset_editor; - int selected_tile; + bool snap_options_visible; public: void set_tileset(const Ref<TileSet> &p_tileset); +private: + void set_snap_options_visible(bool p_visible); + protected: bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List<PropertyInfo> *p_list) const; - TileSetEditorHelper(TileSetEditor *p_tileset_editor); +public: + TilesetEditorContext(TileSetEditor *p_tileset_editor); }; class TileSetEditorPlugin : public EditorPlugin { @@ -214,11 +220,9 @@ class TileSetEditorPlugin : public EditorPlugin { GDCLASS(TileSetEditorPlugin, EditorPlugin); TileSetEditor *tileset_editor; + Button *tileset_editor_button; EditorNode *editor; - ToolButton *tileset_editor_button; - ToolButton *texture_region_button; - public: virtual String get_name() const { return "TileSet"; } bool has_main_screen() const { return false; } diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index b9b8b07a2e..63e89b78ea 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -119,6 +119,9 @@ void VisualShaderEditor::_update_graph() { if (updating) return; + if (visual_shader.is_null()) + return; + graph->set_scroll_ofs(visual_shader->get_graph_offset() * EDSCALE); VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); @@ -190,7 +193,7 @@ void VisualShaderEditor::_update_graph() { } for (int i = 0; i < plugins.size(); i++) { - custom_editor = plugins[i]->create_editor(vsnode); + custom_editor = plugins.write[i]->create_editor(vsnode); if (custom_editor) { break; } diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index af7c4bb379..aad9258ed9 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -915,12 +915,6 @@ void ProjectManager::_update_project_buttons() { CanvasItem *item = Object::cast_to<CanvasItem>(scroll_children->get_child(i)); item->update(); - - Button *show = Object::cast_to<Button>(item->get_node(NodePath("project/path_box/show"))); - if (show) { - String current = item->get_meta("name"); - show->set_visible(selected_list.has(current)); - } } bool empty_selection = selected_list.empty(); @@ -1316,7 +1310,6 @@ void ProjectManager::_load_recent_projects() { path_hb->add_child(show); show->connect("pressed", this, "_show_project", varray(path)); show->set_tooltip(TTR("Show In File Manager")); - show->set_visible(false); Label *fpath = memnew(Label(path)); fpath->set_name("path"); @@ -1757,6 +1750,8 @@ ProjectManager::ProjectManager() { editor_set_scale(custom_display_scale); } break; } + + OS::get_singleton()->set_window_size(OS::get_singleton()->get_window_size() * MAX(1, EDSCALE)); } FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files")); @@ -1781,8 +1776,7 @@ ProjectManager::ProjectManager() { vb->add_constant_override("separation", 15 * EDSCALE); String cp; - cp.push_back(0xA9); - cp.push_back(0); + cp += 0xA9; OS::get_singleton()->set_window_title(VERSION_NAME + String(" - ") + TTR("Project Manager") + " - " + cp + " 2007-2018 Juan Linietsky, Ariel Manzur & Godot Contributors"); HBoxContainer *top_hb = memnew(HBoxContainer); @@ -1825,7 +1819,7 @@ ProjectManager::ProjectManager() { project_filter = memnew(ProjectListFilter); search_box->add_child(project_filter); project_filter->connect("filter_changed", this, "_load_recent_projects"); - project_filter->set_custom_minimum_size(Size2(250, 10)); + project_filter->set_custom_minimum_size(Size2(280, 10) * EDSCALE); search_tree_vb->add_child(search_box); PanelContainer *pc = memnew(PanelContainer); @@ -2023,18 +2017,6 @@ void ProjectListFilter::_setup_filters() { filter_option->add_item(TTR("Path")); } -void ProjectListFilter::_command(int p_command) { - switch (p_command) { - - case CMD_CLEAR_FILTER: { - if (search_box->get_text() != "") { - search_box->clear(); - emit_signal("filter_changed"); - } - } break; - } -} - void ProjectListFilter::_search_text_changed(const String &p_newtext) { emit_signal("filter_changed"); } @@ -2057,13 +2039,14 @@ void ProjectListFilter::_filter_option_selected(int p_idx) { void ProjectListFilter::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE) - clear_search_button->set_icon(get_icon("Close", "EditorIcons")); + if (p_what == NOTIFICATION_ENTER_TREE) { + search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_clear_button_enabled(true); + } } void ProjectListFilter::_bind_methods() { - ClassDB::bind_method(D_METHOD("_command"), &ProjectListFilter::_command); ClassDB::bind_method(D_METHOD("_search_text_changed"), &ProjectListFilter::_search_text_changed); ClassDB::bind_method(D_METHOD("_filter_option_selected"), &ProjectListFilter::_filter_option_selected); @@ -2088,8 +2071,4 @@ ProjectListFilter::ProjectListFilter() { search_box->connect("text_changed", this, "_search_text_changed"); search_box->set_h_size_flags(SIZE_EXPAND_FILL); add_child(search_box); - - clear_search_button = memnew(ToolButton); - clear_search_button->connect("pressed", this, "_command", make_binds(CMD_CLEAR_FILTER)); - add_child(clear_search_button); } diff --git a/editor/project_manager.h b/editor/project_manager.h index a9d23b1f71..ad21e00b0d 100644 --- a/editor/project_manager.h +++ b/editor/project_manager.h @@ -128,13 +128,8 @@ class ProjectListFilter : public HBoxContainer { private: friend class ProjectManager; - enum Command { - CMD_CLEAR_FILTER, - }; - OptionButton *filter_option; LineEdit *search_box; - ToolButton *clear_search_button; enum FilterOption { FILTER_NAME, @@ -142,7 +137,6 @@ private: }; FilterOption _current_filter; - void _command(int p_command); void _search_text_changed(const String &p_newtext); void _setup_filters(); void _filter_option_selected(int p_idx); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index e6ae2d64e7..ea697f5da2 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -81,7 +81,8 @@ void ProjectSettingsEditor::_notification(int p_what) { globals_editor->edit(ProjectSettings::get_singleton()); search_button->set_icon(get_icon("Search", "EditorIcons")); - clear_button->set_icon(get_icon("Close", "EditorIcons")); + search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_clear_button_enabled(true); action_add_error->add_color_override("font_color", get_color("error_color", "Editor")); @@ -119,7 +120,8 @@ void ProjectSettingsEditor::_notification(int p_what) { case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { search_button->set_icon(get_icon("Search", "EditorIcons")); - clear_button->set_icon(get_icon("Close", "EditorIcons")); + search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_clear_button_enabled(true); action_add_error->add_color_override("font_color", get_color("error_color", "Editor")); popup_add->set_item_icon(popup_add->get_item_index(INPUT_KEY), get_icon("Keyboard", "EditorIcons")); popup_add->set_item_icon(popup_add->get_item_index(INPUT_JOY_BUTTON), get_icon("JoyButton", "EditorIcons")); @@ -213,10 +215,8 @@ void ProjectSettingsEditor::_action_edited() { undo_redo->create_action(TTR("Change Action deadzone")); undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, new_action); - undo_redo->add_do_method(this, "_update_actions"); undo_redo->add_do_method(this, "_settings_changed"); undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_action); - undo_redo->add_undo_method(this, "_update_actions"); undo_redo->add_undo_method(this, "_settings_changed"); undo_redo->commit_action(); } @@ -1462,7 +1462,7 @@ void ProjectSettingsEditor::_update_translations() { t->set_editable(0, true); t->set_tooltip(0, l); t->set_checked(0, l_filter.has(l)); - translation_filter_treeitems[i] = t; + translation_filter_treeitems.write[i] = t; } } else { for (int i = 0; i < s; i++) { @@ -1502,7 +1502,7 @@ void ProjectSettingsEditor::_update_translations() { if (langnames.length() > 0) langnames += ","; langnames += names[i]; - translation_locales_idxs_remap[l_idx] = i; + translation_locales_idxs_remap.write[l_idx] = i; l_idx++; } } @@ -1591,15 +1591,6 @@ void ProjectSettingsEditor::_toggle_search_bar(bool p_pressed) { } } -void ProjectSettingsEditor::_clear_search_box() { - - if (search_box->get_text() == "") - return; - - search_box->clear(); - globals_editor->get_inspector()->update_tree(); -} - void ProjectSettingsEditor::set_plugins_page() { tab_container->set_current_tab(plugin_settings->get_index()); @@ -1662,7 +1653,6 @@ void ProjectSettingsEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_translation_filter_option_changed"), &ProjectSettingsEditor::_translation_filter_option_changed); ClassDB::bind_method(D_METHOD("_translation_filter_mode_changed"), &ProjectSettingsEditor::_translation_filter_mode_changed); - ClassDB::bind_method(D_METHOD("_clear_search_box"), &ProjectSettingsEditor::_clear_search_box); ClassDB::bind_method(D_METHOD("_toggle_search_bar"), &ProjectSettingsEditor::_toggle_search_bar); ClassDB::bind_method(D_METHOD("_copy_to_platform_about_to_show"), &ProjectSettingsEditor::_copy_to_platform_about_to_show); @@ -1753,10 +1743,6 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); search_bar->add_child(search_box); - clear_button = memnew(ToolButton); - search_bar->add_child(clear_button); - clear_button->connect("pressed", this, "_clear_search_box"); - globals_editor = memnew(SectionedInspector); props_base->add_child(globals_editor); globals_editor->get_inspector()->set_undo_redo(EditorNode::get_singleton()->get_undo_redo()); diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index 3b74ae1909..b738c4ae20 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -69,7 +69,6 @@ class ProjectSettingsEditor : public AcceptDialog { HBoxContainer *search_bar; Button *search_button; LineEdit *search_box; - ToolButton *clear_button; HBoxContainer *add_prop_bar; AcceptDialog *message; @@ -158,7 +157,6 @@ class ProjectSettingsEditor : public AcceptDialog { void _translation_filter_mode_changed(int p_mode); void _toggle_search_bar(bool p_pressed); - void _clear_search_box(); void _copy_to_platform_about_to_show(); diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 576227344b..b370a711e3 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -90,7 +90,7 @@ bool EditorResourceConversionPlugin::handles(const Ref<Resource> &p_resource) co return false; } -Ref<Resource> EditorResourceConversionPlugin::convert(const Ref<Resource> &p_resource) { +Ref<Resource> EditorResourceConversionPlugin::convert(const Ref<Resource> &p_resource) const { if (get_script_instance()) return get_script_instance()->call("_convert", p_resource); diff --git a/editor/property_editor.h b/editor/property_editor.h index 56743822d2..7d8fa22f3f 100644 --- a/editor/property_editor.h +++ b/editor/property_editor.h @@ -64,7 +64,7 @@ protected: public: virtual String converts_to() const; virtual bool handles(const Ref<Resource> &p_resource) const; - virtual Ref<Resource> convert(const Ref<Resource> &p_resource); + virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const; }; class CustomPropertyEditor : public Popup { diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp index 26dd931321..d2101f1e00 100644 --- a/editor/quick_open.cpp +++ b/editor/quick_open.cpp @@ -195,7 +195,7 @@ Vector<Pair<String, Ref<Texture> > > EditorQuickOpen::_sort_fs(Vector<Pair<Strin Vector<float> scores; scores.resize(list.size()); for (int i = 0; i < list.size(); i++) - scores[i] = _path_cmp(search_text, list[i].first); + scores.write[i] = _path_cmp(search_text, list[i].first); while (list.size() > 0) { @@ -258,6 +258,9 @@ void EditorQuickOpen::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { connect("confirmed", this, "_confirmed"); + + search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_clear_button_enabled(true); } } diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 8d38bf39b5..d17bcef92b 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -119,7 +119,7 @@ void SceneTreeDock::instance(const String &p_file) { if (!edited_scene) { current_option = -1; - accept->get_ok()->set_text(TTR("OK :(")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("No parent to instance a child at.")); accept->popup_centered_minsize(); return; @@ -164,7 +164,7 @@ void SceneTreeDock::_perform_instance_scenes(const Vector<String> &p_files, Node Ref<PackedScene> sdata = ResourceLoader::load(p_files[i]); if (!sdata.is_valid()) { current_option = -1; - accept->get_ok()->set_text(TTR("Ugh")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(vformat(TTR("Error loading scene from %s"), p_files[i])); accept->popup_centered_minsize(); error = true; @@ -174,7 +174,7 @@ void SceneTreeDock::_perform_instance_scenes(const Vector<String> &p_files, Node Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE); if (!instanced_scene) { current_option = -1; - accept->get_ok()->set_text(TTR("Ugh")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(vformat(TTR("Error instancing scene from %s"), p_files[i])); accept->popup_centered_minsize(); error = true; @@ -233,7 +233,7 @@ void SceneTreeDock::_perform_instance_scenes(const Vector<String> &p_files, Node void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base) { Ref<PackedScene> sdata = ResourceLoader::load(p_file); if (!sdata.is_valid()) { - accept->get_ok()->set_text(TTR("Ugh")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(vformat(TTR("Error loading scene from %s"), p_file)); accept->popup_centered_minsize(); return; @@ -241,7 +241,7 @@ void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base) Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE); if (!instanced_scene) { - accept->get_ok()->set_text(TTR("Ugh")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(vformat(TTR("Error instancing scene from %s"), p_file)); accept->popup_centered_minsize(); return; @@ -349,21 +349,33 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { break; Ref<Script> existing = selected->get_script(); - if (existing.is_valid()) - editor->push_item(existing.ptr()); - else { - String path = selected->get_filename(); - if (path == "") { - String root_path = editor_data->get_edited_scene_root()->get_filename(); - if (root_path == "") { - path = "res://" + selected->get_name(); - } else { - path = root_path.get_base_dir() + "/" + selected->get_name(); + + String path = selected->get_filename(); + if (path == "") { + String root_path = editor_data->get_edited_scene_root()->get_filename(); + if (root_path == "") { + path = "res://" + selected->get_name(); + } else { + path = root_path.get_base_dir() + "/" + selected->get_name(); + } + } + + String inherits = selected->get_class(); + if (existing.is_valid()) { + for (int i = 0; i < ScriptServer::get_language_count(); i++) { + ScriptLanguage *l = ScriptServer::get_language(i); + if (l->get_type() == existing->get_class()) { + if (EDITOR_GET("interface/editors/derive_script_globals_by_name").operator bool()) { + String name = l->get_global_class_name(existing->get_path(), NULL); + inherits = editor->get_editor_data().script_class_get_base(name); + } else if (l->can_inherit_from_file()) { + inherits = "\"" + existing->get_path() + "\""; + } } } - script_create_dialog->config(selected->get_class(), path); - script_create_dialog->popup_centered(); } + script_create_dialog->config(inherits, path); + script_create_dialog->popup_centered(); } break; case TOOL_CLEAR_SCRIPT: { @@ -401,7 +413,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (scene_tree->get_selected() == edited_scene) { current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("This operation can't be done on the tree root.")); accept->popup_centered_minsize(); break; @@ -462,7 +474,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (editor_selection->is_selected(edited_scene)) { current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("This operation can't be done on the tree root.")); accept->popup_centered_minsize(); break; @@ -532,7 +544,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (editor_selection->is_selected(edited_scene)) { current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("This operation can't be done on the tree root.")); accept->popup_centered_minsize(); break; @@ -619,7 +631,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { Node *scene = editor_data->get_edited_scene_root(); if (!scene) { - accept->get_ok()->set_text(TTR("I see...")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("This operation can't be done without a scene.")); accept->popup_centered_minsize(); break; @@ -628,7 +640,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { List<Node *> selection = editor_selection->get_selected_node_list(); if (selection.size() != 1) { - accept->get_ok()->set_text(TTR("I see...")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("This operation requires a single selected node.")); accept->popup_centered_minsize(); break; @@ -637,14 +649,14 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { Node *tocopy = selection.front()->get(); if (tocopy == scene) { - accept->get_ok()->set_text(TTR("I see...")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("Can not perform with the root node.")); accept->popup_centered_minsize(); break; } if (tocopy != editor_data->get_edited_scene_root() && tocopy->get_filename() != "") { - accept->get_ok()->set_text(TTR("I see...")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("This operation can't be done on instanced scenes.")); accept->popup_centered_minsize(); break; @@ -785,13 +797,38 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { } break; case TOOL_CREATE_2D_SCENE: case TOOL_CREATE_3D_SCENE: - case TOOL_CREATE_USER_INTERFACE: { + case TOOL_CREATE_USER_INTERFACE: + case TOOL_CREATE_FAVORITE: { Node *new_node; - switch (p_tool) { - case TOOL_CREATE_2D_SCENE: new_node = memnew(Node2D); break; - case TOOL_CREATE_3D_SCENE: new_node = memnew(Spatial); break; - case TOOL_CREATE_USER_INTERFACE: new_node = memnew(Control); break; + + if (TOOL_CREATE_FAVORITE == p_tool) { + String name = selected_favorite_root.get_slicec(' ', 0); + if (ScriptServer::is_global_class(name)) { + new_node = Object::cast_to<Node>(ClassDB::instance(ScriptServer::get_global_class_base(name))); + Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(name), "Script"); + if (new_node && script.is_valid()) { + new_node->set_script(script.get_ref_ptr()); + new_node->set_name(name); + } + } else { + new_node = Object::cast_to<Node>(ClassDB::instance(selected_favorite_root)); + } + if (!new_node) { + ERR_EXPLAIN("Creating root from favorite '" + selected_favorite_root + "' failed. Creating 'Node' instead."); + new_node = memnew(Node); + } + } else { + switch (p_tool) { + case TOOL_CREATE_2D_SCENE: new_node = memnew(Node2D); break; + case TOOL_CREATE_3D_SCENE: new_node = memnew(Spatial); break; + case TOOL_CREATE_USER_INTERFACE: { + Control *node = memnew(Control); + node->set_anchors_and_margins_preset(PRESET_WIDE); //more useful for resizable UIs. + new_node = node; + + } break; + } } editor_data->get_undo_redo().create_action("New Scene Root"); @@ -845,39 +882,67 @@ void SceneTreeDock::_notification(int p_what) { button_create_script->set_icon(get_icon("ScriptCreate", "EditorIcons")); button_clear_script->set_icon(get_icon("ScriptRemove", "EditorIcons")); - filter->add_icon_override("right_icon", get_icon("Search", "EditorIcons")); + filter->set_right_icon(get_icon("Search", "EditorIcons")); + filter->set_clear_button_enabled(true); EditorNode::get_singleton()->get_editor_selection()->connect("selection_changed", this, "_selection_changed"); - create_root_dialog->add_child(memnew(Label(TTR("Create Root Node:")))); + // create_root_dialog + HBoxContainer *top_row = memnew(HBoxContainer); + top_row->set_name("NodeShortcutsTopRow"); + top_row->set_h_size_flags(SIZE_EXPAND_FILL); + top_row->add_child(memnew(Label(TTR("Create Root Node:")))); + top_row->add_spacer(); - Button *button_2d = memnew(Button); - create_root_dialog->add_child(button_2d); + ToolButton *node_shortcuts_toggle = memnew(ToolButton); + node_shortcuts_toggle->set_name("NodeShortcutsToggle"); + node_shortcuts_toggle->set_icon(get_icon("Favorites", "EditorIcons")); + node_shortcuts_toggle->set_toggle_mode(true); + node_shortcuts_toggle->set_pressed(EDITOR_GET("_use_favorites_root_selection")); + node_shortcuts_toggle->set_anchors_and_margins_preset(Control::PRESET_CENTER_RIGHT); + node_shortcuts_toggle->connect("pressed", this, "_update_create_root_dialog"); + top_row->add_child(node_shortcuts_toggle); + + create_root_dialog->add_child(top_row); + + VBoxContainer *node_shortcuts = memnew(VBoxContainer); + node_shortcuts->set_name("NodeShortcuts"); + + VBoxContainer *beginner_node_shortcuts = memnew(VBoxContainer); + beginner_node_shortcuts->set_name("BeginnerNodeShortcuts"); + node_shortcuts->add_child(beginner_node_shortcuts); + Button *button_2d = memnew(Button); + beginner_node_shortcuts->add_child(button_2d); button_2d->set_text(TTR("2D Scene")); button_2d->set_icon(get_icon("Node2D", "EditorIcons")); button_2d->connect("pressed", this, "_tool_selected", make_binds(TOOL_CREATE_2D_SCENE, false)); Button *button_3d = memnew(Button); - create_root_dialog->add_child(button_3d); + beginner_node_shortcuts->add_child(button_3d); button_3d->set_text(TTR("3D Scene")); button_3d->set_icon(get_icon("Spatial", "EditorIcons")); button_3d->connect("pressed", this, "_tool_selected", make_binds(TOOL_CREATE_3D_SCENE, false)); Button *button_ui = memnew(Button); - create_root_dialog->add_child(button_ui); + beginner_node_shortcuts->add_child(button_ui); button_ui->set_text(TTR("User Interface")); button_ui->set_icon(get_icon("Control", "EditorIcons")); button_ui->connect("pressed", this, "_tool_selected", make_binds(TOOL_CREATE_USER_INTERFACE, false)); + VBoxContainer *favorite_node_shortcuts = memnew(VBoxContainer); + favorite_node_shortcuts->set_name("FavoriteNodeShortcuts"); + node_shortcuts->add_child(favorite_node_shortcuts); + Button *button_custom = memnew(Button); - create_root_dialog->add_child(button_custom); + node_shortcuts->add_child(button_custom); button_custom->set_text(TTR("Custom Node")); button_custom->set_icon(get_icon("Add", "EditorIcons")); button_custom->connect("pressed", this, "_tool_selected", make_binds(TOOL_NEW, false)); - create_root_dialog->add_spacer(); - + node_shortcuts->add_spacer(); + create_root_dialog->add_child(node_shortcuts); + _update_create_root_dialog(); } break; case NOTIFICATION_ENTER_TREE: { @@ -893,7 +958,8 @@ void SceneTreeDock::_notification(int p_what) { button_create_script->set_icon(get_icon("ScriptCreate", "EditorIcons")); button_clear_script->set_icon(get_icon("ScriptRemove", "EditorIcons")); - filter->add_icon_override("right_icon", get_icon("Search", "EditorIcons")); + filter->set_right_icon(get_icon("Search", "EditorIcons")); + filter->set_clear_button_enabled(true); } break; case NOTIFICATION_PROCESS: { @@ -1232,7 +1298,7 @@ bool SceneTreeDock::_validate_no_foreign() { if (E->get() != edited_scene && E->get()->get_owner() != edited_scene) { - accept->get_ok()->set_text(TTR("Makes Sense!")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("Can't operate on nodes from a foreign scene!")); accept->popup_centered_minsize(); return false; @@ -1240,7 +1306,7 @@ bool SceneTreeDock::_validate_no_foreign() { if (edited_scene->get_scene_inherited_state().is_valid() && edited_scene->get_scene_inherited_state()->find_node_by_path(edited_scene->get_path_to(E->get())) >= 0) { - accept->get_ok()->set_text(TTR("Makes Sense!")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("Can't operate on nodes the current scene inherits from!")); accept->popup_centered_minsize(); return false; @@ -1426,13 +1492,9 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) { editor_data->get_undo_redo().add_undo_method(E->get(), "set_script", existing); } - editor_data->get_undo_redo().add_do_method(editor, "push_item", p_script.operator->()); - editor_data->get_undo_redo().add_undo_method(editor, "push_item", (Script *)NULL); - - editor_data->get_undo_redo().add_do_method(this, "_update_script_button"); - editor_data->get_undo_redo().add_undo_method(this, "_update_script_button"); - editor_data->get_undo_redo().commit_action(); + + editor->push_item(p_script.operator->()); } void SceneTreeDock::_delete_confirm() { @@ -1521,16 +1583,9 @@ void SceneTreeDock::_delete_confirm() { void SceneTreeDock::_update_script_button() { if (EditorNode::get_singleton()->get_editor_selection()->get_selection().size() == 1) { - if (EditorNode::get_singleton()->get_editor_selection()->get_selection().front()->key()->get_script().is_null()) { - button_create_script->show(); - button_clear_script->hide(); - } else { - button_create_script->hide(); - button_clear_script->show(); - } + button_create_script->show(); } else { button_create_script->hide(); - button_clear_script->hide(); } } @@ -1731,7 +1786,7 @@ void SceneTreeDock::_new_scene_from(String p_file) { List<Node *> selection = editor_selection->get_selected_node_list(); if (selection.size() != 1) { - accept->get_ok()->set_text(TTR("I see...")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("This operation requires a single selected node.")); accept->popup_centered_minsize(); return; @@ -1749,7 +1804,7 @@ void SceneTreeDock::_new_scene_from(String p_file) { memdelete(copy); if (err != OK) { - accept->get_ok()->set_text(TTR("I see...")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("Couldn't save new scene. Likely dependencies (instances) couldn't be satisfied.")); accept->popup_centered_minsize(); return; @@ -1761,14 +1816,14 @@ void SceneTreeDock::_new_scene_from(String p_file) { err = ResourceSaver::save(p_file, sdata, flg); if (err != OK) { - accept->get_ok()->set_text(TTR("I see...")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("Error saving scene.")); accept->popup_centered_minsize(); return; } _replace_with_branch_scene(p_file, base); } else { - accept->get_ok()->set_text(TTR("I see...")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("Error duplicating scene to save it.")); accept->popup_centered_minsize(); return; @@ -1984,6 +2039,8 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { if (selection.size() == 1) { + Node *selected = selection[0]; + subresources.clear(); menu_subresources->clear(); menu_subresources->set_size(Size2(1, 1)); @@ -1994,18 +2051,23 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { menu->add_icon_shortcut(get_icon("Add", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW); menu->add_icon_shortcut(get_icon("Instance", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANCE); menu->add_separator(); + menu->add_icon_shortcut(get_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT); - menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT); + Ref<Script> existing = selected->get_script(); + if (existing.is_valid()) { + menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT); + } menu->add_separator(); menu->add_icon_shortcut(get_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/rename"), TOOL_RENAME); } menu->add_icon_shortcut(get_icon("Reload", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/change_node_type"), TOOL_REPLACE); - menu->add_separator(); - menu->add_icon_shortcut(get_icon("MoveUp", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/move_up"), TOOL_MOVE_UP); - menu->add_icon_shortcut(get_icon("MoveDown", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/move_down"), TOOL_MOVE_DOWN); - menu->add_icon_shortcut(get_icon("Duplicate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/duplicate"), TOOL_DUPLICATE); - menu->add_icon_shortcut(get_icon("Reparent", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/reparent"), TOOL_REPARENT); - + if (scene_tree->get_selected() != edited_scene) { + menu->add_separator(); + menu->add_icon_shortcut(get_icon("MoveUp", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/move_up"), TOOL_MOVE_UP); + menu->add_icon_shortcut(get_icon("MoveDown", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/move_down"), TOOL_MOVE_DOWN); + menu->add_icon_shortcut(get_icon("Duplicate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/duplicate"), TOOL_DUPLICATE); + menu->add_icon_shortcut(get_icon("Reparent", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/reparent"), TOOL_REPARENT); + } if (selection.size() == 1) { menu->add_icon_shortcut(get_icon("NewRoot", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/make_root"), TOOL_MAKE_ROOT); @@ -2135,6 +2197,67 @@ void SceneTreeDock::_local_tree_selected() { edit_local->set_pressed(true); } +void SceneTreeDock::_update_create_root_dialog() { + + BaseButton *toggle = Object::cast_to<BaseButton>(create_root_dialog->get_node(String("NodeShortcutsTopRow/NodeShortcutsToggle"))); + Node *node_shortcuts = create_root_dialog->get_node(String("NodeShortcuts")); + + if (!toggle || !node_shortcuts) + return; + + Control *beginner_nodes = Object::cast_to<Control>(node_shortcuts->get_node(String("BeginnerNodeShortcuts"))); + Control *favorite_nodes = Object::cast_to<Control>(node_shortcuts->get_node(String("FavoriteNodeShortcuts"))); + + if (!beginner_nodes || !favorite_nodes) + return; + + EditorSettings::get_singleton()->set_setting("_use_favorites_root_selection", toggle->is_pressed()); + EditorSettings::get_singleton()->save(); + if (toggle->is_pressed()) { + + for (int i = 0; i < favorite_nodes->get_child_count(); i++) { + favorite_nodes->get_child(i)->queue_delete(); + } + + FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites.Node"), FileAccess::READ); + + if (f) { + + while (!f->eof_reached()) { + String l = f->get_line().strip_edges(); + + if (l != String()) { + Button *button = memnew(Button); + favorite_nodes->add_child(button); + button->set_text(TTR(l)); + String name = l.get_slicec(' ', 0); + if (ScriptServer::is_global_class(name)) + name = ScriptServer::get_global_class_base(name); + button->set_icon(get_icon(name, "EditorIcons")); + button->connect("pressed", this, "_favorite_root_selected", make_binds(l)); + } + } + + memdelete(f); + } + + if (!favorite_nodes->is_visible_in_tree()) { + favorite_nodes->show(); + beginner_nodes->hide(); + } + } else { + if (!beginner_nodes->is_visible_in_tree()) { + beginner_nodes->show(); + favorite_nodes->hide(); + } + } +} + +void SceneTreeDock::_favorite_root_selected(const String &p_class) { + selected_favorite_root = p_class; + _tool_selected(TOOL_CREATE_FAVORITE, false); +} + void SceneTreeDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_tool_selected"), &SceneTreeDock::_tool_selected, DEFVAL(false)); @@ -2163,6 +2286,8 @@ void SceneTreeDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_remote_tree_selected"), &SceneTreeDock::_remote_tree_selected); ClassDB::bind_method(D_METHOD("_local_tree_selected"), &SceneTreeDock::_local_tree_selected); ClassDB::bind_method(D_METHOD("_update_script_button"), &SceneTreeDock::_update_script_button); + ClassDB::bind_method(D_METHOD("_favorite_root_selected"), &SceneTreeDock::_favorite_root_selected); + ClassDB::bind_method(D_METHOD("_update_create_root_dialog"), &SceneTreeDock::_update_create_root_dialog); ClassDB::bind_method(D_METHOD("instance"), &SceneTreeDock::instance); @@ -2288,6 +2413,8 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel create_dialog->set_base_type("Node"); add_child(create_dialog); create_dialog->connect("create", this, "_create"); + create_dialog->connect("favorites_updated", this, "_update_create_root_dialog"); + EditorFileSystem::get_singleton()->connect("script_classes_updated", create_dialog, "_save_and_update_favorite_list"); rename_dialog = memnew(RenameDialog(scene_tree, &editor_data->get_undo_redo())); add_child(rename_dialog); @@ -2324,6 +2451,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel menu = memnew(PopupMenu); add_child(menu); menu->connect("id_pressed", this, "_tool_selected"); + menu->set_hide_on_window_lose_focus(true); menu_subresources = memnew(PopupMenu); menu_subresources->set_name("Sub-Resources"); menu_subresources->connect("id_pressed", this, "_tool_selected"); @@ -2333,11 +2461,12 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel clear_inherit_confirm = memnew(ConfirmationDialog); clear_inherit_confirm->set_text(TTR("Clear Inheritance? (No Undo!)")); - clear_inherit_confirm->get_ok()->set_text(TTR("Clear!")); + clear_inherit_confirm->get_ok()->set_text(TTR("Clear")); add_child(clear_inherit_confirm); set_process_input(true); set_process(true); EDITOR_DEF("interface/editors/show_scene_tree_root_selection", true); + EDITOR_DEF("_use_favorites_root_selection", false); } diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 57f4759747..34a7c98d11 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -86,6 +86,7 @@ class SceneTreeDock : public VBoxContainer { TOOL_CREATE_2D_SCENE, TOOL_CREATE_3D_SCENE, TOOL_CREATE_USER_INTERFACE, + TOOL_CREATE_FAVORITE, }; @@ -141,6 +142,7 @@ class SceneTreeDock : public VBoxContainer { EditorNode *editor; VBoxContainer *create_root_dialog; + String selected_favorite_root; void _add_children_to_popup(Object *p_obj, int p_depth); @@ -201,6 +203,9 @@ class SceneTreeDock : public VBoxContainer { void _remote_tree_selected(); void _local_tree_selected(); + void _update_create_root_dialog(); + void _favorite_root_selected(const String &p_class); + protected: void _notification(int p_what); static void _bind_methods(); diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index 9ce0e973f7..bd661ade53 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -658,7 +658,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da Vector<float> p; p.resize(arr.size()); for (int i = 0; i < arr.size(); i++) { - p[i] = arr[i]; + p.write[i] = arr[i]; if (i < perf_items.size()) { float v = p[i]; @@ -693,7 +693,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da perf_items[i]->set_text(1, vs); perf_items[i]->set_tooltip(1, tt); if (p[i] > perf_max[i]) - perf_max[i] = p[i]; + perf_max.write[i] = p[i]; } } perf_history.push_front(p); @@ -807,7 +807,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da item.signature = "categ::" + name + "::" + item.name; item.name = item.name.capitalize(); c.total_time += item.total; - c.items[i / 2] = item; + c.items.write[i / 2] = item; } metric.categories.push_back(c); } @@ -844,7 +844,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da item.calls = calls; item.self = self; item.total = total; - funcs.items[i] = item; + funcs.items.write[i] = item; } metric.categories.push_back(funcs); @@ -1193,12 +1193,12 @@ void ScriptEditorDebugger::start() { perf_history.clear(); for (int i = 0; i < Performance::MONITOR_MAX; i++) { - perf_max[i] = 0; + perf_max.write[i] = 0; } int remote_port = (int)EditorSettings::get_singleton()->get("network/debug/remote_port"); if (server->listen(remote_port) != OK) { - EditorNode::get_log()->add_message(String("Error listening on port ") + itos(remote_port), true); + EditorNode::get_log()->add_message(String("Error listening on port ") + itos(remote_port), EditorLog::MSG_TYPE_ERROR); return; } @@ -2076,7 +2076,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { it->set_selectable(1, false); it->set_text(0, name.capitalize()); perf_items.push_back(it); - perf_max[i] = 0; + perf_max.write[i] = 0; } } diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp index fe379703e5..4ebba73cb3 100644 --- a/editor/settings_config_dialog.cpp +++ b/editor/settings_config_dialog.cpp @@ -114,22 +114,6 @@ void EditorSettingsDialog::popup_edit_settings() { _focus_current_search_box(); } -void EditorSettingsDialog::_clear_search_box() { - - if (search_box->get_text() == "") - return; - - search_box->clear(); - inspector->get_inspector()->update_tree(); -} - -void EditorSettingsDialog::_clear_shortcut_search_box() { - if (shortcut_search_box->get_text() == "") - return; - - shortcut_search_box->clear(); -} - void EditorSettingsDialog::_filter_shortcuts(const String &p_filter) { shortcut_filter = p_filter; _update_shortcuts(); @@ -198,10 +182,10 @@ void EditorSettingsDialog::_unhandled_input(const Ref<InputEvent> &p_event) { void EditorSettingsDialog::_update_icons() { - search_box->add_icon_override("right_icon", get_icon("Search", "EditorIcons")); - shortcut_search_box->add_icon_override("right_icon", get_icon("Search", "EditorIcons")); - clear_button->set_icon(get_icon("Close", "EditorIcons")); - shortcut_clear_button->set_icon(get_icon("Close", "EditorIcons")); + search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_clear_button_enabled(true); + shortcut_search_box->set_right_icon(get_icon("Search", "EditorIcons")); + shortcut_search_box->set_clear_button_enabled(true); restart_close_button->set_icon(get_icon("Close", "EditorIcons")); restart_container->add_style_override("panel", get_stylebox("bg", "Tree")); @@ -411,8 +395,6 @@ void EditorSettingsDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("_settings_save"), &EditorSettingsDialog::_settings_save); ClassDB::bind_method(D_METHOD("_settings_changed"), &EditorSettingsDialog::_settings_changed); ClassDB::bind_method(D_METHOD("_settings_property_edited"), &EditorSettingsDialog::_settings_property_edited); - ClassDB::bind_method(D_METHOD("_clear_search_box"), &EditorSettingsDialog::_clear_search_box); - ClassDB::bind_method(D_METHOD("_clear_shortcut_search_box"), &EditorSettingsDialog::_clear_shortcut_search_box); ClassDB::bind_method(D_METHOD("_shortcut_button_pressed"), &EditorSettingsDialog::_shortcut_button_pressed); ClassDB::bind_method(D_METHOD("_filter_shortcuts"), &EditorSettingsDialog::_filter_shortcuts); ClassDB::bind_method(D_METHOD("_update_shortcuts"), &EditorSettingsDialog::_update_shortcuts); @@ -451,10 +433,6 @@ EditorSettingsDialog::EditorSettingsDialog() { search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); hbc->add_child(search_box); - clear_button = memnew(ToolButton); - hbc->add_child(clear_button); - clear_button->connect("pressed", this, "_clear_search_box"); - inspector = memnew(SectionedInspector); //inspector->hide_top_label(); inspector->get_inspector()->set_use_filter(true); @@ -500,10 +478,6 @@ EditorSettingsDialog::EditorSettingsDialog() { hbc->add_child(shortcut_search_box); shortcut_search_box->connect("text_changed", this, "_filter_shortcuts"); - shortcut_clear_button = memnew(ToolButton); - hbc->add_child(shortcut_clear_button); - shortcut_clear_button->connect("pressed", this, "_clear_shortcut_search_box"); - shortcuts = memnew(Tree); tab_shortcuts->add_child(shortcuts, true); shortcuts->set_v_size_flags(SIZE_EXPAND_FILL); diff --git a/editor/settings_config_dialog.h b/editor/settings_config_dialog.h index 6cf2eb6bdf..37d32e401d 100644 --- a/editor/settings_config_dialog.h +++ b/editor/settings_config_dialog.h @@ -52,8 +52,6 @@ class EditorSettingsDialog : public AcceptDialog { LineEdit *search_box; LineEdit *shortcut_search_box; - ToolButton *clear_button; - ToolButton *shortcut_clear_button; SectionedInspector *inspector; Timer *timer; diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index 35544f711b..64fdc778d0 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -47,7 +47,10 @@ // Keep small children away from this file. // It's so ugly it will eat them alive -#define HANDLE_HALF_SIZE 0.05 +// The previous comment is kept only for historical reasons. +// No children will be harmed by the viewing of this file... hopefully. + +#define HANDLE_HALF_SIZE 9.5 bool EditorSpatialGizmo::can_draw() const { return is_editable(); @@ -85,11 +88,37 @@ void EditorSpatialGizmo::clear() { void EditorSpatialGizmo::redraw() { - if (get_script_instance() && get_script_instance()->has_method("redraw")) - get_script_instance()->call("redraw"); + ERR_FAIL_COND(!gizmo_plugin); + gizmo_plugin->redraw(this); +} + +String EditorSpatialGizmo::get_handle_name(int p_idx) const { + ERR_FAIL_COND_V(!gizmo_plugin, ""); + return gizmo_plugin->get_handle_name(this, p_idx); +} + +Variant EditorSpatialGizmo::get_handle_value(int p_idx) { + ERR_FAIL_COND_V(!gizmo_plugin, Variant()); + return gizmo_plugin->get_handle_value(this, p_idx); +} + +void EditorSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) { + ERR_FAIL_COND(!gizmo_plugin); + return gizmo_plugin->set_handle(this, p_idx, p_camera, p_point); +} + +void EditorSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { + ERR_FAIL_COND(!gizmo_plugin); + return gizmo_plugin->commit_handle(this, p_idx, p_restore, p_cancel); +} + +void EditorSpatialGizmo::set_spatial_node(Spatial *p_node) { + + ERR_FAIL_NULL(p_node); + spatial_node = p_node; } -void EditorSpatialGizmo::Instance::create_instance(Spatial *p_base) { +void EditorSpatialGizmo::Instance::create_instance(Spatial *p_base, bool p_hidden) { instance = VS::get_singleton()->instance_create2(mesh->get_rid(), p_base->get_world()->get_scenario()); VS::get_singleton()->instance_attach_object_instance_id(instance, p_base->get_instance_id()); @@ -98,7 +127,8 @@ void EditorSpatialGizmo::Instance::create_instance(Spatial *p_base) { if (extra_margin) VS::get_singleton()->instance_set_extra_visibility_margin(instance, 1); VS::get_singleton()->instance_geometry_set_cast_shadows_setting(instance, VS::SHADOW_CASTING_SETTING_OFF); - VS::get_singleton()->instance_set_layer_mask(instance, 1 << SpatialEditorViewport::GIZMO_EDIT_LAYER); //gizmos are 26 + int layer = p_hidden ? 0 : 1 << SpatialEditorViewport::GIZMO_EDIT_LAYER; + VS::get_singleton()->instance_set_layer_mask(instance, layer); //gizmos are 26 } void EditorSpatialGizmo::add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard, const RID &p_skeleton) { @@ -110,7 +140,7 @@ void EditorSpatialGizmo::add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard ins.mesh = p_mesh; ins.skeleton = p_skeleton; if (valid) { - ins.create_instance(spatial_node); + ins.create_instance(spatial_node, hidden); VS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform()); } @@ -159,7 +189,7 @@ void EditorSpatialGizmo::add_lines(const Vector<Vector3> &p_lines, const Ref<Mat ins.billboard = p_billboard; ins.mesh = mesh; if (valid) { - ins.create_instance(spatial_node); + ins.create_instance(spatial_node, hidden); VS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform()); } @@ -210,7 +240,7 @@ void EditorSpatialGizmo::add_unscaled_billboard(const Ref<Material> &p_material, ins.unscaled = true; ins.billboard = true; if (valid) { - ins.create_instance(spatial_node); + ins.create_instance(spatial_node, hidden); VS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform()); } @@ -229,11 +259,11 @@ void EditorSpatialGizmo::add_collision_segments(const Vector<Vector3> &p_lines) collision_segments.resize(from + p_lines.size()); for (int i = 0; i < p_lines.size(); i++) { - collision_segments[from + i] = p_lines[i]; + collision_segments.write[from + i] = p_lines[i]; } } -void EditorSpatialGizmo::add_handles(const Vector<Vector3> &p_handles, bool p_billboard, bool p_secondary) { +void EditorSpatialGizmo::add_handles(const Vector<Vector3> &p_handles, const Ref<Material> &p_material, bool p_billboard, bool p_secondary) { billboard_handle = p_billboard; @@ -257,7 +287,7 @@ void EditorSpatialGizmo::add_handles(const Vector<Vector3> &p_handles, bool p_bi for (int i = 0; i < p_handles.size(); i++) { Color col(1, 1, 1, 1); - if (is_gizmo_handle_highlighted(i)) + if (gizmo_plugin->is_gizmo_handle_highlighted(this, i)) col = Color(0, 0, 1, 0.9); if (SpatialEditor::get_singleton()->get_over_gizmo_handle() != i) @@ -268,10 +298,7 @@ void EditorSpatialGizmo::add_handles(const Vector<Vector3> &p_handles, bool p_bi } a[VS::ARRAY_COLOR] = colors; mesh->add_surface_from_arrays(Mesh::PRIMITIVE_POINTS, a); - if (p_billboard) - mesh->surface_set_material(0, SpatialEditorGizmos::singleton->handle2_material_billboard); - else - mesh->surface_set_material(0, SpatialEditorGizmos::singleton->handle2_material); + mesh->surface_set_material(0, p_material); if (p_billboard) { float md = 0; @@ -288,7 +315,7 @@ void EditorSpatialGizmo::add_handles(const Vector<Vector3> &p_handles, bool p_bi ins.billboard = p_billboard; ins.extra_margin = true; if (valid) { - ins.create_instance(spatial_node); + ins.create_instance(spatial_node, hidden); VS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform()); } instances.push_back(ins); @@ -296,14 +323,14 @@ void EditorSpatialGizmo::add_handles(const Vector<Vector3> &p_handles, bool p_bi int chs = handles.size(); handles.resize(chs + p_handles.size()); for (int i = 0; i < p_handles.size(); i++) { - handles[i + chs] = p_handles[i]; + handles.write[i + chs] = p_handles[i]; } } else { int chs = secondary_handles.size(); secondary_handles.resize(chs + p_handles.size()); for (int i = 0; i < p_handles.size(); i++) { - secondary_handles[i + chs] = p_handles[i]; + secondary_handles.write[i + chs] = p_handles[i]; } } } @@ -330,17 +357,13 @@ void EditorSpatialGizmo::add_solid_box(Ref<Material> &p_material, Vector3 p_size add_mesh(m); } -void EditorSpatialGizmo::set_spatial_node(Spatial *p_node) { - - ERR_FAIL_NULL(p_node); - spatial_node = p_node; -} - bool EditorSpatialGizmo::intersect_frustum(const Camera *p_camera, const Vector<Plane> &p_frustum) { ERR_FAIL_COND_V(!spatial_node, false); ERR_FAIL_COND_V(!valid, false); + if (hidden && !gizmo_plugin->is_selectable_when_hidden()) return false; + if (selectable_icon_size > 0.0f) { Vector3 origin = spatial_node->get_global_transform().get_origin(); @@ -413,7 +436,9 @@ bool EditorSpatialGizmo::intersect_ray(Camera *p_camera, const Point2 &p_point, ERR_FAIL_COND_V(!spatial_node, false); ERR_FAIL_COND_V(!valid, false); - if (r_gizmo_handle) { + if (hidden && !gizmo_plugin->is_selectable_when_hidden()) return false; + + if (r_gizmo_handle && !hidden) { Transform t = spatial_node->get_global_transform(); t.orthonormalize(); @@ -428,7 +453,8 @@ bool EditorSpatialGizmo::intersect_ray(Camera *p_camera, const Point2 &p_point, Vector3 hpos = t.xform(secondary_handles[i]); Vector2 p = p_camera->unproject_position(hpos); - if (p.distance_to(p_point) < SpatialEditorGizmos::singleton->handle_t->get_width() * 0.6) { + + if (p.distance_to(p_point) < HANDLE_HALF_SIZE) { real_t dp = p_camera->get_transform().origin.distance_to(hpos); if (dp < min_d) { @@ -453,7 +479,8 @@ bool EditorSpatialGizmo::intersect_ray(Camera *p_camera, const Point2 &p_point, Vector3 hpos = t.xform(handles[i]); Vector2 p = p_camera->unproject_position(hpos); - if (p.distance_to(p_point) < SpatialEditorGizmos::singleton->handle_t->get_width() * 0.6) { + + if (p.distance_to(p_point) < HANDLE_HALF_SIZE) { real_t dp = p_camera->get_transform().origin.distance_to(hpos); if (dp < min_d) { @@ -504,6 +531,8 @@ bool EditorSpatialGizmo::intersect_ray(Camera *p_camera, const Point2 &p_point, rect.set_position(center - rect.get_size() / 2.0); if (rect.has_point(p_point)) { + r_pos = t.origin; + r_normal = -p_camera->project_ray_normal(p_point); return true; } @@ -597,7 +626,7 @@ void EditorSpatialGizmo::create() { for (int i = 0; i < instances.size(); i++) { - instances[i].create_instance(spatial_node); + instances.write[i].create_instance(spatial_node, hidden); } transform(); @@ -621,99 +650,24 @@ void EditorSpatialGizmo::free() { if (instances[i].instance.is_valid()) VS::get_singleton()->free(instances[i].instance); - instances[i].instance = RID(); + instances.write[i].instance = RID(); } + clear(); + valid = false; } -Ref<SpatialMaterial> EditorSpatialGizmo::create_material(const String &p_name, const Color &p_color, bool p_billboard, bool p_on_top, bool p_use_vertex_color) { - - String name = p_name; - - if (!is_editable()) { - name += "@readonly"; - } else if (is_selected()) { - name += "@selected"; - } - - if (SpatialEditorGizmos::singleton->material_cache.has(name)) { - return SpatialEditorGizmos::singleton->material_cache[name]; - } - - Color color = p_color; - - if (!is_editable()) { - color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/instanced"); - } - if (!is_selected()) { - color.a *= 0.3; - } - - Ref<SpatialMaterial> line_material; - line_material.instance(); - line_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - line_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - if (p_use_vertex_color) { - line_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - line_material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - } - - if (p_billboard) { - line_material->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); +void EditorSpatialGizmo::set_hidden(bool p_hidden) { + hidden = p_hidden; + int layer = hidden ? 0 : 1 << SpatialEditorViewport::GIZMO_EDIT_LAYER; + for (int i = 0; i < instances.size(); ++i) { + VS::get_singleton()->instance_set_layer_mask(instances[i].instance, layer); } - - if (p_on_top && is_selected()) { - line_material->set_on_top_of_alpha(); - } - - line_material->set_albedo(color); - - SpatialEditorGizmos::singleton->material_cache[name] = line_material; - - return line_material; } -Ref<SpatialMaterial> EditorSpatialGizmo::create_icon_material(const String &p_name, const Ref<Texture> &p_texture, bool p_on_top, const Color &p_albedo) { - - String name = p_name; - - if (!is_editable()) { - name += "@readonly"; - } else if (is_selected()) { - name += "@selected"; - } - - if (SpatialEditorGizmos::singleton->material_cache.has(name)) { - return SpatialEditorGizmos::singleton->material_cache[name]; - } - - Color color = p_albedo; - - if (!is_editable()) { - color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/instanced"); - } else if (!is_selected()) { - color.a *= 0.3; - } - - Ref<SpatialMaterial> icon; - icon.instance(); - icon->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - icon->set_cull_mode(SpatialMaterial::CULL_DISABLED); - icon->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_DISABLED); - icon->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - icon->set_albedo(color); - icon->set_texture(SpatialMaterial::TEXTURE_ALBEDO, p_texture); - icon->set_flag(SpatialMaterial::FLAG_FIXED_SIZE, true); - icon->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); - - if (p_on_top && is_selected()) { - icon->set_on_top_of_alpha(); - } - - SpatialEditorGizmos::singleton->material_cache[name] = icon; - - return icon; +void EditorSpatialGizmo::set_plugin(EditorSpatialGizmoPlugin *p_plugin) { + gizmo_plugin = p_plugin; } void EditorSpatialGizmo::_bind_methods() { @@ -726,6 +680,7 @@ void EditorSpatialGizmo::_bind_methods() { ClassDB::bind_method(D_METHOD("add_handles", "handles", "billboard", "secondary"), &EditorSpatialGizmo::add_handles, DEFVAL(false), DEFVAL(false)); ClassDB::bind_method(D_METHOD("set_spatial_node", "node"), &EditorSpatialGizmo::_set_spatial_node); ClassDB::bind_method(D_METHOD("clear"), &EditorSpatialGizmo::clear); + ClassDB::bind_method(D_METHOD("set_hidden", "hidden"), &EditorSpatialGizmo::set_hidden); BIND_VMETHOD(MethodInfo("redraw")); BIND_VMETHOD(MethodInfo(Variant::STRING, "get_handle_name", PropertyInfo(Variant::INT, "index"))); @@ -743,12 +698,17 @@ void EditorSpatialGizmo::_bind_methods() { EditorSpatialGizmo::EditorSpatialGizmo() { valid = false; billboard_handle = false; + hidden = false; base = NULL; + selected = false; + instanced = false; spatial_node = NULL; + gizmo_plugin = NULL; } EditorSpatialGizmo::~EditorSpatialGizmo() { + if (gizmo_plugin != NULL) gizmo_plugin->unregister_gizmo(this); clear(); } @@ -761,7 +721,30 @@ Vector3 EditorSpatialGizmo::get_handle_pos(int p_idx) const { //// light gizmo -String LightSpatialGizmo::get_handle_name(int p_idx) const { +LightSpatialGizmoPlugin::LightSpatialGizmoPlugin() { + + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/light", Color(1, 1, 0.2)); + + create_material("lines", gizmo_color); + create_material("lines_billboard", gizmo_color, true); + + create_icon_material("light_directional_icon", SpatialEditor::get_singleton()->get_icon("GizmoDirectionalLight", "EditorIcons")); + create_icon_material("light_omni_icon", SpatialEditor::get_singleton()->get_icon("GizmoLight", "EditorIcons")); + create_icon_material("light_spot_icon", SpatialEditor::get_singleton()->get_icon("GizmoSpotLight", "EditorIcons")); + + create_handle_material("handles"); + create_handle_material("handles_billboard", true); +} + +bool LightSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<Light>(p_spatial) != NULL; +} + +String LightSpatialGizmoPlugin::get_name() const { + return "Lights"; +} + +String LightSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { if (p_idx == 0) return "Radius"; @@ -769,8 +752,9 @@ String LightSpatialGizmo::get_handle_name(int p_idx) const { return "Aperture"; } -Variant LightSpatialGizmo::get_handle_value(int p_idx) const { +Variant LightSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { + Light *light = Object::cast_to<Light>(p_gizmo->get_spatial_node()); if (p_idx == 0) return light->get_param(Light::PARAM_RANGE); if (p_idx == 1) @@ -808,8 +792,9 @@ static float _find_closest_angle_to_half_pi_arc(const Vector3 &p_from, const Vec return a * 180.0 / Math_PI; } -void LightSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) { +void LightSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { + Light *light = Object::cast_to<Light>(p_gizmo->get_spatial_node()); Transform gt = light->get_global_transform(); gt.orthonormalize(); Transform gi = gt.affine_inverse(); @@ -848,8 +833,9 @@ void LightSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_ } } -void LightSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { +void LightSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { + Light *light = Object::cast_to<Light>(p_gizmo->get_spatial_node()); if (p_cancel) { light->set_param(p_idx == 0 ? Light::PARAM_RANGE : Light::PARAM_SPOT_ANGLE, p_restore); @@ -871,14 +857,16 @@ void LightSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool } } -void LightSpatialGizmo::redraw() { +void LightSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { + + Light *light = Object::cast_to<Light>(p_gizmo->get_spatial_node()); - Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/light"); + p_gizmo->clear(); if (Object::cast_to<DirectionalLight>(light)) { - Ref<Material> material = create_material("light_directional_material", gizmo_color); - Ref<Material> icon = create_icon_material("light_directional_icon", SpatialEditor::get_singleton()->get_icon("GizmoDirectionalLight", "EditorIcons")); + Ref<Material> material = get_material("lines", p_gizmo); + Ref<Material> icon = get_material("light_directional_icon", p_gizmo); const int arrow_points = 7; const float arrow_length = 1.5; @@ -909,16 +897,15 @@ void LightSpatialGizmo::redraw() { } } - add_lines(lines, material); - add_collision_segments(lines); - add_unscaled_billboard(icon, 0.05); + p_gizmo->add_lines(lines, material); + p_gizmo->add_collision_segments(lines); + p_gizmo->add_unscaled_billboard(icon, 0.05); } if (Object::cast_to<OmniLight>(light)) { - Ref<Material> material = create_material("light_omni_material", gizmo_color, true); - Ref<Material> icon = create_icon_material("light_omni_icon", SpatialEditor::get_singleton()->get_icon("GizmoLight", "EditorIcons")); - clear(); + Ref<Material> material = get_material("lines_billboard", p_gizmo); + Ref<Material> icon = get_material("light_omni_icon", p_gizmo); OmniLight *on = Object::cast_to<OmniLight>(light); @@ -941,29 +928,27 @@ void LightSpatialGizmo::redraw() { points.push_back(Vector3(b.x, b.y, 0)); } - add_lines(points, material, true); - add_collision_segments(points); + p_gizmo->add_lines(points, material, true); + p_gizmo->add_collision_segments(points); - add_unscaled_billboard(icon, 0.05); + p_gizmo->add_unscaled_billboard(icon, 0.05); Vector<Vector3> handles; handles.push_back(Vector3(r, 0, 0)); - add_handles(handles, true); + p_gizmo->add_handles(handles, get_material("handles_billboard"), true); } if (Object::cast_to<SpotLight>(light)) { - Ref<Material> material = create_material("light_spot_material", gizmo_color); - Ref<Material> icon = create_icon_material("light_spot_icon", SpatialEditor::get_singleton()->get_icon("GizmoSpotLight", "EditorIcons")); - - clear(); + Ref<Material> material = get_material("lines", p_gizmo); + Ref<Material> icon = get_material("light_spot_icon", p_gizmo); Vector<Vector3> points; - SpotLight *on = Object::cast_to<SpotLight>(light); + SpotLight *sl = Object::cast_to<SpotLight>(light); - float r = on->get_param(Light::PARAM_RANGE); - float w = r * Math::sin(Math::deg2rad(on->get_param(Light::PARAM_SPOT_ANGLE))); - float d = r * Math::cos(Math::deg2rad(on->get_param(Light::PARAM_SPOT_ANGLE))); + float r = sl->get_param(Light::PARAM_RANGE); + float w = r * Math::sin(Math::deg2rad(sl->get_param(Light::PARAM_SPOT_ANGLE))); + float d = r * Math::cos(Math::deg2rad(sl->get_param(Light::PARAM_SPOT_ANGLE))); for (int i = 0; i < 360; i++) { @@ -985,7 +970,7 @@ void LightSpatialGizmo::redraw() { points.push_back(Vector3(0, 0, -r)); points.push_back(Vector3()); - add_lines(points, material); + p_gizmo->add_lines(points, material); Vector<Vector3> handles; handles.push_back(Vector3(0, 0, -r)); @@ -1017,33 +1002,45 @@ void LightSpatialGizmo::redraw() { collision_segments.push_back(Vector3(0, 0, -r)); collision_segments.push_back(Vector3()); - add_handles(handles); - add_collision_segments(collision_segments); - add_unscaled_billboard(icon, 0.05); + p_gizmo->add_handles(handles, get_material("handles")); + p_gizmo->add_collision_segments(collision_segments); + p_gizmo->add_unscaled_billboard(icon, 0.05); } } -LightSpatialGizmo::LightSpatialGizmo(Light *p_light) { +////// + +//// player gizmo +AudioStreamPlayer3DSpatialGizmoPlugin::AudioStreamPlayer3DSpatialGizmoPlugin() { + + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/stream_player_3d", Color(0.4, 0.8, 1)); - light = p_light; - set_spatial_node(p_light); + create_icon_material("stream_player_3d_icon", SpatialEditor::get_singleton()->get_icon("GizmoSpatialSamplePlayer", "EditorIcons")); + create_material("stream_player_3d_material", gizmo_color); + create_handle_material("handles"); } -////// +bool AudioStreamPlayer3DSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<AudioStreamPlayer3D>(p_spatial) != NULL; +} -//// player gizmo +String AudioStreamPlayer3DSpatialGizmoPlugin::get_name() const { + return "AudioStreamPlayer3D"; +} -String AudioStreamPlayer3DSpatialGizmo::get_handle_name(int p_idx) const { +String AudioStreamPlayer3DSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { return "Emission Radius"; } -Variant AudioStreamPlayer3DSpatialGizmo::get_handle_value(int p_idx) const { - +Variant AudioStreamPlayer3DSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { + AudioStreamPlayer3D *player = Object::cast_to<AudioStreamPlayer3D>(p_gizmo->get_spatial_node()); return player->get_emission_angle(); } -void AudioStreamPlayer3DSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) { +void AudioStreamPlayer3DSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { + + AudioStreamPlayer3D *player = Object::cast_to<AudioStreamPlayer3D>(p_gizmo->get_spatial_node()); Transform gt = player->get_global_transform(); gt.orthonormalize(); @@ -1081,7 +1078,9 @@ void AudioStreamPlayer3DSpatialGizmo::set_handle(int p_idx, Camera *p_camera, co } } -void AudioStreamPlayer3DSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { +void AudioStreamPlayer3DSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { + + AudioStreamPlayer3D *player = Object::cast_to<AudioStreamPlayer3D>(p_gizmo->get_spatial_node()); if (p_cancel) { @@ -1097,16 +1096,17 @@ void AudioStreamPlayer3DSpatialGizmo::commit_handle(int p_idx, const Variant &p_ } } -void AudioStreamPlayer3DSpatialGizmo::redraw() { +void AudioStreamPlayer3DSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { - clear(); + AudioStreamPlayer3D *player = Object::cast_to<AudioStreamPlayer3D>(p_gizmo->get_spatial_node()); + + p_gizmo->clear(); - Ref<Material> icon = create_icon_material("stream_player_3d_material", SpatialEditor::get_singleton()->get_icon("GizmoSpatialSamplePlayer", "EditorIcons")); + Ref<Material> icon = get_material("stream_player_3d_icon", p_gizmo); if (player->is_emission_angle_enabled()) { - Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/stream_player_3d"); - Ref<Material> material = create_material("stream_player_3d_material", gizmo_color); + Ref<Material> material = get_material("stream_player_3d_material", p_gizmo); float pc = player->get_emission_angle(); @@ -1124,8 +1124,8 @@ void AudioStreamPlayer3DSpatialGizmo::redraw() { Vector3 from(Math::sin(a) * radius, Math::cos(a) * radius, ofs); Vector3 to(Math::sin(an) * radius, Math::cos(an) * radius, ofs); - points[i * 2 + 0] = from; - points[i * 2 + 1] = to; + points.write[i * 2 + 0] = from; + points.write[i * 2 + 1] = to; } for (int i = 0; i < 4; i++) { @@ -1134,31 +1134,44 @@ void AudioStreamPlayer3DSpatialGizmo::redraw() { Vector3 from(Math::sin(a) * radius, Math::cos(a) * radius, ofs); - points[200 + i * 2 + 0] = from; - points[200 + i * 2 + 1] = Vector3(); + points.write[200 + i * 2 + 0] = from; + points.write[200 + i * 2 + 1] = Vector3(); } - add_lines(points, material); - add_collision_segments(points); + p_gizmo->add_lines(points, material); + p_gizmo->add_collision_segments(points); Vector<Vector3> handles; float ha = Math::deg2rad(player->get_emission_angle()); handles.push_back(Vector3(Math::sin(ha), 0, -Math::cos(ha))); - add_handles(handles); + p_gizmo->add_handles(handles, get_material("handles")); } - add_unscaled_billboard(icon, 0.05); + p_gizmo->add_unscaled_billboard(icon, 0.05); } -AudioStreamPlayer3DSpatialGizmo::AudioStreamPlayer3DSpatialGizmo(AudioStreamPlayer3D *p_player) { +////// + +CameraSpatialGizmoPlugin::CameraSpatialGizmoPlugin() { + + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/camera", Color(0.8, 0.4, 0.8)); - player = p_player; - set_spatial_node(p_player); + create_material("camera_material", gizmo_color); + create_icon_material("camera_icon", SpatialEditor::get_singleton()->get_icon("GizmoCamera", "EditorIcons")); + create_handle_material("handles"); } -////// +bool CameraSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<Camera>(p_spatial) != NULL; +} + +String CameraSpatialGizmoPlugin::get_name() const { + return "Camera"; +} -String CameraSpatialGizmo::get_handle_name(int p_idx) const { +String CameraSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { + + Camera *camera = Object::cast_to<Camera>(p_gizmo->get_spatial_node()); if (camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) { return "FOV"; @@ -1166,7 +1179,10 @@ String CameraSpatialGizmo::get_handle_name(int p_idx) const { return "Size"; } } -Variant CameraSpatialGizmo::get_handle_value(int p_idx) const { + +Variant CameraSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { + + Camera *camera = Object::cast_to<Camera>(p_gizmo->get_spatial_node()); if (camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) { return camera->get_fov(); @@ -1175,7 +1191,10 @@ Variant CameraSpatialGizmo::get_handle_value(int p_idx) const { return camera->get_size(); } } -void CameraSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) { + +void CameraSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { + + Camera *camera = Object::cast_to<Camera>(p_gizmo->get_spatial_node()); Transform gt = camera->get_global_transform(); gt.orthonormalize(); @@ -1201,7 +1220,10 @@ void CameraSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p camera->set("size", d); } } -void CameraSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { + +void CameraSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { + + Camera *camera = Object::cast_to<Camera>(p_gizmo->get_spatial_node()); if (camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) { @@ -1231,16 +1253,17 @@ void CameraSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool } } -void CameraSpatialGizmo::redraw() { +void CameraSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { - clear(); + Camera *camera = Object::cast_to<Camera>(p_gizmo->get_spatial_node()); + + p_gizmo->clear(); Vector<Vector3> lines; Vector<Vector3> handles; - Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/camera"); - Ref<Material> material = create_material("camera_material", gizmo_color); - Ref<Material> icon = create_icon_material("camera_icon", SpatialEditor::get_singleton()->get_icon("GizmoCamera", "EditorIcons")); + Ref<Material> material = get_material("camera_material", p_gizmo); + Ref<Material> icon = get_material("camera_icon", p_gizmo); switch (camera->get_projection()) { @@ -1310,71 +1333,81 @@ void CameraSpatialGizmo::redraw() { } break; } - add_lines(lines, material); - add_collision_segments(lines); - add_unscaled_billboard(icon, 0.05); - add_handles(handles); + p_gizmo->add_lines(lines, material); + p_gizmo->add_collision_segments(lines); + p_gizmo->add_unscaled_billboard(icon, 0.05); + p_gizmo->add_handles(handles, get_material("handles")); } -CameraSpatialGizmo::CameraSpatialGizmo(Camera *p_camera) { +////// - camera = p_camera; - set_spatial_node(camera); +MeshInstanceSpatialGizmoPlugin::MeshInstanceSpatialGizmoPlugin() { } -////// +bool MeshInstanceSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<MeshInstance>(p_spatial) != NULL && Object::cast_to<SoftBody>(p_spatial) == NULL; +} -bool MeshInstanceSpatialGizmo::can_draw() const { - return true; //mesh can always draw (even though nothing is displayed) +String MeshInstanceSpatialGizmoPlugin::get_name() const { + return "MeshInstance"; } -void MeshInstanceSpatialGizmo::redraw() { - clear(); +bool MeshInstanceSpatialGizmoPlugin::can_be_hidden() const { + return false; +} + +void MeshInstanceSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { + + MeshInstance *mesh = Object::cast_to<MeshInstance>(p_gizmo->get_spatial_node()); + + p_gizmo->clear(); Ref<Mesh> m = mesh->get_mesh(); + if (!m.is_valid()) return; //none Ref<TriangleMesh> tm = m->generate_triangle_mesh(); if (tm.is_valid()) { - add_collision_triangles(tm); + p_gizmo->add_collision_triangles(tm); } } -MeshInstanceSpatialGizmo::MeshInstanceSpatialGizmo(MeshInstance *p_mesh) { +///// +Sprite3DSpatialGizmoPlugin::Sprite3DSpatialGizmoPlugin() { +} - mesh = p_mesh; - set_spatial_node(p_mesh); +bool Sprite3DSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<Sprite3D>(p_spatial) != NULL; } -///// +String Sprite3DSpatialGizmoPlugin::get_name() const { + return "Sprite3D"; +} -bool Sprite3DSpatialGizmo::can_draw() const { - return true; +bool Sprite3DSpatialGizmoPlugin::can_be_hidden() const { + return false; } -void Sprite3DSpatialGizmo::redraw() { - clear(); +void Sprite3DSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { + + Sprite3D *sprite = Object::cast_to<Sprite3D>(p_gizmo->get_spatial_node()); + + p_gizmo->clear(); Ref<TriangleMesh> tm = sprite->generate_triangle_mesh(); if (tm.is_valid()) { - add_collision_triangles(tm); + p_gizmo->add_collision_triangles(tm); } } -Sprite3DSpatialGizmo::Sprite3DSpatialGizmo(SpriteBase3D *p_sprite) { - - sprite = p_sprite; - set_spatial_node(p_sprite); -} - /// -void Position3DSpatialGizmo::redraw() { +Position3DSpatialGizmoPlugin::Position3DSpatialGizmoPlugin() { + pos3d_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + cursor_points = Vector<Vector3>(); - clear(); - add_mesh(SpatialEditorGizmos::singleton->pos3d_mesh); - Vector<Vector3> cursor_points; + PoolVector<Color> cursor_colors; float cs = 0.25; cursor_points.push_back(Vector3(+cs, 0, 0)); cursor_points.push_back(Vector3(-cs, 0, 0)); @@ -1382,51 +1415,65 @@ void Position3DSpatialGizmo::redraw() { cursor_points.push_back(Vector3(0, -cs, 0)); cursor_points.push_back(Vector3(0, 0, +cs)); cursor_points.push_back(Vector3(0, 0, -cs)); - add_collision_segments(cursor_points); + cursor_colors.push_back(Color(1, 0.5, 0.5, 0.7)); + cursor_colors.push_back(Color(1, 0.5, 0.5, 0.7)); + cursor_colors.push_back(Color(0.5, 1, 0.5, 0.7)); + cursor_colors.push_back(Color(0.5, 1, 0.5, 0.7)); + cursor_colors.push_back(Color(0.5, 0.5, 1, 0.7)); + cursor_colors.push_back(Color(0.5, 0.5, 1, 0.7)); + + Ref<SpatialMaterial> mat = memnew(SpatialMaterial); + mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + mat->set_line_width(3); + Array d; + d.resize(VS::ARRAY_MAX); + d[Mesh::ARRAY_VERTEX] = cursor_points; + d[Mesh::ARRAY_COLOR] = cursor_colors; + pos3d_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, d); + pos3d_mesh->surface_set_material(0, mat); } -Position3DSpatialGizmo::Position3DSpatialGizmo(Position3D *p_p3d) { +bool Position3DSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<Position3D>(p_spatial) != NULL; +} + +String Position3DSpatialGizmoPlugin::get_name() const { + return "Position3D"; +} + +void Position3DSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { - p3d = p_p3d; - set_spatial_node(p3d); + p_gizmo->clear(); + p_gizmo->add_mesh(pos3d_mesh); + p_gizmo->add_collision_segments(cursor_points); } ///// -void SkeletonSpatialGizmo::redraw() { +SkeletonSpatialGizmoPlugin::SkeletonSpatialGizmoPlugin() { - clear(); + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/skeleton", Color(1, 0.8, 0.4)); + create_material("skeleton_material", gizmo_color); +} - Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/skeleton"); - Ref<Material> material = create_material("skeleton_material", gizmo_color); - SpatialMaterial *sm = Object::cast_to<SpatialMaterial>(material.ptr()); - - { // Reset - Color c(sm->get_albedo()); - c.a = 1; - sm->set_albedo(c); - } - if (sm) { - switch (SpatialEditor::get_singleton()->get_skeleton_visibility_state()) { - case 0: { - // Hidden - Color c(sm->get_albedo()); - c.a = 0; - sm->set_albedo(c); - sm->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - } break; - case 1: - // Visible - sm->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, false); - sm->set_render_priority(SpatialMaterial::RENDER_PRIORITY_MIN); - sm->set_flag(SpatialMaterial::FLAG_DISABLE_DEPTH_TEST, false); - break; - case 2: - // x-ray - sm->set_on_top_of_alpha(); - break; - } - } +bool SkeletonSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<Skeleton>(p_spatial) != NULL; +} + +String SkeletonSpatialGizmoPlugin::get_name() const { + return "Skeleton"; +} + +void SkeletonSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { + + Skeleton *skel = Object::cast_to<Skeleton>(p_gizmo->get_spatial_node()); + + p_gizmo->clear(); + + Ref<Material> material = get_material("skeleton_material", p_gizmo); Ref<SurfaceTool> surface_tool(memnew(SurfaceTool)); @@ -1441,23 +1488,25 @@ void SkeletonSpatialGizmo::redraw() { weights.resize(4); for (int i = 0; i < 4; i++) { - bones[i] = 0; - weights[i] = 0; + bones.write[i] = 0; + weights.write[i] = 0; } - weights[0] = 1; + weights.write[0] = 1; AABB aabb; Color bonecolor = Color(1.0, 0.4, 0.4, 0.3); Color rootcolor = Color(0.4, 1.0, 0.4, 0.1); - for (int i = 0; i < skel->get_bone_count(); i++) { + for (int i_bone = 0; i_bone < skel->get_bone_count(); i_bone++) { + + int i = skel->get_process_order(i_bone); int parent = skel->get_bone_parent(i); if (parent >= 0) { - grests[i] = grests[parent] * skel->get_bone_rest(i); + grests.write[i] = grests[parent] * skel->get_bone_rest(i); Vector3 v0 = grests[parent].origin; Vector3 v1 = grests[i].origin; @@ -1480,7 +1529,7 @@ void SkeletonSpatialGizmo::redraw() { int pointidx = 0; for (int j = 0; j < 3; j++) { - bones[0] = parent; + bones.write[0] = parent; surface_tool->add_bones(bones); surface_tool->add_weights(weights); surface_tool->add_color(rootcolor); @@ -1508,7 +1557,7 @@ void SkeletonSpatialGizmo::redraw() { Vector3 point = v0 + d * dist * 0.2; point += axis * dist * 0.1; - bones[0] = parent; + bones.write[0] = parent; surface_tool->add_bones(bones); surface_tool->add_weights(weights); surface_tool->add_color(bonecolor); @@ -1518,12 +1567,12 @@ void SkeletonSpatialGizmo::redraw() { surface_tool->add_color(bonecolor); surface_tool->add_vertex(point); - bones[0] = parent; + bones.write[0] = parent; surface_tool->add_bones(bones); surface_tool->add_weights(weights); surface_tool->add_color(bonecolor); surface_tool->add_vertex(point); - bones[0] = i; + bones.write[0] = i; surface_tool->add_bones(bones); surface_tool->add_weights(weights); surface_tool->add_color(bonecolor); @@ -1535,7 +1584,7 @@ void SkeletonSpatialGizmo::redraw() { SWAP(points[1], points[2]); for (int j = 0; j < 4; j++) { - bones[0] = parent; + bones.write[0] = parent; surface_tool->add_bones(bones); surface_tool->add_weights(weights); surface_tool->add_color(bonecolor); @@ -1560,8 +1609,8 @@ void SkeletonSpatialGizmo::redraw() { */ } else { - grests[i] = skel->get_bone_rest(i); - bones[0] = i; + grests.write[i] = skel->get_bone_rest(i); + bones.write[0] = i; } /* Transform t = grests[i]; @@ -1604,24 +1653,28 @@ void SkeletonSpatialGizmo::redraw() { } Ref<ArrayMesh> m = surface_tool->commit(); - add_mesh(m, false, skel->get_skeleton()); + p_gizmo->add_mesh(m, false, skel->get_skeleton()); } -SkeletonSpatialGizmo::SkeletonSpatialGizmo(Skeleton *p_skel) { +//// + +PhysicalBoneSpatialGizmoPlugin::PhysicalBoneSpatialGizmoPlugin() { + create_material("joint_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint", Color(0.5, 0.8, 1))); +} - skel = p_skel; - set_spatial_node(p_skel); +bool PhysicalBoneSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<PhysicalBone>(p_spatial) != NULL; } -PhysicalBoneSpatialGizmo::PhysicalBoneSpatialGizmo(PhysicalBone *p_pb) : - EditorSpatialGizmo(), - physical_bone(p_pb) { - set_spatial_node(p_pb); +String PhysicalBoneSpatialGizmoPlugin::get_name() const { + return "PhysicalBones"; } -void PhysicalBoneSpatialGizmo::redraw() { +void PhysicalBoneSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { - clear(); + p_gizmo->clear(); + + PhysicalBone *physical_bone = Object::cast_to<PhysicalBone>(p_gizmo->get_spatial_node()); if (!physical_bone) return; @@ -1635,26 +1688,25 @@ void PhysicalBoneSpatialGizmo::redraw() { switch (physical_bone->get_joint_type()) { case PhysicalBone::JOINT_TYPE_PIN: { - PinJointSpatialGizmo::CreateGizmo(physical_bone->get_joint_offset(), points); + JointSpatialGizmoPlugin::CreatePinJointGizmo(physical_bone->get_joint_offset(), points); } break; case PhysicalBone::JOINT_TYPE_CONE: { const PhysicalBone::ConeJointData *cjd(static_cast<const PhysicalBone::ConeJointData *>(physical_bone->get_joint_data())); - ConeTwistJointSpatialGizmo::CreateGizmo( + JointSpatialGizmoPlugin::CreateConeTwistJointGizmo( physical_bone->get_joint_offset(), physical_bone->get_global_transform() * physical_bone->get_joint_offset(), pb ? pb->get_global_transform() : Transform(), pbp ? pbp->get_global_transform() : Transform(), cjd->swing_span, cjd->twist_span, - points, pb ? &points : NULL, pbp ? &points : NULL); } break; case PhysicalBone::JOINT_TYPE_HINGE: { const PhysicalBone::HingeJointData *hjd(static_cast<const PhysicalBone::HingeJointData *>(physical_bone->get_joint_data())); - HingeJointSpatialGizmo::CreateGizmo( + JointSpatialGizmoPlugin::CreateHingeJointGizmo( physical_bone->get_joint_offset(), physical_bone->get_global_transform() * physical_bone->get_joint_offset(), pb ? pb->get_global_transform() : Transform(), @@ -1669,7 +1721,7 @@ void PhysicalBoneSpatialGizmo::redraw() { case PhysicalBone::JOINT_TYPE_SLIDER: { const PhysicalBone::SliderJointData *sjd(static_cast<const PhysicalBone::SliderJointData *>(physical_bone->get_joint_data())); - SliderJointSpatialGizmo::CreateGizmo( + JointSpatialGizmoPlugin::CreateSliderJointGizmo( physical_bone->get_joint_offset(), physical_bone->get_global_transform() * physical_bone->get_joint_offset(), pb ? pb->get_global_transform() : Transform(), @@ -1685,7 +1737,7 @@ void PhysicalBoneSpatialGizmo::redraw() { case PhysicalBone::JOINT_TYPE_6DOF: { const PhysicalBone::SixDOFJointData *sdofjd(static_cast<const PhysicalBone::SixDOFJointData *>(physical_bone->get_joint_data())); - Generic6DOFJointSpatialGizmo::CreateGizmo( + JointSpatialGizmoPlugin::CreateGeneric6DOFJointGizmo( physical_bone->get_joint_offset(), physical_bone->get_global_transform() * physical_bone->get_joint_offset(), @@ -1721,14 +1773,15 @@ void PhysicalBoneSpatialGizmo::redraw() { return; } - Ref<Material> material = create_material("joint_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint")); + Ref<Material> material = get_material("joint_material", p_gizmo); - add_collision_segments(points); - add_lines(points, material); + p_gizmo->add_collision_segments(points); + p_gizmo->add_lines(points, material); } // FIXME: Kept as reference for reimplementation in 3.1+ #if 0 + void RoomSpatialGizmo::redraw() { clear(); @@ -1745,41 +1798,41 @@ void RoomSpatialGizmo::redraw() { for (int i = 0; i < fc; i++) { - Vector3 fn = r[i].get_plane().normal; + Vector3 fn = r[i].get_plane().normal; - for (int j = 0; j < 3; j++) { + for (int j = 0; j < 3; j++) { - _EdgeKey ek; - ek.from = r[i].vertex[j].snapped(Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON)); - ek.to = r[i].vertex[(j + 1) % 3].snapped(Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON)); - if (ek.from < ek.to) - SWAP(ek.from, ek.to); + _EdgeKey ek; + ek.from = r[i].vertex[j].snapped(Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON)); + ek.to = r[i].vertex[(j + 1) % 3].snapped(Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON)); + if (ek.from < ek.to) + SWAP(ek.from, ek.to); - Map<_EdgeKey, Vector3>::Element *E = edge_map.find(ek); + Map<_EdgeKey, Vector3>::Element *E = edge_map.find(ek); - if (E) { + if (E) { - if (E->get().dot(fn) > 0.9) { + if (E->get().dot(fn) > 0.9) { - E->get() = Vector3(); - } + E->get() = Vector3(); + } - } else { + } else { - edge_map[ek] = fn; - } + edge_map[ek] = fn; + } + } } - } for (Map<_EdgeKey, Vector3>::Element *E = edge_map.front(); E; E = E->next()) { - if (E->get() != Vector3()) { - lines.push_back(E->key().from); - lines.push_back(E->key().to); + if (E->get() != Vector3()) { + lines.push_back(E->key().from); + lines.push_back(E->key().to); + } } - } - add_lines(lines, SpatialEditorGizmos::singleton->room_material); + add_lines(lines, EditorSpatialGizmos::singleton->room_material); add_collision_segments(lines); } @@ -1797,31 +1850,31 @@ void PortalSpatialGizmo::redraw() { Vector<Point2> points = portal->get_shape(); if (points.size() == 0) { - return; - } + return; + } Vector<Vector3> lines; Vector3 center; for (int i = 0; i < points.size(); i++) { - Vector3 f; - f.x = points[i].x; - f.y = points[i].y; - Vector3 fn; - fn.x = points[(i + 1) % points.size()].x; - fn.y = points[(i + 1) % points.size()].y; - center += f; + Vector3 f; + f.x = points[i].x; + f.y = points[i].y; + Vector3 fn; + fn.x = points[(i + 1) % points.size()].x; + fn.y = points[(i + 1) % points.size()].y; + center += f; - lines.push_back(f); - lines.push_back(fn); - } + lines.push_back(f); + lines.push_back(fn); + } center /= points.size(); lines.push_back(center); lines.push_back(center + Vector3(0, 0, 1)); - add_lines(lines, SpatialEditorGizmos::singleton->portal_material); + add_lines(lines, EditorSpatialGizmos::singleton->portal_material); add_collision_segments(lines); } @@ -1834,33 +1887,58 @@ PortalSpatialGizmo::PortalSpatialGizmo(Portal *p_portal) { #endif ///// -void RayCastSpatialGizmo::redraw() { +RayCastSpatialGizmoPlugin::RayCastSpatialGizmoPlugin() { - clear(); + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1)); + create_material("shape_material", gizmo_color); +} + +bool RayCastSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<RayCast>(p_spatial) != NULL; +} + +String RayCastSpatialGizmoPlugin::get_name() const { + return "RayCast"; +} + +void RayCastSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { + + RayCast *raycast = Object::cast_to<RayCast>(p_gizmo->get_spatial_node()); + + p_gizmo->clear(); Vector<Vector3> lines; lines.push_back(Vector3()); lines.push_back(raycast->get_cast_to()); - Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape"); - Ref<Material> material = create_material("shape_material", gizmo_color); + Ref<SpatialMaterial> material = get_material("shape_material", p_gizmo); - add_lines(lines, material); - add_collision_segments(lines); + p_gizmo->add_lines(lines, material); + p_gizmo->add_collision_segments(lines); } -RayCastSpatialGizmo::RayCastSpatialGizmo(RayCast *p_raycast) { +///// + +VehicleWheelSpatialGizmoPlugin::VehicleWheelSpatialGizmoPlugin() { - set_spatial_node(p_raycast); - raycast = p_raycast; + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1)); + create_material("shape_material", gizmo_color); } -///// +bool VehicleWheelSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<VehicleWheel>(p_spatial) != NULL; +} -void VehicleWheelSpatialGizmo::redraw() { +String VehicleWheelSpatialGizmoPlugin::get_name() const { + return "VehicleWheel"; +} - clear(); +void VehicleWheelSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { + + VehicleWheel *car_wheel = Object::cast_to<VehicleWheel>(p_gizmo->get_spatial_node()); + + p_gizmo->clear(); Vector<Vector3> points; @@ -1904,23 +1982,36 @@ void VehicleWheelSpatialGizmo::redraw() { points.push_back(Vector3(0, -r, r * 2)); points.push_back(Vector3(-r * 2 * 0.2, -r, r * 2 * 0.8)); - Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape"); - Ref<Material> material = create_material("shape_material", gizmo_color); + Ref<Material> material = get_material("shape_material", p_gizmo); - add_lines(points, material); - add_collision_segments(points); + p_gizmo->add_lines(points, material); + p_gizmo->add_collision_segments(points); } -VehicleWheelSpatialGizmo::VehicleWheelSpatialGizmo(VehicleWheel *p_car_wheel) { +/////////// - set_spatial_node(p_car_wheel); - car_wheel = p_car_wheel; +SoftBodySpatialGizmoPlugin::SoftBodySpatialGizmoPlugin() { + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1)); + create_material("shape_material", gizmo_color); + create_handle_material("handles"); } -/////////// +bool SoftBodySpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<SoftBody>(p_spatial) != NULL; +} -void SoftBodySpatialGizmo::redraw() { - clear(); +String SoftBodySpatialGizmoPlugin::get_name() const { + return "SoftBody"; +} + +bool SoftBodySpatialGizmoPlugin::is_selectable_when_hidden() const { + return true; +} + +void SoftBodySpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { + SoftBody *soft_body = Object::cast_to<SoftBody>(p_gizmo->get_spatial_node()); + + p_gizmo->clear(); if (!soft_body || soft_body->get_mesh().is_null()) { return; @@ -1936,84 +2027,840 @@ void SoftBodySpatialGizmo::redraw() { return; } + Ref<TriangleMesh> tm = soft_body->get_mesh()->generate_triangle_mesh(); + Vector<Vector3> points; soft_body->get_mesh()->generate_debug_mesh_indices(points); - soft_body->get_mesh()->clear_cache(); - Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape"); - Ref<Material> material = create_material("shape_material", gizmo_color); + Ref<Material> material = get_material("shape_material", p_gizmo); - add_lines(lines, material); - add_collision_segments(lines); - add_handles(points); -} - -bool SoftBodySpatialGizmo::intersect_ray(Camera *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle, bool p_sec_first) { - return EditorSpatialGizmo::intersect_ray(p_camera, p_point, r_pos, r_normal, r_gizmo_handle, p_sec_first); - - /* Perform a shape cast but doesn't work with softbody - PhysicsDirectSpaceState *space_state = PhysicsServer::get_singleton()->space_get_direct_state(SceneTree::get_singleton()->get_root()->get_world()->get_space()); - if (!physics_sphere_shape.is_valid()) { - physics_sphere_shape = PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_SPHERE); - real_t radius = 0.02; - PhysicsServer::get_singleton()->shape_set_data(physics_sphere_shape, radius); - } - - Vector3 sphere_motion(p_camera->project_ray_normal(p_point)); - real_t closest_safe; - real_t closest_unsafe; - PhysicsDirectSpaceState::ShapeRestInfo result; - bool collided = space_state->cast_motion( - physics_sphere_shape, - p_camera->get_transform(), - sphere_motion * Vector3(1000, 1000, 1000), - 0.f, - closest_safe, - closest_unsafe, - Set<RID>(), - 0xFFFFFFFF, - 0xFFFFFFFF, - &result); - - if (collided) { - - if (result.collider_id == soft_body->get_instance_id()) { - print_line("Collided"); - } else { - print_line("Collided but with wrong object: " + itos(result.collider_id)); - } - } else { - print_line("Not collided, motion: x: " + rtos(sphere_motion[0]) + " y: " + rtos(sphere_motion[1]) + " z: " + rtos(sphere_motion[2])); - } - return false; - */ + p_gizmo->add_lines(lines, material); + p_gizmo->add_collision_segments(lines); + p_gizmo->add_handles(points, get_material("handles")); + p_gizmo->add_collision_triangles(tm); +} + +String SoftBodySpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { + return "SoftBody pin point"; +} + +Variant SoftBodySpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { + SoftBody *soft_body = Object::cast_to<SoftBody>(p_gizmo->get_spatial_node()); + return Variant(soft_body->is_point_pinned(p_idx)); } -void SoftBodySpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { +void SoftBodySpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { + SoftBody *soft_body = Object::cast_to<SoftBody>(p_gizmo->get_spatial_node()); soft_body->pin_point_toggle(p_idx); - redraw(); } -bool SoftBodySpatialGizmo::is_gizmo_handle_highlighted(int idx) const { +bool SoftBodySpatialGizmoPlugin::is_gizmo_handle_highlighted(const EditorSpatialGizmo *p_gizmo, int idx) const { + SoftBody *soft_body = Object::cast_to<SoftBody>(p_gizmo->get_spatial_node()); return soft_body->is_point_pinned(idx); } -SoftBodySpatialGizmo::SoftBodySpatialGizmo(SoftBody *p_soft_physics_body) : - EditorSpatialGizmo(), - soft_body(p_soft_physics_body) { - set_spatial_node(p_soft_physics_body); +/////////// + +VisibilityNotifierGizmoPlugin::VisibilityNotifierGizmoPlugin() { + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/visibility_notifier", Color(0.8, 0.5, 0.7)); + create_material("visibility_notifier_material", gizmo_color); + gizmo_color.a = 0.1; + create_material("visibility_notifier_solid_material", gizmo_color); + create_handle_material("handles"); } -SoftBodySpatialGizmo::~SoftBodySpatialGizmo() { - //if (!physics_sphere_shape.is_valid()) { - // PhysicsServer::get_singleton()->free(physics_sphere_shape); - //} +bool VisibilityNotifierGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<VisibilityNotifier>(p_spatial) != NULL; } -/////////// +String VisibilityNotifierGizmoPlugin::get_name() const { + return "VisibilityNotifier"; +} + +String VisibilityNotifierGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { + + switch (p_idx) { + case 0: return "Size X"; + case 1: return "Size Y"; + case 2: return "Size Z"; + case 3: return "Pos X"; + case 4: return "Pos Y"; + case 5: return "Pos Z"; + } + + return ""; +} + +Variant VisibilityNotifierGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { + + VisibilityNotifier *notifier = Object::cast_to<VisibilityNotifier>(p_gizmo->get_spatial_node()); + return notifier->get_aabb(); +} +void VisibilityNotifierGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { + + VisibilityNotifier *notifier = Object::cast_to<VisibilityNotifier>(p_gizmo->get_spatial_node()); + + Transform gt = notifier->get_global_transform(); + + Transform gi = gt.affine_inverse(); + + bool move = p_idx >= 3; + p_idx = p_idx % 3; + + AABB aabb = notifier->get_aabb(); + Vector3 ray_from = p_camera->project_ray_origin(p_point); + Vector3 ray_dir = p_camera->project_ray_normal(p_point); + + Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) }; + + Vector3 ofs = aabb.position + aabb.size * 0.5; + + Vector3 axis; + axis[p_idx] = 1.0; + + if (move) { + + Vector3 ra, rb; + Geometry::get_closest_points_between_segments(ofs - axis * 4096, ofs + axis * 4096, sg[0], sg[1], ra, rb); + + float d = ra[p_idx]; + + aabb.position[p_idx] = d - 1.0 - aabb.size[p_idx] * 0.5; + notifier->set_aabb(aabb); + + } else { + Vector3 ra, rb; + Geometry::get_closest_points_between_segments(ofs, ofs + axis * 4096, sg[0], sg[1], ra, rb); + + float d = ra[p_idx] - ofs[p_idx]; + if (d < 0.001) + d = 0.001; + //resize + aabb.position[p_idx] = (aabb.position[p_idx] + aabb.size[p_idx] * 0.5) - d; + aabb.size[p_idx] = d * 2; + notifier->set_aabb(aabb); + } +} + +void VisibilityNotifierGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { + + VisibilityNotifier *notifier = Object::cast_to<VisibilityNotifier>(p_gizmo->get_spatial_node()); + + if (p_cancel) { + notifier->set_aabb(p_restore); + return; + } + + UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + ur->create_action(TTR("Change Notifier AABB")); + ur->add_do_method(notifier, "set_aabb", notifier->get_aabb()); + ur->add_undo_method(notifier, "set_aabb", p_restore); + ur->commit_action(); +} + +void VisibilityNotifierGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { + + VisibilityNotifier *notifier = Object::cast_to<VisibilityNotifier>(p_gizmo->get_spatial_node()); + + p_gizmo->clear(); + + Vector<Vector3> lines; + AABB aabb = notifier->get_aabb(); + + for (int i = 0; i < 12; i++) { + Vector3 a, b; + aabb.get_edge(i, a, b); + lines.push_back(a); + lines.push_back(b); + } + + Vector<Vector3> handles; + + for (int i = 0; i < 3; i++) { + + Vector3 ax; + ax[i] = aabb.position[i] + aabb.size[i]; + ax[(i + 1) % 3] = aabb.position[(i + 1) % 3] + aabb.size[(i + 1) % 3] * 0.5; + ax[(i + 2) % 3] = aabb.position[(i + 2) % 3] + aabb.size[(i + 2) % 3] * 0.5; + handles.push_back(ax); + } + + Vector3 center = aabb.position + aabb.size * 0.5; + for (int i = 0; i < 3; i++) { + + Vector3 ax; + ax[i] = 1.0; + handles.push_back(center + ax); + lines.push_back(center); + lines.push_back(center + ax); + } + + Ref<Material> material = get_material("visibility_notifier_material", p_gizmo); + + p_gizmo->add_lines(lines, material); + p_gizmo->add_collision_segments(lines); + + if (p_gizmo->is_selected()) { + Ref<Material> solid_material = get_material("visibility_notifier_solid_material", p_gizmo); + p_gizmo->add_solid_box(solid_material, aabb.get_size(), aabb.get_position() + aabb.get_size() / 2.0); + } + + p_gizmo->add_handles(handles, get_material("handles")); +} + +//// + +ParticlesGizmoPlugin::ParticlesGizmoPlugin() { + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/particles", Color(0.8, 0.7, 0.4)); + create_material("particles_material", gizmo_color); + gizmo_color.a = 0.1; + create_material("particles_solid_material", gizmo_color); + create_icon_material("particles_icon", SpatialEditor::get_singleton()->get_icon("GizmoParticles", "EditorIcons")); + create_handle_material("handles"); +} + +bool ParticlesGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<Particles>(p_spatial) != NULL; +} + +String ParticlesGizmoPlugin::get_name() const { + return "Particles"; +} + +bool ParticlesGizmoPlugin::is_selectable_when_hidden() const { + return true; +} + +String ParticlesGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { + + switch (p_idx) { + case 0: return "Size X"; + case 1: return "Size Y"; + case 2: return "Size Z"; + case 3: return "Pos X"; + case 4: return "Pos Y"; + case 5: return "Pos Z"; + } + + return ""; +} +Variant ParticlesGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { + + Particles *particles = Object::cast_to<Particles>(p_gizmo->get_spatial_node()); + return particles->get_visibility_aabb(); +} +void ParticlesGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { + + Particles *particles = Object::cast_to<Particles>(p_gizmo->get_spatial_node()); + + Transform gt = particles->get_global_transform(); + //gt.orthonormalize(); + Transform gi = gt.affine_inverse(); + + bool move = p_idx >= 3; + p_idx = p_idx % 3; + + AABB aabb = particles->get_visibility_aabb(); + Vector3 ray_from = p_camera->project_ray_origin(p_point); + Vector3 ray_dir = p_camera->project_ray_normal(p_point); + + Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) }; + + Vector3 ofs = aabb.position + aabb.size * 0.5; + + Vector3 axis; + axis[p_idx] = 1.0; + + if (move) { + + Vector3 ra, rb; + Geometry::get_closest_points_between_segments(ofs - axis * 4096, ofs + axis * 4096, sg[0], sg[1], ra, rb); + + float d = ra[p_idx]; + + aabb.position[p_idx] = d - 1.0 - aabb.size[p_idx] * 0.5; + particles->set_visibility_aabb(aabb); + + } else { + Vector3 ra, rb; + Geometry::get_closest_points_between_segments(ofs, ofs + axis * 4096, sg[0], sg[1], ra, rb); + + float d = ra[p_idx] - ofs[p_idx]; + if (d < 0.001) + d = 0.001; + //resize + aabb.position[p_idx] = (aabb.position[p_idx] + aabb.size[p_idx] * 0.5) - d; + aabb.size[p_idx] = d * 2; + particles->set_visibility_aabb(aabb); + } +} + +void ParticlesGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { + + Particles *particles = Object::cast_to<Particles>(p_gizmo->get_spatial_node()); + + if (p_cancel) { + particles->set_visibility_aabb(p_restore); + return; + } + + UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + ur->create_action(TTR("Change Particles AABB")); + ur->add_do_method(particles, "set_custom_aabb", particles->get_visibility_aabb()); + ur->add_undo_method(particles, "set_custom_aabb", p_restore); + ur->commit_action(); +} + +void ParticlesGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { + + Particles *particles = Object::cast_to<Particles>(p_gizmo->get_spatial_node()); + + p_gizmo->clear(); + + Vector<Vector3> lines; + AABB aabb = particles->get_visibility_aabb(); + + for (int i = 0; i < 12; i++) { + Vector3 a, b; + aabb.get_edge(i, a, b); + lines.push_back(a); + lines.push_back(b); + } + + Vector<Vector3> handles; + + for (int i = 0; i < 3; i++) { + + Vector3 ax; + ax[i] = aabb.position[i] + aabb.size[i]; + ax[(i + 1) % 3] = aabb.position[(i + 1) % 3] + aabb.size[(i + 1) % 3] * 0.5; + ax[(i + 2) % 3] = aabb.position[(i + 2) % 3] + aabb.size[(i + 2) % 3] * 0.5; + handles.push_back(ax); + } + + Vector3 center = aabb.position + aabb.size * 0.5; + for (int i = 0; i < 3; i++) { + + Vector3 ax; + ax[i] = 1.0; + handles.push_back(center + ax); + lines.push_back(center); + lines.push_back(center + ax); + } + + Ref<Material> material = get_material("particles_material", p_gizmo); + Ref<Material> icon = get_material("particles_icon", p_gizmo); + + p_gizmo->add_lines(lines, material); + p_gizmo->add_collision_segments(lines); + + if (p_gizmo->is_selected()) { + Ref<Material> solid_material = get_material("particles_solid_material", p_gizmo); + p_gizmo->add_solid_box(solid_material, aabb.get_size(), aabb.get_position() + aabb.get_size() / 2.0); + } + + p_gizmo->add_handles(handles, get_material("handles")); + p_gizmo->add_unscaled_billboard(icon, 0.05); +} +//// + +ReflectionProbeGizmoPlugin::ReflectionProbeGizmoPlugin() { + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/reflection_probe", Color(0.6, 1, 0.5)); + + create_material("reflection_probe_material", gizmo_color); + + gizmo_color.a = 0.5; + create_material("reflection_internal_material", gizmo_color); + + gizmo_color.a = 0.1; + create_material("reflection_probe_solid_material", gizmo_color); + + create_icon_material("reflection_probe_icon", SpatialEditor::get_singleton()->get_icon("GizmoReflectionProbe", "EditorIcons")); + create_handle_material("handles"); +} + +bool ReflectionProbeGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<ReflectionProbe>(p_spatial) != NULL; +} + +String ReflectionProbeGizmoPlugin::get_name() const { + return "ReflectionProbe"; +} + +String ReflectionProbeGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { + + switch (p_idx) { + case 0: return "Extents X"; + case 1: return "Extents Y"; + case 2: return "Extents Z"; + case 3: return "Origin X"; + case 4: return "Origin Y"; + case 5: return "Origin Z"; + } + + return ""; +} +Variant ReflectionProbeGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { + + ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_spatial_node()); + return AABB(probe->get_extents(), probe->get_origin_offset()); +} +void ReflectionProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { + + ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_spatial_node()); + Transform gt = probe->get_global_transform(); + + Transform gi = gt.affine_inverse(); + + if (p_idx < 3) { + Vector3 extents = probe->get_extents(); + + Vector3 ray_from = p_camera->project_ray_origin(p_point); + Vector3 ray_dir = p_camera->project_ray_normal(p_point); + + Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; + + Vector3 axis; + axis[p_idx] = 1.0; + + Vector3 ra, rb; + Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); + float d = ra[p_idx]; + if (d < 0.001) + d = 0.001; + + extents[p_idx] = d; + probe->set_extents(extents); + } else { + + p_idx -= 3; + + Vector3 origin = probe->get_origin_offset(); + origin[p_idx] = 0; + + Vector3 ray_from = p_camera->project_ray_origin(p_point); + Vector3 ray_dir = p_camera->project_ray_normal(p_point); + + Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; + + Vector3 axis; + axis[p_idx] = 1.0; + + Vector3 ra, rb; + Geometry::get_closest_points_between_segments(origin - axis * 16384, origin + axis * 16384, sg[0], sg[1], ra, rb); + float d = ra[p_idx]; + d += 0.25; + + origin[p_idx] = d; + probe->set_origin_offset(origin); + } +} + +void ReflectionProbeGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { + + ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_spatial_node()); + + AABB restore = p_restore; + + if (p_cancel) { + probe->set_extents(restore.position); + probe->set_origin_offset(restore.size); + return; + } + + UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + ur->create_action(TTR("Change Probe Extents")); + ur->add_do_method(probe, "set_extents", probe->get_extents()); + ur->add_do_method(probe, "set_origin_offset", probe->get_origin_offset()); + ur->add_undo_method(probe, "set_extents", restore.position); + ur->add_undo_method(probe, "set_origin_offset", restore.size); + ur->commit_action(); +} + +void ReflectionProbeGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { + + ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_spatial_node()); + + p_gizmo->clear(); + + Vector<Vector3> lines; + Vector<Vector3> internal_lines; + Vector3 extents = probe->get_extents(); + + AABB aabb; + aabb.position = -extents; + aabb.size = extents * 2; + + for (int i = 0; i < 12; i++) { + Vector3 a, b; + aabb.get_edge(i, a, b); + lines.push_back(a); + lines.push_back(b); + } + + for (int i = 0; i < 8; i++) { + Vector3 ep = aabb.get_endpoint(i); + internal_lines.push_back(probe->get_origin_offset()); + internal_lines.push_back(ep); + } + + Vector<Vector3> handles; + + for (int i = 0; i < 3; i++) { + + Vector3 ax; + ax[i] = aabb.position[i] + aabb.size[i]; + handles.push_back(ax); + } + + for (int i = 0; i < 3; i++) { + + Vector3 orig_handle = probe->get_origin_offset(); + orig_handle[i] -= 0.25; + lines.push_back(orig_handle); + handles.push_back(orig_handle); + + orig_handle[i] += 0.5; + lines.push_back(orig_handle); + } + + Ref<Material> material = get_material("reflection_probe_material", p_gizmo); + Ref<Material> material_internal = get_material("reflection_internal_material", p_gizmo); + Ref<Material> icon = get_material("reflection_probe_icon", p_gizmo); + + p_gizmo->add_lines(lines, material); + p_gizmo->add_lines(internal_lines, material_internal); + + if (p_gizmo->is_selected()) { + Ref<Material> solid_material = get_material("reflection_probe_solid_material", p_gizmo); + p_gizmo->add_solid_box(solid_material, probe->get_extents() * 2.0); + } + + p_gizmo->add_unscaled_billboard(icon, 0.05); + p_gizmo->add_collision_segments(lines); + p_gizmo->add_handles(handles, get_material("handles")); +} + +GIProbeGizmoPlugin::GIProbeGizmoPlugin() { + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/gi_probe", Color(0.5, 1, 0.6)); + + create_material("gi_probe_material", gizmo_color); + + gizmo_color.a = 0.5; + create_material("gi_probe_internal_material", gizmo_color); + + gizmo_color.a = 0.1; + create_material("gi_probe_solid_material", gizmo_color); + + create_icon_material("gi_probe_icon", SpatialEditor::get_singleton()->get_icon("GizmoGIProbe", "EditorIcons")); + create_handle_material("handles"); +} + +bool GIProbeGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<GIProbe>(p_spatial) != NULL; +} + +String GIProbeGizmoPlugin::get_name() const { + return "GIProbe"; +} + +String GIProbeGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { + + switch (p_idx) { + case 0: return "Extents X"; + case 1: return "Extents Y"; + case 2: return "Extents Z"; + } + + return ""; +} +Variant GIProbeGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { + + GIProbe *probe = Object::cast_to<GIProbe>(p_gizmo->get_spatial_node()); + return probe->get_extents(); +} +void GIProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { + + GIProbe *probe = Object::cast_to<GIProbe>(p_gizmo->get_spatial_node()); + + Transform gt = probe->get_global_transform(); + //gt.orthonormalize(); + Transform gi = gt.affine_inverse(); + + Vector3 extents = probe->get_extents(); + + Vector3 ray_from = p_camera->project_ray_origin(p_point); + Vector3 ray_dir = p_camera->project_ray_normal(p_point); + + Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; + + Vector3 axis; + axis[p_idx] = 1.0; + + Vector3 ra, rb; + Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); + float d = ra[p_idx]; + if (d < 0.001) + d = 0.001; + + extents[p_idx] = d; + probe->set_extents(extents); +} + +void GIProbeGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { + + GIProbe *probe = Object::cast_to<GIProbe>(p_gizmo->get_spatial_node()); + + Vector3 restore = p_restore; + + if (p_cancel) { + probe->set_extents(restore); + return; + } + + UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + ur->create_action(TTR("Change Probe Extents")); + ur->add_do_method(probe, "set_extents", probe->get_extents()); + ur->add_undo_method(probe, "set_extents", restore); + ur->commit_action(); +} + +void GIProbeGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { + + GIProbe *probe = Object::cast_to<GIProbe>(p_gizmo->get_spatial_node()); + + Ref<Material> material = get_material("gi_probe_material", p_gizmo); + Ref<Material> icon = get_material("gi_probe_icon", p_gizmo); + Ref<Material> material_internal = get_material("gi_probe_internal_material", p_gizmo); + + p_gizmo->clear(); + + Vector<Vector3> lines; + Vector3 extents = probe->get_extents(); + + static const int subdivs[GIProbe::SUBDIV_MAX] = { 64, 128, 256, 512 }; + + AABB aabb = AABB(-extents, extents * 2); + int subdiv = subdivs[probe->get_subdiv()]; + float cell_size = aabb.get_longest_axis_size() / subdiv; + + for (int i = 0; i < 12; i++) { + Vector3 a, b; + aabb.get_edge(i, a, b); + lines.push_back(a); + lines.push_back(b); + } + + p_gizmo->add_lines(lines, material); + p_gizmo->add_collision_segments(lines); + + lines.clear(); + + for (int i = 1; i < subdiv; i++) { + + for (int j = 0; j < 3; j++) { + + if (cell_size * i > aabb.size[j]) { + continue; + } + + Vector2 dir; + dir[j] = 1.0; + Vector2 ta, tb; + int j_n1 = (j + 1) % 3; + int j_n2 = (j + 2) % 3; + ta[j_n1] = 1.0; + tb[j_n2] = 1.0; + + for (int k = 0; k < 4; k++) { + + Vector3 from = aabb.position, to = aabb.position; + from[j] += cell_size * i; + to[j] += cell_size * i; + + if (k & 1) { + to[j_n1] += aabb.size[j_n1]; + } else { + + to[j_n2] += aabb.size[j_n2]; + } + + if (k & 2) { + from[j_n1] += aabb.size[j_n1]; + from[j_n2] += aabb.size[j_n2]; + } + + lines.push_back(from); + lines.push_back(to); + } + } + } + + p_gizmo->add_lines(lines, material_internal); + + Vector<Vector3> handles; + + for (int i = 0; i < 3; i++) { + + Vector3 ax; + ax[i] = aabb.position[i] + aabb.size[i]; + handles.push_back(ax); + } + + if (p_gizmo->is_selected()) { + Ref<Material> solid_material = get_material("gi_probe_solid_material", p_gizmo); + p_gizmo->add_solid_box(solid_material, aabb.get_size()); + } + + p_gizmo->add_unscaled_billboard(icon, 0.05); + p_gizmo->add_handles(handles, get_material("handles")); +} + +//// + +BakedIndirectLightGizmoPlugin::BakedIndirectLightGizmoPlugin() { + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/baked_indirect_light", Color(0.5, 0.6, 1)); + + create_material("baked_indirect_light_material", gizmo_color); + + gizmo_color.a = 0.1; + create_material("baked_indirect_light_internal_material", gizmo_color); + + create_icon_material("baked_indirect_light_icon", SpatialEditor::get_singleton()->get_icon("GizmoBakedLightmap", "EditorIcons")); + create_handle_material("handles"); +} + +String BakedIndirectLightGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { + + switch (p_idx) { + case 0: return "Extents X"; + case 1: return "Extents Y"; + case 2: return "Extents Z"; + } + + return ""; +} +Variant BakedIndirectLightGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { + + BakedLightmap *baker = Object::cast_to<BakedLightmap>(p_gizmo->get_spatial_node()); + return baker->get_extents(); +} +void BakedIndirectLightGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { + + BakedLightmap *baker = Object::cast_to<BakedLightmap>(p_gizmo->get_spatial_node()); + + Transform gt = baker->get_global_transform(); + //gt.orthonormalize(); + Transform gi = gt.affine_inverse(); + + Vector3 extents = baker->get_extents(); + + Vector3 ray_from = p_camera->project_ray_origin(p_point); + Vector3 ray_dir = p_camera->project_ray_normal(p_point); + + Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; + + Vector3 axis; + axis[p_idx] = 1.0; + + Vector3 ra, rb; + Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); + float d = ra[p_idx]; + if (d < 0.001) + d = 0.001; + + extents[p_idx] = d; + baker->set_extents(extents); +} + +void BakedIndirectLightGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { + + BakedLightmap *baker = Object::cast_to<BakedLightmap>(p_gizmo->get_spatial_node()); + + Vector3 restore = p_restore; + + if (p_cancel) { + baker->set_extents(restore); + return; + } + + UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + ur->create_action(TTR("Change Probe Extents")); + ur->add_do_method(baker, "set_extents", baker->get_extents()); + ur->add_undo_method(baker, "set_extents", restore); + ur->commit_action(); +} + +bool BakedIndirectLightGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<BakedLightmap>(p_spatial) != NULL; +} + +String BakedIndirectLightGizmoPlugin::get_name() const { + return "BakedLightmap"; +} + +void BakedIndirectLightGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { + + BakedLightmap *baker = Object::cast_to<BakedLightmap>(p_gizmo->get_spatial_node()); + + Ref<Material> material = get_material("baked_indirect_light_material", p_gizmo); + Ref<Material> icon = get_material("baked_indirect_light_icon", p_gizmo); + Ref<Material> material_internal = get_material("baked_indirect_light_internal_material", p_gizmo); + + p_gizmo->clear(); + + Vector<Vector3> lines; + Vector3 extents = baker->get_extents(); + + AABB aabb = AABB(-extents, extents * 2); + + for (int i = 0; i < 12; i++) { + Vector3 a, b; + aabb.get_edge(i, a, b); + lines.push_back(a); + lines.push_back(b); + } + + p_gizmo->add_lines(lines, material); + p_gizmo->add_collision_segments(lines); + + Vector<Vector3> handles; + + for (int i = 0; i < 3; i++) { + + Vector3 ax; + ax[i] = aabb.position[i] + aabb.size[i]; + handles.push_back(ax); + } + + if (p_gizmo->is_selected()) { + p_gizmo->add_solid_box(material_internal, aabb.get_size()); + } + + p_gizmo->add_unscaled_billboard(icon, 0.05); + p_gizmo->add_handles(handles, get_material("handles")); +} + +//// + +CollisionShapeSpatialGizmoPlugin::CollisionShapeSpatialGizmoPlugin() { + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1)); + create_material("shape_material", gizmo_color); + create_handle_material("handles"); +} + +bool CollisionShapeSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<CollisionShape>(p_spatial) != NULL; +} + +String CollisionShapeSpatialGizmoPlugin::get_name() const { + return "CollisionShape"; +} -String CollisionShapeSpatialGizmo::get_handle_name(int p_idx) const { +String CollisionShapeSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { + + const CollisionShape *cs = Object::cast_to<CollisionShape>(p_gizmo->get_spatial_node()); Ref<Shape> s = cs->get_shape(); if (s.is_null()) @@ -2046,7 +2893,10 @@ String CollisionShapeSpatialGizmo::get_handle_name(int p_idx) const { return ""; } -Variant CollisionShapeSpatialGizmo::get_handle_value(int p_idx) const { + +Variant CollisionShapeSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { + + CollisionShape *cs = Object::cast_to<CollisionShape>(p_gizmo->get_spatial_node()); Ref<Shape> s = cs->get_shape(); if (s.is_null()) @@ -2084,7 +2934,10 @@ Variant CollisionShapeSpatialGizmo::get_handle_value(int p_idx) const { return Variant(); } -void CollisionShapeSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) { +void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { + + CollisionShape *cs = Object::cast_to<CollisionShape>(p_gizmo->get_spatial_node()); + Ref<Shape> s = cs->get_shape(); if (s.is_null()) return; @@ -2175,7 +3028,10 @@ void CollisionShapeSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const P cs->set_height(d * 2.0); } } -void CollisionShapeSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { +void CollisionShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { + + CollisionShape *cs = Object::cast_to<CollisionShape>(p_gizmo->get_spatial_node()); + Ref<Shape> s = cs->get_shape(); if (s.is_null()) return; @@ -2252,7 +3108,11 @@ void CollisionShapeSpatialGizmo::commit_handle(int p_idx, const Variant &p_resto ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius()); ur->add_undo_method(ss.ptr(), "set_radius", p_restore); } else { - ur->create_action(TTR("Change Cylinder Shape Height")); + ur->create_action( + /// + + //////// + TTR("Change Cylinder Shape Height")); ur->add_do_method(ss.ptr(), "set_height", ss->get_height()); ur->add_undo_method(ss.ptr(), "set_height", p_restore); } @@ -2275,16 +3135,18 @@ void CollisionShapeSpatialGizmo::commit_handle(int p_idx, const Variant &p_resto ur->commit_action(); } } -void CollisionShapeSpatialGizmo::redraw() { +void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { - clear(); + CollisionShape *cs = Object::cast_to<CollisionShape>(p_gizmo->get_spatial_node()); + + p_gizmo->clear(); Ref<Shape> s = cs->get_shape(); if (s.is_null()) return; - Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape"); - Ref<Material> material = create_material("shape_material", gizmo_color); + Ref<Material> material = get_material("shape_material", p_gizmo); + Ref<Material> handles_material = get_material("handles"); if (Object::cast_to<SphereShape>(*s)) { @@ -2325,11 +3187,11 @@ void CollisionShapeSpatialGizmo::redraw() { collision_segments.push_back(Vector3(b.x, b.y, 0)); } - add_lines(points, material); - add_collision_segments(collision_segments); + p_gizmo->add_lines(points, material); + p_gizmo->add_collision_segments(collision_segments); Vector<Vector3> handles; handles.push_back(Vector3(r, 0, 0)); - add_handles(handles); + p_gizmo->add_handles(handles, handles_material); } if (Object::cast_to<BoxShape>(*s)) { @@ -2356,9 +3218,9 @@ void CollisionShapeSpatialGizmo::redraw() { handles.push_back(ax); } - add_lines(lines, material); - add_collision_segments(lines); - add_handles(handles); + p_gizmo->add_lines(lines, material); + p_gizmo->add_collision_segments(lines); + p_gizmo->add_handles(handles, handles_material); } if (Object::cast_to<CapsuleShape>(*s)) { @@ -2397,7 +3259,7 @@ void CollisionShapeSpatialGizmo::redraw() { points.push_back(Vector3(b.y, 0, b.x) + dud); } - add_lines(points, material); + p_gizmo->add_lines(points, material); Vector<Vector3> collision_segments; @@ -2428,12 +3290,12 @@ void CollisionShapeSpatialGizmo::redraw() { collision_segments.push_back(Vector3(b.y, 0, b.x) + dud); } - add_collision_segments(collision_segments); + p_gizmo->add_collision_segments(collision_segments); Vector<Vector3> handles; handles.push_back(Vector3(cs->get_radius(), 0, 0)); handles.push_back(Vector3(0, 0, cs->get_height() * 0.5 + cs->get_radius())); - add_handles(handles); + p_gizmo->add_handles(handles, handles_material); } if (Object::cast_to<CylinderShape>(*s)) { @@ -2465,7 +3327,7 @@ void CollisionShapeSpatialGizmo::redraw() { } } - add_lines(points, material); + p_gizmo->add_lines(points, material); Vector<Vector3> collision_segments; @@ -2489,12 +3351,12 @@ void CollisionShapeSpatialGizmo::redraw() { } } - add_collision_segments(collision_segments); + p_gizmo->add_collision_segments(collision_segments); Vector<Vector3> handles; handles.push_back(Vector3(cs->get_radius(), 0, 0)); handles.push_back(Vector3(0, cs->get_height() * 0.5, 0)); - add_handles(handles); + p_gizmo->add_handles(handles, handles_material); } if (Object::cast_to<PlaneShape>(*s)) { @@ -2524,8 +3386,8 @@ void CollisionShapeSpatialGizmo::redraw() { points.push_back(p.normal * p.d); points.push_back(p.normal * p.d + p.normal * 3); - add_lines(points, material); - add_collision_segments(points); + p_gizmo->add_lines(points, material); + p_gizmo->add_collision_segments(points); } if (Object::cast_to<ConvexPolygonShape>(*s)) { @@ -2542,12 +3404,12 @@ void CollisionShapeSpatialGizmo::redraw() { Vector<Vector3> points; points.resize(md.edges.size() * 2); for (int i = 0; i < md.edges.size(); i++) { - points[i * 2 + 0] = md.vertices[md.edges[i].a]; - points[i * 2 + 1] = md.vertices[md.edges[i].b]; + points.write[i * 2 + 0] = md.vertices[md.edges[i].a]; + points.write[i * 2 + 1] = md.vertices[md.edges[i].b]; } - add_lines(points, material); - add_collision_segments(points); + p_gizmo->add_lines(points, material); + p_gizmo->add_collision_segments(points); } } } @@ -2559,24 +3421,34 @@ void CollisionShapeSpatialGizmo::redraw() { Vector<Vector3> points; points.push_back(Vector3()); points.push_back(Vector3(0, 0, rs->get_length())); - add_lines(points, material); - add_collision_segments(points); + p_gizmo->add_lines(points, material); + p_gizmo->add_collision_segments(points); Vector<Vector3> handles; handles.push_back(Vector3(0, 0, rs->get_length())); - add_handles(handles); + p_gizmo->add_handles(handles, handles_material); } } -CollisionShapeSpatialGizmo::CollisionShapeSpatialGizmo(CollisionShape *p_cs) { - cs = p_cs; - set_spatial_node(p_cs); +///// + +CollisionPolygonSpatialGizmoPlugin::CollisionPolygonSpatialGizmoPlugin() { + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1)); + create_material("shape_material", gizmo_color); } -///// +bool CollisionPolygonSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<CollisionPolygon>(p_spatial) != NULL; +} -void CollisionPolygonSpatialGizmo::redraw() { +String CollisionPolygonSpatialGizmoPlugin::get_name() const { + return "CollisionPolygon"; +} - clear(); +void CollisionPolygonSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { + + CollisionPolygon *polygon = Object::cast_to<CollisionPolygon>(p_gizmo->get_spatial_node()); + + p_gizmo->clear(); Vector<Vector2> points = polygon->get_polygon(); float depth = polygon->get_depth() * 0.5; @@ -2593,695 +3465,39 @@ void CollisionPolygonSpatialGizmo::redraw() { lines.push_back(Vector3(points[i].x, points[i].y, -depth)); } - Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape"); - Ref<Material> material = create_material("shape_material", gizmo_color); - - add_lines(lines, material); - add_collision_segments(lines); -} - -CollisionPolygonSpatialGizmo::CollisionPolygonSpatialGizmo(CollisionPolygon *p_polygon) { - - set_spatial_node(p_polygon); - polygon = p_polygon; -} -/// - -String VisibilityNotifierGizmo::get_handle_name(int p_idx) const { - - switch (p_idx) { - case 0: return "X"; - case 1: return "Y"; - case 2: return "Z"; - } - - return ""; -} -Variant VisibilityNotifierGizmo::get_handle_value(int p_idx) const { - - return notifier->get_aabb(); -} -void VisibilityNotifierGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) { - - Transform gt = notifier->get_global_transform(); - //gt.orthonormalize(); - Transform gi = gt.affine_inverse(); - - AABB aabb = notifier->get_aabb(); - Vector3 ray_from = p_camera->project_ray_origin(p_point); - Vector3 ray_dir = p_camera->project_ray_normal(p_point); - - Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) }; - Vector3 ofs = aabb.position + aabb.size * 0.5; - - Vector3 axis; - axis[p_idx] = 1.0; - - Vector3 ra, rb; - Geometry::get_closest_points_between_segments(ofs, ofs + axis * 4096, sg[0], sg[1], ra, rb); - float d = ra[p_idx]; - if (d < 0.001) - d = 0.001; - - aabb.position[p_idx] = (aabb.position[p_idx] + aabb.size[p_idx] * 0.5) - d; - aabb.size[p_idx] = d * 2; - notifier->set_aabb(aabb); -} - -void VisibilityNotifierGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { - - if (p_cancel) { - notifier->set_aabb(p_restore); - return; - } - - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Change Notifier Extents")); - ur->add_do_method(notifier, "set_aabb", notifier->get_aabb()); - ur->add_undo_method(notifier, "set_aabb", p_restore); - ur->commit_action(); -} - -void VisibilityNotifierGizmo::redraw() { - - Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/visibility_notifier"); - Ref<Material> material = create_material("visibility_notifier_material", gizmo_color); - - clear(); - - Vector<Vector3> lines; - AABB aabb = notifier->get_aabb(); - - for (int i = 0; i < 12; i++) { - Vector3 a, b; - aabb.get_edge(i, a, b); - lines.push_back(a); - lines.push_back(b); - } - - Vector<Vector3> handles; - - for (int i = 0; i < 3; i++) { - - Vector3 ax; - ax[i] = aabb.position[i] + aabb.size[i]; - handles.push_back(ax); - } - - add_lines(lines, material); - //add_unscaled_billboard(SpatialEditorGizmos::singleton->visi,0.05); - add_collision_segments(lines); - add_handles(handles); -} -VisibilityNotifierGizmo::VisibilityNotifierGizmo(VisibilityNotifier *p_notifier) { - - notifier = p_notifier; - set_spatial_node(p_notifier); -} - -//////// - -/// - -String ParticlesGizmo::get_handle_name(int p_idx) const { - - switch (p_idx) { - case 0: return "Size X"; - case 1: return "Size Y"; - case 2: return "Size Z"; - case 3: return "Pos X"; - case 4: return "Pos Y"; - case 5: return "Pos Z"; - } - - return ""; -} -Variant ParticlesGizmo::get_handle_value(int p_idx) const { - - return particles->get_visibility_aabb(); -} -void ParticlesGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) { - - Transform gt = particles->get_global_transform(); - //gt.orthonormalize(); - Transform gi = gt.affine_inverse(); - - bool move = p_idx >= 3; - p_idx = p_idx % 3; - - AABB aabb = particles->get_visibility_aabb(); - Vector3 ray_from = p_camera->project_ray_origin(p_point); - Vector3 ray_dir = p_camera->project_ray_normal(p_point); - - Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) }; - - Vector3 ofs = aabb.position + aabb.size * 0.5; - - Vector3 axis; - axis[p_idx] = 1.0; - - if (move) { - - Vector3 ra, rb; - Geometry::get_closest_points_between_segments(ofs - axis * 4096, ofs + axis * 4096, sg[0], sg[1], ra, rb); - - float d = ra[p_idx]; - - aabb.position[p_idx] = d - 1.0 - aabb.size[p_idx] * 0.5; - particles->set_visibility_aabb(aabb); - - } else { - Vector3 ra, rb; - Geometry::get_closest_points_between_segments(ofs, ofs + axis * 4096, sg[0], sg[1], ra, rb); - - float d = ra[p_idx] - ofs[p_idx]; - if (d < 0.001) - d = 0.001; - //resize - aabb.position[p_idx] = (aabb.position[p_idx] + aabb.size[p_idx] * 0.5) - d; - aabb.size[p_idx] = d * 2; - particles->set_visibility_aabb(aabb); - } -} - -void ParticlesGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { - - if (p_cancel) { - particles->set_visibility_aabb(p_restore); - return; - } - - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Change Particles AABB")); - ur->add_do_method(particles, "set_custom_aabb", particles->get_visibility_aabb()); - ur->add_undo_method(particles, "set_custom_aabb", p_restore); - ur->commit_action(); -} - -void ParticlesGizmo::redraw() { - - clear(); - - Vector<Vector3> lines; - AABB aabb = particles->get_visibility_aabb(); - - for (int i = 0; i < 12; i++) { - Vector3 a, b; - aabb.get_edge(i, a, b); - lines.push_back(a); - lines.push_back(b); - } - - Vector<Vector3> handles; - - for (int i = 0; i < 3; i++) { - - Vector3 ax; - ax[i] = aabb.position[i] + aabb.size[i]; - ax[(i + 1) % 3] = aabb.position[(i + 1) % 3] + aabb.size[(i + 1) % 3] * 0.5; - ax[(i + 2) % 3] = aabb.position[(i + 2) % 3] + aabb.size[(i + 2) % 3] * 0.5; - handles.push_back(ax); - } - - Vector3 center = aabb.position + aabb.size * 0.5; - for (int i = 0; i < 3; i++) { - - Vector3 ax; - ax[i] = 1.0; - handles.push_back(center + ax); - lines.push_back(center); - lines.push_back(center + ax); - } - - Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/particles"); - Ref<Material> material = create_material("particles_material", gizmo_color); - Ref<Material> icon = create_icon_material("particles_icon", SpatialEditor::get_singleton()->get_icon("GizmoParticles", "EditorIcons")); - - add_lines(lines, material); - add_collision_segments(lines); - - if (is_selected()) { - - gizmo_color.a = 0.1; - Ref<Material> solid_material = create_material("particles_solid_material", gizmo_color); - add_solid_box(solid_material, aabb.get_size(), aabb.get_position() + aabb.get_size() / 2.0); - } - - //add_unscaled_billboard(SpatialEditorGizmos::singleton->visi,0.05); + Ref<Material> material = get_material("shape_material", p_gizmo); - add_handles(handles); - add_unscaled_billboard(icon, 0.05); + p_gizmo->add_lines(lines, material); + p_gizmo->add_collision_segments(lines); } -ParticlesGizmo::ParticlesGizmo(Particles *p_particles) { - particles = p_particles; - set_spatial_node(p_particles); -} - -//////// - -/// - -String ReflectionProbeGizmo::get_handle_name(int p_idx) const { - - switch (p_idx) { - case 0: return "Extents X"; - case 1: return "Extents Y"; - case 2: return "Extents Z"; - case 3: return "Origin X"; - case 4: return "Origin Y"; - case 5: return "Origin Z"; - } - - return ""; -} -Variant ReflectionProbeGizmo::get_handle_value(int p_idx) const { - - return AABB(probe->get_extents(), probe->get_origin_offset()); -} -void ReflectionProbeGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) { - - Transform gt = probe->get_global_transform(); - //gt.orthonormalize(); - Transform gi = gt.affine_inverse(); - - if (p_idx < 3) { - Vector3 extents = probe->get_extents(); - - Vector3 ray_from = p_camera->project_ray_origin(p_point); - Vector3 ray_dir = p_camera->project_ray_normal(p_point); - - Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; - - Vector3 axis; - axis[p_idx] = 1.0; - - Vector3 ra, rb; - Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); - float d = ra[p_idx]; - if (d < 0.001) - d = 0.001; - - extents[p_idx] = d; - probe->set_extents(extents); - } else { - - p_idx -= 3; - - Vector3 origin = probe->get_origin_offset(); - origin[p_idx] = 0; - - Vector3 ray_from = p_camera->project_ray_origin(p_point); - Vector3 ray_dir = p_camera->project_ray_normal(p_point); - - Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; - - Vector3 axis; - axis[p_idx] = 1.0; - - Vector3 ra, rb; - Geometry::get_closest_points_between_segments(origin - axis * 16384, origin + axis * 16384, sg[0], sg[1], ra, rb); - float d = ra[p_idx]; - d += 0.25; - - origin[p_idx] = d; - probe->set_origin_offset(origin); - } -} - -void ReflectionProbeGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { - - AABB restore = p_restore; - - if (p_cancel) { - probe->set_extents(restore.position); - probe->set_origin_offset(restore.size); - return; - } - - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Change Probe Extents")); - ur->add_do_method(probe, "set_extents", probe->get_extents()); - ur->add_do_method(probe, "set_origin_offset", probe->get_origin_offset()); - ur->add_undo_method(probe, "set_extents", restore.position); - ur->add_undo_method(probe, "set_origin_offset", restore.size); - ur->commit_action(); -} - -void ReflectionProbeGizmo::redraw() { - - clear(); - - Vector<Vector3> lines; - Vector<Vector3> internal_lines; - Vector3 extents = probe->get_extents(); - - AABB aabb; - aabb.position = -extents; - aabb.size = extents * 2; - - for (int i = 0; i < 12; i++) { - Vector3 a, b; - aabb.get_edge(i, a, b); - lines.push_back(a); - lines.push_back(b); - } - - for (int i = 0; i < 8; i++) { - Vector3 ep = aabb.get_endpoint(i); - internal_lines.push_back(probe->get_origin_offset()); - internal_lines.push_back(ep); - } - - Vector<Vector3> handles; - - for (int i = 0; i < 3; i++) { - - Vector3 ax; - ax[i] = aabb.position[i] + aabb.size[i]; - handles.push_back(ax); - } - - for (int i = 0; i < 3; i++) { - - Vector3 orig_handle = probe->get_origin_offset(); - orig_handle[i] -= 0.25; - lines.push_back(orig_handle); - handles.push_back(orig_handle); - - orig_handle[i] += 0.5; - lines.push_back(orig_handle); - } - - Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/reflection_probe"); - Ref<Material> material = create_material("reflection_probe_material", gizmo_color); - Ref<Material> icon = create_icon_material("reflection_probe_icon", SpatialEditor::get_singleton()->get_icon("GizmoReflectionProbe", "EditorIcons")); - - Color gizmo_color_internal = gizmo_color; - gizmo_color_internal.a = 0.5; - Ref<Material> material_internal = create_material("reflection_internal_material", gizmo_color_internal); - - add_lines(lines, material); - add_lines(internal_lines, material_internal); - - if (is_selected()) { - - gizmo_color.a = 0.1; - Ref<Material> solid_material = create_material("reflection_probe_solid_material", gizmo_color); - add_solid_box(solid_material, probe->get_extents() * 2.0); - } - - //add_unscaled_billboard(SpatialEditorGizmos::singleton->visi,0.05); - add_unscaled_billboard(icon, 0.05); - add_collision_segments(lines); - add_handles(handles); -} -ReflectionProbeGizmo::ReflectionProbeGizmo(ReflectionProbe *p_probe) { - - probe = p_probe; - set_spatial_node(p_probe); -} - -//////// - -/// - -String GIProbeGizmo::get_handle_name(int p_idx) const { - - switch (p_idx) { - case 0: return "Extents X"; - case 1: return "Extents Y"; - case 2: return "Extents Z"; - } - - return ""; -} -Variant GIProbeGizmo::get_handle_value(int p_idx) const { - - return probe->get_extents(); -} -void GIProbeGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) { - - Transform gt = probe->get_global_transform(); - //gt.orthonormalize(); - Transform gi = gt.affine_inverse(); - - Vector3 extents = probe->get_extents(); - - Vector3 ray_from = p_camera->project_ray_origin(p_point); - Vector3 ray_dir = p_camera->project_ray_normal(p_point); - - Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; - - Vector3 axis; - axis[p_idx] = 1.0; - - Vector3 ra, rb; - Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); - float d = ra[p_idx]; - if (d < 0.001) - d = 0.001; - - extents[p_idx] = d; - probe->set_extents(extents); -} - -void GIProbeGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { - - Vector3 restore = p_restore; - - if (p_cancel) { - probe->set_extents(restore); - return; - } - - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Change Probe Extents")); - ur->add_do_method(probe, "set_extents", probe->get_extents()); - ur->add_undo_method(probe, "set_extents", restore); - ur->commit_action(); -} - -void GIProbeGizmo::redraw() { - - Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/gi_probe"); - Ref<Material> material = create_material("gi_probe_material", gizmo_color); - Ref<Material> icon = create_icon_material("gi_probe_icon", SpatialEditor::get_singleton()->get_icon("GizmoGIProbe", "EditorIcons")); - Color gizmo_color_internal = gizmo_color; - gizmo_color_internal.a = 0.1; - Ref<Material> material_internal = create_material("gi_probe_internal_material", gizmo_color_internal); - - clear(); - - Vector<Vector3> lines; - Vector3 extents = probe->get_extents(); - - static const int subdivs[GIProbe::SUBDIV_MAX] = { 64, 128, 256, 512 }; - - AABB aabb = AABB(-extents, extents * 2); - int subdiv = subdivs[probe->get_subdiv()]; - float cell_size = aabb.get_longest_axis_size() / subdiv; - - for (int i = 0; i < 12; i++) { - Vector3 a, b; - aabb.get_edge(i, a, b); - lines.push_back(a); - lines.push_back(b); - } - - add_lines(lines, material); - add_collision_segments(lines); - - lines.clear(); - - for (int i = 1; i < subdiv; i++) { - - for (int j = 0; j < 3; j++) { - - if (cell_size * i > aabb.size[j]) { - continue; - } - - Vector2 dir; - dir[j] = 1.0; - Vector2 ta, tb; - int j_n1 = (j + 1) % 3; - int j_n2 = (j + 2) % 3; - ta[j_n1] = 1.0; - tb[j_n2] = 1.0; - - for (int k = 0; k < 4; k++) { - - Vector3 from = aabb.position, to = aabb.position; - from[j] += cell_size * i; - to[j] += cell_size * i; - - if (k & 1) { - to[j_n1] += aabb.size[j_n1]; - } else { - - to[j_n2] += aabb.size[j_n2]; - } - - if (k & 2) { - from[j_n1] += aabb.size[j_n1]; - from[j_n2] += aabb.size[j_n2]; - } - - lines.push_back(from); - lines.push_back(to); - } - } - } - - add_lines(lines, material_internal); - - Vector<Vector3> handles; - - for (int i = 0; i < 3; i++) { - - Vector3 ax; - ax[i] = aabb.position[i] + aabb.size[i]; - handles.push_back(ax); - } - - if (is_selected()) { - - gizmo_color.a = 0.1; - Ref<Material> solid_material = create_material("gi_probe_solid_material", gizmo_color); - add_solid_box(solid_material, aabb.get_size()); - } - - add_unscaled_billboard(icon, 0.05); - add_handles(handles); -} -GIProbeGizmo::GIProbeGizmo(GIProbe *p_probe) { - - probe = p_probe; - set_spatial_node(p_probe); -} - -//////// -//////// - -/// - -String BakedIndirectLightGizmo::get_handle_name(int p_idx) const { - - switch (p_idx) { - case 0: return "Extents X"; - case 1: return "Extents Y"; - case 2: return "Extents Z"; - } - - return ""; -} -Variant BakedIndirectLightGizmo::get_handle_value(int p_idx) const { - - return baker->get_extents(); -} -void BakedIndirectLightGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) { - - Transform gt = baker->get_global_transform(); - //gt.orthonormalize(); - Transform gi = gt.affine_inverse(); - - Vector3 extents = baker->get_extents(); - - Vector3 ray_from = p_camera->project_ray_origin(p_point); - Vector3 ray_dir = p_camera->project_ray_normal(p_point); - - Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; - - Vector3 axis; - axis[p_idx] = 1.0; - - Vector3 ra, rb; - Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); - float d = ra[p_idx]; - if (d < 0.001) - d = 0.001; +//// - extents[p_idx] = d; - baker->set_extents(extents); +NavigationMeshSpatialGizmoPlugin::NavigationMeshSpatialGizmoPlugin() { + create_material("navigation_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_edge", Color(0.5, 1, 1))); + create_material("navigation_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_edge_disabled", Color(0.7, 0.7, 0.7))); + create_material("navigation_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_solid", Color(0.5, 1, 1, 0.4))); + create_material("navigation_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_solid_disabled", Color(0.7, 0.7, 0.7, 0.4))); } -void BakedIndirectLightGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { - - Vector3 restore = p_restore; - - if (p_cancel) { - baker->set_extents(restore); - return; - } - - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Change Probe Extents")); - ur->add_do_method(baker, "set_extents", baker->get_extents()); - ur->add_undo_method(baker, "set_extents", restore); - ur->commit_action(); +bool NavigationMeshSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<NavigationMeshInstance>(p_spatial) != NULL; } -void BakedIndirectLightGizmo::redraw() { - - Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/baked_indirect_light"); - Ref<Material> material = create_material("baked_indirect_light_material", gizmo_color); - Ref<Material> icon = create_icon_material("baked_indirect_light_icon", SpatialEditor::get_singleton()->get_icon("GizmoBakedLightmap", "EditorIcons")); - Color gizmo_color_internal = gizmo_color; - gizmo_color_internal.a = 0.1; - Ref<Material> material_internal = create_material("baked_indirect_light_internal_material", gizmo_color_internal); - - clear(); - - Vector<Vector3> lines; - Vector3 extents = baker->get_extents(); - - AABB aabb = AABB(-extents, extents * 2); - - for (int i = 0; i < 12; i++) { - Vector3 a, b; - aabb.get_edge(i, a, b); - lines.push_back(a); - lines.push_back(b); - } - - add_lines(lines, material); - add_collision_segments(lines); - - Vector<Vector3> handles; - - for (int i = 0; i < 3; i++) { - - Vector3 ax; - ax[i] = aabb.position[i] + aabb.size[i]; - handles.push_back(ax); - } - - if (is_selected()) { - - gizmo_color.a = 0.1; - Ref<Material> solid_material = create_material("baked_indirect_light_solid_material", gizmo_color); - add_solid_box(solid_material, aabb.get_size()); - } - - add_unscaled_billboard(icon, 0.05); - add_handles(handles); +String NavigationMeshSpatialGizmoPlugin::get_name() const { + return "NavigationMeshInstance"; } -BakedIndirectLightGizmo::BakedIndirectLightGizmo(BakedLightmap *p_baker) { - baker = p_baker; - set_spatial_node(p_baker); -} +void NavigationMeshSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { -//////// -void NavigationMeshSpatialGizmo::redraw() { + NavigationMeshInstance *navmesh = Object::cast_to<NavigationMeshInstance>(p_gizmo->get_spatial_node()); - Ref<Material> edge_material = create_material("navigation_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/navigation_edge")); - Ref<Material> edge_material_disabled = create_material("navigation_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/navigation_edge_disabled")); - Ref<Material> solid_material = create_material("navigation_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/navigation_solid")); - Ref<Material> solid_material_disabled = create_material("navigation_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/navigation_solid_disabled")); + Ref<Material> edge_material = get_material("navigation_material", p_gizmo); + Ref<Material> edge_material_disabled = get_material("navigation_material", p_gizmo); + Ref<Material> solid_material = get_material("navigation_material", p_gizmo); + Ref<Material> solid_material_disabled = get_material("navigation_material", p_gizmo); - clear(); + p_gizmo->clear(); Ref<NavigationMesh> navmeshie = navmesh->get_navigation_mesh(); if (navmeshie.is_null()) return; @@ -3353,28 +3569,19 @@ void NavigationMeshSpatialGizmo::redraw() { tmesh->create(tmeshfaces); if (lines.size()) - add_lines(lines, navmesh->is_enabled() ? edge_material : edge_material_disabled); - add_collision_triangles(tmesh); + p_gizmo->add_lines(lines, navmesh->is_enabled() ? edge_material : edge_material_disabled); + p_gizmo->add_collision_triangles(tmesh); Ref<ArrayMesh> m = memnew(ArrayMesh); Array a; a.resize(Mesh::ARRAY_MAX); a[0] = tmeshfaces; m->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, a); m->surface_set_material(0, navmesh->is_enabled() ? solid_material : solid_material_disabled); - add_mesh(m); - add_collision_segments(lines); -} - -NavigationMeshSpatialGizmo::NavigationMeshSpatialGizmo(NavigationMeshInstance *p_navmesh) { - - set_spatial_node(p_navmesh); - navmesh = p_navmesh; + p_gizmo->add_mesh(m); + p_gizmo->add_collision_segments(lines); } ////// -/// -/// -/// #define BODY_A_RADIUS 0.25 #define BODY_B_RADIUS 0.27 @@ -3625,38 +3832,169 @@ void JointGizmosDrawer::draw_cone(const Transform &p_offset, const Basis &p_base } } -void PinJointSpatialGizmo::CreateGizmo(const Transform &p_offset, Vector<Vector3> &r_cursor_points) { - float cs = 0.25; +//// - r_cursor_points.push_back(p_offset.translated(Vector3(+cs, 0, 0)).origin); - r_cursor_points.push_back(p_offset.translated(Vector3(-cs, 0, 0)).origin); - r_cursor_points.push_back(p_offset.translated(Vector3(0, +cs, 0)).origin); - r_cursor_points.push_back(p_offset.translated(Vector3(0, -cs, 0)).origin); - r_cursor_points.push_back(p_offset.translated(Vector3(0, 0, +cs)).origin); - r_cursor_points.push_back(p_offset.translated(Vector3(0, 0, -cs)).origin); +JointSpatialGizmoPlugin::JointSpatialGizmoPlugin() { + create_material("joint_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint", Color(0.5, 0.8, 1))); + create_material("joint_body_a_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint_body_a", Color(0.6, 0.8, 1))); + create_material("joint_body_b_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint_body_b", Color(0.6, 0.9, 1))); } -void PinJointSpatialGizmo::redraw() { +bool JointSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<Joint>(p_spatial) != NULL; +} - clear(); - Vector<Vector3> cursor_points; - CreateGizmo(Transform(), cursor_points); - add_collision_segments(cursor_points); +String JointSpatialGizmoPlugin::get_name() const { + return "Joints"; +} - Ref<Material> material = create_material("joint_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint")); +void JointSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { + Joint *joint = Object::cast_to<Joint>(p_gizmo->get_spatial_node()); - add_lines(cursor_points, material); -} + p_gizmo->clear(); -PinJointSpatialGizmo::PinJointSpatialGizmo(PinJoint *p_p3d) { + const Spatial *node_body_a = Object::cast_to<Spatial>(joint->get_node(joint->get_node_a())); + const Spatial *node_body_b = Object::cast_to<Spatial>(joint->get_node(joint->get_node_b())); - p3d = p_p3d; - set_spatial_node(p3d); -} + Ref<Material> common_material = get_material("joint_material", p_gizmo); + Ref<Material> body_a_material = get_material("joint_body_a_material", p_gizmo); + Ref<Material> body_b_material = get_material("joint_body_b_material", p_gizmo); -//// + Vector<Vector3> points; + Vector<Vector3> body_a_points; + Vector<Vector3> body_b_points; -void HingeJointSpatialGizmo::CreateGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_limit_lower, real_t p_limit_upper, bool p_use_limit, Vector<Vector3> &r_common_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) { + if (Object::cast_to<PinJoint>(joint)) { + CreatePinJointGizmo(Transform(), points); + p_gizmo->add_collision_segments(points); + p_gizmo->add_lines(points, common_material); + } + + HingeJoint *hinge = Object::cast_to<HingeJoint>(joint); + if (hinge) { + + CreateHingeJointGizmo( + Transform(), + hinge->get_global_transform(), + node_body_a ? node_body_a->get_global_transform() : Transform(), + node_body_b ? node_body_b->get_global_transform() : Transform(), + hinge->get_param(HingeJoint::PARAM_LIMIT_LOWER), + hinge->get_param(HingeJoint::PARAM_LIMIT_UPPER), + hinge->get_flag(HingeJoint::FLAG_USE_LIMIT), + points, + node_body_a ? &body_a_points : NULL, + node_body_b ? &body_b_points : NULL); + + p_gizmo->add_collision_segments(points); + p_gizmo->add_collision_segments(body_a_points); + p_gizmo->add_collision_segments(body_b_points); + + p_gizmo->add_lines(points, common_material); + p_gizmo->add_lines(body_a_points, body_a_material); + p_gizmo->add_lines(body_b_points, body_b_material); + } + + SliderJoint *slider = Object::cast_to<SliderJoint>(joint); + if (slider) { + + CreateSliderJointGizmo( + Transform(), + slider->get_global_transform(), + node_body_a ? node_body_a->get_global_transform() : Transform(), + node_body_b ? node_body_b->get_global_transform() : Transform(), + slider->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_LOWER), + slider->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_UPPER), + slider->get_param(SliderJoint::PARAM_LINEAR_LIMIT_LOWER), + slider->get_param(SliderJoint::PARAM_LINEAR_LIMIT_UPPER), + points, + node_body_a ? &body_a_points : NULL, + node_body_b ? &body_b_points : NULL); + + p_gizmo->add_collision_segments(points); + p_gizmo->add_collision_segments(body_a_points); + p_gizmo->add_collision_segments(body_b_points); + + p_gizmo->add_lines(points, common_material); + p_gizmo->add_lines(body_a_points, body_a_material); + p_gizmo->add_lines(body_b_points, body_b_material); + } + + ConeTwistJoint *cone = Object::cast_to<ConeTwistJoint>(joint); + if (cone) { + + CreateConeTwistJointGizmo( + Transform(), + cone->get_global_transform(), + node_body_a ? node_body_a->get_global_transform() : Transform(), + node_body_b ? node_body_b->get_global_transform() : Transform(), + cone->get_param(ConeTwistJoint::PARAM_SWING_SPAN), + cone->get_param(ConeTwistJoint::PARAM_TWIST_SPAN), + node_body_a ? &body_a_points : NULL, + node_body_b ? &body_b_points : NULL); + + p_gizmo->add_collision_segments(body_a_points); + p_gizmo->add_collision_segments(body_b_points); + + p_gizmo->add_lines(body_a_points, body_a_material); + p_gizmo->add_lines(body_b_points, body_b_material); + } + + Generic6DOFJoint *gen = Object::cast_to<Generic6DOFJoint>(joint); + if (gen) { + + CreateGeneric6DOFJointGizmo( + Transform(), + gen->get_global_transform(), + node_body_a ? node_body_a->get_global_transform() : Transform(), + node_body_b ? node_body_b->get_global_transform() : Transform(), + + gen->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT), + gen->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT), + gen->get_param_x(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT), + gen->get_param_x(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT), + gen->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT), + gen->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT), + + gen->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT), + gen->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT), + gen->get_param_y(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT), + gen->get_param_y(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT), + gen->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT), + gen->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT), + + gen->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT), + gen->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT), + gen->get_param_z(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT), + gen->get_param_z(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT), + gen->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT), + gen->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT), + + points, + node_body_a ? &body_a_points : NULL, + node_body_a ? &body_b_points : NULL); + + p_gizmo->add_collision_segments(points); + p_gizmo->add_collision_segments(body_a_points); + p_gizmo->add_collision_segments(body_b_points); + + p_gizmo->add_lines(points, common_material); + p_gizmo->add_lines(body_a_points, body_a_material); + p_gizmo->add_lines(body_b_points, body_b_material); + } +} + +void JointSpatialGizmoPlugin::CreatePinJointGizmo(const Transform &p_offset, Vector<Vector3> &r_cursor_points) { + float cs = 0.25; + + r_cursor_points.push_back(p_offset.translated(Vector3(+cs, 0, 0)).origin); + r_cursor_points.push_back(p_offset.translated(Vector3(-cs, 0, 0)).origin); + r_cursor_points.push_back(p_offset.translated(Vector3(0, +cs, 0)).origin); + r_cursor_points.push_back(p_offset.translated(Vector3(0, -cs, 0)).origin); + r_cursor_points.push_back(p_offset.translated(Vector3(0, 0, +cs)).origin); + r_cursor_points.push_back(p_offset.translated(Vector3(0, 0, -cs)).origin); +} + +void JointSpatialGizmoPlugin::CreateHingeJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_limit_lower, real_t p_limit_upper, bool p_use_limit, Vector<Vector3> &r_common_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) { r_common_points.push_back(p_offset.translated(Vector3(0, 0, 0.5)).origin); r_common_points.push_back(p_offset.translated(Vector3(0, 0, -0.5)).origin); @@ -3688,52 +4026,7 @@ void HingeJointSpatialGizmo::CreateGizmo(const Transform &p_offset, const Transf } } -void HingeJointSpatialGizmo::redraw() { - - const Spatial *node_body_a = Object::cast_to<Spatial>(p3d->get_node(p3d->get_node_a())); - const Spatial *node_body_b = Object::cast_to<Spatial>(p3d->get_node(p3d->get_node_b())); - - Vector<Vector3> points; - Vector<Vector3> body_a_points; - Vector<Vector3> body_b_points; - CreateGizmo( - Transform(), - p3d->get_global_transform(), - node_body_a ? node_body_a->get_global_transform() : Transform(), - node_body_b ? node_body_b->get_global_transform() : Transform(), - p3d->get_param(HingeJoint::PARAM_LIMIT_LOWER), - p3d->get_param(HingeJoint::PARAM_LIMIT_UPPER), - p3d->get_flag(HingeJoint::FLAG_USE_LIMIT), - points, - node_body_a ? &body_a_points : NULL, - node_body_b ? &body_b_points : NULL); - - clear(); - - Ref<Material> common_material = create_material("joint_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint")); - Ref<Material> body_a_material = create_material("joint_body_a_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint_body_a")); - Ref<Material> body_b_material = create_material("joint_body_b_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint_body_b")); - - add_collision_segments(points); - add_collision_segments(body_a_points); - add_collision_segments(body_b_points); - - add_lines(points, common_material); - add_lines(body_a_points, body_a_material); - add_lines(body_b_points, body_b_material); -} - -HingeJointSpatialGizmo::HingeJointSpatialGizmo(HingeJoint *p_p3d) { - - p3d = p_p3d; - set_spatial_node(p3d); -} - -/////// -/// -//// - -void SliderJointSpatialGizmo::CreateGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_angular_limit_lower, real_t p_angular_limit_upper, real_t p_linear_limit_lower, real_t p_linear_limit_upper, Vector<Vector3> &r_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) { +void JointSpatialGizmoPlugin::CreateSliderJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_angular_limit_lower, real_t p_angular_limit_upper, real_t p_linear_limit_lower, real_t p_linear_limit_upper, Vector<Vector3> &r_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) { p_linear_limit_lower = -p_linear_limit_lower; p_linear_limit_upper = -p_linear_limit_upper; @@ -3793,53 +4086,7 @@ void SliderJointSpatialGizmo::CreateGizmo(const Transform &p_offset, const Trans true); } -void SliderJointSpatialGizmo::redraw() { - - const Spatial *node_body_a = Object::cast_to<Spatial>(p3d->get_node(p3d->get_node_a())); - const Spatial *node_body_b = Object::cast_to<Spatial>(p3d->get_node(p3d->get_node_b())); - - clear(); - Vector<Vector3> cursor_points; - Vector<Vector3> body_a_points; - Vector<Vector3> body_b_points; - - CreateGizmo( - Transform(), - p3d->get_global_transform(), - node_body_a ? node_body_a->get_global_transform() : Transform(), - node_body_b ? node_body_b->get_global_transform() : Transform(), - p3d->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_LOWER), - p3d->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_UPPER), - p3d->get_param(SliderJoint::PARAM_LINEAR_LIMIT_LOWER), - p3d->get_param(SliderJoint::PARAM_LINEAR_LIMIT_UPPER), - cursor_points, - node_body_a ? &body_a_points : NULL, - node_body_b ? &body_b_points : NULL); - - Ref<Material> material = create_material("joint_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint")); - Ref<Material> body_a_material = create_material("joint_body_a_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint_body_a")); - Ref<Material> body_b_material = create_material("joint_body_b_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint_body_b")); - - add_collision_segments(cursor_points); - add_collision_segments(body_a_points); - add_collision_segments(body_b_points); - - add_lines(cursor_points, material); - add_lines(body_a_points, body_a_material); - add_lines(body_b_points, body_b_material); -} - -SliderJointSpatialGizmo::SliderJointSpatialGizmo(SliderJoint *p_p3d) { - - p3d = p_p3d; - set_spatial_node(p3d); -} - -/////// -/// -//// - -void ConeTwistJointSpatialGizmo::CreateGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_swing, real_t p_twist, Vector<Vector3> &r_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) { +void JointSpatialGizmoPlugin::CreateConeTwistJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_swing, real_t p_twist, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) { if (r_body_a_points) JointGizmosDrawer::draw_cone( @@ -3858,51 +4105,7 @@ void ConeTwistJointSpatialGizmo::CreateGizmo(const Transform &p_offset, const Tr *r_body_b_points); } -void ConeTwistJointSpatialGizmo::redraw() { - - const Spatial *node_body_a = Object::cast_to<Spatial>(p3d->get_node(p3d->get_node_a())); - const Spatial *node_body_b = Object::cast_to<Spatial>(p3d->get_node(p3d->get_node_b())); - - clear(); - Vector<Vector3> points; - Vector<Vector3> body_a_points; - Vector<Vector3> body_b_points; - - CreateGizmo( - Transform(), - p3d->get_global_transform(), - node_body_a ? node_body_a->get_global_transform() : Transform(), - node_body_b ? node_body_b->get_global_transform() : Transform(), - p3d->get_param(ConeTwistJoint::PARAM_SWING_SPAN), - p3d->get_param(ConeTwistJoint::PARAM_TWIST_SPAN), - points, - node_body_a ? &body_a_points : NULL, - node_body_b ? &body_b_points : NULL); - - Ref<Material> material = create_material("joint_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint")); - Ref<Material> body_a_material = create_material("joint_body_a_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint_body_a")); - Ref<Material> body_b_material = create_material("joint_body_b_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint_body_b")); - - add_collision_segments(points); - add_collision_segments(body_a_points); - add_collision_segments(body_b_points); - - add_lines(points, material); - add_lines(body_a_points, body_a_material); - add_lines(body_b_points, body_b_material); -} - -ConeTwistJointSpatialGizmo::ConeTwistJointSpatialGizmo(ConeTwistJoint *p_p3d) { - - p3d = p_p3d; - set_spatial_node(p3d); -} - -/////// -/// -//// - -void Generic6DOFJointSpatialGizmo::CreateGizmo( +void JointSpatialGizmoPlugin::CreateGeneric6DOFJointGizmo( const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, @@ -4051,510 +4254,3 @@ void Generic6DOFJointSpatialGizmo::CreateGizmo( #undef ADD_VTX } - -void Generic6DOFJointSpatialGizmo::redraw() { - - const Spatial *node_body_a = Object::cast_to<Spatial>(p3d->get_node(p3d->get_node_a())); - const Spatial *node_body_b = Object::cast_to<Spatial>(p3d->get_node(p3d->get_node_b())); - - clear(); - Vector<Vector3> cursor_points; - Vector<Vector3> body_a_points; - Vector<Vector3> body_b_points; - - CreateGizmo( - Transform(), - p3d->get_global_transform(), - node_body_a ? node_body_a->get_global_transform() : Transform(), - node_body_b ? node_body_b->get_global_transform() : Transform(), - - p3d->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT), - p3d->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT), - p3d->get_param_x(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT), - p3d->get_param_x(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT), - p3d->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT), - p3d->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT), - - p3d->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT), - p3d->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT), - p3d->get_param_y(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT), - p3d->get_param_y(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT), - p3d->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT), - p3d->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT), - - p3d->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT), - p3d->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT), - p3d->get_param_z(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT), - p3d->get_param_z(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT), - p3d->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT), - p3d->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT), - - cursor_points, - node_body_a ? &body_a_points : NULL, - node_body_a ? &body_b_points : NULL); - - Ref<Material> material = create_material("joint_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint")); - Ref<Material> body_a_material = create_material("joint_body_a_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint_body_a")); - Ref<Material> body_b_material = create_material("joint_body_b_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint_body_b")); - - add_collision_segments(cursor_points); - add_collision_segments(body_a_points); - add_collision_segments(body_b_points); - - add_lines(cursor_points, material); - add_lines(body_a_points, body_a_material); - add_lines(body_b_points, body_b_material); -} - -Generic6DOFJointSpatialGizmo::Generic6DOFJointSpatialGizmo(Generic6DOFJoint *p_p3d) { - - p3d = p_p3d; - set_spatial_node(p3d); -} - -/////// -/// -//// - -SpatialEditorGizmos *SpatialEditorGizmos::singleton = NULL; - -Ref<SpatialEditorGizmo> SpatialEditorGizmos::get_gizmo(Spatial *p_spatial) { - - if (Object::cast_to<Light>(p_spatial)) { - - Ref<LightSpatialGizmo> lsg = memnew(LightSpatialGizmo(Object::cast_to<Light>(p_spatial))); - return lsg; - } - - if (Object::cast_to<Camera>(p_spatial)) { - - Ref<CameraSpatialGizmo> lsg = memnew(CameraSpatialGizmo(Object::cast_to<Camera>(p_spatial))); - return lsg; - } - - if (Object::cast_to<Skeleton>(p_spatial)) { - - Ref<SkeletonSpatialGizmo> lsg = memnew(SkeletonSpatialGizmo(Object::cast_to<Skeleton>(p_spatial))); - return lsg; - } - - if (Object::cast_to<PhysicalBone>(p_spatial)) { - - Ref<PhysicalBoneSpatialGizmo> pbsg = memnew(PhysicalBoneSpatialGizmo(Object::cast_to<PhysicalBone>(p_spatial))); - return pbsg; - } - - if (Object::cast_to<Position3D>(p_spatial)) { - - Ref<Position3DSpatialGizmo> lsg = memnew(Position3DSpatialGizmo(Object::cast_to<Position3D>(p_spatial))); - return lsg; - } - - if (Object::cast_to<SoftBody>(p_spatial)) { - - Ref<SoftBodySpatialGizmo> misg = memnew(SoftBodySpatialGizmo(Object::cast_to<SoftBody>(p_spatial))); - return misg; - } - - if (Object::cast_to<MeshInstance>(p_spatial)) { - - Ref<MeshInstanceSpatialGizmo> misg = memnew(MeshInstanceSpatialGizmo(Object::cast_to<MeshInstance>(p_spatial))); - return misg; - } - - /*if (Object::cast_to<Room>(p_spatial)) { - - Ref<RoomSpatialGizmo> misg = memnew(RoomSpatialGizmo(Object::cast_to<Room>(p_spatial))); - return misg; - }*/ - - if (Object::cast_to<NavigationMeshInstance>(p_spatial)) { - - Ref<NavigationMeshSpatialGizmo> misg = memnew(NavigationMeshSpatialGizmo(Object::cast_to<NavigationMeshInstance>(p_spatial))); - return misg; - } - - if (Object::cast_to<RayCast>(p_spatial)) { - - Ref<RayCastSpatialGizmo> misg = memnew(RayCastSpatialGizmo(Object::cast_to<RayCast>(p_spatial))); - return misg; - } - /* - if (Object::cast_to<Portal>(p_spatial)) { - - Ref<PortalSpatialGizmo> misg = memnew(PortalSpatialGizmo(Object::cast_to<Portal>(p_spatial))); - return misg; - } -*/ - - if (Object::cast_to<CollisionShape>(p_spatial)) { - - Ref<CollisionShapeSpatialGizmo> misg = memnew(CollisionShapeSpatialGizmo(Object::cast_to<CollisionShape>(p_spatial))); - return misg; - } - - if (Object::cast_to<VisibilityNotifier>(p_spatial)) { - - Ref<VisibilityNotifierGizmo> misg = memnew(VisibilityNotifierGizmo(Object::cast_to<VisibilityNotifier>(p_spatial))); - return misg; - } - - if (Object::cast_to<Particles>(p_spatial)) { - - Ref<ParticlesGizmo> misg = memnew(ParticlesGizmo(Object::cast_to<Particles>(p_spatial))); - return misg; - } - - if (Object::cast_to<ReflectionProbe>(p_spatial)) { - - Ref<ReflectionProbeGizmo> misg = memnew(ReflectionProbeGizmo(Object::cast_to<ReflectionProbe>(p_spatial))); - return misg; - } - if (Object::cast_to<GIProbe>(p_spatial)) { - - Ref<GIProbeGizmo> misg = memnew(GIProbeGizmo(Object::cast_to<GIProbe>(p_spatial))); - return misg; - } - if (Object::cast_to<BakedLightmap>(p_spatial)) { - - Ref<BakedIndirectLightGizmo> misg = memnew(BakedIndirectLightGizmo(Object::cast_to<BakedLightmap>(p_spatial))); - return misg; - } - - if (Object::cast_to<VehicleWheel>(p_spatial)) { - - Ref<VehicleWheelSpatialGizmo> misg = memnew(VehicleWheelSpatialGizmo(Object::cast_to<VehicleWheel>(p_spatial))); - return misg; - } - if (Object::cast_to<PinJoint>(p_spatial)) { - - Ref<PinJointSpatialGizmo> misg = memnew(PinJointSpatialGizmo(Object::cast_to<PinJoint>(p_spatial))); - return misg; - } - - if (Object::cast_to<HingeJoint>(p_spatial)) { - - Ref<HingeJointSpatialGizmo> misg = memnew(HingeJointSpatialGizmo(Object::cast_to<HingeJoint>(p_spatial))); - return misg; - } - - if (Object::cast_to<SliderJoint>(p_spatial)) { - - Ref<SliderJointSpatialGizmo> misg = memnew(SliderJointSpatialGizmo(Object::cast_to<SliderJoint>(p_spatial))); - return misg; - } - - if (Object::cast_to<ConeTwistJoint>(p_spatial)) { - - Ref<ConeTwistJointSpatialGizmo> misg = memnew(ConeTwistJointSpatialGizmo(Object::cast_to<ConeTwistJoint>(p_spatial))); - return misg; - } - - if (Object::cast_to<Generic6DOFJoint>(p_spatial)) { - - Ref<Generic6DOFJointSpatialGizmo> misg = memnew(Generic6DOFJointSpatialGizmo(Object::cast_to<Generic6DOFJoint>(p_spatial))); - return misg; - } - - if (Object::cast_to<CollisionPolygon>(p_spatial)) { - - Ref<CollisionPolygonSpatialGizmo> misg = memnew(CollisionPolygonSpatialGizmo(Object::cast_to<CollisionPolygon>(p_spatial))); - return misg; - } - - if (Object::cast_to<AudioStreamPlayer3D>(p_spatial)) { - - Ref<AudioStreamPlayer3DSpatialGizmo> misg = memnew(AudioStreamPlayer3DSpatialGizmo(Object::cast_to<AudioStreamPlayer3D>(p_spatial))); - return misg; - } - - return Ref<SpatialEditorGizmo>(); -} - -SpatialEditorGizmos::SpatialEditorGizmos() { - - singleton = this; - - handle_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); - handle_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - handle_material->set_on_top_of_alpha(); - handle_material->set_albedo(Color(0.8, 0.8, 0.8)); - handle_material_billboard = handle_material->duplicate(); - handle_material_billboard->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); - - handle2_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); - handle2_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - handle2_material->set_flag(SpatialMaterial::FLAG_USE_POINT_SIZE, true); - handle_t = SpatialEditor::get_singleton()->get_icon("Editor3DHandle", "EditorIcons"); - handle2_material->set_point_size(handle_t->get_width()); - handle2_material->set_texture(SpatialMaterial::TEXTURE_ALBEDO, handle_t); - handle2_material->set_albedo(Color(1, 1, 1)); - handle2_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - handle2_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - handle2_material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - handle2_material->set_on_top_of_alpha(); - handle2_material_billboard = handle2_material->duplicate(); - handle2_material_billboard->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); - handle2_material_billboard->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); - handle2_material_billboard->set_on_top_of_alpha(); - - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/light", Color(1, 1, 0.2)); - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/stream_player_3d", Color(0.4, 0.8, 1)); - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/camera", Color(0.8, 0.4, 0.8)); - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/skeleton", Color(1, 0.8, 0.4)); - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/visibility_notifier", Color(0.8, 0.5, 0.7)); - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/particles", Color(0.8, 0.7, 0.4)); - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/reflection_probe", Color(0.6, 1, 0.5)); - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/gi_probe", Color(0.5, 1, 0.6)); - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/baked_indirect_light", Color(0.5, 0.6, 1)); - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1)); - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint", Color(0.5, 0.8, 1)); - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint_body_a", Color(0.6, 0.8, 1)); - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint_body_b", Color(0.6, 0.9, 1)); - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_edge", Color(0.5, 1, 1)); - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_edge_disabled", Color(0.7, 0.7, 0.7)); - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_solid", Color(0.5, 1, 1, 0.4)); - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_solid_disabled", Color(0.7, 0.7, 0.7, 0.4)); - EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instanced", Color(0.7, 0.7, 0.7, 0.5)); - -#if 0 - light_material = create_line_material(Color(1, 1, 0.2)); - light_material_omni = create_line_material(Color(1, 1, 0.2)); - light_material_omni->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); - - light_material_omni_icon = Ref<SpatialMaterial>(memnew(SpatialMaterial)); - light_material_omni_icon->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - light_material_omni_icon->set_cull_mode(SpatialMaterial::CULL_DISABLED); - light_material_omni_icon->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_DISABLED); - light_material_omni_icon->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - light_material_omni_icon->set_albedo(Color(1, 1, 1, 0.9)); - light_material_omni_icon->set_texture(SpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("GizmoLight", "EditorIcons")); - light_material_omni_icon->set_flag(SpatialMaterial::FLAG_FIXED_SIZE, true); - light_material_omni_icon->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); - - light_material_directional_icon = Ref<SpatialMaterial>(memnew(SpatialMaterial)); - light_material_directional_icon->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - light_material_directional_icon->set_cull_mode(SpatialMaterial::CULL_DISABLED); - light_material_directional_icon->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_DISABLED); - light_material_directional_icon->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - light_material_directional_icon->set_albedo(Color(1, 1, 1, 0.9)); - light_material_directional_icon->set_texture(SpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("GizmoDirectionalLight", "EditorIcons")); - light_material_directional_icon->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); - light_material_directional_icon->set_depth_scale(1); - - camera_material = create_line_material(Color(1.0, 0.5, 1.0)); - - navmesh_edge_material = create_line_material(Color(0.1, 0.8, 1.0)); - navmesh_solid_material = create_solid_material(Color(0.1, 0.8, 1.0, 0.4)); - navmesh_edge_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, false); - navmesh_edge_material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, false); - navmesh_solid_material->set_cull_mode(SpatialMaterial::CULL_DISABLED); - - navmesh_edge_material_disabled = create_line_material(Color(1.0, 0.8, 0.1)); - navmesh_solid_material_disabled = create_solid_material(Color(1.0, 0.8, 0.1, 0.4)); - navmesh_edge_material_disabled->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, false); - navmesh_edge_material_disabled->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, false); - navmesh_solid_material_disabled->set_cull_mode(SpatialMaterial::CULL_DISABLED); - - skeleton_material = create_line_material(Color(0.6, 1.0, 0.3)); - skeleton_material->set_cull_mode(SpatialMaterial::CULL_DISABLED); - skeleton_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - skeleton_material->set_on_top_of_alpha(); - skeleton_material->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_DISABLED); - - //position 3D Shared mesh - - pos3d_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); - { - - PoolVector<Vector3> cursor_points; - PoolVector<Color> cursor_colors; - float cs = 0.25; - cursor_points.push_back(Vector3(+cs, 0, 0)); - cursor_points.push_back(Vector3(-cs, 0, 0)); - cursor_points.push_back(Vector3(0, +cs, 0)); - cursor_points.push_back(Vector3(0, -cs, 0)); - cursor_points.push_back(Vector3(0, 0, +cs)); - cursor_points.push_back(Vector3(0, 0, -cs)); - cursor_colors.push_back(Color(1, 0.5, 0.5, 0.7)); - cursor_colors.push_back(Color(1, 0.5, 0.5, 0.7)); - cursor_colors.push_back(Color(0.5, 1, 0.5, 0.7)); - cursor_colors.push_back(Color(0.5, 1, 0.5, 0.7)); - cursor_colors.push_back(Color(0.5, 0.5, 1, 0.7)); - cursor_colors.push_back(Color(0.5, 0.5, 1, 0.7)); - - Ref<SpatialMaterial> mat = memnew(SpatialMaterial); - mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - mat->set_line_width(3); - Array d; - d.resize(VS::ARRAY_MAX); - d[Mesh::ARRAY_VERTEX] = cursor_points; - d[Mesh::ARRAY_COLOR] = cursor_colors; - pos3d_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, d); - pos3d_mesh->surface_set_material(0, mat); - } - - listener_line_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); - { - - PoolVector<Vector3> cursor_points; - PoolVector<Color> cursor_colors; - cursor_points.push_back(Vector3(0, 0, 0)); - cursor_points.push_back(Vector3(0, 0, -1.0)); - cursor_colors.push_back(Color(0.5, 0.5, 0.5, 0.7)); - cursor_colors.push_back(Color(0.5, 0.5, 0.5, 0.7)); - - Ref<SpatialMaterial> mat = memnew(SpatialMaterial); - mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - mat->set_line_width(3); - Array d; - d.resize(VS::ARRAY_MAX); - d[Mesh::ARRAY_VERTEX] = cursor_points; - d[Mesh::ARRAY_COLOR] = cursor_colors; - listener_line_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, d); - listener_line_mesh->surface_set_material(0, mat); - } - - room_material = create_line_material(Color(1.0, 0.6, 0.9)); - portal_material = create_line_material(Color(1.0, 0.8, 0.6)); - raycast_material = create_line_material(Color(1.0, 0.8, 0.6)); - car_wheel_material = create_line_material(Color(0.6, 0.8, 1.0)); - visibility_notifier_material = create_line_material(Color(1.0, 0.5, 1.0)); - particles_material = create_line_material(Color(1.0, 1.0, 0.5)); - reflection_probe_material = create_line_material(Color(0.5, 1.0, 0.7)); - reflection_probe_material_internal = create_line_material(Color(0.3, 0.8, 0.5, 0.15)); - gi_probe_material = create_line_material(Color(0.7, 1.0, 0.5)); - gi_probe_material_internal = create_line_material(Color(0.5, 0.8, 0.3, 0.1)); - joint_material = create_line_material(Color(0.6, 0.8, 1.0)); - - stream_player_icon = Ref<SpatialMaterial>(memnew(SpatialMaterial)); - stream_player_icon->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - stream_player_icon->set_cull_mode(SpatialMaterial::CULL_DISABLED); - stream_player_icon->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_DISABLED); - stream_player_icon->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - stream_player_icon->set_albedo(Color(1, 1, 1, 0.9)); - stream_player_icon->set_texture(SpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("GizmoSpatialStreamPlayer", "EditorIcons")); - - visibility_notifier_icon = Ref<SpatialMaterial>(memnew(SpatialMaterial)); - visibility_notifier_icon->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - visibility_notifier_icon->set_cull_mode(SpatialMaterial::CULL_DISABLED); - visibility_notifier_icon->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_DISABLED); - visibility_notifier_icon->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - visibility_notifier_icon->set_albedo(Color(1, 1, 1, 0.9)); - visibility_notifier_icon->set_texture(SpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("Visible", "EditorIcons")); - - listener_icon = Ref<SpatialMaterial>(memnew(SpatialMaterial)); - listener_icon->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - listener_icon->set_cull_mode(SpatialMaterial::CULL_DISABLED); - listener_icon->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_DISABLED); - listener_icon->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - listener_icon->set_albedo(Color(1, 1, 1, 0.9)); - listener_icon->set_texture(SpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("GizmoListener", "EditorIcons")); - - { - - PoolVector<Vector3> vertices; - -#undef ADD_VTX -#define ADD_VTX(m_idx) \ - vertices.push_back(face_points[m_idx]); - - for (int i = 0; i < 6; i++) { - - Vector3 face_points[4]; - - for (int j = 0; j < 4; j++) { - - float v[3]; - v[0] = 1.0; - v[1] = 1 - 2 * ((j >> 1) & 1); - v[2] = v[1] * (1 - 2 * (j & 1)); - - for (int k = 0; k < 3; k++) { - - if (i < 3) - face_points[j][(i + k) % 3] = v[k]; - else - face_points[3 - j][(i + k) % 3] = -v[k]; - } - } - //tri 1 - ADD_VTX(0); - ADD_VTX(1); - ADD_VTX(2); - //tri 2 - ADD_VTX(2); - ADD_VTX(3); - ADD_VTX(0); - } - - test_cube_tm = Ref<TriangleMesh>(memnew(TriangleMesh)); - test_cube_tm->create(vertices); - } - - shape_material = create_line_material(Color(0.2, 1, 1.0)); -#endif - - pos3d_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); - { - - PoolVector<Vector3> cursor_points; - PoolVector<Color> cursor_colors; - float cs = 0.25; - cursor_points.push_back(Vector3(+cs, 0, 0)); - cursor_points.push_back(Vector3(-cs, 0, 0)); - cursor_points.push_back(Vector3(0, +cs, 0)); - cursor_points.push_back(Vector3(0, -cs, 0)); - cursor_points.push_back(Vector3(0, 0, +cs)); - cursor_points.push_back(Vector3(0, 0, -cs)); - cursor_colors.push_back(Color(1, 0.5, 0.5, 0.7)); - cursor_colors.push_back(Color(1, 0.5, 0.5, 0.7)); - cursor_colors.push_back(Color(0.5, 1, 0.5, 0.7)); - cursor_colors.push_back(Color(0.5, 1, 0.5, 0.7)); - cursor_colors.push_back(Color(0.5, 0.5, 1, 0.7)); - cursor_colors.push_back(Color(0.5, 0.5, 1, 0.7)); - - Ref<SpatialMaterial> mat = memnew(SpatialMaterial); - mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - mat->set_line_width(3); - Array d; - d.resize(VS::ARRAY_MAX); - d[Mesh::ARRAY_VERTEX] = cursor_points; - d[Mesh::ARRAY_COLOR] = cursor_colors; - pos3d_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, d); - pos3d_mesh->surface_set_material(0, mat); - } - - listener_line_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); - { - - PoolVector<Vector3> cursor_points; - PoolVector<Color> cursor_colors; - cursor_points.push_back(Vector3(0, 0, 0)); - cursor_points.push_back(Vector3(0, 0, -1.0)); - cursor_colors.push_back(Color(0.5, 0.5, 0.5, 0.7)); - cursor_colors.push_back(Color(0.5, 0.5, 0.5, 0.7)); - - Ref<SpatialMaterial> mat = memnew(SpatialMaterial); - mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - mat->set_line_width(3); - Array d; - d.resize(VS::ARRAY_MAX); - d[Mesh::ARRAY_VERTEX] = cursor_points; - d[Mesh::ARRAY_COLOR] = cursor_colors; - listener_line_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, d); - listener_line_mesh->surface_set_material(0, mat); - } -} diff --git a/editor/spatial_editor_gizmos.h b/editor/spatial_editor_gizmos.h index 198d028516..877590b91d 100644 --- a/editor/spatial_editor_gizmos.h +++ b/editor/spatial_editor_gizmos.h @@ -55,187 +55,120 @@ class Camera; -class EditorSpatialGizmo : public SpatialEditorGizmo { +class LightSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { - GDCLASS(EditorSpatialGizmo, SpatialGizmo); + GDCLASS(LightSpatialGizmoPlugin, EditorSpatialGizmoPlugin); - struct Instance { - - RID instance; - Ref<ArrayMesh> mesh; - RID skeleton; - bool billboard; - bool unscaled; - bool can_intersect; - bool extra_margin; - Instance() { - - billboard = false; - unscaled = false; - can_intersect = false; - extra_margin = false; - } - - void create_instance(Spatial *p_base); - }; - - Vector<Vector3> collision_segments; - Ref<TriangleMesh> collision_mesh; - - struct Handle { - Vector3 pos; - bool billboard; - }; - - Vector<Vector3> handles; - Vector<Vector3> secondary_handles; - float selectable_icon_size = -1.0f; - bool billboard_handle; +public: + bool has_gizmo(Spatial *p_spatial); + String get_name() const; - bool valid; - Spatial *base; - Vector<Instance> instances; - Spatial *spatial_node; + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + void redraw(EditorSpatialGizmo *p_gizmo); - void _set_spatial_node(Node *p_node) { set_spatial_node(Object::cast_to<Spatial>(p_node)); } + LightSpatialGizmoPlugin(); +}; -protected: - void add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard = false); - void add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard = false, const RID &p_skeleton = RID()); - void add_collision_segments(const Vector<Vector3> &p_lines); - void add_collision_triangles(const Ref<TriangleMesh> &p_tmesh); - void add_unscaled_billboard(const Ref<Material> &p_material, float p_scale = 1); - void add_handles(const Vector<Vector3> &p_handles, bool p_billboard = false, bool p_secondary = false); - void add_solid_box(Ref<Material> &p_material, Vector3 p_size, Vector3 p_position = Vector3()); +class AudioStreamPlayer3DSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { - void set_spatial_node(Spatial *p_node); - const Spatial *get_spatial_node() const { return spatial_node; } + GDCLASS(AudioStreamPlayer3DSpatialGizmoPlugin, EditorSpatialGizmoPlugin); - static void _bind_methods(); +public: + bool has_gizmo(Spatial *p_spatial); + String get_name() const; - Ref<SpatialMaterial> create_material(const String &p_name, const Color &p_color, bool p_billboard = false, bool p_on_top = false, bool p_use_vertex_color = false); - Ref<SpatialMaterial> create_icon_material(const String &p_name, const Ref<Texture> &p_texture, bool p_on_top = false, const Color &p_albedo = Color(1, 1, 1, 1)); + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + void redraw(EditorSpatialGizmo *p_gizmo); -public: - virtual Vector3 get_handle_pos(int p_idx) const; - virtual bool intersect_frustum(const Camera *p_camera, const Vector<Plane> &p_frustum); - virtual bool intersect_ray(Camera *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle = NULL, bool p_sec_first = false); - - void clear(); - void create(); - void transform(); - virtual void redraw(); - void free(); - virtual bool is_editable() const; - virtual bool can_draw() const; - - EditorSpatialGizmo(); - ~EditorSpatialGizmo(); + AudioStreamPlayer3DSpatialGizmoPlugin(); }; -class LightSpatialGizmo : public EditorSpatialGizmo { - - GDCLASS(LightSpatialGizmo, EditorSpatialGizmo); +class CameraSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { - Light *light; + GDCLASS(CameraSpatialGizmoPlugin, EditorSpatialGizmoPlugin); public: - virtual String get_handle_name(int p_idx) const; - virtual Variant get_handle_value(int p_idx) const; - virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); - virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); + bool has_gizmo(Spatial *p_spatial); + String get_name() const; - void redraw(); - LightSpatialGizmo(Light *p_light = NULL); -}; + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + void redraw(EditorSpatialGizmo *p_gizmo); -class AudioStreamPlayer3DSpatialGizmo : public EditorSpatialGizmo { + CameraSpatialGizmoPlugin(); +}; - GDCLASS(AudioStreamPlayer3DSpatialGizmo, EditorSpatialGizmo); +class MeshInstanceSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { - AudioStreamPlayer3D *player; + GDCLASS(MeshInstanceSpatialGizmoPlugin, EditorSpatialGizmoPlugin); public: - virtual String get_handle_name(int p_idx) const; - virtual Variant get_handle_value(int p_idx) const; - virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); - virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + bool can_be_hidden() const; + void redraw(EditorSpatialGizmo *p_gizmo); - void redraw(); - AudioStreamPlayer3DSpatialGizmo(AudioStreamPlayer3D *p_player = NULL); + MeshInstanceSpatialGizmoPlugin(); }; -class CameraSpatialGizmo : public EditorSpatialGizmo { - - GDCLASS(CameraSpatialGizmo, EditorSpatialGizmo); +class Sprite3DSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { - Camera *camera; + GDCLASS(Sprite3DSpatialGizmoPlugin, EditorSpatialGizmoPlugin); public: - virtual String get_handle_name(int p_idx) const; - virtual Variant get_handle_value(int p_idx) const; - virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); - virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + bool can_be_hidden() const; + void redraw(EditorSpatialGizmo *p_gizmo); - void redraw(); - CameraSpatialGizmo(Camera *p_camera = NULL); + Sprite3DSpatialGizmoPlugin(); }; -class MeshInstanceSpatialGizmo : public EditorSpatialGizmo { +class Position3DSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { - GDCLASS(MeshInstanceSpatialGizmo, EditorSpatialGizmo); + GDCLASS(Position3DSpatialGizmoPlugin, EditorSpatialGizmoPlugin); - MeshInstance *mesh; + Ref<ArrayMesh> pos3d_mesh; + Vector<Vector3> cursor_points; public: - virtual bool can_draw() const; - void redraw(); - MeshInstanceSpatialGizmo(MeshInstance *p_mesh = NULL); -}; - -class Sprite3DSpatialGizmo : public EditorSpatialGizmo { - - GDCLASS(Sprite3DSpatialGizmo, EditorSpatialGizmo); - - SpriteBase3D *sprite; + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + void redraw(EditorSpatialGizmo *p_gizmo); -public: - virtual bool can_draw() const; - void redraw(); - Sprite3DSpatialGizmo(SpriteBase3D *p_sprite = NULL); + Position3DSpatialGizmoPlugin(); }; -class Position3DSpatialGizmo : public EditorSpatialGizmo { - - GDCLASS(Position3DSpatialGizmo, EditorSpatialGizmo); +class SkeletonSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { - Position3D *p3d; + GDCLASS(SkeletonSpatialGizmoPlugin, EditorSpatialGizmoPlugin); public: - void redraw(); - Position3DSpatialGizmo(Position3D *p_p3d = NULL); -}; - -class SkeletonSpatialGizmo : public EditorSpatialGizmo { - - GDCLASS(SkeletonSpatialGizmo, EditorSpatialGizmo); + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + void redraw(EditorSpatialGizmo *p_gizmo); - Skeleton *skel; - -public: - void redraw(); - SkeletonSpatialGizmo(Skeleton *p_skel = NULL); + SkeletonSpatialGizmoPlugin(); }; -class PhysicalBoneSpatialGizmo : public EditorSpatialGizmo { - GDCLASS(PhysicalBoneSpatialGizmo, EditorSpatialGizmo); +class PhysicalBoneSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { - PhysicalBone *physical_bone; + GDCLASS(PhysicalBoneSpatialGizmoPlugin, EditorSpatialGizmoPlugin); public: - //virtual Transform get_global_gizmo_transform(); - virtual void redraw(); - PhysicalBoneSpatialGizmo(PhysicalBone *p_pb = NULL); + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + void redraw(EditorSpatialGizmo *p_gizmo); + + PhysicalBoneSpatialGizmoPlugin(); }; #if 0 @@ -251,154 +184,166 @@ public: }; #endif -class VisibilityNotifierGizmo : public EditorSpatialGizmo { - - GDCLASS(VisibilityNotifierGizmo, EditorSpatialGizmo); +class RayCastSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { - VisibilityNotifier *notifier; + GDCLASS(RayCastSpatialGizmoPlugin, EditorSpatialGizmoPlugin); public: - virtual String get_handle_name(int p_idx) const; - virtual Variant get_handle_value(int p_idx) const; - virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); - virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + void redraw(EditorSpatialGizmo *p_gizmo); - void redraw(); - VisibilityNotifierGizmo(VisibilityNotifier *p_notifier = NULL); + RayCastSpatialGizmoPlugin(); }; -class ParticlesGizmo : public EditorSpatialGizmo { - - GDCLASS(ParticlesGizmo, EditorSpatialGizmo); +class VehicleWheelSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { - Particles *particles; + GDCLASS(VehicleWheelSpatialGizmoPlugin, EditorSpatialGizmoPlugin); public: - virtual String get_handle_name(int p_idx) const; - virtual Variant get_handle_value(int p_idx) const; - virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); - virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + void redraw(EditorSpatialGizmo *p_gizmo); - void redraw(); - ParticlesGizmo(Particles *p_particles = NULL); + VehicleWheelSpatialGizmoPlugin(); }; -class ReflectionProbeGizmo : public EditorSpatialGizmo { - - GDCLASS(ReflectionProbeGizmo, EditorSpatialGizmo); +class SoftBodySpatialGizmoPlugin : public EditorSpatialGizmoPlugin { - ReflectionProbe *probe; + GDCLASS(SoftBodySpatialGizmoPlugin, EditorSpatialGizmoPlugin); public: - virtual String get_handle_name(int p_idx) const; - virtual Variant get_handle_value(int p_idx) const; - virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); - virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + bool is_selectable_when_hidden() const; + void redraw(EditorSpatialGizmo *p_gizmo); - void redraw(); - ReflectionProbeGizmo(ReflectionProbe *p_probe = NULL); -}; + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel); + bool is_gizmo_handle_highlighted(const EditorSpatialGizmo *p_gizmo, int idx) const; -class GIProbeGizmo : public EditorSpatialGizmo { + SoftBodySpatialGizmoPlugin(); +}; - GDCLASS(GIProbeGizmo, EditorSpatialGizmo); +class VisibilityNotifierGizmoPlugin : public EditorSpatialGizmoPlugin { - GIProbe *probe; + GDCLASS(VisibilityNotifierGizmoPlugin, EditorSpatialGizmoPlugin); public: - virtual String get_handle_name(int p_idx) const; - virtual Variant get_handle_value(int p_idx) const; - virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); - virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + void redraw(EditorSpatialGizmo *p_gizmo); - void redraw(); - GIProbeGizmo(GIProbe *p_probe = NULL); -}; + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); -class BakedIndirectLightGizmo : public EditorSpatialGizmo { + VisibilityNotifierGizmoPlugin(); +}; - GDCLASS(BakedIndirectLightGizmo, EditorSpatialGizmo); +class ParticlesGizmoPlugin : public EditorSpatialGizmoPlugin { - BakedLightmap *baker; + GDCLASS(ParticlesGizmoPlugin, EditorSpatialGizmoPlugin); public: - virtual String get_handle_name(int p_idx) const; - virtual Variant get_handle_value(int p_idx) const; - virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); - virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + bool is_selectable_when_hidden() const; + void redraw(EditorSpatialGizmo *p_gizmo); - void redraw(); - BakedIndirectLightGizmo(BakedLightmap *p_baker = NULL); + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + + ParticlesGizmoPlugin(); }; -class SoftBodySpatialGizmo : public EditorSpatialGizmo { - GDCLASS(SoftBodySpatialGizmo, EditorSpatialGizmo); +class ReflectionProbeGizmoPlugin : public EditorSpatialGizmoPlugin { - class SoftBody *soft_body; - //RID physics_sphere_shape; // Used for raycast that doesn't work, in this moment, with softbody + GDCLASS(ReflectionProbeGizmoPlugin, EditorSpatialGizmoPlugin); public: - void redraw(); - virtual bool intersect_ray(Camera *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle = NULL, bool p_sec_first = false); - virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel); + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + void redraw(EditorSpatialGizmo *p_gizmo); - virtual bool is_gizmo_handle_highlighted(int idx) const; + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); - SoftBodySpatialGizmo(SoftBody *p_soft_physics_body = NULL); - ~SoftBodySpatialGizmo(); + ReflectionProbeGizmoPlugin(); }; -class CollisionShapeSpatialGizmo : public EditorSpatialGizmo { - - GDCLASS(CollisionShapeSpatialGizmo, EditorSpatialGizmo); +class GIProbeGizmoPlugin : public EditorSpatialGizmoPlugin { - CollisionShape *cs; + GDCLASS(GIProbeGizmoPlugin, EditorSpatialGizmoPlugin); public: - virtual String get_handle_name(int p_idx) const; - virtual Variant get_handle_value(int p_idx) const; - virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); - virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); - void redraw(); - CollisionShapeSpatialGizmo(CollisionShape *p_cs = NULL); -}; + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + void redraw(EditorSpatialGizmo *p_gizmo); + + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); -class CollisionPolygonSpatialGizmo : public EditorSpatialGizmo { + GIProbeGizmoPlugin(); +}; - GDCLASS(CollisionPolygonSpatialGizmo, EditorSpatialGizmo); +class BakedIndirectLightGizmoPlugin : public EditorSpatialGizmoPlugin { - CollisionPolygon *polygon; + GDCLASS(BakedIndirectLightGizmoPlugin, EditorSpatialGizmoPlugin); public: - void redraw(); - CollisionPolygonSpatialGizmo(CollisionPolygon *p_polygon = NULL); -}; + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + void redraw(EditorSpatialGizmo *p_gizmo); -class RayCastSpatialGizmo : public EditorSpatialGizmo { + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + + BakedIndirectLightGizmoPlugin(); +}; - GDCLASS(RayCastSpatialGizmo, EditorSpatialGizmo); +class CollisionShapeSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { - RayCast *raycast; + GDCLASS(CollisionShapeSpatialGizmoPlugin, EditorSpatialGizmoPlugin); public: - void redraw(); - RayCastSpatialGizmo(RayCast *p_raycast = NULL); -}; + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + void redraw(EditorSpatialGizmo *p_gizmo); + + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); -class VehicleWheelSpatialGizmo : public EditorSpatialGizmo { + CollisionShapeSpatialGizmoPlugin(); +}; - GDCLASS(VehicleWheelSpatialGizmo, EditorSpatialGizmo); +class CollisionPolygonSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { - VehicleWheel *car_wheel; + GDCLASS(CollisionPolygonSpatialGizmoPlugin, EditorSpatialGizmoPlugin); public: - void redraw(); - VehicleWheelSpatialGizmo(VehicleWheel *p_car_wheel = NULL); + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + void redraw(EditorSpatialGizmo *p_gizmo); + + CollisionPolygonSpatialGizmoPlugin(); }; -class NavigationMeshSpatialGizmo : public EditorSpatialGizmo { +class NavigationMeshSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { - GDCLASS(NavigationMeshSpatialGizmo, EditorSpatialGizmo); + GDCLASS(NavigationMeshSpatialGizmoPlugin, EditorSpatialGizmoPlugin); struct _EdgeKey { @@ -408,11 +353,12 @@ class NavigationMeshSpatialGizmo : public EditorSpatialGizmo { bool operator<(const _EdgeKey &p_with) const { return from == p_with.from ? to < p_with.to : from < p_with.from; } }; - NavigationMeshInstance *navmesh; - public: - void redraw(); - NavigationMeshSpatialGizmo(NavigationMeshInstance *p_navmesh = NULL); + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + void redraw(EditorSpatialGizmo *p_gizmo); + + NavigationMeshSpatialGizmoPlugin(); }; class JointGizmosDrawer { @@ -421,7 +367,7 @@ public: static Basis look_body_toward(Vector3::Axis p_axis, const Transform &joint_transform, const Transform &body_transform); static Basis look_body_toward_x(const Transform &p_joint_transform, const Transform &p_body_transform); static Basis look_body_toward_y(const Transform &p_joint_transform, const Transform &p_body_transform); - /// Special function just used for physics joints, it that returns a basis constrained toward Joint Z axis + /// Special function just used for physics joints, it returns a basis constrained toward Joint Z axis /// with axis X and Y that are looking toward the body and oriented toward up static Basis look_body_toward_z(const Transform &p_joint_transform, const Transform &p_body_transform); @@ -430,66 +376,20 @@ public: static void draw_cone(const Transform &p_offset, const Basis &p_base, real_t p_swing, real_t p_twist, Vector<Vector3> &r_points); }; -class PinJointSpatialGizmo : public EditorSpatialGizmo { - - GDCLASS(PinJointSpatialGizmo, EditorSpatialGizmo); - - PinJoint *p3d; - -public: - static void CreateGizmo(const Transform &p_offset, Vector<Vector3> &r_cursor_points); - - void redraw(); - PinJointSpatialGizmo(PinJoint *p_p3d = NULL); -}; - -class HingeJointSpatialGizmo : public EditorSpatialGizmo { - - GDCLASS(HingeJointSpatialGizmo, EditorSpatialGizmo); - - HingeJoint *p3d; - -public: - static void CreateGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_limit_lower, real_t p_limit_upper, bool p_use_limit, Vector<Vector3> &r_common_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points); - - void redraw(); - HingeJointSpatialGizmo(HingeJoint *p_p3d = NULL); -}; - -class SliderJointSpatialGizmo : public EditorSpatialGizmo { - - GDCLASS(SliderJointSpatialGizmo, EditorSpatialGizmo); - - SliderJoint *p3d; - -public: - static void CreateGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_angular_limit_lower, real_t p_angular_limit_upper, real_t p_linear_limit_lower, real_t p_linear_limit_upper, Vector<Vector3> &r_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points); - - void redraw(); - SliderJointSpatialGizmo(SliderJoint *p_p3d = NULL); -}; - -class ConeTwistJointSpatialGizmo : public EditorSpatialGizmo { - - GDCLASS(ConeTwistJointSpatialGizmo, EditorSpatialGizmo); +class JointSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { - ConeTwistJoint *p3d; + GDCLASS(JointSpatialGizmoPlugin, EditorSpatialGizmoPlugin); public: - static void CreateGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_swing, real_t p_twist, Vector<Vector3> &r_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points); - - void redraw(); - ConeTwistJointSpatialGizmo(ConeTwistJoint *p_p3d = NULL); -}; - -class Generic6DOFJointSpatialGizmo : public EditorSpatialGizmo { - - GDCLASS(Generic6DOFJointSpatialGizmo, EditorSpatialGizmo); - - Generic6DOFJoint *p3d; - -public: - static void CreateGizmo( + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + void redraw(EditorSpatialGizmo *p_gizmo); + + static void CreatePinJointGizmo(const Transform &p_offset, Vector<Vector3> &r_cursor_points); + static void CreateHingeJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_limit_lower, real_t p_limit_upper, bool p_use_limit, Vector<Vector3> &r_common_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points); + static void CreateSliderJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_angular_limit_lower, real_t p_angular_limit_upper, real_t p_linear_limit_lower, real_t p_linear_limit_upper, Vector<Vector3> &r_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points); + static void CreateConeTwistJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_swing, real_t p_twist, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points); + static void CreateGeneric6DOFJointGizmo( const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, @@ -516,26 +416,7 @@ public: Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points); - void redraw(); - Generic6DOFJointSpatialGizmo(Generic6DOFJoint *p_p3d = NULL); + JointSpatialGizmoPlugin(); }; -class SpatialEditorGizmos { - -public: - HashMap<String, Ref<SpatialMaterial> > material_cache; - - Ref<SpatialMaterial> handle2_material; - Ref<SpatialMaterial> handle2_material_billboard; - Ref<SpatialMaterial> handle_material; - Ref<SpatialMaterial> handle_material_billboard; - Ref<Texture> handle_t; - Ref<ArrayMesh> pos3d_mesh; - Ref<ArrayMesh> listener_line_mesh; - static SpatialEditorGizmos *singleton; - - Ref<SpatialEditorGizmo> get_gizmo(Spatial *p_spatial); - - SpatialEditorGizmos(); -}; #endif // SPATIAL_EDITOR_GIZMOS_H diff --git a/editor/translations/af.po b/editor/translations/af.po index c5853bbb2f..d4c8bc26f4 100644 --- a/editor/translations/af.po +++ b/editor/translations/af.po @@ -7328,6 +7328,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +msgid "View log" +msgstr "" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/ar.po b/editor/translations/ar.po index ccf2b97d9a..1535ccafb6 100644 --- a/editor/translations/ar.po +++ b/editor/translations/ar.po @@ -2,7 +2,6 @@ # Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. # Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) # This file is distributed under the same license as the Godot source code. -# # Adel <dragonhunter250@gmail.com>, 2018. # athomield <athomield@hotmail.com>, 2017. # Basil Al-Khateeb <basil.y.alkhateeb@gmail.com>, 2017. @@ -15,13 +14,12 @@ # omar anwar aglan <omar.aglan91@yahoo.com>, 2017-2018. # OWs Tetra <owstetra@gmail.com>, 2017. # Rached Noureddine <rached.noureddine@gmail.com>, 2018. -# Rex_sa <asd1234567890m@gmail.com>, 2017. +# Rex_sa <asd1234567890m@gmail.com>, 2017, 2018. # Wajdi Feki <wajdi.feki@gmail.com>, 2017. -# msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-05-28 18:34+0000\n" +"PO-Revision-Date: 2018-07-15 19:34+0000\n" "Last-Translator: Rached Noureddine <rached.noureddine@gmail.com>\n" "Language-Team: Arabic <https://hosted.weblate.org/projects/godot-engine/" "godot/ar/>\n" @@ -30,7 +28,7 @@ msgstr "" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " "&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n" -"X-Generator: Weblate 3.0-dev\n" +"X-Generator: Weblate 3.1-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -4331,11 +4329,11 @@ msgstr "ولد رؤية AABB" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Remove Point from Curve" -msgstr "" +msgstr "إزالة نقطة من المنحنى" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Remove Out-Control from Curve" -msgstr "" +msgstr "أزل Out-Control من المنحنى" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Remove In-Control from Curve" @@ -7392,6 +7390,11 @@ msgstr "بناء المشروع" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "إظهار الملفات" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" @@ -8076,7 +8079,7 @@ msgstr "" #: scene/resources/dynamic_font.cpp msgid "Invalid font size." -msgstr "" +msgstr "حجم الخط غير صالح" #~ msgid "Next" #~ msgstr "التالي" diff --git a/editor/translations/bg.po b/editor/translations/bg.po index 9f366b3d2f..71b9216b46 100644 --- a/editor/translations/bg.po +++ b/editor/translations/bg.po @@ -7383,6 +7383,11 @@ msgstr "Проект" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Преглед на файловете" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/bn.po b/editor/translations/bn.po index 3d00e3450c..aa36beefb6 100644 --- a/editor/translations/bn.po +++ b/editor/translations/bn.po @@ -7773,6 +7773,11 @@ msgstr "নতুন প্রকল্প" msgid "Warnings" msgstr "সতর্কতা" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "ফাইল" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/ca.po b/editor/translations/ca.po index d2bffb0f84..085241296e 100644 --- a/editor/translations/ca.po +++ b/editor/translations/ca.po @@ -7438,6 +7438,11 @@ msgstr "Munta el Projecte" msgid "Warnings" msgstr "Avisos" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Visualitza Fitxers" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "Final de la traça de la pila d'excepció interna" diff --git a/editor/translations/cs.po b/editor/translations/cs.po index 1066bbad94..b4cf176796 100644 --- a/editor/translations/cs.po +++ b/editor/translations/cs.po @@ -7372,6 +7372,11 @@ msgstr "Sestavit projekt" msgid "Warnings" msgstr "Varování" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Zobrazit soubory" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/da.po b/editor/translations/da.po index 3b5854334a..fcfdb6d249 100644 --- a/editor/translations/da.po +++ b/editor/translations/da.po @@ -7445,6 +7445,11 @@ msgstr "Projekt" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Vis filer" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/de.po b/editor/translations/de.po index d5d63f654b..c61d78e37e 100644 --- a/editor/translations/de.po +++ b/editor/translations/de.po @@ -27,12 +27,15 @@ # Tim Schellenberg <smwleod@gmail.com>, 2017. # Timo Schwarzer <account@timoschwarzer.com>, 2016-2018. # viernullvier <hannes.breul+github@gmail.com>, 2016. +# Arndt Heuvel <codeforpb@schatzkarten.net>, 2018. +# Gordon <gkone@gmx.net>, 2018. +# chillhelm <wilhelm@neubert.online>, 2018. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-06-19 19:38+0000\n" -"Last-Translator: nimradium <nimra242001@gmail.com>\n" +"PO-Revision-Date: 2018-07-05 12:38+0000\n" +"Last-Translator: So Wieso <sowieso@dukun.de>\n" "Language-Team: German <https://hosted.weblate.org/projects/godot-engine/" "godot/de/>\n" "Language: de\n" @@ -40,7 +43,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 3.0.1\n" +"X-Generator: Weblate 3.1-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -331,8 +334,7 @@ msgstr "Optimieren" #: editor/animation_editor.cpp msgid "Select an AnimationPlayer from the Scene Tree to edit animations." msgstr "" -"Wählen Sie einen AnimationPlayer aus dem Szenenbaum aus, um Animationen zu " -"bearbeiten." +"AnimationPlayer aus dem Szenenbaum auswählen um Animationen zu bearbeiten." #: editor/animation_editor.cpp msgid "Key" @@ -1948,7 +1950,7 @@ msgstr "Umwandeln zu..." #: editor/editor_node.cpp msgid "MeshLibrary..." -msgstr "MeshLibrary..." +msgstr "Mesh-Bibliothek..." #: editor/editor_node.cpp msgid "TileSet..." @@ -2483,7 +2485,7 @@ msgstr "Mirrors werden geladen, bitte warten..." #: editor/export_template_manager.cpp msgid "Remove template version '%s'?" -msgstr "Template-Version '%s' entfernen?" +msgstr "Template-Version ‚%s‘ entfernen?" #: editor/export_template_manager.cpp msgid "Can't open export templates zip." @@ -6048,8 +6050,8 @@ msgid "" "Couldn't load project.godot in project path (error %d). It may be missing or " "corrupted." msgstr "" -"Konnte project.godot im Projektpfad nicht laden (Fehler %d). Sie könnte " -"fehlen oder beschädigt worden sein." +"Die Datei project.godot im Projektpfad konnte nicht geladen werden (Fehler " +"%d). Sie könnte fehlen oder beschädigt sein." #: editor/project_manager.cpp msgid "Couldn't edit project.godot in project path." @@ -7490,6 +7492,11 @@ msgstr "Projekt bauen" msgid "Warnings" msgstr "Warnungen" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Dateien anzeigen" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "Ende des inneren Exception-Stack-Traces" diff --git a/editor/translations/de_CH.po b/editor/translations/de_CH.po index 26f824bc4b..7d11a9d09f 100644 --- a/editor/translations/de_CH.po +++ b/editor/translations/de_CH.po @@ -7424,6 +7424,11 @@ msgstr "Projektname:" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Datei(en) öffnen" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot index 1cb31e0ee9..d0f1d04a10 100644 --- a/editor/translations/editor.pot +++ b/editor/translations/editor.pot @@ -7265,6 +7265,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +msgid "View log" +msgstr "" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/el.po b/editor/translations/el.po index b3275b4647..4a9560e602 100644 --- a/editor/translations/el.po +++ b/editor/translations/el.po @@ -2,13 +2,11 @@ # Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. # Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) # This file is distributed under the same license as the Godot source code. -# # George Tsiamasiotis <gtsiam@windowslive.com>, 2017-2018. -# msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-05-20 09:37+0000\n" +"PO-Revision-Date: 2018-07-21 22:38+0000\n" "Last-Translator: George Tsiamasiotis <gtsiam@windowslive.com>\n" "Language-Team: Greek <https://hosted.weblate.org/projects/godot-engine/godot/" "el/>\n" @@ -16,7 +14,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 3.0-dev\n" +"X-Generator: Weblate 3.1-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -1135,7 +1133,7 @@ msgstr "Εμφάνιση στη διαχείριση αρχείων" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "New Folder..." -msgstr "Νέος φάκελος" +msgstr "Νέος φάκελος..." #: editor/editor_file_dialog.cpp msgid "Refresh" @@ -2698,7 +2696,7 @@ msgstr "Μετονομασία..." #: editor/filesystem_dock.cpp msgid "Move To..." -msgstr "Μετακίνηση σε" +msgstr "Μετακίνηση σε..." #: editor/filesystem_dock.cpp msgid "Open Scene(s)" @@ -2710,15 +2708,15 @@ msgstr "Στιγμιότυπο" #: editor/filesystem_dock.cpp msgid "Edit Dependencies..." -msgstr "Επεξεργασία εξαρτήσεων" +msgstr "Επεξεργασία εξαρτήσεων..." #: editor/filesystem_dock.cpp msgid "View Owners..." -msgstr "Προβολή ιδιοκτητών" +msgstr "Προβολή ιδιοκτητών..." #: editor/filesystem_dock.cpp msgid "Duplicate..." -msgstr "Αναπαραγωγή" +msgstr "Αναπαραγωγή..." #: editor/filesystem_dock.cpp msgid "Previous Directory" @@ -4031,7 +4029,7 @@ msgstr "Δημιουργία περιγράμματος" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh" -msgstr "Πλέγμα" +msgstr "Πλέγμα..." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Trimesh Static Body" @@ -5712,9 +5710,8 @@ msgid "Options" msgstr "Επιλογές" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Has,Many,Options" -msgstr "Έχει,Πάρα,Πολλές,Επιλογές!" +msgstr "Έχει,Πολλές,Επιλογές" #: editor/plugins/theme_editor_plugin.cpp msgid "Tab 1" @@ -6001,9 +5998,8 @@ msgid "Imported Project" msgstr "Εισαγμένο έργο" #: editor/project_manager.cpp -#, fuzzy msgid "Invalid Project Name." -msgstr "Όνομα έργου:" +msgstr "Άκυρο όνομα έργου." #: editor/project_manager.cpp msgid "Couldn't create folder." @@ -6207,13 +6203,12 @@ msgid "Mouse Button" msgstr "Κουμπί ποντικιού" #: editor/project_settings_editor.cpp -#, fuzzy msgid "" "Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or " "'\"'." msgstr "" "Άκυρο όνομα ενέργειας. Δεν μπορεί να είναι άδειο ή να περιέχει '/', ':', " -"'=', '\\' ή '\"'" +"'=', '\\' ή '\"'." #: editor/project_settings_editor.cpp msgid "Action '%s' already exists!" @@ -7474,6 +7469,11 @@ msgstr "Δόμηση έργου" msgid "Warnings" msgstr "Προειδοποιήσεις" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Προβολή αρχείων" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "Τέλος ιχνηλάτησης στοίβας εσωτερικής εξαίρεσης" diff --git a/editor/translations/es.po b/editor/translations/es.po index 89118d2501..8e1f0b13c9 100644 --- a/editor/translations/es.po +++ b/editor/translations/es.po @@ -29,12 +29,13 @@ # Swyter <swyterzone@gmail.com>, 2016-2017. # Vazquinhos <vazquinhos@gmail.com>, 2018. # Yovani Damián <blackblex@gmail.com>, 2018. +# Andrus Diaz German <andrusdiazaleman@gmail.com>, 2018. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-06-22 08:31+0000\n" -"Last-Translator: R. Joshua Seville <rjoshua@protonmail.com>\n" +"PO-Revision-Date: 2018-07-20 16:43+0000\n" +"Last-Translator: Javier Ocampos <xavier.ocampos@gmail.com>\n" "Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/" "godot/es/>\n" "Language: es\n" @@ -54,19 +55,19 @@ msgstr "Toda la Selección" #: editor/animation_editor.cpp msgid "Anim Change Keyframe Time" -msgstr "Cambiar el tiempo del Fotograma Clave de Animación" +msgstr "Cambiar el Tiempo del Fotograma Clave de Animación" #: editor/animation_editor.cpp msgid "Anim Change Transition" -msgstr "Cambiar Transición de Animación" +msgstr "Cambiar la Transición de Animación" #: editor/animation_editor.cpp msgid "Anim Change Transform" -msgstr "Cambiar transformación de animación" +msgstr "Cambiar la Transformación de la Animación" #: editor/animation_editor.cpp msgid "Anim Change Keyframe Value" -msgstr "Cambiar valor del Fotograma Clave de Animación" +msgstr "Cambiar valor de la Clave de Animación" #: editor/animation_editor.cpp msgid "Anim Change Call" @@ -114,7 +115,7 @@ msgstr "Cambiar Modo de Ciclo de Pista de Animación" #: editor/animation_editor.cpp msgid "Edit Node Curve" -msgstr "Editar Nodo de Curva" +msgstr "Editar Curva del Nodo" #: editor/animation_editor.cpp msgid "Edit Selection Curve" @@ -163,7 +164,7 @@ msgstr "Escalar Selección" #: editor/animation_editor.cpp msgid "Scale From Cursor" -msgstr "Escalar desde cursor" +msgstr "Escalar Desde Cursor" #: editor/animation_editor.cpp msgid "Goto Next Step" @@ -212,11 +213,11 @@ msgstr "Limpiar Animación" #: editor/animation_editor.cpp msgid "Create NEW track for %s and insert key?" -msgstr "¿Quieres crear una NUEVA pista para %s e insertar clave?" +msgstr "¿Crear NUEVA pista para %s e insertar clave?" #: editor/animation_editor.cpp msgid "Create %d NEW tracks and insert keys?" -msgstr "¿Quieres crear %d NUEVAS pistas e insertar claves?" +msgstr "¿Crear %d NUEVAS pistas e insertar claves?" #: editor/animation_editor.cpp editor/create_dialog.cpp #: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp @@ -288,7 +289,7 @@ msgstr "Activar/Desactivar Bucle de Animación." #: editor/animation_editor.cpp msgid "Add new tracks." -msgstr "Añadir Nuevas Pistas." +msgstr "Añadir nuevas pistas." #: editor/animation_editor.cpp msgid "Move current track up." @@ -308,7 +309,7 @@ msgstr "Herramientas de pistas" #: editor/animation_editor.cpp msgid "Enable editing of individual keys by clicking them." -msgstr "Habilitar la edición de claves individuales al hacer clic." +msgstr "Habilitar la edición de claves individuales haciendo clic en ellas." #: editor/animation_editor.cpp msgid "Anim. Optimizer" @@ -366,7 +367,7 @@ msgstr "Limpiar todas las animaciones" #: editor/animation_editor.cpp msgid "Clean-Up Animation(s) (NO UNDO!)" -msgstr "Limpiar todas las animaciones (IRREVERSIBLE)" +msgstr "Limpiar las Animación(es) (¡IRREVERSIBLE!)" #: editor/animation_editor.cpp msgid "Clean-Up" @@ -374,39 +375,39 @@ msgstr "Limpiar" #: editor/array_property_edit.cpp msgid "Resize Array" -msgstr "Redimensionar «array»" +msgstr "Redimensionar Array" #: editor/array_property_edit.cpp msgid "Change Array Value Type" -msgstr "Cambiar tipo de valor del «array»" +msgstr "Cambiar Tipo de Valor del Array" #: editor/array_property_edit.cpp msgid "Change Array Value" -msgstr "Cambiar valor del «array»" +msgstr "Cambiar Valor del Array" #: editor/code_editor.cpp msgid "Go to Line" -msgstr "Ir a línea" +msgstr "Ir a Línea" #: editor/code_editor.cpp msgid "Line Number:" -msgstr "Número de línea:" +msgstr "Número de Línea:" #: editor/code_editor.cpp msgid "No Matches" -msgstr "Sin coincidencias" +msgstr "Sin Coincidencias" #: editor/code_editor.cpp msgid "Replaced %d occurrence(s)." -msgstr "%d ocurrencia/s reemplazadas." +msgstr "%d Ocurrencia(s) Reemplazada(s)." #: editor/code_editor.cpp msgid "Match Case" -msgstr "Coincidir mayús/minúsculas" +msgstr "Coincidir Mayús/Minúsculas" #: editor/code_editor.cpp msgid "Whole Words" -msgstr "Palabras completas" +msgstr "Palabras Completas" #: editor/code_editor.cpp msgid "Replace" @@ -414,11 +415,11 @@ msgstr "Reemplazar" #: editor/code_editor.cpp msgid "Replace All" -msgstr "Reemplazar todo" +msgstr "Reemplazar Todo" #: editor/code_editor.cpp msgid "Selection Only" -msgstr "Sólo selección" +msgstr "Sólo Selección" #: editor/code_editor.cpp msgid "Zoom In" @@ -430,7 +431,7 @@ msgstr "Alejar" #: editor/code_editor.cpp msgid "Reset Zoom" -msgstr "Restablecer zoom" +msgstr "Restablecer Zoom" #: editor/code_editor.cpp editor/script_editor_debugger.cpp msgid "Line:" @@ -449,8 +450,8 @@ msgid "" "Target method not found! Specify a valid method or attach a script to target " "Node." msgstr "" -"No se encontró el método del objetivo! Especifica un método válido o adjunta " -"un script al Nodo objetivo." +"¡Método objetivo no encontrado! Especifica un método válido o añade un " +"script al Nodo objetivo." #: editor/connections_dialog.cpp msgid "Connect To Node:" @@ -471,11 +472,11 @@ msgstr "Quitar" #: editor/connections_dialog.cpp msgid "Add Extra Call Argument:" -msgstr "Añadir argumento extra de llamada:" +msgstr "Añadir Argumento Extra de Llamada:" #: editor/connections_dialog.cpp msgid "Extra Call Arguments:" -msgstr "Argumentos extras de llamada:" +msgstr "Argumentos Extras de Llamada:" #: editor/connections_dialog.cpp msgid "Path to Node:" @@ -483,7 +484,7 @@ msgstr "Ruta al Nodo:" #: editor/connections_dialog.cpp msgid "Make Function" -msgstr "Crear función" +msgstr "Crear Función" #: editor/connections_dialog.cpp msgid "Deferred" @@ -538,7 +539,7 @@ msgstr "Señales" #: editor/create_dialog.cpp msgid "Change %s Type" -msgstr "Cambiar el tipo de %s" +msgstr "Cambiar el Tipo de %s" #: editor/create_dialog.cpp editor/project_settings_editor.cpp #: modules/visual_script/visual_script_editor.cpp @@ -579,11 +580,11 @@ msgstr "Descripción:" #: editor/dependency_editor.cpp msgid "Search Replacement For:" -msgstr "Buscar reemplazo para:" +msgstr "Buscar Reemplazo Para:" #: editor/dependency_editor.cpp msgid "Dependencies For:" -msgstr "Dependencias para:" +msgstr "Dependencias Para:" #: editor/dependency_editor.cpp msgid "" @@ -622,7 +623,7 @@ msgstr "Dependencias:" #: editor/dependency_editor.cpp msgid "Fix Broken" -msgstr "Arreglar rota(s)" +msgstr "Arreglar Rota(s)" #: editor/dependency_editor.cpp msgid "Dependency Editor" @@ -630,7 +631,7 @@ msgstr "Editor de Dependencias" #: editor/dependency_editor.cpp msgid "Search Replacement Resource:" -msgstr "Buscar recurso de reemplazo:" +msgstr "Buscar Recurso de Reemplazo:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help.cpp editor/editor_node.cpp editor/filesystem_dock.cpp @@ -641,13 +642,11 @@ msgstr "Abrir" #: editor/dependency_editor.cpp msgid "Owners Of:" -msgstr "Dueños de:" +msgstr "Dueños De:" #: editor/dependency_editor.cpp msgid "Remove selected files from the project? (no undo)" -msgstr "" -"¿Quieres quitar los archivos seleccionados del proyecto? (No puedes " -"deshacerlo)" +msgstr "¿Quitar los archivos seleccionados del proyecto? (irreversible)" #: editor/dependency_editor.cpp msgid "" @@ -657,7 +656,7 @@ msgid "" msgstr "" "Otros recursos necesitan los archivos que estás intentando quitar para " "funcionar.\n" -"¿Seguro que quieres quitarlos? (No puedes deshacerlo)" +"¿Quitarlos de todos modos? (irreversible)" #: editor/dependency_editor.cpp msgid "Cannot remove:" @@ -673,7 +672,7 @@ msgstr "La escena no se pudo cargar porque faltan las siguientes dependencias:" #: editor/dependency_editor.cpp editor/editor_node.cpp msgid "Open Anyway" -msgstr "Abrir de todos modos" +msgstr "Abrir de Todos Modos" #: editor/dependency_editor.cpp msgid "Which action should be taken?" @@ -689,23 +688,23 @@ msgstr "¡Hubo errores al cargar!" #: editor/dependency_editor.cpp msgid "Permanently delete %d item(s)? (No undo!)" -msgstr "¿Quieres eliminar permanentemente %d elementos? (Irreversible)" +msgstr "¿Eliminar permanentemente %d elemento(s)? (¡Irreversible!)" #: editor/dependency_editor.cpp msgid "Owns" -msgstr "Es dueño de" +msgstr "Dueño de" #: editor/dependency_editor.cpp msgid "Resources Without Explicit Ownership:" -msgstr "Recursos sin propietario explícito:" +msgstr "Recursos Sin Propietario Explícito:" #: editor/dependency_editor.cpp editor/editor_node.cpp msgid "Orphan Resource Explorer" -msgstr "Explorador de recursos huérfanos" +msgstr "Explorador de Recursos Huérfanos" #: editor/dependency_editor.cpp msgid "Delete selected files?" -msgstr "¿Quieres eliminar los archivos seleccionados?" +msgstr "¿Eliminar los archivos seleccionados?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp @@ -745,7 +744,7 @@ msgstr "Desarrollador Principal" #: editor/editor_about.cpp msgid "Project Manager " -msgstr "Administrador de proyectos " +msgstr "Administrador de Proyectos " #: editor/editor_about.cpp msgid "Developers" @@ -757,11 +756,11 @@ msgstr "Autores" #: editor/editor_about.cpp msgid "Platinum Sponsors" -msgstr "Patrocinadores Platinum" +msgstr "Patrocinadores de Platino" #: editor/editor_about.cpp msgid "Gold Sponsors" -msgstr "Patrocinadores Gold" +msgstr "Patrocinadores de Oro" #: editor/editor_about.cpp msgid "Mini Sponsors" @@ -769,11 +768,11 @@ msgstr "Mini Patrocinadores" #: editor/editor_about.cpp msgid "Gold Donors" -msgstr "Donantes Gold" +msgstr "Donantes de Oro" #: editor/editor_about.cpp msgid "Silver Donors" -msgstr "Donantes Silver" +msgstr "Donantes de Plata" #: editor/editor_about.cpp msgid "Bronze Donors" @@ -825,7 +824,7 @@ msgstr "Descomprimiendo Assets" #: editor/editor_asset_installer.cpp editor/project_manager.cpp msgid "Package Installed Successfully!" -msgstr "¡El paquete se ha instalado correctamente!" +msgstr "¡Paquete Instalado Exitosamente!" #: editor/editor_asset_installer.cpp #: editor/plugins/asset_library_editor_plugin.cpp @@ -859,19 +858,19 @@ msgstr "Cambiar Volumen de Bus de Audio" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Solo" -msgstr "Act./Desact. Solo de Bus de Audio" +msgstr "Alternar Solo de Bus de Audio" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Mute" -msgstr "Alternar Mute del Bus de Audio" +msgstr "Alternar Silencio de Bus de Audio" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Bypass Effects" -msgstr "Alternar puenteado de efectos en Bus de Audio" +msgstr "Alternar Puenteado de Efectos de Bus de Audio" #: editor/editor_audio_buses.cpp msgid "Select Audio Bus Send" -msgstr "Seleccionar Envío de Audio Bus" +msgstr "Seleccionar Envío de Bus de Audio" #: editor/editor_audio_buses.cpp msgid "Add Audio Bus Effect" @@ -928,7 +927,7 @@ msgstr "Añadir Bus de Audio" #: editor/editor_audio_buses.cpp msgid "Master bus can't be deleted!" -msgstr "¡No se puede borrar el Bus Maestro!" +msgstr "¡No se puede borrar el bus maestro!" #: editor/editor_audio_buses.cpp msgid "Delete Audio Bus" @@ -940,7 +939,7 @@ msgstr "Duplicar Bus de Audio" #: editor/editor_audio_buses.cpp msgid "Reset Bus Volume" -msgstr "Restablecer Volumen del Bus" +msgstr "Restablecer Volumen de Bus" #: editor/editor_audio_buses.cpp msgid "Move Audio Bus" @@ -948,7 +947,7 @@ msgstr "Mover Bus de Audio" #: editor/editor_audio_buses.cpp msgid "Save Audio Bus Layout As..." -msgstr "Guardar configuración de los Buses de Audio como..." +msgstr "Guardar Configuración de Bus de Audio Como..." #: editor/editor_audio_buses.cpp msgid "Location for New Layout..." @@ -956,7 +955,7 @@ msgstr "Ubicación para Nueva Configuración..." #: editor/editor_audio_buses.cpp msgid "Open Audio Bus Layout" -msgstr "Abrir configuración de Bus de Audio" +msgstr "Abrir Configuración de Bus de Audio" #: editor/editor_audio_buses.cpp msgid "There is no 'res://default_bus_layout.tres' file." @@ -1002,7 +1001,7 @@ msgstr "Cargar configuración de Bus por defecto." #: editor/editor_autoload_settings.cpp msgid "Invalid name." -msgstr "El nombre no es correcto." +msgstr "Nombre inválido." #: editor/editor_autoload_settings.cpp msgid "Valid characters:" @@ -1011,24 +1010,24 @@ msgstr "Letras válidas:" #: editor/editor_autoload_settings.cpp msgid "Invalid name. Must not collide with an existing engine class name." msgstr "" -"El nombre no es correcto. No puede coincidir con el nombre de una clase que " -"ya exista en el motor gráfico." +"Nombre inválido. No debe coincidir con el nombre de una clase que ya exista " +"en el motor gráfico." #: editor/editor_autoload_settings.cpp msgid "Invalid name. Must not collide with an existing buit-in type name." msgstr "" -"El nombre no es correcto. No puede coincidir con un nombre de tipo que ya " -"esté integrado en el motor gráfico." +"Nombre inválido. No debe coincidir con un nombre de tipo que ya esté " +"integrado en el motor gráfico." #: editor/editor_autoload_settings.cpp msgid "Invalid name. Must not collide with an existing global constant name." msgstr "" -"El nombre no es correcto. No puede coincidir con un nombre de constante " -"global ya existente en el motor gráfico." +"Nombre inválido. No debe coincidir con un nombre de constante global ya " +"existente en el motor gráfico." #: editor/editor_autoload_settings.cpp msgid "Invalid Path." -msgstr "Ruta incorrecta." +msgstr "Ruta Inválida." #: editor/editor_autoload_settings.cpp msgid "File does not exist." @@ -1052,7 +1051,7 @@ msgstr "Renombrar Autoload" #: editor/editor_autoload_settings.cpp msgid "Toggle AutoLoad Globals" -msgstr "Des/Activar Globales de Autoload" +msgstr "Alternar Globales de Autoload" #: editor/editor_autoload_settings.cpp msgid "Move Autoload" @@ -1106,7 +1105,7 @@ msgstr "[vacío]" #: editor/editor_data.cpp msgid "[unsaved]" -msgstr "[no guardado]" +msgstr "[sin guardar]" #: editor/editor_dir_dialog.cpp msgid "Please select a base directory first" @@ -1114,12 +1113,12 @@ msgstr "Por favor, selecciona primero un directorio base" #: editor/editor_dir_dialog.cpp msgid "Choose a Directory" -msgstr "Elige una carpeta" +msgstr "Elige un Directorio" #: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp #: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp msgid "Create Folder" -msgstr "Crear carpeta" +msgstr "Crear Carpeta" #: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp #: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp @@ -1139,7 +1138,7 @@ msgstr "Elegir" #: editor/editor_export.cpp msgid "Storing File:" -msgstr "Archivo de almacenamiento:" +msgstr "Archivo de Almacenamiento:" #: editor/editor_export.cpp msgid "Packing" @@ -1147,11 +1146,11 @@ msgstr "Empaquetando" #: editor/editor_export.cpp platform/javascript/export/export.cpp msgid "Template file not found:" -msgstr "No se encontró archivo de plantilla:" +msgstr "Archivo de plantilla no encontrado:" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "File Exists, Overwrite?" -msgstr "El archivo ya existe, ¿quieres sobreescribirlo?" +msgstr "El Archivo ya Existe, ¿Quieres Sobreescribirlo?" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Select Current Folder" @@ -1159,15 +1158,15 @@ msgstr "Seleccionar Carpeta Actual" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "Copy Path" -msgstr "Copiar ruta" +msgstr "Copiar Ruta" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "Show In File Manager" -msgstr "Mostrar en el navegador de archivos" +msgstr "Mostrar en el Navegador de Archivos" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "New Folder..." -msgstr "Nueva carpeta..." +msgstr "Nueva Carpeta..." #: editor/editor_file_dialog.cpp msgid "Refresh" @@ -1183,19 +1182,19 @@ msgstr "Todos los archivos (*)" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Open a File" -msgstr "Abrir un archivo" +msgstr "Abrir un Archivo" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Open File(s)" -msgstr "Abrir archivo/s" +msgstr "Abrir Archivo(s)" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Open a Directory" -msgstr "Abrir una carpeta" +msgstr "Abrir un Directorio" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Open a File or Directory" -msgstr "Abrir un archivo o carpeta" +msgstr "Abrir un Archivo o Directorio" #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -1205,7 +1204,7 @@ msgstr "Guardar" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Save a File" -msgstr "Guardar un archivo" +msgstr "Guardar un Archivo" #: editor/editor_file_dialog.cpp msgid "Go Back" @@ -1221,27 +1220,27 @@ msgstr "Subir" #: editor/editor_file_dialog.cpp msgid "Toggle Hidden Files" -msgstr "Ver/ocultar archivos ocultos" +msgstr "Ver/ocultar Archivos Ocultos" #: editor/editor_file_dialog.cpp msgid "Toggle Favorite" -msgstr "Añadir/quitar favorito" +msgstr "Añadir/quitar Favorito" #: editor/editor_file_dialog.cpp msgid "Toggle Mode" -msgstr "Cambiar modo" +msgstr "Cambiar Modo" #: editor/editor_file_dialog.cpp msgid "Focus Path" -msgstr "Seleccionar ruta" +msgstr "Seleccionar Ruta" #: editor/editor_file_dialog.cpp msgid "Move Favorite Up" -msgstr "Subir favorito" +msgstr "Subir Favorito" #: editor/editor_file_dialog.cpp msgid "Move Favorite Down" -msgstr "Bajar favorito" +msgstr "Bajar Favorito" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Go to parent folder" @@ -1249,7 +1248,7 @@ msgstr "Ir a la carpeta principal" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Directories & Files:" -msgstr "Carpetas y archivos:" +msgstr "Directorios y Archivos:" #: editor/editor_file_dialog.cpp msgid "Preview:" @@ -1266,7 +1265,7 @@ msgstr "Debe tener una extensión válida." #: editor/editor_file_system.cpp msgid "ScanSources" -msgstr "Analizando fuentes" +msgstr "Analizando Fuentes" #: editor/editor_file_system.cpp msgid "(Re)Importing Assets" @@ -1275,15 +1274,15 @@ msgstr "(Re)Importando Assets" #: editor/editor_help.cpp editor/editor_node.cpp #: editor/plugins/script_editor_plugin.cpp msgid "Search Help" -msgstr "Ayuda de búsqueda" +msgstr "Ayuda de Búsqueda" #: editor/editor_help.cpp msgid "Class List:" -msgstr "Lista de clases:" +msgstr "Lista de Clases:" #: editor/editor_help.cpp msgid "Search Classes" -msgstr "Buscar clases" +msgstr "Buscar Clases" #: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp msgid "Top" @@ -1303,7 +1302,7 @@ msgstr "Heredada por:" #: editor/editor_help.cpp msgid "Brief Description:" -msgstr "Descripción breve:" +msgstr "Descripción Breve:" #: editor/editor_help.cpp msgid "Members" @@ -1323,11 +1322,11 @@ msgstr "Métodos públicos:" #: editor/editor_help.cpp msgid "GUI Theme Items" -msgstr "Elementos del Tema de GUI" +msgstr "Elementos del Tema de Interfaz" #: editor/editor_help.cpp msgid "GUI Theme Items:" -msgstr "Elementos de tema de interfaz:" +msgstr "Elementos del Tema de Interfaz:" #: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp msgid "Signals:" @@ -1359,7 +1358,7 @@ msgstr "Descripción" #: editor/editor_help.cpp msgid "Online Tutorials:" -msgstr "Tutoriales en línea:" +msgstr "Tutoriales en Línea:" #: editor/editor_help.cpp msgid "" @@ -1367,8 +1366,8 @@ msgid "" "$url]contribute one[/url][/color] or [color=$color][url=$url2]request one[/" "url][/color]." msgstr "" -"De momento no hay tutoriales para esta clase, puedes [color=$color][url=" -"$url]añadir uno[/url][/color] o [color=$color][url=$url2]pedir uno[color=" +"Actualmente no hay tutoriales para esta clase, puedes [color=$color][url=" +"$url]aportar uno[/url][/color] o [color=$color][url=$url2]pedir uno[color=" "$color][url=$url2]." #: editor/editor_help.cpp @@ -1393,7 +1392,7 @@ msgstr "Métodos" #: editor/editor_help.cpp msgid "Method Description:" -msgstr "Descripción de métodos:" +msgstr "Descripción del Método:" #: editor/editor_help.cpp msgid "" @@ -1405,11 +1404,11 @@ msgstr "" #: editor/editor_help.cpp msgid "Search Text" -msgstr "Texto de búsqueda" +msgstr "Texto de Búsqueda" #: editor/editor_help.cpp msgid "Find" -msgstr "Búsqueda" +msgstr "Buscar" #: editor/editor_log.cpp msgid "Output:" @@ -1420,11 +1419,11 @@ msgstr "Salida:" #: modules/gdnative/gdnative_library_editor_plugin.cpp scene/gui/line_edit.cpp #: scene/gui/text_edit.cpp msgid "Clear" -msgstr "Borrar todo" +msgstr "Borrar Todo" #: editor/editor_log.cpp msgid "Clear Output" -msgstr "Borrar salida" +msgstr "Borrar Salida" #: editor/editor_node.cpp msgid "Project export failed with error code %d." @@ -1432,7 +1431,7 @@ msgstr "La exportación del proyecto falló con el código de error %d." #: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Error saving resource!" -msgstr "¡Hubo un error al guardar el recurso!" +msgstr "¡Error al guardar el recurso!" #: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Save Resource As..." @@ -1485,7 +1484,7 @@ msgstr "Analizando" #: editor/editor_node.cpp msgid "Creating Thumbnail" -msgstr "Creando miniatura" +msgstr "Creando Miniatura" #: editor/editor_node.cpp msgid "This operation can't be done without a tree root." @@ -1501,7 +1500,7 @@ msgstr "" #: editor/editor_node.cpp msgid "Failed to load resource." -msgstr "Hubo un problema al cargar el recurso." +msgstr "Error al cargar el recurso." #: editor/editor_node.cpp msgid "Can't load MeshLibrary for merging!" @@ -1529,7 +1528,7 @@ msgstr "Se han sobrescrito los ajustes predeterminados del editor." #: editor/editor_node.cpp msgid "Layout name not found!" -msgstr "¡No se encuentra el nombre del ajuste!" +msgstr "¡Nombre del ajuste no encontrado!" #: editor/editor_node.cpp msgid "Restored default layout to base settings." @@ -1594,23 +1593,23 @@ msgstr "Ocultar todas las propiedades" #: editor/editor_node.cpp msgid "Copy Params" -msgstr "Copiar parámetros" +msgstr "Copiar Parámetros" #: editor/editor_node.cpp msgid "Paste Params" -msgstr "Pegar parámetros" +msgstr "Pegar Parámetros" #: editor/editor_node.cpp editor/plugins/resource_preloader_editor_plugin.cpp msgid "Paste Resource" -msgstr "Pegar recurso" +msgstr "Pegar Recurso" #: editor/editor_node.cpp msgid "Copy Resource" -msgstr "Copiar recurso" +msgstr "Copiar Recurso" #: editor/editor_node.cpp msgid "Make Built-In" -msgstr "Convertirlo en integrado" +msgstr "Convertirlo en Integrado" #: editor/editor_node.cpp msgid "Make Sub-Resources Unique" @@ -1618,7 +1617,7 @@ msgstr "Creación de Subrecursos Únicos" #: editor/editor_node.cpp msgid "Open in Help" -msgstr "Abrir en la ayuda" +msgstr "Abrir en la Ayuda" #: editor/editor_node.cpp msgid "There is no defined scene to run." @@ -1711,11 +1710,11 @@ msgstr "Esta operación no puede realizarse sin una escena." #: editor/editor_node.cpp msgid "Export Mesh Library" -msgstr "Exportar biblioteca de mallas" +msgstr "Exportar Librería de Mallas" #: editor/editor_node.cpp msgid "This operation can't be done without a root node." -msgstr "Esta operación no puede realizarse sin un Nodo Raíz." +msgstr "Esta operación no puede realizarse sin un nodo raíz." #: editor/editor_node.cpp msgid "Export Tile Set" @@ -1727,7 +1726,7 @@ msgstr "Esta operación no puede realizarse sin un nodo seleccionado." #: editor/editor_node.cpp msgid "Current scene not saved. Open anyway?" -msgstr "La escena actual no se ha guardado. ¿Quieres abrirla de todos modos?" +msgstr "Escena actual no guardada ¿Abrir de todos modos?" #: editor/editor_node.cpp msgid "Can't reload a scene that was never saved." @@ -2320,7 +2319,7 @@ msgstr "Abrir Editor anterior" #: editor/editor_plugin.cpp msgid "Creating Mesh Previews" -msgstr "Creando vistas previas de las mallas" +msgstr "Creación de Vistas Previas de Malla" #: editor/editor_plugin.cpp msgid "Thumbnail..." @@ -2851,7 +2850,7 @@ msgstr "Generando \"Lightmaps\"" #: editor/import/resource_importer_scene.cpp msgid "Generating for Mesh: " -msgstr "Generando para modelo: " +msgstr "Generando para Malla: " #: editor/import/resource_importer_scene.cpp msgid "Running Custom Script..." @@ -3122,7 +3121,7 @@ msgstr "Posterior" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Depth" -msgstr "Profundidad" +msgstr "Depth" #: editor/plugins/animation_player_editor_plugin.cpp msgid "1 step" @@ -3996,7 +3995,7 @@ msgstr "Clic derecho: Borrar punto." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh is empty!" -msgstr "¡La malla está vacía!" +msgstr "¡La Malla está vacía!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Static Trimesh Body" @@ -4020,11 +4019,11 @@ msgstr "Crear forma convexa" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Navigation Mesh" -msgstr "Crear malla de navegación" +msgstr "Crear Malla de Navegación" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Contained Mesh is not of type ArrayMesh." -msgstr "La malla que contiene no es del tipo ArrayMesh." +msgstr "La Malla contenedora no es del tipo ArrayMesh." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "UV Unwrap failed, mesh may not be manifold?" @@ -4042,7 +4041,7 @@ msgstr "El modelo no tiene UV en esta capa" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "MeshInstance lacks a Mesh!" -msgstr "¡MeshInstance no tiene malla!" +msgstr "¡MeshInstance no tiene Malla!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh has not surface to create outlines from!" @@ -4050,7 +4049,7 @@ msgstr "¡La malla no tiene superficie de la que crear contornos!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh primitive type is not PRIMITIVE_TRIANGLES!" -msgstr "El tipo de la malla primitiva no es PRIMITIVE_TRIANGLES!" +msgstr "¡El tipo primitivo de malla no es PRIMITIVE_TRIANGLES!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Could not create outline!" @@ -4098,7 +4097,7 @@ msgstr "Desenvuelva UV2 para Lightmap/AO" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Outline Mesh" -msgstr "Crear contorno de malla" +msgstr "Crear Contorno de Malla" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Outline Size:" @@ -4107,12 +4106,14 @@ msgstr "Tamaño del contorno:" #: editor/plugins/multimesh_editor_plugin.cpp msgid "No mesh source specified (and no MultiMesh set in node)." msgstr "" -"No se especificó malla de origen (y no hay MultiMesh establecido en el nodo)." +"No se ha especificado ninguna malla de origen (y no hay MultiMesh " +"establecido en el nodo)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "No mesh source specified (and MultiMesh contains no Mesh)." msgstr "" -"No se especificó malla de origen (y MultiMesh no contiene ningún Mesh)." +"No se ha especificado ninguna malla de origen (y MultiMesh no contiene " +"ninguna Mesh)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Mesh source is invalid (invalid path)." @@ -4120,11 +4121,11 @@ msgstr "El origen de la malla es inválido (ruta inválida)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Mesh source is invalid (not a MeshInstance)." -msgstr "La malla elegida no es correcta (no es un MeshInstance)." +msgstr "El origen de la malla es inválido (no es un MeshInstance)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Mesh source is invalid (contains no Mesh resource)." -msgstr "La malla elegida no es correcta (no contiene ningún recurso Mesh)." +msgstr "El origen de la malla es inválido (no contiene ningún recurso Mesh)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "No surface source specified." @@ -4152,7 +4153,7 @@ msgstr "No se pudo mapear el área." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Select a Source Mesh:" -msgstr "Elige un origen de malla:" +msgstr "Elige un origen de Malla:" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Select a Target Surface:" @@ -4172,7 +4173,7 @@ msgstr "Superficie objetivo:" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Source Mesh:" -msgstr "Modelo 3D elegido:" +msgstr "Malla de origen:" #: editor/plugins/multimesh_editor_plugin.cpp msgid "X-Axis" @@ -4212,11 +4213,11 @@ msgstr "¡Calcular!" #: editor/plugins/navigation_mesh_editor_plugin.cpp msgid "Bake the navigation mesh." -msgstr "Pre-calcular la malla de navegación 3D." +msgstr "Pre-calcular la malla de navegación." #: editor/plugins/navigation_mesh_editor_plugin.cpp msgid "Clear the navigation mesh." -msgstr "Vaciar malla de navegación 3D." +msgstr "Vaciar malla de navegación." #: editor/plugins/navigation_mesh_generator.cpp msgid "Setting up Configuration..." @@ -4501,7 +4502,7 @@ msgstr "Crear mapa UV" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Transform UV Map" -msgstr "Transformar mapa UV" +msgstr "Transformar Mapa UV" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Polygon 2D UV Editor" @@ -5416,11 +5417,11 @@ msgstr "Activar Vista Libre" #: editor/plugins/spatial_editor_plugin.cpp msgid "Transform" -msgstr "Transform" +msgstr "Transformar" #: editor/plugins/spatial_editor_plugin.cpp msgid "Transform Dialog..." -msgstr "Ventana de transformación..." +msgstr "Dialogo de Transformación..." #: editor/plugins/spatial_editor_plugin.cpp msgid "1 Viewport" @@ -5497,7 +5498,7 @@ msgstr "Profundidad máxima de vista:" #: editor/plugins/spatial_editor_plugin.cpp msgid "Transform Change" -msgstr "Transformar" +msgstr "Cambio de Transformación" #: editor/plugins/spatial_editor_plugin.cpp msgid "Translate:" @@ -6644,7 +6645,7 @@ msgstr "Reemparentar ubicación (selecciona un nuevo padre):" #: editor/reparent_dialog.cpp msgid "Keep Global Transform" -msgstr "Mantener transformación global" +msgstr "Mantener Transformación Global" #: editor/reparent_dialog.cpp editor/scene_tree_dock.cpp msgid "Reparent" @@ -7498,6 +7499,11 @@ msgstr "Compilar Proyecto" msgid "Warnings" msgstr "Advertencias" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Ver Archivos" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "Fin del reporte de la pila de excepciones" diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po index 64ee2404f1..bea184b813 100644 --- a/editor/translations/es_AR.po +++ b/editor/translations/es_AR.po @@ -7464,6 +7464,11 @@ msgstr "Construir Proyecto" msgid "Warnings" msgstr "Advertencias" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Ver Archivos" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "Fin del stack trace de excepción interna" diff --git a/editor/translations/fa.po b/editor/translations/fa.po index f674ef99cc..eb192ececb 100644 --- a/editor/translations/fa.po +++ b/editor/translations/fa.po @@ -2,26 +2,25 @@ # Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. # Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) # This file is distributed under the same license as the Godot source code. -# # alabd14313 <alabd14313@yahoo.com>, 2016. # Dante Marshal <Marshal.Devilhunter@gmail.com>, 2018. # hamed nasib <cghamed752@chmail.ir>, 2016. # Hasan Hejdari Nasab <hsn6@openmailbox.org>, 2017. # rezapouya <r.pouya@chmail.ir>, 2016. # sayyed hamed nasib <cghamed752@chmail.ir>, 2017. -# +# Behrooz Kashani <bkashani@gmail.com>, 2018. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-04-29 05:39+0000\n" -"Last-Translator: Dante Marshal <Marshal.Devilhunter@gmail.com>\n" +"PO-Revision-Date: 2018-07-24 19:42+0000\n" +"Last-Translator: Behrooz Kashani <bkashani@gmail.com>\n" "Language-Team: Persian <https://hosted.weblate.org/projects/godot-engine/" "godot/fa/>\n" "Language: fa\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 3.0-dev\n" +"X-Generator: Weblate 3.1-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -636,9 +635,8 @@ msgstr "" "آیا در هر صورت حذف شوند؟(بدون برگشت)" #: editor/dependency_editor.cpp -#, fuzzy msgid "Cannot remove:" -msgstr "ناتوانی در حذف :" +msgstr "امکان حذف وجود ندارد :" #: editor/dependency_editor.cpp msgid "Error loading:" @@ -743,9 +741,8 @@ msgid "Gold Sponsors" msgstr "اسپانسرهای درجه ۲" #: editor/editor_about.cpp -#, fuzzy msgid "Mini Sponsors" -msgstr "اسپانسرهای دیگر" +msgstr "اسپانسرهای کوچک" #: editor/editor_about.cpp msgid "Gold Donors" @@ -789,7 +786,7 @@ msgstr "اجزا" #: editor/editor_about.cpp msgid "Licenses" -msgstr "" +msgstr "گواهینامه" #: editor/editor_asset_installer.cpp editor/project_manager.cpp msgid "Error opening package file, not in zip format." @@ -7420,6 +7417,11 @@ msgstr "پروژه" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "نمایش پرونده ها" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/fi.po b/editor/translations/fi.po index f80efffd42..11f9bb51c7 100644 --- a/editor/translations/fi.po +++ b/editor/translations/fi.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-06-14 20:37+0000\n" +"PO-Revision-Date: 2018-07-19 10:36+0000\n" "Last-Translator: Tapani Niemi <tapani.niemi@kapsi.fi>\n" "Language-Team: Finnish <https://hosted.weblate.org/projects/godot-engine/" "godot/fi/>\n" @@ -20,7 +20,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 3.0.1\n" +"X-Generator: Weblate 3.1-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -2128,7 +2128,7 @@ msgstr "Käynnistä muokattavana oleva skene." #: editor/editor_node.cpp msgid "Play Scene" -msgstr "Toista skene" +msgstr "Pelaa skeneä" #: editor/editor_node.cpp msgid "Play custom scene" @@ -2414,7 +2414,7 @@ msgstr "Lataa uudelleen" #: editor/export_template_manager.cpp msgid "Uninstall" -msgstr "Poista" +msgstr "Poista asennus" #: editor/export_template_manager.cpp msgid "(Installed)" @@ -2475,7 +2475,7 @@ msgstr "" #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Can't resolve." -msgstr "Yhdistäminen epäonnistui." +msgstr "Yhdeydenselvitys epäonnistui." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp @@ -2520,11 +2520,11 @@ msgstr "Yhteys katkaistu" #: editor/export_template_manager.cpp msgid "Resolving" -msgstr "Selvitetään" +msgstr "Selvitetään yhteyttä" #: editor/export_template_manager.cpp msgid "Can't Resolve" -msgstr "Yhdistäminen epäonnistui" +msgstr "Yhteyden selvittäminen epäonnistui" #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp @@ -2809,7 +2809,7 @@ msgstr "Luodaan meshille: " #: editor/import/resource_importer_scene.cpp msgid "Running Custom Script..." -msgstr "Suorita valitsemasi skripti..." +msgstr "Suoritetaan mukautettua skriptiä..." #: editor/import/resource_importer_scene.cpp msgid "Couldn't load post-import script:" @@ -2940,7 +2940,7 @@ msgstr "VIRHE: Virheellinen animaation nimi!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "ERROR: Animation name already exists!" -msgstr "VIrhe: Samanniminen animaatio on jo olemassa!" +msgstr "VIRHE: Samanniminen animaatio on jo olemassa!" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -3316,7 +3316,8 @@ msgstr "Pyyntö epäonnistui, liikaa uudelleenohjauksia" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Bad download hash, assuming file has been tampered with." -msgstr "Latauksessa väärä hash, oletetaan että tiedostoa on näpelöity." +msgstr "" +"Latauksessa väärä hajautuskoodi, oletetaan että tiedostoa on näpelöity." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Expected:" @@ -3328,7 +3329,7 @@ msgstr "Saatiin:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Failed sha256 hash check" -msgstr "sha256 hash-tarkistus epäonnistui" +msgstr "sha256-hajautusarvon tarkistus epäonnistui" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Asset Download Error:" @@ -3442,7 +3443,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Failed creating lightmap images, make sure path is writable." msgstr "" -"Lightmap-kuvien luonti epäonnistui, varmista, että polku on " +"Lightmap-kuvien luonti epäonnistui. Varmista, että polku on " "kirjoituskelpoinen." #: editor/plugins/baked_lightmap_editor_plugin.cpp @@ -5301,11 +5302,11 @@ msgstr "Tarttumisen tila (%s)" #: editor/plugins/spatial_editor_plugin.cpp msgid "Bottom View" -msgstr "Pohjanäkymä" +msgstr "Alanäkymä" #: editor/plugins/spatial_editor_plugin.cpp msgid "Top View" -msgstr "Huippunäkymä" +msgstr "Ylänäkymä" #: editor/plugins/spatial_editor_plugin.cpp msgid "Rear View" @@ -7110,7 +7111,7 @@ msgstr "Aseta puusta" #: editor/settings_config_dialog.cpp msgid "Shortcuts" -msgstr "Pikakuvakkeet" +msgstr "Pikanäppäimet" #: editor/settings_config_dialog.cpp msgid "Binding" @@ -7435,6 +7436,11 @@ msgstr "Käännä projekti" msgid "Warnings" msgstr "Varoitukset" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Näytä tiedostot" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "Sisemmän poikkeuksen kutsupinon loppu" diff --git a/editor/translations/fr.po b/editor/translations/fr.po index ee1d7b2cad..5c28d84a90 100644 --- a/editor/translations/fr.po +++ b/editor/translations/fr.po @@ -40,12 +40,14 @@ # Tommy Melançon-Roy <tommel1234@hotmail.com>, 2017-2018. # Willow <theotimefd@aol.com>, 2018. # Xananax <xananax@yelostudio.com>, 2017-2018. +# Perrier Mathis <mathis.perrier73@gmail.com>, 2018. +# Ewan Lehnebach <ewan.lehnebach@gmail.com>, 2018. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-06-12 16:38+0000\n" -"Last-Translator: Philippe Gervaise <blah@malvese.org>\n" +"PO-Revision-Date: 2018-07-21 12:37+0000\n" +"Last-Translator: Perrier Mathis <mathis.perrier73@gmail.com>\n" "Language-Team: French <https://hosted.weblate.org/projects/godot-engine/" "godot/fr/>\n" "Language: fr\n" @@ -53,7 +55,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 3.0.1\n" +"X-Generator: Weblate 3.1-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -65,11 +67,11 @@ msgstr "Toute la sélection" #: editor/animation_editor.cpp msgid "Anim Change Keyframe Time" -msgstr "Changer l'heure de l'animation des images clés" +msgstr "Animation Changer l'heure de l'image clé" #: editor/animation_editor.cpp msgid "Anim Change Transition" -msgstr "Transition du changement d'animation" +msgstr "Animation Changer la transition" #: editor/animation_editor.cpp msgid "Anim Change Transform" @@ -77,7 +79,7 @@ msgstr "Animation Changer la transformation" #: editor/animation_editor.cpp msgid "Anim Change Keyframe Value" -msgstr "Changer la valeur de l'animation des images clés" +msgstr "Animation Changer la valeur de l'image clé" #: editor/animation_editor.cpp msgid "Anim Change Call" @@ -4076,7 +4078,7 @@ msgstr "Créer le contour" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh" -msgstr "Maillage" +msgstr "Maillages" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Trimesh Static Body" @@ -6512,7 +6514,7 @@ msgstr "Remaps par langue :" #: editor/project_settings_editor.cpp msgid "Locale" -msgstr "Langue" +msgstr "Localisation" #: editor/project_settings_editor.cpp msgid "Locales Filter" @@ -7513,6 +7515,11 @@ msgstr "Compiler le projet" msgid "Warnings" msgstr "Avertissements" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Voir Fichiers" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "Fin de la trace d'appel (stack trace) intrinsèque" diff --git a/editor/translations/he.po b/editor/translations/he.po index 0f1881211f..6dfd0ab3a5 100644 --- a/editor/translations/he.po +++ b/editor/translations/he.po @@ -7294,6 +7294,10 @@ msgstr "" msgid "Warnings" msgstr "אזהרות" +#: modules/mono/editor/mono_bottom_panel.cpp +msgid "View log" +msgstr "" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/hi.po b/editor/translations/hi.po index 3340f13471..606da1d118 100644 --- a/editor/translations/hi.po +++ b/editor/translations/hi.po @@ -7327,6 +7327,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +msgid "View log" +msgstr "" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/hu.po b/editor/translations/hu.po index b04dd073df..84c64138dc 100644 --- a/editor/translations/hu.po +++ b/editor/translations/hu.po @@ -7405,6 +7405,11 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Fájlok Megtekintése" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/id.po b/editor/translations/id.po index 3956378ce7..a0356b8178 100644 --- a/editor/translations/id.po +++ b/editor/translations/id.po @@ -10,7 +10,7 @@ # Fajar Ru <kzofajar@gmail.com>, 2018. # Khairul Hidayat <khairulcyber4rt@gmail.com>, 2016. # Reza Hidayat Bayu Prabowo <rh.bayu.prabowo@gmail.com>, 2018. -# Romi Kusuma Bakti <romikusumab@gmail.com>, 2017. +# Romi Kusuma Bakti <romikusumab@gmail.com>, 2017, 2018. # Sofyan Sugianto <sofyanartem@gmail.com>, 2017-2018. # Tito <ijavadroid@gmail.com>, 2018. # Tom My <tom.asadinawan@gmail.com>, 2017. @@ -18,8 +18,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-06-22 08:30+0000\n" -"Last-Translator: Fajar Ru <kzofajar@gmail.com>\n" +"PO-Revision-Date: 2018-07-15 12:38+0000\n" +"Last-Translator: Romi Kusuma Bakti <romikusumab@gmail.com>\n" "Language-Team: Indonesian <https://hosted.weblate.org/projects/godot-engine/" "godot/id/>\n" "Language: id\n" @@ -917,9 +917,8 @@ msgid "Delete Audio Bus" msgstr "Hapus Bus Audio" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Duplicate Audio Bus" -msgstr "Duplikat Audio Bus" +msgstr "Duplikatkan Bus Audio" #: editor/editor_audio_buses.cpp msgid "Reset Bus Volume" @@ -976,9 +975,8 @@ msgid "Save this Bus Layout to a file." msgstr "Simpan Layout Bus ke berkas." #: editor/editor_audio_buses.cpp editor/import_dock.cpp -#, fuzzy msgid "Load Default" -msgstr "Muat Konfigurasi Bawaan" +msgstr "Muat Default" #: editor/editor_audio_buses.cpp msgid "Load the default Bus Layout." @@ -1294,18 +1292,16 @@ msgid "Members:" msgstr "Member-member:" #: editor/editor_help.cpp -#, fuzzy msgid "Public Methods" -msgstr "Fungsi Publik" +msgstr "Metode Publik" #: editor/editor_help.cpp msgid "Public Methods:" msgstr "Metode Publik:" #: editor/editor_help.cpp -#, fuzzy msgid "GUI Theme Items" -msgstr "Item-item Tema GUI:" +msgstr "Item Tema GUI" #: editor/editor_help.cpp msgid "GUI Theme Items:" @@ -1422,9 +1418,8 @@ msgstr "Simpan Resource Sebagai..." #: editor/editor_node.cpp editor/plugins/spatial_editor_plugin.cpp #: editor/scene_tree_dock.cpp -#, fuzzy msgid "I see..." -msgstr "Aku tahu..." +msgstr "Mengerti..." #: editor/editor_node.cpp msgid "Can't open file for writing:" @@ -1471,9 +1466,8 @@ msgid "Creating Thumbnail" msgstr "Membuat Thumbnail" #: editor/editor_node.cpp -#, fuzzy msgid "This operation can't be done without a tree root." -msgstr "Tindakan ini tidak bisa dilakukan tanpa \"tree root\"" +msgstr "Operasi ini tidak dapat diselesaikan tanpa root pohon." #: editor/editor_node.cpp msgid "" @@ -2712,7 +2706,7 @@ msgstr "Buka Scene" #: editor/filesystem_dock.cpp msgid "Instance" -msgstr "" +msgstr "Instance" #: editor/filesystem_dock.cpp msgid "Edit Dependencies..." @@ -2821,18 +2815,16 @@ msgid "Importing Scene..." msgstr "Mengimpor scene..." #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Generating Lightmaps" -msgstr "Sedang Membuat Pemetaan Cahaya" +msgstr "Membuat Pemetaan Cahaya" #: editor/import/resource_importer_scene.cpp msgid "Generating for Mesh: " msgstr "" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Running Custom Script..." -msgstr "Menjalankan Skrip Buatan..." +msgstr "Menjalankan Script Khusus..." #: editor/import/resource_importer_scene.cpp msgid "Couldn't load post-import script:" @@ -2868,7 +2860,7 @@ msgstr "Impor sebagai:" #: editor/import_dock.cpp editor/property_editor.cpp msgid "Preset..." -msgstr "" +msgstr "Prasetel..." #: editor/import_dock.cpp msgid "Reimport" @@ -7563,6 +7555,11 @@ msgstr "Proyek" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "File:" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/is.po b/editor/translations/is.po index 98a376edca..0d6200fba1 100644 --- a/editor/translations/is.po +++ b/editor/translations/is.po @@ -7301,6 +7301,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +msgid "View log" +msgstr "" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/it.po b/editor/translations/it.po index 2d566fe163..afb8c5cfb8 100644 --- a/editor/translations/it.po +++ b/editor/translations/it.po @@ -2,7 +2,6 @@ # Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. # Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) # This file is distributed under the same license as the Godot source code. -# # Alessio Corridori <alessiocorridori@hotmail.com>, 2018. # Dario Bonfanti <bonfi.96@hotmail.it>, 2016-2017. # Dario D'Ambra <legione0@gmail.com>, 2017. @@ -15,13 +14,13 @@ # RealAquilus <JamesHeller@live.it>, 2017. # Samuele Zolfanelli <samdazel@gmail.com>, 2018. # Sean Bone <seanbone@zumguy.com>, 2017. -# +# Red Pill <redpill902@gmail.com>, 2018. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-05-18 16:39+0000\n" -"Last-Translator: Alessio Corridori <alessiocorridori@hotmail.com>\n" +"PO-Revision-Date: 2018-06-25 18:40+0000\n" +"Last-Translator: Red Pill <redpill902@gmail.com>\n" "Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/" "godot/it/>\n" "Language: it\n" @@ -29,7 +28,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 3.0-dev\n" +"X-Generator: Weblate 3.1-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -40,9 +39,8 @@ msgid "All Selection" msgstr "Seleziona Tutto" #: editor/animation_editor.cpp -#, fuzzy msgid "Anim Change Keyframe Time" -msgstr "Anim Cambia Valore" +msgstr "Anim Cambia Tempo di Keyframe" #: editor/animation_editor.cpp msgid "Anim Change Transition" @@ -7640,6 +7638,11 @@ msgstr "Progetto" msgid "Warnings" msgstr "Avvertimento" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Vedi Files" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/ja.po b/editor/translations/ja.po index 5ce73d0442..d7e2c07ac2 100644 --- a/editor/translations/ja.po +++ b/editor/translations/ja.po @@ -8251,6 +8251,11 @@ msgstr "プロジェクト" msgid "Warnings" msgstr "警告" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "ビューファイル:" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/ko.po b/editor/translations/ko.po index be6b540a9a..197a11efa2 100644 --- a/editor/translations/ko.po +++ b/editor/translations/ko.po @@ -14,8 +14,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-06-07 16:40+0000\n" -"Last-Translator: pgyage3263 <pgyage3263@naver.com>\n" +"PO-Revision-Date: 2018-07-21 04:38+0000\n" +"Last-Translator: 송태섭 <xotjq237@gmail.com>\n" "Language-Team: Korean <https://hosted.weblate.org/projects/godot-engine/" "godot/ko/>\n" "Language: ko\n" @@ -23,7 +23,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 3.0\n" +"X-Generator: Weblate 3.1-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -4003,7 +4003,7 @@ msgstr "외곽선 만들기" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh" -msgstr "메시" +msgstr "Mesh" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Trimesh Static Body" @@ -7412,6 +7412,11 @@ msgstr "프로젝트 빌드" msgid "Warnings" msgstr "경고" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "파일 보기" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "내부 예외 스택 추적의 끝" diff --git a/editor/translations/lt.po b/editor/translations/lt.po index bf4443627a..639e086d4c 100644 --- a/editor/translations/lt.po +++ b/editor/translations/lt.po @@ -7295,6 +7295,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +msgid "View log" +msgstr "" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/ms.po b/editor/translations/ms.po index 19d8b6b7d8..09c7b39e08 100644 --- a/editor/translations/ms.po +++ b/editor/translations/ms.po @@ -2,22 +2,21 @@ # Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. # Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) # This file is distributed under the same license as the Godot source code. -# # Sam Vanguard <syafz119@gmail.com>, 2018. # Shaqir Rafiq <moshamoradev@gmail.com>, 2018. -# +# Syaz Amirin <amirin123z@gmail.com>, 2018. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-06-05 19:27+0000\n" -"Last-Translator: Shaqir Rafiq <moshamoradev@gmail.com>\n" +"PO-Revision-Date: 2018-06-30 09:40+0000\n" +"Last-Translator: Syaz Amirin <amirin123z@gmail.com>\n" "Language-Team: Malay <https://hosted.weblate.org/projects/godot-engine/godot/" "ms/>\n" "Language: ms\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 3.0\n" +"X-Generator: Weblate 3.1-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -2014,11 +2013,11 @@ msgstr "" #: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp msgid "Community" -msgstr "" +msgstr "Komuniti" #: editor/editor_node.cpp msgid "About" -msgstr "" +msgstr "Tentang" #: editor/editor_node.cpp msgid "Play the project." @@ -6244,7 +6243,7 @@ msgstr "" #: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp msgid "General" -msgstr "" +msgstr "Am" #: editor/project_settings_editor.cpp editor/property_editor.cpp msgid "Property:" @@ -7273,6 +7272,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +msgid "View log" +msgstr "" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/nb.po b/editor/translations/nb.po index e76053150c..abc026771d 100644 --- a/editor/translations/nb.po +++ b/editor/translations/nb.po @@ -14,8 +14,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-06-22 08:31+0000\n" -"Last-Translator: Frank T. Rambol <frank@d-fect.com>\n" +"PO-Revision-Date: 2018-06-28 14:40+0000\n" +"Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n" "Language-Team: Norwegian Bokmål <https://hosted.weblate.org/projects/godot-" "engine/godot/nb/>\n" "Language: nb\n" @@ -1756,7 +1756,9 @@ msgstr "Velg en HovedScene" #: editor/editor_node.cpp #, fuzzy msgid "Unable to enable addon plugin at: '%s' parsing of config failed." -msgstr "Kan ikke aktivere addon-plugin på: '%s' parsing av konfig feilet." +msgstr "" +"Kan ikke aktivere tilleggs-programtillegg på: \"%s\" tolking av oppsett " +"mislyktes." #: editor/editor_node.cpp msgid "Unable to find script field for addon plugin at: 'res://addons/%s'." @@ -1912,9 +1914,8 @@ msgid "MeshLibrary..." msgstr "MeshBibliotek..." #: editor/editor_node.cpp -#, fuzzy msgid "TileSet..." -msgstr "TileSet…" +msgstr "Flissett…" #: editor/editor_node.cpp editor/plugins/script_text_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp @@ -7495,6 +7496,11 @@ msgstr "Prosjekt" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Vis Filer" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/nl.po b/editor/translations/nl.po index bfedf322b3..240d99182f 100644 --- a/editor/translations/nl.po +++ b/editor/translations/nl.po @@ -2,7 +2,6 @@ # Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. # Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) # This file is distributed under the same license as the Godot source code. -# # aelspire <aelspire@gmail.com>, 2017. # Aram Nap <xyphex.aram@gmail.com>, 2017. # Arjan219 <arjannugteren1@gmail.com>, 2017-2018. @@ -24,19 +23,19 @@ # Willem <studiebolmail@gmail.com>, 2018. # Wout Standaert <wout@blobkat.com>, 2017. # Zatherz <zatherz@linux.pl>, 2017. -# +# Tahar Meijs <tntmeijs@gmail.com>, 2018. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-05-21 18:36+0000\n" -"Last-Translator: Johannes Smit <smitjohannes96@gmail.com>\n" +"PO-Revision-Date: 2018-06-30 15:36+0000\n" +"Last-Translator: Tahar Meijs <tntmeijs@gmail.com>\n" "Language-Team: Dutch <https://hosted.weblate.org/projects/godot-engine/godot/" "nl/>\n" "Language: nl\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 3.0-dev\n" +"X-Generator: Weblate 3.1-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -6427,7 +6426,7 @@ msgstr "" #: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp msgid "General" -msgstr "" +msgstr "Algemeen" #: editor/project_settings_editor.cpp editor/property_editor.cpp msgid "Property:" @@ -7492,6 +7491,11 @@ msgstr "Project" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Bekijk Bestanden" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/pl.po b/editor/translations/pl.po index 5ca2760249..a133a4d8d5 100644 --- a/editor/translations/pl.po +++ b/editor/translations/pl.po @@ -27,7 +27,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-06-22 08:31+0000\n" +"PO-Revision-Date: 2018-07-14 08:42+0000\n" "Last-Translator: RM <synaptykq@gmail.com>\n" "Language-Team: Polish <https://hosted.weblate.org/projects/godot-engine/" "godot/pl/>\n" @@ -1975,7 +1975,7 @@ msgstr "Wyjdź do Listy Projektów" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp msgid "Debug" -msgstr "Debuguj" +msgstr "Debugowanie" #: editor/editor_node.cpp msgid "Deploy with Remote Debug" @@ -3093,7 +3093,7 @@ msgstr "Poprzednie" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Future" -msgstr "Następne" +msgstr "Przyszłość" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Depth" @@ -3154,7 +3154,7 @@ msgstr "Czas Przejścia Między Animacjami" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Animation" -msgstr "Animacja" +msgstr "Animacje" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "New name:" @@ -6514,7 +6514,7 @@ msgstr "Mapowanie w zależności od lokalizacji:" #: editor/project_settings_editor.cpp msgid "Locale" -msgstr "Lokalizacja" +msgstr "Języki" #: editor/project_settings_editor.cpp msgid "Locales Filter" @@ -7137,7 +7137,7 @@ msgstr "Monitor" #: editor/script_editor_debugger.cpp msgid "Value" -msgstr "Wartość" +msgstr "Value" #: editor/script_editor_debugger.cpp msgid "Monitors" @@ -7525,6 +7525,11 @@ msgstr "Zbuduj projekt" msgid "Warnings" msgstr "Ostrzeżenia" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Pokaż pliki" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" @@ -7672,11 +7677,11 @@ msgstr "Dodaj węzeł(y) z drzewa" #: modules/visual_script/visual_script_editor.cpp msgid "Add Getter Property" -msgstr "" +msgstr "Dodaj właściwość Gettera" #: modules/visual_script/visual_script_editor.cpp msgid "Add Setter Property" -msgstr "" +msgstr "Dodaj właściwość Settera" #: modules/visual_script/visual_script_editor.cpp msgid "Change Base Type" @@ -7712,7 +7717,7 @@ msgstr "Iterator" #: modules/visual_script/visual_script_editor.cpp msgid "While" -msgstr "" +msgstr "While" #: modules/visual_script/visual_script_editor.cpp msgid "Return" @@ -8045,7 +8050,7 @@ msgstr "" #: scene/3d/arvr_nodes.cpp msgid "ARVRCamera must have an ARVROrigin node as its parent" -msgstr "ARVRCamera musi dziedziczyć po ARVROrigin node" +msgstr "ARVRCamera musi dziedziczyć po węźle ARVROrigin" #: scene/3d/arvr_nodes.cpp #, fuzzy @@ -8073,11 +8078,11 @@ msgstr "" #: scene/3d/arvr_nodes.cpp msgid "ARVROrigin requires an ARVRCamera child node" -msgstr "ARVROrigin wymaga by ARVRCamera dziedziczyła po node" +msgstr "ARVROrigin wymaga dziedziczącego po nim ARVRCamera" #: scene/3d/baked_lightmap.cpp msgid "%d%%" -msgstr "" +msgstr "%d%%" #: scene/3d/baked_lightmap.cpp msgid "(Time Left: %d:%02d s)" @@ -8106,6 +8111,10 @@ msgid "" "Consider adding CollisionShape or CollisionPolygon children nodes to define " "its shape." msgstr "" +"Ten węzeł nie posiada podwezła, który definiowałby jego kształt, więc nie " +"może wchodzić w interakcje z przestrzenią.\n" +"Powinieneś dodać węzeł \"CollisionShape2D\" lub \"CollisionPolygon2D\" jako " +"jego podwęzeł aby zdefiniować jego kształt." #: scene/3d/collision_polygon.cpp msgid "" diff --git a/editor/translations/pr.po b/editor/translations/pr.po index 0c085024e0..ee30748cee 100644 --- a/editor/translations/pr.po +++ b/editor/translations/pr.po @@ -7350,6 +7350,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +msgid "View log" +msgstr "" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po index 6d26cbc500..472fb1e7bc 100644 --- a/editor/translations/pt_BR.po +++ b/editor/translations/pt_BR.po @@ -23,12 +23,13 @@ # Renato Rotenberg <renato.rotenberg@gmail.com>, 2017. # Rodolfo R Gomes <rodolforg@gmail.com>, 2017-2018. # Tiago Almeida <thyagoeap@gmail.com>, 2017. +# Mauricio Luan Carneiro deSouza <newmailmlcs@gmail.com>, 2018. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: 2016-05-30\n" -"PO-Revision-Date: 2018-06-16 18:43+0000\n" -"Last-Translator: Rodolfo R Gomes <rodolforg@gmail.com>\n" +"PO-Revision-Date: 2018-07-26 09:14+0000\n" +"Last-Translator: Mauricio Luan Carneiro deSouza <newmailmlcs@gmail.com>\n" "Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/" "godot-engine/godot/pt_BR/>\n" "Language: pt_BR\n" @@ -36,7 +37,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 3.0.1\n" +"X-Generator: Weblate 3.1-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -4036,7 +4037,7 @@ msgstr "Criar Contorno" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh" -msgstr "Mesh" +msgstr "Malha" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Trimesh Static Body" @@ -5100,7 +5101,7 @@ msgstr "Transformação do Eixo-Z." #: editor/plugins/spatial_editor_plugin.cpp msgid "View Plane Transform." -msgstr "Visualizar Transformação do Plano." +msgstr "Transformação do Plano de Visão." #: editor/plugins/spatial_editor_plugin.cpp msgid "Scaling: " @@ -5236,7 +5237,7 @@ msgstr "Visualizar Gizmos" #: editor/plugins/spatial_editor_plugin.cpp msgid "View Information" -msgstr "VIsualizar Informação" +msgstr "Visualizar Informações" #: editor/plugins/spatial_editor_plugin.cpp msgid "View FPS" @@ -7049,7 +7050,7 @@ msgstr "Processo Filho Conectado" #: editor/script_editor_debugger.cpp msgid "Copy Error" -msgstr "Erro ao Copiar" +msgstr "Copiar Erro" #: editor/script_editor_debugger.cpp msgid "Inspect Previous Instance" @@ -7463,6 +7464,11 @@ msgstr "Compilar Projeto" msgid "Warnings" msgstr "Avisos" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Ver Arquivos" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "Fim da pilha de rastreamento de exceção interna" diff --git a/editor/translations/pt_PT.po b/editor/translations/pt_PT.po index 71275cd19a..d111d1dd4b 100644 --- a/editor/translations/pt_PT.po +++ b/editor/translations/pt_PT.po @@ -7442,6 +7442,11 @@ msgstr "Construir Projeto" msgid "Warnings" msgstr "Avisos" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Ver Ficheiros" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "Fim do stack trace de exceção interna" diff --git a/editor/translations/ro.po b/editor/translations/ro.po index eaf931092a..c5a4e35903 100644 --- a/editor/translations/ro.po +++ b/editor/translations/ro.po @@ -7400,6 +7400,11 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Vizualizează Fișierele" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/ru.po b/editor/translations/ru.po index 97c7284404..1c888d3330 100644 --- a/editor/translations/ru.po +++ b/editor/translations/ru.po @@ -17,12 +17,15 @@ # Sergey <maligin.serega2010@yandex.ru>, 2018. # Sergey Agarkov <zorgsoft@gmail.com>, 2017. # teriva <spirin.cos@yandex.ru>, 2018. +# Aleksey Terentyev <terentjew.alexey@ya.ru>, 2018. +# Игорь Д <protorian.di@gmail.com>, 2018. +# Егор Бураков <fend.q@mail.ru>, 2018. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-06-18 19:42+0000\n" -"Last-Translator: ijet <my-ijet@mail.ru>\n" +"PO-Revision-Date: 2018-07-22 04:43+0000\n" +"Last-Translator: Егор Бураков <fend.q@mail.ru>\n" "Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/" "godot/ru/>\n" "Language: ru\n" @@ -31,7 +34,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 3.0.1\n" +"X-Generator: Weblate 3.1-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -2347,7 +2350,7 @@ msgstr "Кадр %" #: editor/editor_profiler.cpp msgid "Physics Frame %" -msgstr "Физический шаг %" +msgstr "Кадр физики %" #: editor/editor_profiler.cpp editor/script_editor_debugger.cpp msgid "Time:" @@ -2359,7 +2362,7 @@ msgstr "Включительно" #: editor/editor_profiler.cpp msgid "Self" -msgstr "" +msgstr "Субъект" #: editor/editor_profiler.cpp msgid "Frame #:" @@ -4029,7 +4032,7 @@ msgstr "Создать контур" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh" -msgstr "Полисетка" +msgstr "Массив" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Trimesh Static Body" @@ -5561,7 +5564,7 @@ msgstr "Предпросмотр StyleBox:" #: editor/plugins/style_box_editor_plugin.cpp msgid "StyleBox" -msgstr "" +msgstr "StyleBox" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Set Region Rect" @@ -5684,14 +5687,12 @@ msgid "Checked Item" msgstr "Отмеченный элемент" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Radio Item" -msgstr "Добавить элемент" +msgstr "Переключатель" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Checked Radio Item" -msgstr "Отмеченный элемент" +msgstr "Отмеченный переключатель" #: editor/plugins/theme_editor_plugin.cpp msgid "Has" @@ -7233,7 +7234,7 @@ msgstr "Библиотеки: " #: modules/gdnative/register_types.cpp msgid "GDNative" -msgstr "" +msgstr "GDNative" #: modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -7450,6 +7451,11 @@ msgstr "Собрать проект" msgid "Warnings" msgstr "Предупреждения" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Просмотр Файлов" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "Конец трассировки внутреннего стека исключений" diff --git a/editor/translations/sk.po b/editor/translations/sk.po index 9716dee696..94b6c137d0 100644 --- a/editor/translations/sk.po +++ b/editor/translations/sk.po @@ -7354,6 +7354,11 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Súbor:" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/sl.po b/editor/translations/sl.po index 0fe619654f..66e3c43bee 100644 --- a/editor/translations/sl.po +++ b/editor/translations/sl.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-06-10 08:44+0000\n" +"PO-Revision-Date: 2018-06-27 13:43+0000\n" "Last-Translator: matevž lapajne <sivar.lapajne@gmail.com>\n" "Language-Team: Slovenian <https://hosted.weblate.org/projects/godot-engine/" "godot/sl/>\n" @@ -19,7 +19,7 @@ msgstr "" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" "%100==4 ? 2 : 3;\n" -"X-Generator: Weblate 3.0.1-dev\n" +"X-Generator: Weblate 3.1-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -3340,23 +3340,23 @@ msgstr "Razreševanje..." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Error making request" -msgstr "" +msgstr "Napaka pri izdelavi zahteve" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Idle" -msgstr "" +msgstr "Nedejaven" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Retry" -msgstr "" +msgstr "Ponovi" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Download Error" -msgstr "" +msgstr "Napaka Pri Prenosu" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Download for this asset is already in progress!" -msgstr "" +msgstr "Prenos za ta dodatek je že v teku!" #: editor/plugins/asset_library_editor_plugin.cpp msgid "first" @@ -3382,7 +3382,7 @@ msgstr "Vse" #: editor/plugins/asset_library_editor_plugin.cpp #: editor/project_settings_editor.cpp msgid "Plugins" -msgstr "" +msgstr "Vtičniki" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Sort:" @@ -3390,7 +3390,7 @@ msgstr "Razvrsti:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Reverse" -msgstr "" +msgstr "Obrni" #: editor/plugins/asset_library_editor_plugin.cpp #: editor/project_settings_editor.cpp @@ -3407,15 +3407,15 @@ msgstr "Podpora..." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Official" -msgstr "" +msgstr "Uradno" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Testing" -msgstr "" +msgstr "Preskušanje" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Assets ZIP File" -msgstr "" +msgstr "Dodatki v ZIP Datoteki" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" @@ -3423,6 +3423,9 @@ msgid "" "Save your scene (for images to be saved in the same dir), or pick a save " "path from the BakedLightmap properties." msgstr "" +"Ni mogoče določiti poti shranjevanja slik svetlobnih kart.\n" +"Shrani prizor (za slike, da bodo shranjene v isti mapi), ali izberi pot za " +"shranitev iz lastnosti Zapečene Svetlobne karte." #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" @@ -3435,53 +3438,54 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Failed creating lightmap images, make sure path is writable." msgstr "" +"Napaka pri izdelavi slik, svetlobnih kart. Poskrbite, da je pot zapisljiva." #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Bake Lightmaps" -msgstr "" +msgstr "Zapeči Svetlobne karte" #: editor/plugins/camera_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Preview" -msgstr "" +msgstr "Predogled" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Configure Snap" -msgstr "" +msgstr "Nastavi Zaskok" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Grid Offset:" -msgstr "" +msgstr "Mrežni Zamik:" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Grid Step:" -msgstr "" +msgstr "Mrežni Korak:" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Rotation Offset:" -msgstr "" +msgstr "Rotacijski Odmik:" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Rotation Step:" -msgstr "" +msgstr "Rotacijski Korak:" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Move Pivot" -msgstr "" +msgstr "Premakni Točko" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Move Action" -msgstr "" +msgstr "Premakni Dejanje" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Move vertical guide" -msgstr "" +msgstr "Premakni navpični vodnik" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Create new vertical guide" -msgstr "" +msgstr "Ustvari nov navpični vodnik" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Remove vertical guide" @@ -3489,59 +3493,61 @@ msgstr "Odstranite navpični vodnik" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Move horizontal guide" -msgstr "" +msgstr "Premakni vodoravni vodnik" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Create new horizontal guide" -msgstr "" +msgstr "Ustvari nov vodoravni vodnik" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Remove horizontal guide" -msgstr "Odstrani vodoravno vodilo" +msgstr "Odstrani vodoravni vodnik" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Create new horizontal and vertical guides" -msgstr "" +msgstr "Ustvari nov vodoravni in navpični vodnik" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Edit IK Chain" -msgstr "" +msgstr "Uredi Verigo IK" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Edit CanvasItem" -msgstr "" +msgstr "Uredi Platno Stvari" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" -msgstr "" +msgstr "Samo Sidrišča" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Change Anchors and Margins" -msgstr "" +msgstr "Spremeni Sidrišča in Robove" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Change Anchors" -msgstr "" +msgstr "Spremeni Sidrišča" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Paste Pose" -msgstr "" +msgstr "Prilepi Pozicijo" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Select Mode" -msgstr "Izberite Način" +msgstr "Izberi Način" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Drag: Rotate" -msgstr "Povlecite: Zavrti" +msgstr "Povleci: Vrtenje" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Alt+Drag: Move" -msgstr "" +msgstr "Alt+Drag: Premakni" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving)." msgstr "" +"Pritisni 'v' za Spremembo Točke in 'Shift+v' za Vleko Točke (med " +"premikanjem)." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Alt+RMB: Depth list selection" @@ -3561,16 +3567,16 @@ msgid "" "Show a list of all objects at the position clicked\n" "(same as Alt+RMB in select mode)." msgstr "" -"Ob kliku prikaži seznam vseh objektov na tem mestu.\n" +"Ob kliku prikaži seznam vseh objektov na tem mestu\n" "(isto kot Alt+RMB v načinu izbire)." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Click to change object's rotation pivot." -msgstr "" +msgstr "Klikni, če želiš spremeniti rotacijsko točko objekta." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Pan Mode" -msgstr "" +msgstr "Način Plošče" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Toggles snapping" @@ -3578,66 +3584,66 @@ msgstr "Preklopi pripenjanje" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Snap" -msgstr "" +msgstr "Uporabi Pripenjanje" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snapping options" -msgstr "" +msgstr "Možnosti pripenjanja" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to grid" -msgstr "" +msgstr "Pripni na mrežo" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Rotation Snap" -msgstr "" +msgstr "Uporabi Rotacijsko Pripenjanje" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Configure Snap..." -msgstr "Preoblikuj Zaskok..." +msgstr "Nastavi Pripenjanje..." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap Relative" -msgstr "" +msgstr "Pripni Relativno" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Pixel Snap" -msgstr "" +msgstr "Uporabi Pripenjanje Pikslov" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Smart snapping" -msgstr "" +msgstr "Pametno pripenjanje" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to parent" -msgstr "" +msgstr "Pripni na Predhodnika" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to node anchor" -msgstr "" +msgstr "Pripni na gradnik vodilo" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to node sides" -msgstr "" +msgstr "Pripni na gradnik strani" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to other nodes" -msgstr "" +msgstr "Pripni na druge gradnike" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to guides" -msgstr "" +msgstr "Pripni na vodnike" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Lock the selected object in place (can't be moved)." -msgstr "Izbrani predmet zaklenite na svoje mesto (ga ni mogoče premakniti)." +msgstr "Izbrani predmet zakleni na svoje mesto (ni ga mogoče premakniti)." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Unlock the selected object (can be moved)." -msgstr "Odklenite izbrani predmet (ga lahko premaknete)." +msgstr "Odkleni izbrani predmet (lahko ga premaknete)." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Makes sure the object's children are not selectable." @@ -5945,9 +5951,8 @@ msgid "Imported Project" msgstr "" #: editor/project_manager.cpp -#, fuzzy msgid "Invalid Project Name." -msgstr "Ime Projekta:" +msgstr "Neveljavno Ime Projekta." #: editor/project_manager.cpp msgid "Couldn't create folder." @@ -7374,6 +7379,11 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Ogled datotek" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/sr_Cyrl.po b/editor/translations/sr_Cyrl.po index c838174131..9998a16e3a 100644 --- a/editor/translations/sr_Cyrl.po +++ b/editor/translations/sr_Cyrl.po @@ -7461,6 +7461,11 @@ msgstr "Пројекат" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Погледај датотеке" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/sr_Latn.po b/editor/translations/sr_Latn.po index 975418d4fb..4d293a592d 100644 --- a/editor/translations/sr_Latn.po +++ b/editor/translations/sr_Latn.po @@ -7272,6 +7272,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +msgid "View log" +msgstr "" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/sv.po b/editor/translations/sv.po index 9ec654128a..f9e65bb600 100644 --- a/editor/translations/sv.po +++ b/editor/translations/sv.po @@ -2,24 +2,24 @@ # Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. # Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) # This file is distributed under the same license as the Godot source code. -# # bergmarklund <davemcgroin@gmail.com>, 2017, 2018. # Christoffer Sundbom <christoffer_karlsson@live.se>, 2017. # Jakob Sinclair <sinclair.jakob@mailbox.org>, 2018. # . <grenoscar@gmail.com>, 2018. -# +# Kristoffer Grundström <kristoffer.grundstrom1983@gmail.com>, 2018. +# Magnus Helander <helander@fastmail.net>, 2018. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-05-07 11:42+0000\n" -"Last-Translator: anonymous <>\n" +"PO-Revision-Date: 2018-07-24 12:44+0000\n" +"Last-Translator: Magnus Helander <helander@fastmail.net>\n" "Language-Team: Swedish <https://hosted.weblate.org/projects/godot-engine/" "godot/sv/>\n" "Language: sv\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 3.0-dev\n" +"X-Generator: Weblate 3.1-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -30,9 +30,8 @@ msgid "All Selection" msgstr "Alla urval" #: editor/animation_editor.cpp -#, fuzzy msgid "Anim Change Keyframe Time" -msgstr "Anim Ändra Värde" +msgstr "Anim Ändra Nyckelram Tid" #: editor/animation_editor.cpp msgid "Anim Change Transition" @@ -88,16 +87,15 @@ msgstr "Ändra Anim Spårets Värde Läge" #: editor/animation_editor.cpp msgid "Anim Track Change Wrap Mode" -msgstr "" +msgstr "Anim Spåra Ändra Linda om Läge" #: editor/animation_editor.cpp msgid "Edit Node Curve" msgstr "Redigera Nodkurva" #: editor/animation_editor.cpp -#, fuzzy msgid "Edit Selection Curve" -msgstr "Redigera Urval Kurva" +msgstr "Redigera Urvalsurva" #: editor/animation_editor.cpp msgid "Anim Delete Keys" @@ -7903,6 +7901,11 @@ msgstr "Projekt" msgid "Warnings" msgstr "Varning" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Visa Filer" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/ta.po b/editor/translations/ta.po index d7910c2c87..d3d80facc3 100644 --- a/editor/translations/ta.po +++ b/editor/translations/ta.po @@ -7274,6 +7274,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +msgid "View log" +msgstr "" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/th.po b/editor/translations/th.po index 4db8459f1b..2393ca98a9 100644 --- a/editor/translations/th.po +++ b/editor/translations/th.po @@ -7359,6 +7359,11 @@ msgstr "Build โปรเจกต์" msgid "Warnings" msgstr "คำเตือน" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "ดูไฟล์" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "สิ้นสุดสแตคข้อผิดพลาดภายใน" diff --git a/editor/translations/tr.po b/editor/translations/tr.po index 292cec4063..abe7d485fa 100644 --- a/editor/translations/tr.po +++ b/editor/translations/tr.po @@ -17,18 +17,19 @@ # razah <icnikerazah@gmail.com>, 2017-2018. # stnmycri <satenmeycri@gmail.com>, 2017-2018. # Yavuz Günay <yavuzgunay@gmail.com>, 2017. +# Onur Sanır <onursanir@gmail.com>, 2018. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-06-10 09:46+0000\n" -"Last-Translator: Aykut YILDIRIM <aykutyildirim@windowslive.com>\n" +"PO-Revision-Date: 2018-07-07 20:42+0000\n" +"Last-Translator: Onur Sanır <onursanir@gmail.com>\n" "Language-Team: Turkish <https://hosted.weblate.org/projects/godot-engine/" "godot/tr/>\n" "Language: tr\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 3.0.1-dev\n" +"X-Generator: Weblate 3.1-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -5696,9 +5697,8 @@ msgid "Options" msgstr "Seçenekler" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Has,Many,Options" -msgstr "Bir Çok,Seçenek,Var!" +msgstr "Birçok,Seçenek,Var" #: editor/plugins/theme_editor_plugin.cpp msgid "Tab 1" @@ -7438,6 +7438,11 @@ msgstr "Projeyi İnşa et" msgid "Warnings" msgstr "Uyarılar" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Dosyaları Görüntüle" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "İç özel durum yığını izlemesinin sonu" diff --git a/editor/translations/uk.po b/editor/translations/uk.po index 067c7be724..d940561131 100644 --- a/editor/translations/uk.po +++ b/editor/translations/uk.po @@ -7447,6 +7447,11 @@ msgstr "Зібрати проект" msgid "Warnings" msgstr "Попередження" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "Перегляд файлів" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "Кінець трасування стека для внутрішнього виключення" diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po index 0162eb0788..3857bff9b0 100644 --- a/editor/translations/ur_PK.po +++ b/editor/translations/ur_PK.po @@ -7331,6 +7331,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +msgid "View log" +msgstr "" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/vi.po b/editor/translations/vi.po index 6651bd170c..faf77300b8 100644 --- a/editor/translations/vi.po +++ b/editor/translations/vi.po @@ -2,25 +2,24 @@ # Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. # Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) # This file is distributed under the same license as the Godot source code. -# # 01lifeleft <01lifeleft@gmail.com>, 2018. # Dlean Jeans <dleanjeans@gmail.com>, 2018. # Hai Le <dark.hades.1102@gmail.com>, 2017. # Nguyễn Tuấn Anh <anhnt.fami@gmail.com>, 2017. # Tung Le <tungkradle@gmail.com>, 2017. -# +# 38569459 <xxx38569459@gmail.com>, 2018. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-04-18 15:44+0000\n" -"Last-Translator: 01lifeleft <01lifeleft@gmail.com>\n" +"PO-Revision-Date: 2018-07-22 06:42+0000\n" +"Last-Translator: 38569459 <xxx38569459@gmail.com>\n" "Language-Team: Vietnamese <https://hosted.weblate.org/projects/godot-engine/" "godot/vi/>\n" "Language: vi\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 3.0-dev\n" +"X-Generator: Weblate 3.1-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -141,24 +140,24 @@ msgstr "Chọn Scale" #: editor/animation_editor.cpp msgid "Scale From Cursor" -msgstr "" +msgstr "Scale từ trỏ chuột" #: editor/animation_editor.cpp msgid "Goto Next Step" -msgstr "" +msgstr "Đến Step tiếp theo" #: editor/animation_editor.cpp msgid "Goto Prev Step" -msgstr "" +msgstr "Đến Step trước đó" #: editor/animation_editor.cpp editor/plugins/curve_editor_plugin.cpp #: editor/property_editor.cpp msgid "Linear" -msgstr "" +msgstr "Tuyến" #: editor/animation_editor.cpp editor/plugins/theme_editor_plugin.cpp msgid "Constant" -msgstr "" +msgstr "Cố định" #: editor/animation_editor.cpp msgid "In" @@ -178,11 +177,11 @@ msgstr "Ngoài-Trong" #: editor/animation_editor.cpp msgid "Transitions" -msgstr "" +msgstr "Chuyển tiếp" #: editor/animation_editor.cpp msgid "Optimize Animation" -msgstr "" +msgstr "Tối ưu Animation" #: editor/animation_editor.cpp msgid "Clean-Up Animation" @@ -190,11 +189,11 @@ msgstr "Dọn dẹp Animation" #: editor/animation_editor.cpp msgid "Create NEW track for %s and insert key?" -msgstr "" +msgstr "Tạo track mới cho %s và chèn key?" #: editor/animation_editor.cpp msgid "Create %d NEW tracks and insert keys?" -msgstr "" +msgstr "Tạo %d track mới và chèn key?" #: editor/animation_editor.cpp editor/create_dialog.cpp #: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp @@ -210,15 +209,15 @@ msgstr "Tạo & Chèn Anim" #: editor/animation_editor.cpp msgid "Anim Insert Track & Key" -msgstr "" +msgstr "Chèn Track & Key Anim" #: editor/animation_editor.cpp msgid "Anim Insert Key" -msgstr "" +msgstr "Chèn Key Anim" #: editor/animation_editor.cpp msgid "Change Anim Len" -msgstr "" +msgstr "Đổi độ dài Anim" #: editor/animation_editor.cpp msgid "Change Anim Loop" @@ -226,23 +225,25 @@ msgstr "Đổi vòng lặp Anim" #: editor/animation_editor.cpp msgid "Anim Create Typed Value Key" -msgstr "" +msgstr "Tạo Key để nhập giá trị Anim" #: editor/animation_editor.cpp msgid "Anim Insert" msgstr "Chèn Anim" #: editor/animation_editor.cpp +#, fuzzy msgid "Anim Scale Keys" -msgstr "" +msgstr "Anim Scale Keys" #: editor/animation_editor.cpp msgid "Anim Add Call Track" msgstr "Thêm Track Gọi Function" #: editor/animation_editor.cpp +#, fuzzy msgid "Animation zoom." -msgstr "" +msgstr "Phóng Animation." #: editor/animation_editor.cpp msgid "Length (s):" @@ -266,27 +267,27 @@ msgstr "Mở/Tắt lặp animation." #: editor/animation_editor.cpp msgid "Add new tracks." -msgstr "" +msgstr "Thêm track mới." #: editor/animation_editor.cpp msgid "Move current track up." -msgstr "" +msgstr "Di chuyển track lên." #: editor/animation_editor.cpp msgid "Move current track down." -msgstr "" +msgstr "Di chuyển track xuống." #: editor/animation_editor.cpp msgid "Remove selected track." -msgstr "" +msgstr "Bỏ track đang chọn." #: editor/animation_editor.cpp msgid "Track tools" -msgstr "" +msgstr "Công cụ Track" #: editor/animation_editor.cpp msgid "Enable editing of individual keys by clicking them." -msgstr "" +msgstr "Cho phép chỉnh sửa từng key riêng bằng cách chọn chúng." #: editor/animation_editor.cpp msgid "Anim. Optimizer" @@ -306,162 +307,171 @@ msgstr "" #: editor/animation_editor.cpp msgid "Optimize" -msgstr "" +msgstr "Tối ưu" #: editor/animation_editor.cpp msgid "Select an AnimationPlayer from the Scene Tree to edit animations." msgstr "Chọn một AnimationPlayer từ Scene Tree để chỉnh sửa animation." #: editor/animation_editor.cpp +#, fuzzy msgid "Key" -msgstr "" +msgstr "Mã" #: editor/animation_editor.cpp msgid "Transition" -msgstr "" +msgstr "Chuyển tiếp" #: editor/animation_editor.cpp msgid "Scale Ratio:" -msgstr "" +msgstr "Tỉ lệ Scale:" #: editor/animation_editor.cpp msgid "Call Functions in Which Node?" -msgstr "" +msgstr "Gọi Function từ Node nào?" #: editor/animation_editor.cpp msgid "Remove invalid keys" -msgstr "" +msgstr "Hủy key không đúng chuẩn" #: editor/animation_editor.cpp +#, fuzzy msgid "Remove unresolved and empty tracks" -msgstr "" +msgstr "Gỡ bỏ track trống và không tìm thấy" #: editor/animation_editor.cpp msgid "Clean-up all animations" -msgstr "" +msgstr "Dọn dẹp tất cả animations" #: editor/animation_editor.cpp msgid "Clean-Up Animation(s) (NO UNDO!)" -msgstr "" +msgstr "Dọn dẹp tất cả Animation (KHÔNG THỂ HỒI LẠI)" #: editor/animation_editor.cpp msgid "Clean-Up" -msgstr "" +msgstr "Dọn dẹp" #: editor/array_property_edit.cpp msgid "Resize Array" -msgstr "" +msgstr "Đổi lại size Array" #: editor/array_property_edit.cpp msgid "Change Array Value Type" -msgstr "" +msgstr "Đổi loại giá trị Array" #: editor/array_property_edit.cpp msgid "Change Array Value" -msgstr "" +msgstr "Đổi giá trị Array" #: editor/code_editor.cpp msgid "Go to Line" -msgstr "" +msgstr "Đến Dòng" #: editor/code_editor.cpp msgid "Line Number:" -msgstr "" +msgstr "Dòng số:" #: editor/code_editor.cpp msgid "No Matches" -msgstr "" +msgstr "Không tìm thấy" #: editor/code_editor.cpp msgid "Replaced %d occurrence(s)." msgstr "" #: editor/code_editor.cpp +#, fuzzy msgid "Match Case" -msgstr "" +msgstr "Trùng khớp" #: editor/code_editor.cpp msgid "Whole Words" -msgstr "" +msgstr "Cả từ" #: editor/code_editor.cpp msgid "Replace" -msgstr "" +msgstr "Thay thế" #: editor/code_editor.cpp msgid "Replace All" -msgstr "" +msgstr "Thay thế tất cả" #: editor/code_editor.cpp msgid "Selection Only" -msgstr "" +msgstr "Chỉ lựa chọn" #: editor/code_editor.cpp msgid "Zoom In" -msgstr "" +msgstr "Phóng to" #: editor/code_editor.cpp msgid "Zoom Out" -msgstr "" +msgstr "Thu nhỏ" #: editor/code_editor.cpp msgid "Reset Zoom" -msgstr "" +msgstr "Đặt lại phóng" #: editor/code_editor.cpp editor/script_editor_debugger.cpp msgid "Line:" -msgstr "" +msgstr "Dòng:" #: editor/code_editor.cpp +#, fuzzy msgid "Col:" -msgstr "" +msgstr "Col:" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" -msgstr "" +msgstr "Cách thức trong Node được chọn phải được ghi rõ!" #: editor/connections_dialog.cpp msgid "" "Target method not found! Specify a valid method or attach a script to target " "Node." msgstr "" +"Cách thức của đối tượng không tìm thấy! ghi rõ một cách thức hợp lệ hoặc " +"đính kèm một script cho đối tượng Node." #: editor/connections_dialog.cpp msgid "Connect To Node:" -msgstr "" +msgstr "Kết nối đến Node:" #: editor/connections_dialog.cpp editor/editor_autoload_settings.cpp #: editor/groups_editor.cpp editor/plugins/item_list_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp msgid "Add" -msgstr "" +msgstr "Thêm" #: editor/connections_dialog.cpp editor/dependency_editor.cpp #: editor/plugins/animation_tree_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp editor/project_manager.cpp #: editor/project_settings_editor.cpp msgid "Remove" -msgstr "" +msgstr "Xóa" #: editor/connections_dialog.cpp +#, fuzzy msgid "Add Extra Call Argument:" -msgstr "" +msgstr "Thêm đối số:" #: editor/connections_dialog.cpp msgid "Extra Call Arguments:" msgstr "" #: editor/connections_dialog.cpp +#, fuzzy msgid "Path to Node:" -msgstr "" +msgstr "Đường đến Node:" #: editor/connections_dialog.cpp msgid "Make Function" -msgstr "" +msgstr "Tạo Function" #: editor/connections_dialog.cpp +#, fuzzy msgid "Deferred" -msgstr "" +msgstr "Hoãn lại" #: editor/connections_dialog.cpp msgid "Oneshot" @@ -479,45 +489,45 @@ msgstr "" #: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Close" -msgstr "" +msgstr "Tắt" #: editor/connections_dialog.cpp msgid "Connect" -msgstr "" +msgstr "Kết nối" #: editor/connections_dialog.cpp msgid "Connect '%s' to '%s'" -msgstr "" +msgstr "Kết nối '%s' đến '%s'" #: editor/connections_dialog.cpp msgid "Connecting Signal:" -msgstr "" +msgstr "Đang kết nối Signal:" #: editor/connections_dialog.cpp msgid "Disconnect '%s' from '%s'" -msgstr "" +msgstr "Hủy kết nối '%s' từ '%s'" #: editor/connections_dialog.cpp msgid "Connect..." -msgstr "" +msgstr "Kết nối..." #: editor/connections_dialog.cpp #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Disconnect" -msgstr "" +msgstr "Hủy kết nối" #: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp msgid "Signals" -msgstr "" +msgstr "Tín hiệu" #: editor/create_dialog.cpp msgid "Change %s Type" -msgstr "" +msgstr "Đổi %s Type" #: editor/create_dialog.cpp editor/project_settings_editor.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Change" -msgstr "" +msgstr "Đổi" #: editor/create_dialog.cpp msgid "Create New %s" @@ -526,38 +536,39 @@ msgstr "Tạo %s Mới" #: editor/create_dialog.cpp editor/editor_file_dialog.cpp #: editor/filesystem_dock.cpp msgid "Favorites:" -msgstr "" +msgstr "Ưa thích:" #: editor/create_dialog.cpp editor/editor_file_dialog.cpp msgid "Recent:" -msgstr "" +msgstr "Gần đây:" #: editor/create_dialog.cpp editor/editor_node.cpp #: editor/plugins/asset_library_editor_plugin.cpp #: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/quick_open.cpp msgid "Search:" -msgstr "" +msgstr "Tìm kiếm:" #: editor/create_dialog.cpp editor/editor_help.cpp #: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp #: editor/quick_open.cpp msgid "Matches:" -msgstr "" +msgstr "Phù hợp:" #: editor/create_dialog.cpp editor/editor_help.cpp #: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp #: editor/script_editor_debugger.cpp msgid "Description:" -msgstr "" +msgstr "Mô tả:" #: editor/dependency_editor.cpp msgid "Search Replacement For:" -msgstr "" +msgstr "Tìm kiếm thay thế cho:" #: editor/dependency_editor.cpp +#, fuzzy msgid "Dependencies For:" -msgstr "" +msgstr "Phần phụ thuộc cho:" #: editor/dependency_editor.cpp msgid "" @@ -2017,12 +2028,14 @@ msgid "Issue Tracker" msgstr "" #: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp +#, fuzzy msgid "Community" -msgstr "" +msgstr "Cộng đồng" #: editor/editor_node.cpp +#, fuzzy msgid "About" -msgstr "" +msgstr "Thông tin" #: editor/editor_node.cpp msgid "Play the project." @@ -4223,7 +4236,7 @@ msgstr "" #: editor/plugins/particles_editor_plugin.cpp msgid "Volume" -msgstr "" +msgstr "Âm lượng" #: editor/plugins/particles_editor_plugin.cpp msgid "Emission Source: " @@ -4265,7 +4278,7 @@ msgstr "" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp msgid "Select Points" -msgstr "" +msgstr "Chọn Points" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp @@ -4275,12 +4288,12 @@ msgstr "" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp msgid "Click: Add Point" -msgstr "" +msgstr "Nhấp: Tạo Point" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp msgid "Right Click: Delete Point" -msgstr "" +msgstr "Nhấp chuột phải: Xóa Point" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Select Control Points (Shift+Drag)" @@ -4299,7 +4312,7 @@ msgstr "" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp msgid "Delete Point" -msgstr "" +msgstr "Xóa Point" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp @@ -4562,27 +4575,27 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp msgid "Save Theme" -msgstr "" +msgstr "Lưu Theme" #: editor/plugins/script_editor_plugin.cpp msgid "Save Theme As" -msgstr "" +msgstr "Lưu Theme thành" #: editor/plugins/script_editor_plugin.cpp msgid "Close Docs" -msgstr "" +msgstr "Đóng Docs" #: editor/plugins/script_editor_plugin.cpp msgid "Close All" -msgstr "" +msgstr "Đóng tất cả" #: editor/plugins/script_editor_plugin.cpp msgid "Close Other Tabs" -msgstr "" +msgstr "Đóng tất cả Tab" #: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp msgid "Run" -msgstr "" +msgstr "Chạy" #: editor/plugins/script_editor_plugin.cpp msgid "Toggle Scripts Panel" @@ -4591,12 +4604,12 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp msgid "Find..." -msgstr "" +msgstr "Tìm..." #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp msgid "Find Next" -msgstr "" +msgstr "Tìm tiếp theo" #: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp msgid "Step Over" @@ -4613,7 +4626,7 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp #: editor/script_editor_debugger.cpp msgid "Continue" -msgstr "" +msgstr "Tiếp tục" #: editor/plugins/script_editor_plugin.cpp msgid "Keep Debugger Open" @@ -4645,11 +4658,11 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp msgid "Discard" -msgstr "" +msgstr "Hủy" #: editor/plugins/script_editor_plugin.cpp msgid "Create Script" -msgstr "" +msgstr "Tạo Script" #: editor/plugins/script_editor_plugin.cpp msgid "" @@ -4680,7 +4693,7 @@ msgstr "" #: editor/plugins/script_text_editor.cpp msgid "Pick Color" -msgstr "" +msgstr "Chọn màu" #: editor/plugins/script_text_editor.cpp msgid "Convert Case" @@ -4701,13 +4714,13 @@ msgstr "" #: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp #: scene/gui/text_edit.cpp msgid "Cut" -msgstr "" +msgstr "Cắt" #: editor/plugins/script_text_editor.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Copy" -msgstr "" +msgstr "Copy" #: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp #: scene/gui/text_edit.cpp @@ -6252,8 +6265,9 @@ msgid "Project Settings (project.godot)" msgstr "" #: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp +#, fuzzy msgid "General" -msgstr "" +msgstr "Tổng quan" #: editor/project_settings_editor.cpp editor/property_editor.cpp msgid "Property:" @@ -7283,6 +7297,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +msgid "View log" +msgstr "" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po index 48e30ceab3..51e0181fc8 100644 --- a/editor/translations/zh_CN.po +++ b/editor/translations/zh_CN.po @@ -7372,6 +7372,11 @@ msgstr "构建项目" msgid "Warnings" msgstr "警告" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "查看文件" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "内部异常堆栈追朔结束" diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po index 568390a7a8..de03512af1 100644 --- a/editor/translations/zh_HK.po +++ b/editor/translations/zh_HK.po @@ -7589,6 +7589,11 @@ msgstr "專案" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "檔案" + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po index 38b565a37f..df0c474322 100644 --- a/editor/translations/zh_TW.po +++ b/editor/translations/zh_TW.po @@ -2,7 +2,6 @@ # Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. # Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) # This file is distributed under the same license as the Godot source code. -# # Allen H <w84miracle@gmail.com>, 2017. # Billy SU <g4691821@gmail.com>, 2018. # Chao Yu <casd82@gmail.com>, 2017. @@ -12,19 +11,18 @@ # popcade <popcade@gmail.com>, 2016. # Qing <icinriiq@gmail.com>, 2018. # Sam Pan <sampan66@gmail.com>, 2016. -# msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-04-24 09:35+0000\n" -"Last-Translator: Qing <icinriiq@gmail.com>\n" +"PO-Revision-Date: 2018-07-15 16:35+0000\n" +"Last-Translator: Kisaragi Hiu <mail@kisaragi-hiu.com>\n" "Language-Team: Chinese (Traditional) <https://hosted.weblate.org/projects/" "godot-engine/godot/zh_Hant/>\n" "Language: zh_TW\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 3.0-dev\n" +"X-Generator: Weblate 3.1-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -35,9 +33,8 @@ msgid "All Selection" msgstr "所有的選擇" #: editor/animation_editor.cpp -#, fuzzy msgid "Anim Change Keyframe Time" -msgstr "動畫更改座標" +msgstr "動畫更改關鍵幀時間" #: editor/animation_editor.cpp msgid "Anim Change Transition" @@ -52,9 +49,8 @@ msgid "Anim Change Keyframe Value" msgstr "動畫更改關鍵幀數值" #: editor/animation_editor.cpp -#, fuzzy msgid "Anim Change Call" -msgstr "動畫改變呼叫" +msgstr "動畫更改呼叫" #: editor/animation_editor.cpp msgid "Anim Add Track" @@ -345,7 +341,7 @@ msgstr "移除無效按鍵" #: editor/animation_editor.cpp msgid "Remove unresolved and empty tracks" -msgstr "" +msgstr "刪除未解決或是空的軌道" #: editor/animation_editor.cpp msgid "Clean-up all animations" @@ -523,9 +519,8 @@ msgid "Signals" msgstr "信號" #: editor/create_dialog.cpp -#, fuzzy msgid "Change %s Type" -msgstr "變更鏡頭尺寸" +msgstr "變更 %s 尺寸" #: editor/create_dialog.cpp editor/project_settings_editor.cpp #: modules/visual_script/visual_script_editor.cpp @@ -533,9 +528,8 @@ msgid "Change" msgstr "更換" #: editor/create_dialog.cpp -#, fuzzy msgid "Create New %s" -msgstr "新增" +msgstr "新增 %s" #: editor/create_dialog.cpp editor/editor_file_dialog.cpp #: editor/filesystem_dock.cpp @@ -618,7 +612,7 @@ msgstr "相依性編輯器" #: editor/dependency_editor.cpp msgid "Search Replacement Resource:" -msgstr "" +msgstr "搜尋替代資源:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help.cpp editor/editor_node.cpp editor/filesystem_dock.cpp @@ -670,7 +664,7 @@ msgstr "修復相依性" #: editor/dependency_editor.cpp msgid "Errors loading!" -msgstr "" +msgstr "載入錯誤!" #: editor/dependency_editor.cpp msgid "Permanently delete %d item(s)? (No undo!)" @@ -682,7 +676,7 @@ msgstr "擁有" #: editor/dependency_editor.cpp msgid "Resources Without Explicit Ownership:" -msgstr "" +msgstr "沒有明定擁有者的資源:" #: editor/dependency_editor.cpp editor/editor_node.cpp msgid "Orphan Resource Explorer" @@ -701,16 +695,19 @@ msgid "Delete" msgstr "刪除" #: editor/dictionary_property_edit.cpp +#, fuzzy msgid "Change Dictionary Key" -msgstr "" +msgstr "改變字典 key" #: editor/dictionary_property_edit.cpp +#, fuzzy msgid "Change Dictionary Value" -msgstr "" +msgstr "改變字典 value" #: editor/editor_about.cpp +#, fuzzy msgid "Thanks from the Godot community!" -msgstr "" +msgstr "Godot 社群感謝你!" #: editor/editor_about.cpp msgid "Thanks!" @@ -718,7 +715,7 @@ msgstr "謝謝!" #: editor/editor_about.cpp msgid "Godot Engine contributors" -msgstr "" +msgstr "Godot Engine 貢獻者" #: editor/editor_about.cpp msgid "Project Founders" @@ -726,12 +723,11 @@ msgstr "專案創始人" #: editor/editor_about.cpp msgid "Lead Developer" -msgstr "" +msgstr "主開發者" #: editor/editor_about.cpp -#, fuzzy msgid "Project Manager " -msgstr "專案創始人" +msgstr "專案管理人 " #: editor/editor_about.cpp msgid "Developers" @@ -739,35 +735,38 @@ msgstr "開發者" #: editor/editor_about.cpp msgid "Authors" -msgstr "" +msgstr "作者" #: editor/editor_about.cpp msgid "Platinum Sponsors" -msgstr "" +msgstr "白金贊助" #: editor/editor_about.cpp msgid "Gold Sponsors" -msgstr "" +msgstr "黃金贊助" #: editor/editor_about.cpp +#, fuzzy msgid "Mini Sponsors" -msgstr "" +msgstr "迷你贊助" #: editor/editor_about.cpp msgid "Gold Donors" -msgstr "" +msgstr "黃金捐贈者" #: editor/editor_about.cpp +#, fuzzy msgid "Silver Donors" -msgstr "" +msgstr "白銀捐贈者" #: editor/editor_about.cpp +#, fuzzy msgid "Bronze Donors" -msgstr "" +msgstr "紅銅捐贈者" #: editor/editor_about.cpp msgid "Donors" -msgstr "" +msgstr "捐贈者" #: editor/editor_about.cpp msgid "License" @@ -775,7 +774,7 @@ msgstr "授權" #: editor/editor_about.cpp msgid "Thirdparty License" -msgstr "" +msgstr "第三方授權條款" #: editor/editor_about.cpp msgid "" @@ -784,14 +783,16 @@ msgid "" "is an exhaustive list of all such thirdparty components with their " "respective copyright statements and license terms." msgstr "" +"Godot Engine 依賴著許多與 MIT 授權條款相容、自由開源的第三方函式庫。以下是這" +"些第三方元件的完整列表,附有它們各自的著作權宣示與授權條款。" #: editor/editor_about.cpp msgid "All Components" -msgstr "" +msgstr "所有元件" #: editor/editor_about.cpp msgid "Components" -msgstr "" +msgstr "元件" #: editor/editor_about.cpp msgid "Licenses" @@ -799,21 +800,20 @@ msgstr "授權" #: editor/editor_asset_installer.cpp editor/project_manager.cpp msgid "Error opening package file, not in zip format." -msgstr "" +msgstr "開啟套件檔案出錯,非 zip 格式。" #: editor/editor_asset_installer.cpp -#, fuzzy msgid "Uncompressing Assets" -msgstr "(重新)載入素材" +msgstr "正在解壓縮素材" #: editor/editor_asset_installer.cpp editor/project_manager.cpp msgid "Package Installed Successfully!" -msgstr "" +msgstr "套件安裝成功!" #: editor/editor_asset_installer.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Success!" -msgstr "" +msgstr "成功!" #: editor/editor_asset_installer.cpp #: editor/plugins/asset_library_editor_plugin.cpp @@ -821,147 +821,148 @@ msgid "Install" msgstr "安裝" #: editor/editor_asset_installer.cpp +#, fuzzy msgid "Package Installer" -msgstr "" +msgstr "套件安裝" #: editor/editor_audio_buses.cpp msgid "Speakers" -msgstr "" +msgstr "喇叭" #: editor/editor_audio_buses.cpp msgid "Add Effect" -msgstr "" +msgstr "新增效果" #: editor/editor_audio_buses.cpp msgid "Rename Audio Bus" -msgstr "" +msgstr "重新命名 Audio Bus" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Change Audio Bus Volume" -msgstr "重設縮放大小" +msgstr "變更 Audio Bus 音量" #: editor/editor_audio_buses.cpp +#, fuzzy msgid "Toggle Audio Bus Solo" -msgstr "" +msgstr "切換 Audio Bus 的 Solo" #: editor/editor_audio_buses.cpp +#, fuzzy msgid "Toggle Audio Bus Mute" -msgstr "" +msgstr "切換 Audio Bus 的 Mute" #: editor/editor_audio_buses.cpp +#, fuzzy msgid "Toggle Audio Bus Bypass Effects" -msgstr "" +msgstr "切換 Audio Bus 忽略效果" #: editor/editor_audio_buses.cpp msgid "Select Audio Bus Send" -msgstr "" +msgstr "選擇 Audio Bus 輸出地點" #: editor/editor_audio_buses.cpp msgid "Add Audio Bus Effect" -msgstr "" +msgstr "新增 Audio Bus 效果" #: editor/editor_audio_buses.cpp msgid "Move Bus Effect" -msgstr "" +msgstr "移動 Bus 效果" #: editor/editor_audio_buses.cpp msgid "Delete Bus Effect" -msgstr "" +msgstr "刪除 Bus 效果" #: editor/editor_audio_buses.cpp msgid "Audio Bus, Drag and Drop to rearrange." -msgstr "" +msgstr "Audio Bus。拖放以重新排列。" #: editor/editor_audio_buses.cpp +#, fuzzy msgid "Solo" -msgstr "" +msgstr "Solo" #: editor/editor_audio_buses.cpp msgid "Mute" msgstr "靜音" #: editor/editor_audio_buses.cpp +#, fuzzy msgid "Bypass" -msgstr "" +msgstr "忽略效果 (Bypass)" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Bus options" -msgstr "除錯選項" +msgstr "Bus 選項" #: editor/editor_audio_buses.cpp editor/filesystem_dock.cpp #: editor/plugins/tile_map_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "Duplicate" -msgstr "" +msgstr "製作複本" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Reset Volume" -msgstr "重設縮放大小" +msgstr "重設音量" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Delete Effect" -msgstr "刪除" +msgstr "刪除效果" #: editor/editor_audio_buses.cpp msgid "Audio" -msgstr "" +msgstr "聲音" #: editor/editor_audio_buses.cpp msgid "Add Audio Bus" -msgstr "" +msgstr "新增 Audio Bus" #: editor/editor_audio_buses.cpp msgid "Master bus can't be deleted!" -msgstr "" +msgstr "Master Bus 不能被刪除!" #: editor/editor_audio_buses.cpp msgid "Delete Audio Bus" -msgstr "" +msgstr "刪除 Audio Bus" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Duplicate Audio Bus" -msgstr "複製所選" +msgstr "製作 Audio Bus 的複本" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Reset Bus Volume" -msgstr "重設縮放大小" +msgstr "重設 Bus 音量" #: editor/editor_audio_buses.cpp msgid "Move Audio Bus" -msgstr "" +msgstr "移動 Audio Bus" #: editor/editor_audio_buses.cpp msgid "Save Audio Bus Layout As..." -msgstr "" +msgstr "另存 Audio Bus 配置為..." #: editor/editor_audio_buses.cpp +#, fuzzy msgid "Location for New Layout..." -msgstr "" +msgstr "新配置的位置..." #: editor/editor_audio_buses.cpp msgid "Open Audio Bus Layout" -msgstr "" +msgstr "開啟 Audio Bus 配置" #: editor/editor_audio_buses.cpp msgid "There is no 'res://default_bus_layout.tres' file." -msgstr "" +msgstr "「res://default_bus_layout.tres」檔案不存在。" #: editor/editor_audio_buses.cpp msgid "Invalid file, not an audio bus layout." -msgstr "" +msgstr "檔案格式不正確,不是 Audio Bus 配置檔。" #: editor/editor_audio_buses.cpp msgid "Add Bus" -msgstr "" +msgstr "新增 Bus" #: editor/editor_audio_buses.cpp msgid "Create a new Bus Layout." -msgstr "" +msgstr "建立新的 Bus 配置。" #: editor/editor_audio_buses.cpp editor/property_editor.cpp #: editor/script_create_dialog.cpp @@ -970,7 +971,7 @@ msgstr "載入" #: editor/editor_audio_buses.cpp msgid "Load an existing Bus Layout." -msgstr "" +msgstr "讀取現存的 Bus 配置。" #: editor/editor_audio_buses.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -979,7 +980,7 @@ msgstr "另存新檔" #: editor/editor_audio_buses.cpp msgid "Save this Bus Layout to a file." -msgstr "" +msgstr "儲存目前的 Bus 配置到檔案裡。" #: editor/editor_audio_buses.cpp editor/import_dock.cpp msgid "Load Default" @@ -987,7 +988,7 @@ msgstr "載入預設值" #: editor/editor_audio_buses.cpp msgid "Load the default Bus Layout." -msgstr "" +msgstr "載入預設的 Bus 配置。" #: editor/editor_autoload_settings.cpp msgid "Invalid name." @@ -999,7 +1000,7 @@ msgstr "合法字元:" #: editor/editor_autoload_settings.cpp msgid "Invalid name. Must not collide with an existing engine class name." -msgstr "" +msgstr "不正確的名字。名字不能與現有的 engine class 名衝突。" #: editor/editor_autoload_settings.cpp msgid "Invalid name. Must not collide with an existing buit-in type name." @@ -1022,16 +1023,19 @@ msgid "Not in resource path." msgstr "在資源路徑中找不到" #: editor/editor_autoload_settings.cpp +#, fuzzy msgid "Add AutoLoad" -msgstr "" +msgstr "新增 AutoLoad" #: editor/editor_autoload_settings.cpp +#, fuzzy msgid "Autoload '%s' already exists!" -msgstr "" +msgstr "Autoload「%s」已經存在!" #: editor/editor_autoload_settings.cpp +#, fuzzy msgid "Rename Autoload" -msgstr "" +msgstr "重新命名 Autoload" #: editor/editor_autoload_settings.cpp msgid "Toggle AutoLoad Globals" @@ -1039,19 +1043,21 @@ msgstr "" #: editor/editor_autoload_settings.cpp msgid "Move Autoload" -msgstr "" +msgstr "移動 Autoload" #: editor/editor_autoload_settings.cpp +#, fuzzy msgid "Remove Autoload" -msgstr "" +msgstr "刪除 Autoload" #: editor/editor_autoload_settings.cpp msgid "Enable" msgstr "啟用" #: editor/editor_autoload_settings.cpp +#, fuzzy msgid "Rearrange Autoloads" -msgstr "" +msgstr "重新排列 Autoload" #: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp #: scene/gui/file_dialog.cpp @@ -1084,16 +1090,18 @@ msgid "Updating scene..." msgstr "更新場景中..." #: editor/editor_data.cpp +#, fuzzy msgid "[empty]" -msgstr "" +msgstr "(空)" #: editor/editor_data.cpp msgid "[unsaved]" -msgstr "" +msgstr "(未儲存)" #: editor/editor_dir_dialog.cpp +#, fuzzy msgid "Please select a base directory first" -msgstr "" +msgstr "請先選擇一個基底的資料夾" #: editor/editor_dir_dialog.cpp msgid "Choose a Directory" @@ -1122,7 +1130,7 @@ msgstr "選擇" #: editor/editor_export.cpp msgid "Storing File:" -msgstr "" +msgstr "儲存檔案:" #: editor/editor_export.cpp msgid "Packing" @@ -1137,22 +1145,20 @@ msgid "File Exists, Overwrite?" msgstr "檔案已經存在, 要覆寫嗎?" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp -#, fuzzy msgid "Select Current Folder" -msgstr "新增資料夾" +msgstr "選擇目前的資料夾" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "Copy Path" -msgstr "" +msgstr "複製路徑" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "Show In File Manager" -msgstr "" +msgstr "在檔案管理員內顯示" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp -#, fuzzy msgid "New Folder..." -msgstr "新增資料夾" +msgstr "新增資料夾..." #: editor/editor_file_dialog.cpp msgid "Refresh" @@ -1160,7 +1166,7 @@ msgstr "重新整理" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "All Recognized" -msgstr "" +msgstr "可認得全部" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "All Files (*)" @@ -1168,7 +1174,7 @@ msgstr "所有類型檔案" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Open a File" -msgstr "" +msgstr "開啟檔案" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Open File(s)" @@ -1190,7 +1196,7 @@ msgstr "儲存" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Save a File" -msgstr "" +msgstr "儲存檔案" #: editor/editor_file_dialog.cpp msgid "Go Back" @@ -1209,12 +1215,13 @@ msgid "Toggle Hidden Files" msgstr "切換顯示隱藏檔案" #: editor/editor_file_dialog.cpp +#, fuzzy msgid "Toggle Favorite" -msgstr "" +msgstr "切換最愛" #: editor/editor_file_dialog.cpp msgid "Toggle Mode" -msgstr "" +msgstr "切換模式" #: editor/editor_file_dialog.cpp msgid "Focus Path" @@ -1247,8 +1254,9 @@ msgid "File:" msgstr "檔案:" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp +#, fuzzy msgid "Must use a valid extension." -msgstr "" +msgstr "必須使用有效的副檔名。" #: editor/editor_file_system.cpp msgid "ScanSources" @@ -1261,27 +1269,28 @@ msgstr "(重新)載入素材" #: editor/editor_help.cpp editor/editor_node.cpp #: editor/plugins/script_editor_plugin.cpp msgid "Search Help" -msgstr "" +msgstr "搜尋幫助" #: editor/editor_help.cpp msgid "Class List:" -msgstr "" +msgstr "Class 列表:" #: editor/editor_help.cpp msgid "Search Classes" -msgstr "" +msgstr "搜尋 Class" #: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp +#, fuzzy msgid "Top" -msgstr "" +msgstr "上面" #: editor/editor_help.cpp editor/property_editor.cpp msgid "Class:" -msgstr "" +msgstr "Class:" #: editor/editor_help.cpp editor/scene_tree_editor.cpp msgid "Inherits:" -msgstr "" +msgstr "繼承:" #: editor/editor_help.cpp msgid "Inherited by:" @@ -1305,19 +1314,19 @@ msgstr "" #: editor/editor_help.cpp msgid "Public Methods:" -msgstr "" +msgstr "公開 method:" #: editor/editor_help.cpp msgid "GUI Theme Items" -msgstr "" +msgstr "介面主題項目" #: editor/editor_help.cpp msgid "GUI Theme Items:" -msgstr "" +msgstr "介面主題項目:" #: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp msgid "Signals:" -msgstr "" +msgstr "訊號:" #: editor/editor_help.cpp msgid "Enumerations" @@ -1333,11 +1342,11 @@ msgstr "" #: editor/editor_help.cpp msgid "Constants" -msgstr "" +msgstr "定數" #: editor/editor_help.cpp msgid "Constants:" -msgstr "" +msgstr "定數:" #: editor/editor_help.cpp msgid "Description" @@ -1345,7 +1354,7 @@ msgstr "描述:" #: editor/editor_help.cpp msgid "Online Tutorials:" -msgstr "" +msgstr "線上教學:" #: editor/editor_help.cpp msgid "" @@ -1353,20 +1362,25 @@ msgid "" "$url]contribute one[/url][/color] or [color=$color][url=$url2]request one[/" "url][/color]." msgstr "" +"目前沒有這個 class 的教學,你可以[color=$color][url=$url]貢獻一個[/url][/" +"color]或[color=$color][url=$url2]要求一個[/url][/color]。" #: editor/editor_help.cpp msgid "Properties" msgstr "" #: editor/editor_help.cpp +#, fuzzy msgid "Property Description:" -msgstr "" +msgstr "Property 說明:" #: editor/editor_help.cpp msgid "" "There is currently no description for this property. Please help us by " "[color=$color][url=$url]contributing one[/url][/color]!" msgstr "" +"目前沒有這個 property 的說明。請幫我們[color=$color][url=$url]貢獻[/url][/" +"color]一個!" #: editor/editor_help.cpp msgid "Methods" @@ -1374,13 +1388,15 @@ msgstr "方法" #: editor/editor_help.cpp msgid "Method Description:" -msgstr "" +msgstr "Method 說明:" #: editor/editor_help.cpp msgid "" "There is currently no description for this method. Please help us by [color=" "$color][url=$url]contributing one[/url][/color]!" msgstr "" +"目前沒有這個 method 的說明。請幫我們[color=$color][url=$url]貢獻[/url][/" +"color]一個!" #: editor/editor_help.cpp msgid "Search Text" @@ -1408,15 +1424,15 @@ msgstr "輸出:" #: editor/editor_node.cpp msgid "Project export failed with error code %d." -msgstr "" +msgstr "專案輸出失敗,錯誤代碼是 %d。" #: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Error saving resource!" -msgstr "" +msgstr "儲存資源錯誤!" #: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Save Resource As..." -msgstr "" +msgstr "另存資源為..." #: editor/editor_node.cpp editor/plugins/spatial_editor_plugin.cpp #: editor/scene_tree_dock.cpp @@ -1424,16 +1440,17 @@ msgid "I see..." msgstr "我知道了" #: editor/editor_node.cpp +#, fuzzy msgid "Can't open file for writing:" -msgstr "" +msgstr "無法以寫入模式開啟檔案:" #: editor/editor_node.cpp msgid "Requested file format unknown:" -msgstr "" +msgstr "要求了不明的檔案格式:" #: editor/editor_node.cpp msgid "Error while saving." -msgstr "" +msgstr "儲存中發生了錯誤。" #: editor/editor_node.cpp msgid "Can't open '%s'." @@ -1445,11 +1462,12 @@ msgstr "分析 \"%s\" 時發生錯誤。" #: editor/editor_node.cpp msgid "Unexpected end of file '%s'." -msgstr "" +msgstr "意料外的檔案結尾 (EOF) '%s'。" #: editor/editor_node.cpp +#, fuzzy msgid "Missing '%s' or its dependencies." -msgstr "" +msgstr "缺失 '%s' 或它的依存。" #: editor/editor_node.cpp msgid "Error while loading '%s'." @@ -1457,7 +1475,7 @@ msgstr "載入 \"%s\" 時發生錯誤。" #: editor/editor_node.cpp msgid "Saving Scene" -msgstr "" +msgstr "正在儲存場景" #: editor/editor_node.cpp msgid "Analyzing" @@ -7424,6 +7442,11 @@ msgstr "專案設定" msgid "Warnings" msgstr "" +#: modules/mono/editor/mono_bottom_panel.cpp +#, fuzzy +msgid "View log" +msgstr "過濾檔案..." + #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" msgstr "" |