summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/SCsub169
-rw-r--r--editor/code_editor.cpp27
-rw-r--r--editor/code_editor.h4
-rw-r--r--editor/create_dialog.cpp26
-rw-r--r--editor/create_dialog.h2
-rw-r--r--editor/doc/doc_data.cpp5
-rw-r--r--editor/editor_about.cpp2
-rw-r--r--editor/editor_builders.py412
-rw-r--r--editor/editor_file_dialog.cpp6
-rw-r--r--editor/editor_file_system.cpp2
-rw-r--r--editor/editor_help.cpp44
-rw-r--r--editor/editor_inspector.cpp78
-rw-r--r--editor/editor_inspector.h3
-rw-r--r--editor/editor_log.cpp32
-rw-r--r--editor/editor_log.h9
-rw-r--r--editor/editor_node.cpp114
-rw-r--r--editor/editor_node.h1
-rw-r--r--editor/editor_plugin.cpp13
-rw-r--r--editor/editor_plugin.h2
-rw-r--r--editor/editor_properties.cpp141
-rw-r--r--editor/editor_properties.h1
-rw-r--r--editor/editor_properties_array_dict.cpp49
-rw-r--r--editor/editor_settings.cpp20
-rw-r--r--editor/editor_spin_slider.cpp31
-rw-r--r--editor/editor_spin_slider.h4
-rw-r--r--editor/editor_themes.cpp11
-rw-r--r--editor/export_template_manager.cpp22
-rw-r--r--editor/export_template_manager.h2
-rw-r--r--editor/filesystem_dock.cpp17
-rw-r--r--editor/groups_editor.cpp6
-rw-r--r--editor/icons/SCsub90
-rw-r--r--editor/icons/editor_icons_builders.py96
-rw-r--r--editor/icons/icon_add_atlas_tile.svg3
-rw-r--r--editor/icons/icon_add_autotile.svg3
-rw-r--r--editor/icons/icon_add_single_tile.svg3
-rw-r--r--editor/icons/icon_information_sign.svg70
-rw-r--r--editor/icons/icon_texture_3_d.svg75
-rw-r--r--editor/icons/icon_texture_array.svg77
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp39
-rw-r--r--editor/import/editor_scene_importer_gltf.h1
-rw-r--r--editor/import/resource_importer_image.cpp79
-rw-r--r--editor/import/resource_importer_image.h27
-rw-r--r--editor/import/resource_importer_layered_texture.cpp274
-rw-r--r--editor/import/resource_importer_layered_texture.h57
-rw-r--r--editor/import/resource_importer_obj.cpp9
-rw-r--r--editor/inspector_dock.cpp5
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp35
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp60
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h2
-rw-r--r--editor/plugins/editor_preview_plugins.cpp95
-rw-r--r--editor/plugins/editor_preview_plugins.h35
-rw-r--r--editor/plugins/particles_editor_plugin.cpp18
-rw-r--r--editor/plugins/path_editor_plugin.cpp93
-rw-r--r--editor/plugins/path_editor_plugin.h18
-rw-r--r--editor/plugins/script_editor_plugin.cpp32
-rw-r--r--editor/plugins/script_text_editor.cpp188
-rw-r--r--editor/plugins/script_text_editor.h6
-rw-r--r--editor/plugins/shader_editor_plugin.cpp11
-rw-r--r--editor/plugins/skeleton_ik_editor_plugin.cpp110
-rw-r--r--editor/plugins/skeleton_ik_editor_plugin.h65
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp453
-rw-r--r--editor/plugins/spatial_editor_plugin.h148
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp28
-rw-r--r--editor/plugins/texture_region_editor_plugin.h5
-rw-r--r--editor/plugins/tile_map_editor_plugin.cpp23
-rw-r--r--editor/plugins/tile_map_editor_plugin.h1
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp1906
-rw-r--r--editor/plugins/tile_set_editor_plugin.h160
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp3
-rw-r--r--editor/project_manager.cpp35
-rw-r--r--editor/project_manager.h6
-rw-r--r--editor/project_settings_editor.cpp22
-rw-r--r--editor/project_settings_editor.h2
-rw-r--r--editor/quick_open.cpp3
-rw-r--r--editor/scene_tree_dock.cpp210
-rw-r--r--editor/scene_tree_dock.h5
-rw-r--r--editor/script_editor_debugger.cpp2
-rw-r--r--editor/settings_config_dialog.cpp34
-rw-r--r--editor/settings_config_dialog.h2
-rw-r--r--editor/spatial_editor_gizmos.cpp3224
-rw-r--r--editor/spatial_editor_gizmos.h497
81 files changed, 5885 insertions, 3815 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/code_editor.cpp b/editor/code_editor.cpp
index 4ce8556add..9d4333bc29 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -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/create_dialog.cpp b/editor/create_dialog.cpp
index 3e0c1f2d53..5dd5b7fcc5 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -86,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")) {
@@ -425,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: {
@@ -543,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() {
@@ -554,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);
}
@@ -566,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() {
@@ -673,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();
}
@@ -688,12 +700,14 @@ 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() {
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 2803762973..91a29f5717 100644
--- a/editor/doc/doc_data.cpp
+++ b/editor/doc/doc_data.cpp
@@ -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);
}
}
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_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_file_dialog.cpp b/editor/editor_file_dialog.cpp
index 7d56c4985a..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();
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 20e8a7915f..4e6f3853c6 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;
}
}
@@ -988,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;
}
@@ -1016,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;
}
@@ -1024,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);
@@ -1186,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;
}
}
@@ -1199,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;
}
@@ -1211,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;
}
@@ -1224,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;
@@ -1578,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;
}
@@ -1632,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;
}
@@ -1663,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;
}
@@ -1752,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:
@@ -1781,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;
}
@@ -1844,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;
}
@@ -1864,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;
}
@@ -1885,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;
}
@@ -2162,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: {
@@ -2776,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;
}
@@ -3844,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());
@@ -3853,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();
+ }
}
}
@@ -4537,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() {
@@ -4638,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);
@@ -4730,8 +4773,10 @@ 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("interface/inspector/resources_types_to_open_in_new_inspector", "SpatialMaterial,Script");
EDITOR_DEF("run/auto_save/save_before_running", true);
theme_base = memnew(Control);
@@ -4908,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));
@@ -4925,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);
@@ -5031,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);
@@ -5076,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");
@@ -5111,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."));
@@ -5135,8 +5189,9 @@ 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();
@@ -5172,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);
@@ -5392,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);
@@ -5554,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 b7224c9393..85aa37ec7e 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -223,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_properties.cpp b/editor/editor_properties.cpp
index 4fae8467b4..59798bfab3 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -46,11 +46,22 @@ EditorPropertyNil::EditorPropertyNil() {
}
///////////////////// TEXT /////////////////////////
+
+void EditorPropertyText::_text_entered(const String &p_string) {
+ if (updating)
+ return;
+
+ if (text->has_focus()) {
+ text->release_focus();
+ _text_changed(p_string);
+ }
+}
+
void EditorPropertyText::_text_changed(const String &p_string) {
if (updating)
return;
- emit_signal("property_changed", get_edited_property(), p_string, true);
+ emit_signal("property_changed", get_edited_property(), p_string);
}
void EditorPropertyText::update_property() {
@@ -64,6 +75,7 @@ void EditorPropertyText::update_property() {
void EditorPropertyText::_bind_methods() {
ClassDB::bind_method(D_METHOD("_text_changed", "txt"), &EditorPropertyText::_text_changed);
+ ClassDB::bind_method(D_METHOD("_text_entered", "txt"), &EditorPropertyText::_text_entered);
}
EditorPropertyText::EditorPropertyText() {
@@ -71,6 +83,8 @@ EditorPropertyText::EditorPropertyText() {
add_child(text);
add_focusable(text);
text->connect("text_changed", this, "_text_changed");
+ text->connect("text_entered", this, "_text_entered");
+
updating = false;
}
@@ -78,12 +92,12 @@ EditorPropertyText::EditorPropertyText() {
void EditorPropertyMultilineText::_big_text_changed() {
text->set_text(big_text->get_text());
- emit_signal("property_changed", get_edited_property(), big_text->get_text(), true);
+ emit_signal("property_changed", get_edited_property(), big_text->get_text());
}
void EditorPropertyMultilineText::_text_changed() {
- emit_signal("property_changed", get_edited_property(), text->get_text(), true);
+ emit_signal("property_changed", get_edited_property(), text->get_text());
}
void EditorPropertyMultilineText::_open_big_text() {
@@ -568,6 +582,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");
@@ -576,8 +591,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();
@@ -681,6 +696,7 @@ void EditorPropertyLayers::setup(LayerType p_layer_type) {
}
Vector<String> names;
+ Vector<String> tooltips;
for (int i = 0; i < 20; i++) {
String name;
@@ -692,12 +708,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() {
@@ -1067,18 +1083,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;
}
@@ -1193,19 +1226,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 /////////////////////////
@@ -1257,18 +1306,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;
}
@@ -1321,19 +1388,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;
}
@@ -2171,7 +2254,7 @@ void EditorPropertyResource::_sub_inspector_object_id_selected(int p_id) {
void EditorPropertyResource::_open_editor_pressed() {
RES res = get_edited_object()->get(get_edited_property());
if (res.is_valid()) {
- EditorNode::get_singleton()->edit_resource(res.ptr());
+ EditorNode::get_singleton()->edit_item(res.ptr());
}
}
diff --git a/editor/editor_properties.h b/editor/editor_properties.h
index ccd73d2539..d5fac9c1a0 100644
--- a/editor/editor_properties.h
+++ b/editor/editor_properties.h
@@ -54,6 +54,7 @@ class EditorPropertyText : public EditorProperty {
bool updating;
void _text_changed(const String &p_string);
+ void _text_entered(const String &p_string);
protected:
static void _bind_methods();
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index 2bd28170e7..8203c85c6a 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -210,8 +210,8 @@ void EditorPropertyArray::update_property() {
default: {}
}
- if (!array.is_array()) {
- edit->set_text(arrtype + "[" + Variant::get_type_name(array.get_type()) + "]");
+ if (array.get_type() == Variant::NIL) {
+ edit->set_text(String("(Nil) ") + arrtype);
edit->set_pressed(false);
if (vbox) {
memdelete(vbox);
@@ -219,7 +219,7 @@ void EditorPropertyArray::update_property() {
return;
}
- edit->set_text(arrtype + "[" + itos(array.call("size")) + "]");
+ edit->set_text(arrtype + "(size " + itos(array.call("size")) + ")");
#ifdef TOOLS_ENABLED
@@ -613,7 +613,13 @@ void EditorPropertyDictionary::_change_type(Object *p_button, int p_index) {
void EditorPropertyDictionary::_add_key_value() {
+ // Do not allow nil as valid key. I experienced errors with this
+ if (object->get_new_item_key().get_type() == Variant::NIL) {
+ return;
+ }
+
Dictionary dict = object->get_dict();
+
dict[object->get_new_item_key()] = object->get_new_item_value();
object->set_new_item_key(Variant());
object->set_new_item_value(Variant());
@@ -663,9 +669,20 @@ void EditorPropertyDictionary::_change_type_menu(int p_index) {
void EditorPropertyDictionary::update_property() {
- Dictionary dict = get_edited_object()->get(get_edited_property());
+ Variant updated_val = get_edited_object()->get(get_edited_property());
+
+ if (updated_val.get_type() == Variant::NIL) {
+ edit->set_text("Dictionary (Nil)"); //This provides symmetry with the array property.
+ edit->set_pressed(false);
+ if (vbox) {
+ memdelete(vbox);
+ }
+ return;
+ }
+
+ Dictionary dict = updated_val;
- edit->set_text("Dict[" + itos(dict.size()) + "]");
+ edit->set_text("Dictionary (size " + itos(dict.size()) + ")");
#ifdef TOOLS_ENABLED
@@ -695,9 +712,9 @@ void EditorPropertyDictionary::update_property() {
page->set_h_size_flags(SIZE_EXPAND_FILL);
page->connect("value_changed", this, "_page_changed");
} else {
- //bye bye children of the box
- while (vbox->get_child_count() > 1) {
- memdelete(vbox->get_child(1));
+ // Queue childs for deletion, delete immediately might cause errors.
+ for (size_t i = 1; i < vbox->get_child_count(); i++) {
+ vbox->get_child(i)->queue_delete();
}
}
@@ -941,10 +958,10 @@ void EditorPropertyDictionary::update_property() {
prop->update_property();
if (i == amount + 1) {
- Button *add_item = memnew(Button);
- add_item->set_text(TTR("Add Key/Value Pair"));
- add_vbox->add_child(add_item);
- add_item->connect("pressed", this, "_add_key_value");
+ Button *butt_add_item = memnew(Button);
+ butt_add_item->set_text(TTR("Add Key/Value Pair"));
+ butt_add_item->connect("pressed", this, "_add_key_value");
+ add_vbox->add_child(butt_add_item);
}
}
@@ -965,8 +982,16 @@ void EditorPropertyDictionary::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
}
}
+
void EditorPropertyDictionary::_edit_pressed() {
+ Variant prop_val = get_edited_object()->get(get_edited_property());
+ if (prop_val.get_type() == Variant::NIL) {
+ Variant::CallError ce;
+ prop_val = Variant::construct(Variant::DICTIONARY, NULL, 0, ce);
+ get_edited_object()->set(get_edited_property(), prop_val);
+ }
+
get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed());
update_property();
}
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 02e121b5f1..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);
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/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/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_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index 7cfaa9070f..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"];
}
@@ -1657,6 +1656,7 @@ 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);
+ print_line("**creating mesh for: " + n->name);
GLTFMesh &mesh = state.meshes.write[n->mesh];
mi->set_mesh(mesh.mesh);
if (mesh.mesh->get_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,10 +1750,8 @@ 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.write[i].godot_bone_index = bone_index;
@@ -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_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/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/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index e98dfceb90..4ed2b051aa 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -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/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index eed6b5a95c..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));
}
}
@@ -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/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/particles_editor_plugin.cpp b/editor/plugins/particles_editor_plugin.cpp
index 1f5a4a8a36..7732103220 100644
--- a/editor/plugins/particles_editor_plugin.cpp
+++ b/editor/plugins/particles_editor_plugin.cpp
@@ -270,6 +270,12 @@ void ParticlesEditor::_menu_option(int p_option) {
switch (p_option) {
case MENU_OPTION_GENERATE_AABB: {
+ float gen_time = node->get_lifetime();
+
+ if (gen_time < 1.0)
+ generate_seconds->set_value(1.0);
+ else
+ generate_seconds->set_value(trunc(gen_time) + 1.0);
generate_aabb->popup_centered_minsize();
} break;
case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH: {
@@ -323,7 +329,15 @@ void ParticlesEditor::_generate_aabb() {
EditorProgress ep("gen_aabb", TTR("Generating AABB"), int(time));
+ bool was_emitting = node->is_emitting();
+ if (!was_emitting) {
+ node->set_emitting(true);
+ OS::get_singleton()->delay_usec(1000);
+ }
+
+ running = 0.0;
AABB rect;
+
while (running < time) {
uint64_t ticks = OS::get_singleton()->get_ticks_usec();
@@ -339,6 +353,10 @@ void ParticlesEditor::_generate_aabb() {
running += (OS::get_singleton()->get_ticks_usec() - ticks) / 1000000.0;
}
+ if (!was_emitting) {
+ node->set_emitting(false);
+ }
+
node->set_visibility_aabb(rect);
}
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 3b82e6578b..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;
}
}
@@ -2402,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);
-
+ }
+ 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_separator();
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);
@@ -2895,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));
@@ -2956,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);
@@ -3005,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");
@@ -3013,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();
@@ -3094,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_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 eab1588a55..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;
@@ -2867,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);
@@ -3099,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;
@@ -3113,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;
@@ -3308,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();
}
@@ -3389,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();
@@ -3397,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();
@@ -3429,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;
@@ -3892,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();
@@ -4048,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) {
@@ -4121,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) {
@@ -4128,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();
@@ -4140,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();
@@ -4214,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) {
@@ -4388,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;
}
}
@@ -4519,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);
@@ -4605,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++) {
@@ -4725,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];
@@ -5005,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);
@@ -5018,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"));
@@ -5084,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;
+ }
}
}
}
@@ -5158,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);
@@ -5363,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);
@@ -5583,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;
@@ -5596,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 bd449a28df..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 {
@@ -233,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;
@@ -489,10 +560,10 @@ 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
};
@@ -500,6 +571,7 @@ private:
Button *tool_option_button[TOOL_OPT_MAX];
MenuButton *transform_menu;
+ PopupMenu *gizmos_menu;
MenuButton *view_menu;
ToolButton *lock_button;
@@ -531,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;
@@ -539,6 +612,7 @@ private:
void _instance_scene();
void _init_indicators();
+ void _init_gizmos_menu();
void _init_grid();
void _finish_indicators();
void _finish_grid();
@@ -558,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;
@@ -598,8 +675,6 @@ 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();
@@ -632,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();
@@ -668,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/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 435ef229c5..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() {
@@ -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);
@@ -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);
@@ -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 9218fed907..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());
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 95d39953cf..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"));
@@ -1782,7 +1777,6 @@ ProjectManager::ProjectManager() {
String cp;
cp += 0xA9;
- cp += '0';
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 2b2e03ce38..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();
}
@@ -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/quick_open.cpp b/editor/quick_open.cpp
index 907bb50f7e..d2101f1e00 100644
--- a/editor/quick_open.cpp
+++ b/editor/quick_open.cpp
@@ -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 d8982c751c..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;
@@ -413,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;
@@ -474,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;
@@ -544,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;
@@ -631,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;
@@ -640,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;
@@ -649,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;
@@ -797,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");
@@ -857,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: {
@@ -905,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: {
@@ -1244,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;
@@ -1252,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;
@@ -1732,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;
@@ -1750,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;
@@ -1762,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;
@@ -1985,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));
@@ -1995,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);
@@ -2136,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));
@@ -2164,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);
@@ -2289,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);
@@ -2325,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");
@@ -2334,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 e483fde4bc..bd661ade53 100644
--- a/editor/script_editor_debugger.cpp
+++ b/editor/script_editor_debugger.cpp
@@ -1198,7 +1198,7 @@ void ScriptEditorDebugger::start() {
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;
}
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 c450c0fd4c..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());
}
@@ -233,7 +263,7 @@ void EditorSpatialGizmo::add_collision_segments(const Vector<Vector3> &p_lines)
}
}
-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);
@@ -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.write[i].create_instance(spatial_node);
+ instances.write[i].create_instance(spatial_node, hidden);
}
transform();
@@ -624,96 +653,21 @@ void EditorSpatialGizmo::free() {
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();
@@ -1138,27 +1138,40 @@ void AudioStreamPlayer3DSpatialGizmo::redraw() {
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));
@@ -1452,7 +1499,9 @@ void SkeletonSpatialGizmo::redraw() {
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);
@@ -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)) {
@@ -2546,8 +3408,8 @@ void CollisionShapeSpatialGizmo::redraw() {
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