summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/SCsub61
-rw-r--r--editor/doc/doc_data.cpp60
-rw-r--r--editor/doc/doc_dump.cpp2
-rw-r--r--editor/editor_export.cpp2
-rw-r--r--editor/editor_file_system.cpp8
-rw-r--r--editor/editor_fonts.cpp15
-rw-r--r--editor/editor_help.cpp26
-rw-r--r--editor/editor_node.cpp141
-rw-r--r--editor/editor_node.h13
-rw-r--r--editor/editor_plugin.cpp4
-rw-r--r--editor/editor_resource_preview.cpp12
-rw-r--r--editor/editor_settings.cpp25
-rw-r--r--editor/editor_settings.h3
-rw-r--r--editor/editor_themes.cpp28
-rw-r--r--editor/editor_themes.h2
-rw-r--r--editor/filesystem_dock.cpp190
-rw-r--r--editor/filesystem_dock.h1
-rw-r--r--editor/icons/icon_GUI_toggle_off.svg6
-rw-r--r--editor/icons/icon_GUI_toggle_on.svg6
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp6
-rw-r--r--editor/import/resource_importer_scene.cpp87
-rw-r--r--editor/import_dock.cpp79
-rw-r--r--editor/import_dock.h2
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.cpp8
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp10
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp29
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h3
-rw-r--r--editor/plugins/editor_preview_plugins.cpp8
-rw-r--r--editor/plugins/material_editor_plugin.cpp38
-rw-r--r--editor/plugins/material_editor_plugin.h8
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp2
-rw-r--r--editor/plugins/script_editor_plugin.cpp325
-rw-r--r--editor/plugins/script_editor_plugin.h14
-rw-r--r--editor/plugins/script_text_editor.cpp12
-rw-r--r--editor/plugins/shader_editor_plugin.cpp399
-rw-r--r--editor/plugins/shader_editor_plugin.h18
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp122
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp1
-rw-r--r--editor/plugins/tile_map_editor_plugin.cpp4
-rw-r--r--editor/project_export.cpp2
-rw-r--r--editor/project_manager.cpp5
-rw-r--r--editor/project_settings_editor.cpp11
-rw-r--r--editor/property_editor.cpp2
-rw-r--r--editor/scene_tree_dock.cpp70
-rw-r--r--editor/scene_tree_dock.h10
-rw-r--r--editor/scene_tree_editor.cpp6
-rw-r--r--editor/script_create_dialog.cpp2
47 files changed, 1338 insertions, 550 deletions
diff --git a/editor/SCsub b/editor/SCsub
index c531d2c7a6..75ec422bd5 100644
--- a/editor/SCsub
+++ b/editor/SCsub
@@ -21,11 +21,11 @@ def make_certs_header(target, source, env):
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")
+ 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(byte_to_str(buf[i]) + ",\n")
+ g.write("\t" + byte_to_str(buf[i]) + ",\n")
g.write("};\n")
g.write("#endif")
@@ -43,7 +43,7 @@ def make_doc_header(target, source, env):
continue
f = open_utf8(src, "r")
content = f.read()
- buf+=content
+ buf += content
buf = encode_utf8(docbegin + buf + docend)
decomp_size = len(buf)
@@ -53,11 +53,11 @@ def make_doc_header(target, source, env):
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")
+ 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(byte_to_str(buf[i]) + ",\n")
+ g.write("\t" + byte_to_str(buf[i]) + ",\n")
g.write("};\n")
g.write("#endif")
@@ -82,10 +82,10 @@ def make_fonts_header(target, source, env):
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")
+ 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(byte_to_str(buf[i]) + ",\n")
+ g.write("\t" + byte_to_str(buf[i]) + ",\n")
g.write("};\n")
@@ -116,11 +116,9 @@ def make_translations_header(target, source, env):
buf = zlib.compress(buf)
name = os.path.splitext(os.path.basename(sorted_paths[i]))[0]
- #g.write("static const int _translation_"+name+"_compressed_size="+str(len(buf))+";\n")
- #g.write("static const int _translation_"+name+"_uncompressed_size="+str(decomp_size)+";\n")
- g.write("static const unsigned char _translation_" + name + "_compressed[]={\n")
+ g.write("static const unsigned char _translation_" + name + "_compressed[] = {\n")
for i in range(len(buf)):
- g.write(byte_to_str(buf[i]) + ",\n")
+ g.write("\t" + byte_to_str(buf[i]) + ",\n")
g.write("};\n")
@@ -132,10 +130,10 @@ def make_translations_header(target, source, env):
g.write("\tint uncomp_size;\n")
g.write("\tconst unsigned char* data;\n")
g.write("};\n\n")
- g.write("static EditorTranslationList _editor_translations[]={\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("\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")
@@ -392,13 +390,13 @@ def make_license_header(target, source, env):
def _make_doc_data_class_path(to_path):
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("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")
- g.write("static const _DocDataClassPath _doc_data_class_paths["+str(len(env.doc_class_path)+1)+"]={\n");
- for c in env.doc_class_path:
- g.write("{\""+c+"\",\""+env.doc_class_path[c]+"\"},\n")
- g.write("{NULL,NULL}\n")
+ g.write("static const _DocDataClassPath _doc_data_class_paths[" + str(len(env.doc_class_path) + 1) + "] = {\n");
+ for c in sorted(env.doc_class_path):
+ g.write("\t{\"" + c + "\", \"" + env.doc_class_path[c] + "\"},\n")
+ g.write("\t{NULL, NULL}\n")
g.write("};\n")
@@ -418,11 +416,22 @@ if env['tools']:
# API documentation
docs = []
- for f in os.listdir(os.path.join(env.Dir('#').abspath, "doc/classes")):
- docs.append("#doc/classes/" + f)
+ doc_dirs = ["doc/classes"]
+
+ for p in env.doc_class_path.values():
+ if p not in doc_dirs:
+ doc_dirs.append(p)
+
+ for d in doc_dirs:
+ try:
+ for f in os.listdir(os.path.join(env.Dir('#').abspath, d)):
+ docs.append("#" + os.path.join(d, f))
+ except OSError:
+ pass
_make_doc_data_class_path(os.path.join(env.Dir('#').abspath, "editor/doc"))
+ docs = sorted(docs)
env.Depends("#editor/doc_data_compressed.gen.h", docs)
env.Command("#editor/doc_data_compressed.gen.h", docs, make_doc_header)
# Certificates
diff --git a/editor/doc/doc_data.cpp b/editor/doc/doc_data.cpp
index 057b2d827d..f7f823c945 100644
--- a/editor/doc/doc_data.cpp
+++ b/editor/doc/doc_data.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "doc_data.h"
+#include "engine.h"
#include "global_constants.h"
#include "io/compression.h"
#include "io/marshalls.h"
@@ -529,7 +530,7 @@ void DocData::generate(bool p_basic_types) {
{
- String cname = "@Global Scope";
+ String cname = "@GlobalScope";
class_list[cname] = ClassDoc();
ClassDoc &c = class_list[cname];
c.name = cname;
@@ -543,14 +544,14 @@ void DocData::generate(bool p_basic_types) {
c.constants.push_back(cd);
}
- List<ProjectSettings::Singleton> singletons;
- ProjectSettings::get_singleton()->get_singletons(&singletons);
+ List<Engine::Singleton> singletons;
+ Engine::get_singleton()->get_singletons(&singletons);
//servers (this is kind of hackish)
- for (List<ProjectSettings::Singleton>::Element *E = singletons.front(); E; E = E->next()) {
+ for (List<Engine::Singleton>::Element *E = singletons.front(); E; E = E->next()) {
PropertyDoc pd;
- ProjectSettings::Singleton &s = E->get();
+ Engine::Singleton &s = E->get();
pd.name = s.name;
pd.type = s.ptr->get_class();
while (String(ClassDB::get_parent_class(pd.type)) != "Object")
@@ -615,11 +616,6 @@ void DocData::generate(bool p_basic_types) {
}
}
-static String _format_description(const String &string) {
-
- return string.dedent().strip_edges().replace("\n", "\n\n");
-}
-
static Error _parse_methods(Ref<XMLParser> &parser, Vector<DocData::MethodDoc> &methods) {
String section = parser->get_node_name();
@@ -666,7 +662,7 @@ static Error _parse_methods(Ref<XMLParser> &parser, Vector<DocData::MethodDoc> &
parser->read();
if (parser->get_node_type() == XMLParser::NODE_TEXT)
- method.description = _format_description(parser->get_node_data());
+ method.description = parser->get_node_data();
}
} else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name() == element)
@@ -781,20 +777,20 @@ Error DocData::_load(Ref<XMLParser> parser) {
parser->read();
if (parser->get_node_type() == XMLParser::NODE_TEXT)
- c.brief_description = _format_description(parser->get_node_data());
+ c.brief_description = parser->get_node_data();
} else if (name == "description") {
parser->read();
if (parser->get_node_type() == XMLParser::NODE_TEXT)
- c.description = _format_description(parser->get_node_data());
+ c.description = parser->get_node_data();
} else if (name == "tutorials") {
parser->read();
if (parser->get_node_type() == XMLParser::NODE_TEXT)
- c.tutorials = parser->get_node_data().strip_edges();
+ c.tutorials = parser->get_node_data();
} else if (name == "demos") {
parser->read();
if (parser->get_node_type() == XMLParser::NODE_TEXT)
- c.demos = parser->get_node_data().strip_edges();
+ c.demos = parser->get_node_data();
} else if (name == "methods") {
Error err = _parse_methods(parser, c.methods);
@@ -828,7 +824,7 @@ Error DocData::_load(Ref<XMLParser> parser) {
prop.enumeration = parser->get_attribute_value("enum");
parser->read();
if (parser->get_node_type() == XMLParser::NODE_TEXT)
- prop.description = _format_description(parser->get_node_data());
+ prop.description = parser->get_node_data();
c.properties.push_back(prop);
} else {
ERR_EXPLAIN("Invalid tag in doc file: " + name);
@@ -857,7 +853,7 @@ Error DocData::_load(Ref<XMLParser> parser) {
prop.type = parser->get_attribute_value("type");
parser->read();
if (parser->get_node_type() == XMLParser::NODE_TEXT)
- prop.description = parser->get_node_data().strip_edges();
+ prop.description = parser->get_node_data();
c.theme_properties.push_back(prop);
} else {
ERR_EXPLAIN("Invalid tag in doc file: " + name);
@@ -888,7 +884,7 @@ Error DocData::_load(Ref<XMLParser> parser) {
}
parser->read();
if (parser->get_node_type() == XMLParser::NODE_TEXT)
- constant.description = parser->get_node_data().strip_edges();
+ constant.description = parser->get_node_data();
c.constants.push_back(constant);
} else {
ERR_EXPLAIN("Invalid tag in doc file: " + name);
@@ -915,6 +911,8 @@ Error DocData::_load(Ref<XMLParser> parser) {
static void _write_string(FileAccess *f, int p_tablevel, const String &p_string) {
+ if (p_string == "")
+ return;
String tab;
for (int i = 0; i < p_tablevel; i++)
tab += "\t";
@@ -953,24 +951,20 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri
if (c.category == "")
category = "Core";
header += " category=\"" + category + "\"";
- header += " version=\"" + String(VERSION_MKSTRING) + "\"";
+ header += String(" version=\"") + _MKSTR(VERSION_MAJOR) + "." + _MKSTR(VERSION_MINOR) + "-" + _MKSTR(VERSION_STATUS) + "\"";
header += ">";
_write_string(f, 0, header);
_write_string(f, 1, "<brief_description>");
- if (c.brief_description != "")
- _write_string(f, 2, c.brief_description.xml_escape());
+ _write_string(f, 2, c.brief_description.strip_edges().xml_escape());
_write_string(f, 1, "</brief_description>");
_write_string(f, 1, "<description>");
- if (c.description != "")
- _write_string(f, 2, c.description.xml_escape());
+ _write_string(f, 2, c.description.strip_edges().xml_escape());
_write_string(f, 1, "</description>");
_write_string(f, 1, "<tutorials>");
- if (c.tutorials != "")
- _write_string(f, 2, c.tutorials.xml_escape());
+ _write_string(f, 2, c.tutorials.strip_edges().xml_escape());
_write_string(f, 1, "</tutorials>");
_write_string(f, 1, "<demos>");
- if (c.demos != "")
- _write_string(f, 2, c.demos.xml_escape());
+ _write_string(f, 2, c.demos.strip_edges().xml_escape());
_write_string(f, 1, "</demos>");
_write_string(f, 1, "<methods>");
@@ -1014,8 +1008,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri
}
_write_string(f, 3, "<description>");
- if (m.description != "")
- _write_string(f, 4, m.description.xml_escape());
+ _write_string(f, 4, m.description.strip_edges().xml_escape());
_write_string(f, 3, "</description>");
_write_string(f, 2, "</method>");
@@ -1036,8 +1029,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri
}
PropertyDoc &p = c.properties[i];
_write_string(f, 2, "<member name=\"" + p.name + "\" type=\"" + p.type + "\" setter=\"" + p.setter + "\" getter=\"" + p.getter + "\"" + enum_text + ">");
- if (p.description != "")
- _write_string(f, 3, p.description.xml_escape());
+ _write_string(f, 3, p.description.strip_edges().xml_escape());
_write_string(f, 2, "</member>");
}
_write_string(f, 1, "</members>");
@@ -1060,8 +1052,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri
}
_write_string(f, 3, "<description>");
- if (m.description != "")
- _write_string(f, 4, m.description.xml_escape());
+ _write_string(f, 4, m.description.strip_edges().xml_escape());
_write_string(f, 3, "</description>");
_write_string(f, 2, "</signal>");
@@ -1080,8 +1071,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri
} else {
_write_string(f, 2, "<constant name=\"" + k.name + "\" value=\"" + k.value + "\" enum=\"" + k.enumeration + "\">");
}
- if (k.description != "")
- _write_string(f, 3, k.description.xml_escape());
+ _write_string(f, 3, k.description.strip_edges().xml_escape());
_write_string(f, 2, "</constant>");
}
diff --git a/editor/doc/doc_dump.cpp b/editor/doc/doc_dump.cpp
index 2ba7e3c779..13dbb149d5 100644
--- a/editor/doc/doc_dump.cpp
+++ b/editor/doc/doc_dump.cpp
@@ -82,8 +82,8 @@ void DocDump::dump(const String &p_file) {
FileAccess *f = FileAccess::open(p_file, FileAccess::WRITE);
_write_string(f, 0, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
+ _write_string(f, 0, String("<doc version=\"") + _MKSTR(VERSION_MAJOR) + "." + _MKSTR(VERSION_MINOR) + "-" + _MKSTR(VERSION_STATUS) + "\" name=\"Engine Types\">");
- _write_string(f, 0, "<doc version=\"" + String(VERSION_MKSTRING) + "\" name=\"Engine Types\">");
while (class_list.size()) {
String name = class_list.front()->get();
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index efe32b99ab..a458a10cd2 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -982,7 +982,7 @@ void EditorExport::remove_export_preset(int p_idx) {
void EditorExport::add_export_plugin(const Ref<EditorExportPlugin> &p_plugin) {
- if (export_plugins.find(p_plugin) == 1) {
+ if (export_plugins.find(p_plugin) == -1) {
export_plugins.push_back(p_plugin);
}
}
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index a6fc8dcddf..9db3bcba00 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -821,8 +821,6 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
scan_actions.push_back(ia);
}
}
-
- EditorResourcePreview::get_singleton()->check_for_invalidation(p_dir->get_file_path(i));
}
for (int i = 0; i < p_dir->subdirs.size(); i++) {
@@ -915,7 +913,8 @@ void EditorFileSystem::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
- scan();
+ call_deferred("scan"); //this should happen after every editor node entered the tree
+
} break;
case NOTIFICATION_EXIT_TREE: {
if (use_threads && thread) {
@@ -1266,7 +1265,6 @@ void EditorFileSystem::update_file(const String &p_file) {
fs->files[cpos]->deps = _get_dependencies(p_file);
fs->files[cpos]->import_valid = ResourceLoader::is_import_valid(p_file);
- EditorResourcePreview::get_singleton()->call_deferred("check_for_invalidation", p_file);
call_deferred("emit_signal", "filesystem_changed"); //update later
}
@@ -1436,6 +1434,8 @@ void EditorFileSystem::_reimport_file(const String &p_file) {
r->set_import_last_modified_time(0);
}
}
+
+ EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
}
void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index 05f9da03e1..7e20077fd6 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -122,20 +122,24 @@ void editor_register_fonts(Ref<Theme> p_theme) {
dfmono->set_font_ptr(_font_Hack_Regular, _font_Hack_Regular_size);
//dfd->set_force_autohinter(true); //just looks better..i think?
- MAKE_DEFAULT_FONT(df, int(EditorSettings::get_singleton()->get("interface/editor/font_size")) * EDSCALE);
+ int default_font_size = int(EditorSettings::get_singleton()->get("interface/editor/font_size")) * EDSCALE;
+ MAKE_DEFAULT_FONT(df, default_font_size);
p_theme->set_default_theme_font(df);
+ MAKE_DEFAULT_FONT(df_title, default_font_size + 2 * EDSCALE);
+ p_theme->set_font("title", "EditorFonts", df_title);
+
//Ref<BitmapFont> doc_font = make_font(_bi_font_doc_font_height,_bi_font_doc_font_ascent,0,_bi_font_doc_font_charcount,_bi_font_doc_font_characters,p_theme->get_icon("DocFont","EditorIcons"));
//Ref<BitmapFont> doc_title_font = make_font(_bi_font_doc_title_font_height,_bi_font_doc_title_font_ascent,0,_bi_font_doc_title_font_charcount,_bi_font_doc_title_font_characters,p_theme->get_icon("DocTitleFont","EditorIcons"));
//Ref<BitmapFont> doc_code_font = make_font(_bi_font_doc_code_font_height,_bi_font_doc_code_font_ascent,0,_bi_font_doc_code_font_charcount,_bi_font_doc_code_font_characters,p_theme->get_icon("DocCodeFont","EditorIcons"));
- MAKE_DEFAULT_FONT(df_title, int(EDITOR_DEF("text_editor/help/help_title_font_size", 16)) * EDSCALE);
+ MAKE_DEFAULT_FONT(df_doc_title, int(EDITOR_DEF("text_editor/help/help_title_font_size", 16)) * EDSCALE);
MAKE_DEFAULT_FONT(df_doc, int(EDITOR_DEF("text_editor/help/help_font_size", 14)) * EDSCALE);
p_theme->set_font("doc", "EditorFonts", df_doc);
- p_theme->set_font("doc_title", "EditorFonts", df_title);
+ p_theme->set_font("doc_title", "EditorFonts", df_doc_title);
MAKE_DEFAULT_FONT(df_rulers, int(EDITOR_DEF("canvas_item_editor/rulers", 8)) * EDSCALE);
p_theme->set_font("rulers", "EditorFonts", df_rulers);
@@ -176,9 +180,4 @@ void editor_register_fonts(Ref<Theme> p_theme) {
df_output_code->set_font_data(dfmono);
MAKE_FALLBACKS(df_output_code);
p_theme->set_font("status_source", "EditorFonts", df_output_code);
-
- //replace default theme
- Ref<Texture> di;
- Ref<StyleBox> ds;
- fill_default_theme(p_theme, df, df_doc, di, ds, EDSCALE);
}
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 03cd2c9b6b..cc7f1cac43 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -555,7 +555,7 @@ void EditorHelp::_class_desc_select(const String &p_select) {
if (select.find(".") != -1) {
class_name = select.get_slice(".", 0);
} else {
- class_name = "@Global Scope";
+ class_name = "@GlobalScope";
}
emit_signal("go_to_help", "class_enum:" + class_name + ":" + select);
return;
@@ -1478,9 +1478,10 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
Color font_color_hl = p_rt->get_color("headline_color", "EditorHelp");
Color link_color = p_rt->get_color("accent_color", "Editor").linear_interpolate(font_color_hl, 0.8);
- String bbcode = p_bbcode.replace("\t", " ").replace("\r", " ").strip_edges();
+ String bbcode = p_bbcode.dedent().replace("\t", "").replace("\r", "").strip_edges();
List<String> tag_stack;
+ bool code_tag = false;
int pos = 0;
while (pos < bbcode.length()) {
@@ -1491,7 +1492,10 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
brk_pos = bbcode.length();
if (brk_pos > pos) {
- p_rt->add_text(bbcode.substr(pos, brk_pos - pos));
+ String text = bbcode.substr(pos, brk_pos - pos);
+ if (!code_tag)
+ text = text.replace("\n", "\n\n");
+ p_rt->add_text(text);
}
if (brk_pos == bbcode.length())
@@ -1500,7 +1504,11 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
int brk_end = bbcode.find("]", brk_pos + 1);
if (brk_end == -1) {
- p_rt->add_text(bbcode.substr(brk_pos, bbcode.length() - brk_pos));
+
+ String text = bbcode.substr(brk_pos, bbcode.length() - brk_pos);
+ if (!code_tag)
+ text = text.replace("\n", "\n\n");
+ p_rt->add_text(text);
break;
}
@@ -1509,20 +1517,23 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
if (tag.begins_with("/")) {
bool tag_ok = tag_stack.size() && tag_stack.front()->get() == tag.substr(1, tag.length());
- if (tag_stack.size()) {
- }
if (!tag_ok) {
p_rt->add_text("[");
- pos++;
+ pos = brk_pos + 1;
continue;
}
tag_stack.pop_front();
pos = brk_end + 1;
+ code_tag = false;
if (tag != "/img")
p_rt->pop();
+ } else if (code_tag) {
+
+ p_rt->add_text("[");
+ pos = brk_pos + 1;
} else if (tag.begins_with("method ")) {
@@ -1559,6 +1570,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
//use monospace font
p_rt->push_font(doc_code_font);
+ code_tag = true;
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "center") {
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 3513126a9b..b3a8490fe9 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -284,9 +284,10 @@ void EditorNode::_notification(int p_what) {
if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/editor/always_show_close_button_in_scene_tabs", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
property_editor->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/editor/capitalize_properties", true)));
- Ref<Theme> theme = create_editor_theme(theme_base->get_theme());
+ Ref<Theme> theme = create_custom_theme(theme_base->get_theme());
theme_base->set_theme(theme);
+ gui_base->set_theme(theme);
gui_base->add_style_override("panel", gui_base->get_stylebox("Background", "EditorStyles"));
play_button_panel->add_style_override("panel", gui_base->get_stylebox("PlayButtonPanel", "EditorStyles"));
@@ -871,7 +872,7 @@ void EditorNode::_find_node_types(Node *p_node, int &count_2d, int &count_3d) {
_find_node_types(p_node->get_child(i), count_2d, count_3d);
}
-void EditorNode::_save_scene_with_preview(String p_file) {
+void EditorNode::_save_scene_with_preview(String p_file, int p_idx) {
EditorProgress save("save", TTR("Saving Scene"), 4);
save.step(TTR("Analyzing"), 0);
@@ -937,7 +938,7 @@ void EditorNode::_save_scene_with_preview(String p_file) {
}
save.step(TTR("Saving Scene"), 4);
- _save_scene(p_file);
+ _save_scene(p_file, p_idx);
EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
}
@@ -1095,10 +1096,7 @@ void EditorNode::_dialog_action(String p_file) {
if (file->get_mode() == EditorFileDialog::MODE_SAVE_FILE) {
_save_default_environment();
- if (scene_idx != editor_data.get_edited_scene())
- _save_scene(p_file, scene_idx);
- else
- _save_scene_with_preview(p_file);
+ _save_scene_with_preview(p_file, scene_idx);
if (scene_idx != -1)
_discard_changes();
@@ -1111,7 +1109,7 @@ void EditorNode::_dialog_action(String p_file) {
_save_default_environment();
_save_scene_with_preview(p_file);
- _run(true);
+ _run(false);
}
} break;
@@ -1825,7 +1823,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
if (scene && scene->get_filename() != "") {
if (scene_idx != editor_data.get_edited_scene())
- _save_scene(scene->get_filename(), scene_idx);
+ _save_scene_with_preview(scene->get_filename(), scene_idx);
else
_save_scene_with_preview(scene->get_filename());
@@ -1933,6 +1931,15 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
} break;
case FILE_EXPORT_TILESET: {
+ //Make sure that the scene has a root before trying to convert to tileset
+ if (!editor_data.get_edited_scene_root()) {
+ current_option = -1;
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("This operation can't be done without a root node."));
+ accept->popup_centered_minsize();
+ break;
+ }
+
List<String> extensions;
Ref<TileSet> ml(memnew(TileSet));
ResourceSaver::get_recognized_extensions(ml, &extensions);
@@ -3254,11 +3261,11 @@ void EditorNode::register_editor_types() {
ClassDB::register_class<EditorScript>();
ClassDB::register_class<EditorSelection>();
ClassDB::register_class<EditorFileDialog>();
- ClassDB::register_class<EditorSettings>();
+ ClassDB::register_virtual_class<EditorSettings>();
ClassDB::register_class<EditorSpatialGizmo>();
- ClassDB::register_class<EditorResourcePreview>();
+ ClassDB::register_virtual_class<EditorResourcePreview>();
ClassDB::register_class<EditorResourcePreviewGenerator>();
- ClassDB::register_class<EditorFileSystem>();
+ ClassDB::register_virtual_class<EditorFileSystem>();
ClassDB::register_class<EditorFileSystemDirectory>();
ClassDB::register_virtual_class<ScriptEditor>();
ClassDB::register_virtual_class<EditorInterface>();
@@ -4217,61 +4224,53 @@ Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) {
return drag_data;
}
-Variant EditorNode::drag_files(const Vector<String> &p_files, Control *p_from) {
-
- VBoxContainer *files = memnew(VBoxContainer);
-
- int max_files = 6;
-
- for (int i = 0; i < MIN(max_files, p_files.size()); i++) {
-
- Label *label = memnew(Label);
- label->set_text(p_files[i].get_file());
- files->add_child(label);
+Variant EditorNode::drag_files_and_dirs(const Vector<String> &p_paths, Control *p_from) {
+ bool has_folder = false;
+ bool has_file = false;
+ for (int i = 0; i < p_paths.size(); i++) {
+ bool is_folder = p_paths[i].ends_with("/");
+ has_folder |= is_folder;
+ has_file |= !is_folder;
}
- if (p_files.size() > max_files) {
-
+ int max_rows = 6;
+ int num_rows = p_paths.size() > max_rows ? max_rows - 1 : p_paths.size(); //Don't waste a row to say "1 more file" - list it instead.
+ VBoxContainer *vbox = memnew(VBoxContainer);
+ for (int i = 0; i < num_rows; i++) {
+ HBoxContainer *hbox = memnew(HBoxContainer);
+ TextureRect *icon = memnew(TextureRect);
Label *label = memnew(Label);
- label->set_text(vformat(TTR("%d more file(s)"), p_files.size() - max_files));
- files->add_child(label);
- }
- Dictionary drag_data;
- drag_data["type"] = "files";
- drag_data["files"] = p_files;
- drag_data["from"] = p_from;
- p_from->set_drag_preview(files); //wait until it enters scene
-
- return drag_data;
-}
-
-Variant EditorNode::drag_files_and_dirs(const Vector<String> &p_files, Control *p_from) {
-
- VBoxContainer *files = memnew(VBoxContainer);
-
- int max_files = 6;
-
- for (int i = 0; i < MIN(max_files, p_files.size()); i++) {
-
- Label *label = memnew(Label);
- label->set_text(p_files[i].get_file());
- files->add_child(label);
+ if (p_paths[i].ends_with("/")) {
+ label->set_text(p_paths[i].substr(0, p_paths[i].length() - 1).get_file());
+ icon->set_texture(gui_base->get_icon("Folder", "EditorIcons"));
+ } else {
+ label->set_text(p_paths[i].get_file());
+ icon->set_texture(gui_base->get_icon("File", "EditorIcons"));
+ }
+ icon->set_size(Size2(16, 16));
+ hbox->add_child(icon);
+ hbox->add_child(label);
+ vbox->add_child(hbox);
}
- if (p_files.size() > max_files) {
-
+ if (p_paths.size() > num_rows) {
Label *label = memnew(Label);
- label->set_text(vformat(TTR("%d more file(s) or folder(s)"), p_files.size() - max_files));
- files->add_child(label);
+ if (has_file && has_folder) {
+ label->set_text(vformat(TTR("%d more files or folders"), p_paths.size() - num_rows));
+ } else if (has_folder) {
+ label->set_text(vformat(TTR("%d more folders"), p_paths.size() - num_rows));
+ } else {
+ label->set_text(vformat(TTR("%d more files"), p_paths.size() - num_rows));
+ }
+ vbox->add_child(label);
}
+ p_from->set_drag_preview(vbox); //wait until it enters scene
+
Dictionary drag_data;
- drag_data["type"] = "files_and_dirs";
- drag_data["files"] = p_files;
+ drag_data["type"] = has_folder ? "files_and_dirs" : "files";
+ drag_data["files"] = p_paths;
drag_data["from"] = p_from;
-
- p_from->set_drag_preview(files); //wait until it enters scene
-
return drag_data;
}
@@ -4690,9 +4689,9 @@ EditorNode::EditorNode() {
theme_base->add_child(gui_base);
gui_base->set_anchors_and_margins_preset(Control::PRESET_WIDE);
- Ref<Theme> theme = create_editor_theme();
+ Ref<Theme> theme = create_custom_theme();
theme_base->set_theme(theme);
- gui_base->set_theme(create_custom_theme());
+ gui_base->set_theme(theme);
gui_base->add_style_override("panel", gui_base->get_stylebox("Background", "EditorStyles"));
resource_preview = memnew(EditorResourcePreview);
@@ -5387,12 +5386,12 @@ EditorNode::EditorNode() {
save_confirmation->connect("confirmed", this, "_menu_confirm_current");
save_confirmation->connect("custom_action", this, "_discard_changes");
- file_templates = memnew(FileDialog);
+ file_templates = memnew(EditorFileDialog);
file_templates->set_title(TTR("Import Templates From ZIP File"));
gui_base->add_child(file_templates);
- file_templates->set_mode(FileDialog::MODE_OPEN_FILE);
- file_templates->set_access(FileDialog::ACCESS_FILESYSTEM);
+ file_templates->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ file_templates->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
file_templates->clear_filters();
file_templates->add_filter("*.tpz ; Template Package");
@@ -5400,15 +5399,15 @@ EditorNode::EditorNode() {
gui_base->add_child(file);
file->set_current_dir("res://");
- file_export = memnew(FileDialog);
- file_export->set_access(FileDialog::ACCESS_FILESYSTEM);
+ file_export = memnew(EditorFileDialog);
+ file_export->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
gui_base->add_child(file_export);
file_export->set_title(TTR("Export Project"));
file_export->connect("file_selected", this, "_dialog_action");
- file_export_lib = memnew(FileDialog);
+ file_export_lib = memnew(EditorFileDialog);
file_export_lib->set_title(TTR("Export Library"));
- file_export_lib->set_mode(FileDialog::MODE_SAVE_FILE);
+ file_export_lib->set_mode(EditorFileDialog::MODE_SAVE_FILE);
file_export_lib->connect("file_selected", this, "_dialog_action");
file_export_lib_merge = memnew(CheckButton);
file_export_lib_merge->set_text(TTR("Merge With Existing"));
@@ -5421,10 +5420,10 @@ EditorNode::EditorNode() {
file_export_password->set_editable(false);
file_export->get_vbox()->add_margin_child(TTR("Password:"), file_export_password);
- file_script = memnew(FileDialog);
+ file_script = memnew(EditorFileDialog);
file_script->set_title(TTR("Open & Run a Script"));
- file_script->set_access(FileDialog::ACCESS_FILESYSTEM);
- file_script->set_mode(FileDialog::MODE_OPEN_FILE);
+ file_script->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ file_script->set_mode(EditorFileDialog::MODE_OPEN_FILE);
List<String> sexts;
ResourceLoader::get_recognized_extensions_for_type("Script", &sexts);
for (List<String>::Element *E = sexts.front(); E; E = E->next()) {
@@ -5534,6 +5533,10 @@ EditorNode::EditorNode() {
spatial_mat_convert.instance();
resource_conversion_plugins.push_back(spatial_mat_convert);
+ Ref<CanvasItemMaterialConversionPlugin> canvas_item_mat_convert;
+ canvas_item_mat_convert.instance();
+ resource_conversion_plugins.push_back(canvas_item_mat_convert);
+
Ref<ParticlesMaterialConversionPlugin> particles_mat_convert;
particles_mat_convert.instance();
resource_conversion_plugins.push_back(particles_mat_convert);
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 32d46e686b..81ff886228 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -294,10 +294,10 @@ private:
ProjectSettingsEditor *project_settings;
EditorFileDialog *file;
ExportTemplateManager *export_template_manager;
- FileDialog *file_templates;
- FileDialog *file_export;
- FileDialog *file_export_lib;
- FileDialog *file_script;
+ EditorFileDialog *file_templates;
+ EditorFileDialog *file_export;
+ EditorFileDialog *file_export_lib;
+ EditorFileDialog *file_script;
CheckButton *file_export_lib_merge;
LineEdit *file_export_password;
String current_path;
@@ -503,7 +503,7 @@ private:
void _mark_unsaved_scenes();
void _find_node_types(Node *p_node, int &count_2d, int &count_3d);
- void _save_scene_with_preview(String p_file);
+ void _save_scene_with_preview(String p_file, int p_idx = -1);
Map<String, Set<String> > dependency_errors;
@@ -765,8 +765,7 @@ public:
void remove_bottom_panel_item(Control *p_item);
Variant drag_resource(const Ref<Resource> &p_res, Control *p_from);
- Variant drag_files(const Vector<String> &p_files, Control *p_from);
- Variant drag_files_and_dirs(const Vector<String> &p_files, Control *p_from);
+ Variant drag_files_and_dirs(const Vector<String> &p_paths, Control *p_from);
void add_tool_menu_item(const String &p_name, Object *p_handler, const String &p_callback, const Variant &p_ud = Variant());
void add_tool_submenu_item(const String &p_name, PopupMenu *p_submenu);
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index c8abc1f9db..0bd677ca1b 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -76,11 +76,11 @@ Vector<Ref<Texture> > EditorInterface::make_mesh_previews(const Vector<Ref<Mesh>
//VS::get_singleton()->camera_set_perspective(camera,45,0.1,10);
VS::get_singleton()->camera_set_orthogonal(camera, 1.0, 0.01, 1000.0);
- RID light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+ RID light = VS::get_singleton()->directional_light_create();
RID light_instance = VS::get_singleton()->instance_create2(light, scenario);
VS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
- RID light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+ RID light2 = VS::get_singleton()->directional_light_create();
VS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7));
//VS::get_singleton()->light_set_color(light2, VS::LIGHT_COLOR_SPECULAR, Color(0.0, 0.0, 0.0));
RID light_instance2 = VS::get_singleton()->instance_create2(light2, scenario);
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index f92962a4cb..5b4bdb59d3 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -86,7 +86,6 @@ void EditorResourcePreview::_thread_func(void *ud) {
void EditorResourcePreview::_preview_ready(const String &p_str, const Ref<Texture> &p_texture, ObjectID id, const StringName &p_func, const Variant &p_ud) {
- //print_line("preview is ready");
preview_mutex->lock();
String path = p_str;
@@ -121,7 +120,6 @@ Ref<Texture> EditorResourcePreview::_generate_preview(const QueueItem &p_item, c
type = p_item.resource->get_class();
else
type = ResourceLoader::get_resource_type(p_item.path);
- //print_line("resource type is: "+type);
if (type == "")
return Ref<Texture>(); //could not guess type
@@ -144,7 +142,6 @@ Ref<Texture> EditorResourcePreview::_generate_preview(const QueueItem &p_item, c
if (!p_item.resource.is_valid()) {
// cache the preview in case it's a resource on disk
if (generated.is_valid()) {
- //print_line("was generated");
int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
thumbnail_size *= EDSCALE;
//wow it generated a preview... save cache
@@ -164,15 +161,11 @@ Ref<Texture> EditorResourcePreview::_generate_preview(const QueueItem &p_item, c
void EditorResourcePreview::_thread() {
- //print_line("begin thread");
while (!exit) {
- //print_line("wait for semaphore");
preview_sem->wait();
preview_mutex->lock();
- //print_line("blue team go");
-
if (queue.size()) {
QueueItem item = queue.front()->get();
@@ -189,12 +182,11 @@ void EditorResourcePreview::_thread() {
preview_mutex->unlock();
} else {
+
preview_mutex->unlock();
Ref<ImageTexture> texture;
- //print_line("pop from queue "+item.path);
-
int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
thumbnail_size *= EDSCALE;
@@ -304,7 +296,6 @@ void EditorResourcePreview::queue_edited_resource_preview(const Ref<Resource> &p
cache.erase(path_id); //erase if exists, since it will be regen
- //print_line("send to thread "+p_path);
QueueItem item;
item.function = p_receiver_func;
item.id = p_receiver->get_instance_id();
@@ -328,7 +319,6 @@ void EditorResourcePreview::queue_resource_preview(const String &p_path, Object
return;
}
- //print_line("send to thread "+p_path);
QueueItem item;
item.function = p_receiver_func;
item.id = p_receiver->get_instance_id();
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index bc91fcdf04..bf4ef3ae39 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -135,6 +135,7 @@ bool EditorSettings::_get(const StringName &p_name, Variant &r_ret) const {
void EditorSettings::_initial_set(const StringName &p_name, const Variant &p_value) {
set(p_name, p_value);
props[p_name].initial = p_value;
+ props[p_name].initial_set = true;
}
struct _EVCSort {
@@ -214,6 +215,14 @@ void EditorSettings::_add_property_info_bind(const Dictionary &p_info) {
}
// Default configs
+bool EditorSettings::has_default_value(const String &p_setting) const {
+
+ _THREAD_SAFE_METHOD_
+
+ if (!props.has(p_setting))
+ return false;
+ return props[p_setting].initial_set;
+}
void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
@@ -834,10 +843,10 @@ void EditorSettings::setup_network() {
hint += ip;
}
- set("network/debug/remote_host", lip);
+ _initial_set("network/debug/remote_host", lip);
add_property_hint(PropertyInfo(Variant::STRING, "network/debug/remote_host", PROPERTY_HINT_ENUM, hint));
- set("network/debug/remote_port", port);
+ _initial_set("network/debug/remote_port", port);
add_property_hint(PropertyInfo(Variant::INT, "network/debug/remote_port", PROPERTY_HINT_RANGE, "1,65535,1"));
}
@@ -915,16 +924,20 @@ void EditorSettings::set_initial_value(const StringName &p_setting, const Varian
ERR_FAIL_COND(!props.has(p_setting));
props[p_setting].initial = p_value;
+ props[p_setting].initial_set = true;
}
Variant _EDITOR_DEF(const String &p_setting, const Variant &p_default) {
+ Variant ret = p_default;
if (EditorSettings::get_singleton()->has_setting(p_setting))
- return EditorSettings::get_singleton()->get(p_setting);
- EditorSettings::get_singleton()->set(p_setting, p_default);
- EditorSettings::get_singleton()->set_initial_value(p_setting, p_default);
+ ret = EditorSettings::get_singleton()->get(p_setting);
+ if (!EditorSettings::get_singleton()->has_default_value(p_setting)) {
+ EditorSettings::get_singleton()->set_initial_value(p_setting, p_default);
+ EditorSettings::get_singleton()->set(p_setting, p_default);
+ }
- return p_default;
+ return ret;
}
Variant _EDITOR_GET(const String &p_setting) {
diff --git a/editor/editor_settings.h b/editor/editor_settings.h
index a74be6494a..29665369c4 100644
--- a/editor/editor_settings.h
+++ b/editor/editor_settings.h
@@ -66,11 +66,13 @@ private:
int order;
Variant variant;
Variant initial;
+ bool initial_set;
bool hide_from_editor;
bool save;
VariantContainer() {
order = 0;
hide_from_editor = false;
+ initial_set = false;
save = false;
}
VariantContainer(const Variant &p_variant, int p_order) {
@@ -128,6 +130,7 @@ public:
static void destroy();
void set_optimize_save(bool p_optimize);
+ bool has_default_value(const String &p_setting) const;
void set_setting(const String &p_setting, const Variant &p_value);
Variant get_setting(const String &p_setting) const;
bool has_setting(const String &p_setting) const;
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 29859a1a56..0f9f50095d 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -568,6 +568,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_constant("modulate_arrow", "OptionButton", true);
// CheckButton
+ theme->set_stylebox("normal", "CheckButton", style_menu);
+ theme->set_stylebox("pressed", "CheckButton", style_menu);
+ theme->set_stylebox("disabled", "CheckButton", style_menu);
+ theme->set_stylebox("hover", "CheckButton", style_menu);
+
theme->set_icon("on", "CheckButton", theme->get_icon("GuiToggleOn", "EditorIcons"));
theme->set_icon("off", "CheckButton", theme->get_icon("GuiToggleOff", "EditorIcons"));
@@ -577,7 +582,22 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_color_disabled", "CheckButton", font_color_disabled);
theme->set_color("icon_color_hover", "CheckButton", font_color_hl);
+ theme->set_constant("hseparation", "CheckButton", 4 * EDSCALE);
+ theme->set_constant("check_vadjust", "CheckButton", 0 * EDSCALE);
+
// Checkbox
+ Ref<StyleBoxFlat> sb_checkbox = style_menu->duplicate();
+ // HACK, in reality, the checkbox draws the text over the icon by default, so the margin compensates that.
+ const int cb_w = theme->get_icon("GuiChecked", "EditorIcons")->get_width() + default_margin_size;
+ sb_checkbox->set_default_margin(MARGIN_LEFT, cb_w * EDSCALE);
+ sb_checkbox->set_default_margin(MARGIN_RIGHT, default_margin_size * EDSCALE);
+ sb_checkbox->set_default_margin(MARGIN_TOP, default_margin_size * EDSCALE);
+ sb_checkbox->set_default_margin(MARGIN_BOTTOM, default_margin_size * EDSCALE);
+
+ theme->set_stylebox("normal", "CheckBox", sb_checkbox);
+ theme->set_stylebox("pressed", "CheckBox", sb_checkbox);
+ theme->set_stylebox("disabled", "CheckBox", sb_checkbox);
+ theme->set_stylebox("hover", "CheckBox", sb_checkbox);
theme->set_icon("checked", "CheckBox", theme->get_icon("GuiChecked", "EditorIcons"));
theme->set_icon("unchecked", "CheckBox", theme->get_icon("GuiUnchecked", "EditorIcons"));
theme->set_icon("radio_checked", "CheckBox", theme->get_icon("GuiRadioChecked", "EditorIcons"));
@@ -589,6 +609,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_color_disabled", "CheckBox", font_color_disabled);
theme->set_color("icon_color_hover", "CheckBox", font_color_hl);
+ theme->set_constant("hseparation", "CheckBox", 4 * EDSCALE);
+ theme->set_constant("check_vadjust", "CheckBox", 0 * EDSCALE);
+
// PopupMenu
Ref<StyleBoxFlat> style_popup_menu = style_popup;
theme->set_stylebox("panel", "PopupMenu", style_popup_menu);
@@ -801,6 +824,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_constant("close_h_ofs", "WindowDialog", 22 * EDSCALE);
theme->set_constant("close_v_ofs", "WindowDialog", 20 * EDSCALE);
theme->set_constant("title_height", "WindowDialog", 24 * EDSCALE);
+ theme->set_font("title_font", "WindowDialog", theme->get_font("title", "EditorFonts"));
// complex window, for now only Editor settings and Project settings
Ref<StyleBoxFlat> style_complex_window = style_window->duplicate();
@@ -1043,12 +1067,14 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
return theme;
}
-Ref<Theme> create_custom_theme() {
+Ref<Theme> create_custom_theme(const Ref<Theme> p_theme) {
Ref<Theme> theme;
String custom_theme = EditorSettings::get_singleton()->get("interface/theme/custom_theme");
if (custom_theme != "") {
theme = ResourceLoader::load(custom_theme);
+ } else {
+ theme = create_editor_theme(p_theme);
}
String global_font = EditorSettings::get_singleton()->get("interface/editor/custom_font");
diff --git a/editor/editor_themes.h b/editor/editor_themes.h
index a644c5936f..6f3b83e0b0 100644
--- a/editor/editor_themes.h
+++ b/editor/editor_themes.h
@@ -34,6 +34,6 @@
Ref<Theme> create_editor_theme(Ref<Theme> p_theme = NULL);
-Ref<Theme> create_custom_theme();
+Ref<Theme> create_custom_theme(Ref<Theme> p_theme = NULL);
#endif
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 00cbd9bb72..7abddb9f67 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -333,7 +333,7 @@ void FileSystemDock::navigate_to_path(const String &p_path) {
} else if (dirAccess->dir_exists(p_path)) {
path = p_path;
} else {
- ERR_EXPLAIN(TTR("Cannot navigate to '" + p_path + "' as it has not been found in the file system!"));
+ ERR_EXPLAIN(vformat(TTR("Cannot navigate to '%s' as it has not been found in the file system!"), p_path));
ERR_FAIL();
}
@@ -1186,78 +1186,36 @@ void FileSystemDock::set_display_mode(int p_mode) {
}
Variant FileSystemDock::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
+ bool is_favorite = false;
+ Vector<String> paths;
if (p_from == tree) {
-
TreeItem *selected = tree->get_selected();
if (!selected)
return Variant();
- String fpath = selected->get_metadata(0);
- if (fpath == String())
+ String folder = selected->get_metadata(0);
+ if (folder == String())
return Variant();
- if (!fpath.ends_with("/"))
- fpath = fpath + "/";
- Vector<String> paths;
- paths.push_back(fpath);
- Dictionary d = EditorNode::get_singleton()->drag_files(paths, p_from);
-
- if (selected->get_parent() && tree->get_root()->get_children() == selected->get_parent()) {
- //a favorite.. treat as such
- d["type"] = "favorite";
- }
-
- return d;
- }
-
- if (p_from == files) {
-
- List<int> seldirs;
- List<int> selfiles;
+ paths.push_back(folder.ends_with("/") ? folder : (folder + "/"));
+ is_favorite = selected->get_parent() != NULL && tree->get_root()->get_children() == selected->get_parent();
+ } else if (p_from == files) {
for (int i = 0; i < files->get_item_count(); i++) {
if (files->is_selected(i)) {
- String fpath = files->get_item_metadata(i);
- if (fpath.ends_with("/"))
- seldirs.push_back(i);
- else
- selfiles.push_back(i);
+ paths.push_back(files->get_item_metadata(i));
}
}
+ }
- if (seldirs.empty() && selfiles.empty())
- return Variant();
- /*
- if (seldirs.size() && selfiles.size())
- return Variant(); //can't really mix files and dirs (i think?) - yes you can, commenting
- */
-
- /*if (selfiles.size()==1) {
- Ref<Resource> resource = ResourceLoader::load(files->get_item_metadata(selfiles.front()->get()));
- if (resource.is_valid()) {
- return EditorNode::get_singleton()->drag_resource(resource,p_from);
- }
- }*/
-
- Vector<String> fnames;
- if (selfiles.size() > 0 || seldirs.size() > 0) {
- if (selfiles.size() > 0) {
- for (List<int>::Element *E = selfiles.front(); E; E = E->next()) {
- fnames.push_back(files->get_item_metadata(E->get()));
- }
- if (seldirs.size() == 0)
- return EditorNode::get_singleton()->drag_files(fnames, p_from);
- }
-
- for (List<int>::Element *E = seldirs.front(); E; E = E->next()) {
- fnames.push_back(files->get_item_metadata(E->get()));
- }
+ if (paths.empty())
+ return Variant();
- return EditorNode::get_singleton()->drag_files_and_dirs(fnames, p_from);
- }
+ Dictionary drag_data = EditorNode::get_singleton()->drag_files_and_dirs(paths, p_from);
+ if (is_favorite) {
+ drag_data["type"] = "favorite";
}
-
- return Variant();
+ return drag_data;
}
bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
@@ -1288,36 +1246,25 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da
}
if (drag_data.has("type") && String(drag_data["type"]) == "resource") {
- return true;
+ String to_dir = _get_drag_target_folder(p_point, p_from);
+ return !to_dir.empty();
}
if (drag_data.has("type") && (String(drag_data["type"]) == "files" || String(drag_data["type"]) == "files_and_dirs")) {
+ String to_dir = _get_drag_target_folder(p_point, p_from);
+ if (to_dir.empty())
+ return false;
+ //Attempting to move a folder into itself will fail later
+ //Rather than bring up a message don't try to do it in the first place
+ to_dir = to_dir.ends_with("/") ? to_dir : (to_dir + "/");
Vector<String> fnames = drag_data["files"];
-
- if (p_from == files) {
-
- int at_pos = files->get_item_at_position(p_point);
- if (at_pos != -1) {
-
- String dir = files->get_item_metadata(at_pos);
- if (dir.ends_with("/"))
- return true;
- }
- }
-
- if (p_from == tree) {
-
- TreeItem *ti = tree->get_item_at_position(p_point);
- if (!ti)
- return false;
-
- String fpath = ti->get_metadata(0);
- if (fpath == String())
+ for (int i = 0; i < fnames.size(); ++i) {
+ if (fnames[i].ends_with("/") && to_dir.begins_with(fnames[i]))
return false;
-
- return true;
}
+
+ return true;
}
return false;
@@ -1393,66 +1340,16 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
if (drag_data.has("type") && String(drag_data["type"]) == "resource") {
Ref<Resource> res = drag_data["resource"];
-
- if (!res.is_valid()) {
- return;
- }
-
- if (p_from == tree) {
-
- TreeItem *ti = tree->get_item_at_position(p_point);
- if (!ti)
- return;
-
- String fpath = ti->get_metadata(0);
- if (fpath == String())
- return;
-
- EditorNode::get_singleton()->save_resource_as(res, fpath);
- return;
- }
-
- if (p_from == files) {
- String save_path = path;
-
- int at_pos = files->get_item_at_position(p_point);
- if (at_pos != -1) {
- String to_dir = files->get_item_metadata(at_pos);
- if (to_dir.ends_with("/")) {
- save_path = to_dir;
- if (save_path != "res://")
- save_path = save_path.substr(0, save_path.length() - 1);
- }
- }
-
- EditorNode::get_singleton()->save_resource_as(res, save_path);
- return;
+ String to_dir = _get_drag_target_folder(p_point, p_from);
+ if (res.is_valid() && !to_dir.empty()) {
+ EditorNode::get_singleton()->push_item(res.ptr());
+ EditorNode::get_singleton()->save_resource_as(res, to_dir);
}
}
if (drag_data.has("type") && (String(drag_data["type"]) == "files" || String(drag_data["type"]) == "files_and_dirs")) {
-
- if (p_from == files || p_from == tree) {
-
- String to_dir;
-
- if (p_from == files) {
-
- int at_pos = files->get_item_at_position(p_point);
- ERR_FAIL_COND(at_pos == -1);
- to_dir = files->get_item_metadata(at_pos);
- } else {
- TreeItem *ti = tree->get_item_at_position(p_point);
- if (!ti)
- return;
- to_dir = ti->get_metadata(0);
- ERR_FAIL_COND(to_dir == String());
- }
-
- if (to_dir != "res://" && to_dir.ends_with("/")) {
- to_dir = to_dir.substr(0, to_dir.length() - 1);
- }
-
+ String to_dir = _get_drag_target_folder(p_point, p_from);
+ if (!to_dir.empty()) {
Vector<String> fnames = drag_data["files"];
to_move.clear();
for (int i = 0; i < fnames.size(); i++) {
@@ -1463,6 +1360,25 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
}
}
+String FileSystemDock::_get_drag_target_folder(const Point2 &p_point, Control *p_from) const {
+ if (p_from == files) {
+ int pos = files->get_item_at_position(p_point, true);
+ if (pos == -1)
+ return path;
+
+ String target = files->get_item_metadata(pos);
+ return target.ends_with("/") ? target : path;
+ }
+
+ if (p_from == tree) {
+ TreeItem *ti = tree->get_item_at_position(p_point);
+ if (ti && ti != tree->get_root()->get_children())
+ return ti->get_metadata(0);
+ }
+
+ return String();
+}
+
void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) {
//Right clicking ".." should clear current selection
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index 2cb0573a3d..249621564d 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -209,6 +209,7 @@ private:
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+ String _get_drag_target_folder(const Point2 &p_point, Control *p_from) const;
void _preview_invalidated(const String &p_path);
void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata);
diff --git a/editor/icons/icon_GUI_toggle_off.svg b/editor/icons/icon_GUI_toggle_off.svg
index 0d43b158b5..aea0f85f96 100644
--- a/editor/icons/icon_GUI_toggle_off.svg
+++ b/editor/icons/icon_GUI_toggle_off.svg
@@ -1,5 +1,5 @@
-<svg width="64" height="32" version="1.1" viewBox="0 0 64 31.999998" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1020.4)">
-<path transform="translate(0 1020.4)" d="m24 4.002c-6.6307 0-12 5.3654-12 11.996v0.003906c0 6.6307 5.3693 12 12 12h16c6.6307 0 12-5.3693 12-12v-0.003906c0-6.6307-5.3693-11.996-12-11.996h-16zm0 2h16c5.5573 0 10 4.4388 10 9.9961v0.003906c0 5.5573-4.4427 10-10 10h-16c-5.5573 0-10-4.4427-10-10v-0.003906c0-5.5573 4.4427-9.9961 10-9.9961zm7 4.9961a1.0001 1.0001 0 0 0 -1 1v8a1 1 0 0 0 1 1 1 1 0 0 0 1 -1v-3h2a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-2v-2h4a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-5zm9 0a1.0001 1.0001 0 0 0 -1 1v4 4a1 1 0 0 0 1 1 1 1 0 0 0 1 -1v-3h2a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-2v-2h4a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-5zm-17 0.003906c-2.7496 0-5 2.2504-5 5s2.2504 5 5 5 5-2.2504 5-5-2.2504-5-5-5zm0 2c1.6687 0 3 1.3313 3 3s-1.3313 3-3 3-3-1.3313-3-3 1.3313-3 3-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" fill-opacity=".78431" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<svg width="42" height="26" version="1.1" viewBox="0 0 42 25.999998" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1026.4)">
+<path d="m13 1027.4c-6.6307 0-12 5.3663-12 11.998 0 6.6318 5.3693 12.002 12 12.002h16c6.6307 0 12-5.3702 12-12.002 0-6.6317-5.3693-11.998-12-11.998zm0 2.0003h16c5.5573 0 10 4.4395 10 9.9977 0 5.5583-4.4427 10.002-10 10.002h-16c-5.5573 0-10-4.4434-10-10.002 0-5.5582 4.4427-9.9977 10-9.9977zm7 4.9969a1.0001 1.0003 0 0 0 -1 1.0002v8.0013a1 1.0002 0 0 0 1 1.0002 1 1.0002 0 0 0 1 -1.0002v-3.0005h2a1 1.0002 0 0 0 1 -1.0002 1 1.0002 0 0 0 -1 -1.0001h-2v-2.0003h4a1 1.0002 0 0 0 1 -1.0002 1 1.0002 0 0 0 -1 -1.0002zm9 0a1.0001 1.0003 0 0 0 -1 1.0002v8.0013a1 1.0002 0 0 0 1 1.0002 1 1.0002 0 0 0 1 -1.0002v-3.0005h2a1 1.0002 0 0 0 1 -1.0002 1 1.0002 0 0 0 -1 -1.0001h-2v-2.0003h4a1 1.0002 0 0 0 1 -1.0002 1 1.0002 0 0 0 -1 -1.0002zm-17 0c-2.7496 0-5 2.2508-5 5.0008 0 2.7501 2.2504 5.0009 5 5.0009s5-2.2508 5-5.0009c0-2.75-2.2504-5.0008-5-5.0008zm0 2.0004c1.6687 0 3 1.3315 3 3.0004 0 1.669-1.3313 3.0005-3 3.0005s-3-1.3315-3-3.0005c0-1.6689 1.3313-3.0004 3-3.0004z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" fill-opacity=".78431" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_GUI_toggle_on.svg b/editor/icons/icon_GUI_toggle_on.svg
index fd2b915fc3..c0a11810d4 100644
--- a/editor/icons/icon_GUI_toggle_on.svg
+++ b/editor/icons/icon_GUI_toggle_on.svg
@@ -1,5 +1,5 @@
-<svg width="64" height="32" version="1.1" viewBox="0 0 64 31.999998" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1020.4)">
-<path transform="translate(0 1020.4)" d="m24 4.002c-6.6307 0-12 5.3654-12 11.996 0 6.6307 5.3693 12 12 12h16c6.6307 0 12-5.3693 12-12 0-6.6307-5.3693-11.996-12-11.996h-16zm17 6.9961a1 1 0 0 1 1 1v8a1.0001 1.0001 0 0 1 -1.752 0.66211l-5.248-6v5.3379a1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1v-8a1.0001 1.0001 0 0 1 1.752 -0.6582l5.248 6v-5.3418a1 1 0 0 1 1 -1zm-15 0.003906c2.7496 0 5 2.2504 5 5s-2.2504 5-5 5-5-2.2504-5-5 2.2504-5 5-5zm0 2c-1.6687 0-3 1.3313-3 3s1.3313 3 3 3 3-1.3313 3-3-1.3313-3-3-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" fill-opacity=".78431" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<svg width="42" height="26" version="1.1" viewBox="0 0 42 25.999998" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1026.4)">
+<path d="m13 1027.4c-6.6307 0-12 5.3662-12 11.998s5.3693 12.002 12 12.002h16c6.6307 0 12-5.3702 12-12.002s-5.3693-11.998-12-11.998zm17 6.9972a1 1.0002 0 0 1 1 1.0001v8.0014a1.0001 1.0003 0 0 1 -1.752 0.6623l-5.248-6.001v5.3387a1 1.0002 0 0 1 -1 1.0001 1 1.0002 0 0 1 -1 -1.0001v-8.0014a1.0001 1.0003 0 0 1 1.752 -0.6583l5.248 6.001v-5.3427a1 1.0002 0 0 1 1 -1.0001zm-15 0c2.7496 0 5 2.2507 5 5.0008s-2.2504 5.0008-5 5.0008-5-2.2507-5-5.0008 2.2504-5.0008 5-5.0008zm0 2.0003c-1.6687 0-3 1.3315-3 3.0005s1.3313 3.0005 3 3.0005 3-1.3315 3-3.0005-1.3313-3.0005-3-3.0005z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" fill-opacity=".78431" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index 831eb74b66..397bb6ad68 100644
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ b/editor/import/editor_scene_importer_gltf.cpp
@@ -1,5 +1,6 @@
#include "editor_scene_importer_gltf.h"
#include "io/json.h"
+#include "math_defs.h"
#include "os/file_access.h"
#include "os/os.h"
#include "scene/3d/camera.h"
@@ -1378,8 +1379,8 @@ Error EditorSceneImporterGLTF::_parse_skins(GLTFState &state) {
state.nodes[skin_node]->skeleton_children.push_back(i);
}
- state.skins.push_back(skin);
}
+ state.skins.push_back(skin);
}
print_line("total skins: " + itos(state.skins.size()));
@@ -1419,7 +1420,8 @@ Error EditorSceneImporterGLTF::_parse_cameras(GLTFState &state) {
camera.perspective = true;
if (d.has("perspective")) {
Dictionary ppt = d["perspective"];
- camera.fov_size = ppt["yfov"];
+ // GLTF spec is in radians, Godot's camera is in degrees.
+ camera.fov_size = (double)ppt["yfov"] * 180.0 / Math_PI;
camera.zfar = ppt["zfar"];
camera.znear = ppt["znear"];
} else {
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index 660db9ac27..d8c3b8d3ed 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -232,16 +232,26 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Array
}
}
- if (_teststr(name, "colonly")) {
+ if (_teststr(name, "colonly") || _teststr(name, "convcolonly")) {
if (isroot)
return p_node;
MeshInstance *mi = Object::cast_to<MeshInstance>(p_node);
if (mi) {
- Node *col = mi->create_trimesh_collision_node();
- ERR_FAIL_COND_V(!col, NULL);
+ Node *col;
+
+ if (_teststr(name, "colonly")) {
+ col = mi->create_trimesh_collision_node();
+ ERR_FAIL_COND_V(!col, NULL);
+
+ col->set_name(_fixstr(name, "colonly"));
+ } else {
+ col = mi->create_convex_collision_node();
+ ERR_FAIL_COND_V(!col, NULL);
+
+ col->set_name(_fixstr(name, "convcolonly"));
+ }
- col->set_name(_fixstr(name, "colonly"));
Object::cast_to<Spatial>(col)->set_transform(mi->get_transform());
p_node->replace_by(col);
memdelete(p_node);
@@ -328,15 +338,25 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Array
rb->add_child(colshape);
colshape->set_owner(p_node->get_owner());
- } else if (_teststr(name, "col") && Object::cast_to<MeshInstance>(p_node)) {
+ } else if ((_teststr(name, "col") || (_teststr(name, "convcol"))) && Object::cast_to<MeshInstance>(p_node)) {
MeshInstance *mi = Object::cast_to<MeshInstance>(p_node);
+ Node *col;
- mi->set_name(_fixstr(name, "col"));
- Node *col = mi->create_trimesh_collision_node();
- ERR_FAIL_COND_V(!col, NULL);
+ if (_teststr(name, "col")) {
+ mi->set_name(_fixstr(name, "col"));
+ col = mi->create_trimesh_collision_node();
+ ERR_FAIL_COND_V(!col, NULL);
+
+ col->set_name("col");
+ } else {
+ mi->set_name(_fixstr(name, "convcol"));
+ col = mi->create_convex_collision_node();
+ ERR_FAIL_COND_V(!col, NULL);
+
+ col->set_name("convcol");
+ }
- col->set_name("col");
p_node->add_child(col);
StaticBody *sb = Object::cast_to<StaticBody>(col);
@@ -527,26 +547,55 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Array
#endif
} else if (Object::cast_to<MeshInstance>(p_node)) {
- //last attempt, maybe collision insde the mesh data
+ //last attempt, maybe collision inside the mesh data
MeshInstance *mi = Object::cast_to<MeshInstance>(p_node);
Ref<ArrayMesh> mesh = mi->get_mesh();
if (!mesh.is_null()) {
- if (_teststr(mesh->get_name(), "col")) {
-
- mesh->set_name(_fixstr(mesh->get_name(), "col"));
+ if (_teststr(mesh->get_name(), "col") || _teststr(mesh->get_name(), "convcol")) {
Ref<Shape> shape;
+ if (_teststr(mesh->get_name(), "col")) {
+ mesh->set_name(_fixstr(mesh->get_name(), "col"));
+
+ if (collision_map.has(mesh)) {
+ shape = collision_map[mesh];
+
+ } else {
+
+ shape = mesh->create_trimesh_shape();
+ if (!shape.is_null())
+ collision_map[mesh] = shape;
+ }
+ } else if (_teststr(mesh->get_name(), "convcol")) {
+ mesh->set_name(_fixstr(mesh->get_name(), "convcol"));
+
+ if (collision_map.has(mesh)) {
+ shape = collision_map[mesh];
+
+ } else {
+
+ shape = mesh->create_convex_shape();
+ if (!shape.is_null())
+ collision_map[mesh] = shape;
+ }
+ }
- if (collision_map.has(mesh)) {
- shape = collision_map[mesh];
+ if (!shape.is_null()) {
+ StaticBody *col = memnew(StaticBody);
+ CollisionShape *cshape = memnew(CollisionShape);
+ cshape->set_shape(shape);
+ col->add_child(cshape);
- } else {
+ col->set_transform(mi->get_transform());
+ col->set_name(mi->get_name());
+ p_node->replace_by(col);
+ memdelete(p_node);
+ p_node = col;
- shape = mesh->create_trimesh_shape();
- if (!shape.is_null())
- collision_map[mesh] = shape;
+ cshape->set_name("shape");
+ cshape->set_owner(p_node->get_owner());
}
}
}
diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp
index 77fd6d883a..84d55b4d14 100644
--- a/editor/import_dock.cpp
+++ b/editor/import_dock.cpp
@@ -87,23 +87,7 @@ void ImportDock::set_edit_path(const String &p_path) {
return;
}
- List<ResourceImporter::ImportOption> options;
- params->importer->get_import_options(&options);
-
- params->properties.clear();
- params->values.clear();
-
- for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
-
- params->properties.push_back(E->get().option);
- if (config->has_section_key("params", E->get().option.name)) {
- params->values[E->get().option.name] = config->get_value("params", E->get().option.name);
- } else {
- params->values[E->get().option.name] = E->get().default_value;
- }
- }
-
- params->update();
+ _update_options(config);
List<Ref<ResourceImporter> > importers;
ResourceFormatImporter::get_singleton()->get_importers_for_extension(p_path.get_extension(), &importers);
@@ -125,6 +109,34 @@ void ImportDock::set_edit_path(const String &p_path) {
}
}
+ params->paths.clear();
+ params->paths.push_back(p_path);
+ import->set_disabled(false);
+ import_as->set_disabled(false);
+
+ imported->set_text(p_path.get_file());
+}
+
+void ImportDock::_update_options(const Ref<ConfigFile> &p_config) {
+
+ List<ResourceImporter::ImportOption> options;
+ params->importer->get_import_options(&options);
+
+ params->properties.clear();
+ params->values.clear();
+
+ for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
+
+ params->properties.push_back(E->get().option);
+ if (p_config.is_valid() && p_config->has_section_key("params", E->get().option.name)) {
+ params->values[E->get().option.name] = p_config->get_value("params", E->get().option.name);
+ } else {
+ params->values[E->get().option.name] = E->get().default_value;
+ }
+ }
+
+ params->update();
+
preset->get_popup()->clear();
if (params->importer->get_preset_count() == 0) {
@@ -142,13 +154,6 @@ void ImportDock::set_edit_path(const String &p_path) {
preset->get_popup()->add_separator();
preset->get_popup()->add_item(vformat(TTR("Clear Default for '%s'"), params->importer->get_visible_name()), ITEM_CLEAR_DEFAULT);
}
-
- params->paths.clear();
- params->paths.push_back(p_path);
- import->set_disabled(false);
- import_as->set_disabled(false);
-
- imported->set_text(p_path.get_file());
}
void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) {
@@ -263,6 +268,24 @@ void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) {
imported->set_text(itos(p_paths.size()) + TTR(" Files"));
}
+void ImportDock::_importer_selected(int i_idx) {
+ String name = import_as->get_selected_metadata();
+ Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(name);
+ ERR_FAIL_COND(importer.is_null());
+
+ params->importer = importer;
+
+ Ref<ConfigFile> config;
+ if (params->paths.size()) {
+ config.instance();
+ Error err = config->load(params->paths[0] + ".import");
+ if (err != OK) {
+ config.unref();
+ }
+ }
+ _update_options(config);
+}
+
void ImportDock::_preset_selected(int p_idx) {
int item_id = preset->get_popup()->get_item_id(p_idx);
@@ -336,6 +359,7 @@ void ImportDock::_reimport() {
Error err = config->load(params->paths[i] + ".import");
ERR_CONTINUE(err != OK);
+ config->set_value("remap", "importer", params->importer->get_importer_name());
config->erase_section("params");
for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) {
@@ -356,12 +380,18 @@ void ImportDock::_notification(int p_what) {
imported->add_style_override("normal", get_stylebox("normal", "LineEdit"));
} break;
+
+ case NOTIFICATION_ENTER_TREE: {
+
+ import_opts->edit(params);
+ } break;
}
}
void ImportDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_reimport"), &ImportDock::_reimport);
ClassDB::bind_method(D_METHOD("_preset_selected"), &ImportDock::_preset_selected);
+ ClassDB::bind_method(D_METHOD("_importer_selected"), &ImportDock::_importer_selected);
}
void ImportDock::initialize_import_options() const {
@@ -379,6 +409,7 @@ ImportDock::ImportDock() {
HBoxContainer *hb = memnew(HBoxContainer);
add_margin_child(TTR("Import As:"), hb);
import_as = memnew(OptionButton);
+ import_as->connect("item_selected", this, "_importer_selected");
hb->add_child(import_as);
import_as->set_h_size_flags(SIZE_EXPAND_FILL);
preset = memnew(MenuButton);
diff --git a/editor/import_dock.h b/editor/import_dock.h
index 029c458320..28c29e4b20 100644
--- a/editor/import_dock.h
+++ b/editor/import_dock.h
@@ -54,6 +54,8 @@ class ImportDock : public VBoxContainer {
ImportDockParameters *params;
void _preset_selected(int p_idx);
+ void _importer_selected(int i_idx);
+ void _update_options(const Ref<ConfigFile> &p_config = Ref<ConfigFile>());
void _reimport();
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp
index f2f913d2b3..736e176ab8 100644
--- a/editor/plugins/abstract_polygon_2d_editor.cpp
+++ b/editor/plugins/abstract_polygon_2d_editor.cpp
@@ -563,6 +563,14 @@ void AbstractPolygon2DEditor::forward_draw_over_canvas(Control *p_canvas) {
const Vector2 next_point = xform.xform(p2);
vpc->draw_line(point, next_point, col, 2);
}
+ }
+
+ for (int i = 0; i < n_points; i++) {
+
+ const Vertex vertex(j, i);
+
+ const Vector2 p = (vertex == edited_point) ? edited_point.pos : (points[i] + offset);
+ const Vector2 point = xform.xform(p);
Ref<Texture> handle = vertex == active_point ? selected_handle : default_handle;
vpc->draw_texture(handle, point - handle->get_size() * 0.5);
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index cd53264437..d2e7feb6e1 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -33,6 +33,8 @@
#include "editor_settings.h"
#include "io/json.h"
+#include "version_generated.gen.h"
+
void EditorAssetLibraryItem::configure(const String &p_title, int p_asset_id, const String &p_category, int p_category_id, const String &p_author, int p_author_id, int p_rating, const String &p_cost) {
title->set_text(p_title);
@@ -867,6 +869,8 @@ void EditorAssetLibrary::_search(int p_page) {
}
args += String() + "sort=" + sort_key[sort->get_selected()];
+ args += "&godot_version=" + itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR);
+
String support_list;
for (int i = 0; i < SUPPORT_MAX; i++) {
if (support->get_popup()->is_item_checked(i)) {
@@ -1348,13 +1352,11 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
search_hb2->add_child(memnew(Label(TTR("Site:") + " ")));
repository = memnew(OptionButton);
- // FIXME: Reenable me once GH-7147 is fixed.
- /*
repository->add_item("godotengine.org");
repository->set_item_metadata(0, "https://godotengine.org/asset-library/api");
- */
repository->add_item("localhost");
- repository->set_item_metadata(/*1*/ 0, "http://127.0.0.1/asset-library/api");
+ repository->set_item_metadata(1, "http://127.0.0.1/asset-library/api");
+
repository->connect("item_selected", this, "_repository_changed");
search_hb2->add_child(repository);
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 3807c8961a..38467369db 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -3623,7 +3623,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
if (key_pos)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d, "position", n2d->get_position(), existing);
if (key_rot)
- AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d, "rotation_deg", Math::rad2deg(n2d->get_rotation()), existing);
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d, "rotation_degrees", Math::rad2deg(n2d->get_rotation()), existing);
if (key_scale)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d, "scale", n2d->get_scale(), existing);
@@ -3654,7 +3654,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
if (key_pos)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(), "position", F->get()->get_position(), existing);
if (key_rot)
- AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(), "rotation_deg", Math::rad2deg(F->get()->get_rotation()), existing);
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(), "rotation_degrees", Math::rad2deg(F->get()->get_rotation()), existing);
if (key_scale)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(), "scale", F->get()->get_scale(), existing);
}
@@ -3668,7 +3668,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
if (key_pos)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl, "rect_position", ctrl->get_position(), existing);
if (key_rot)
- AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl, "rect_rotation", ctrl->get_rotation_deg(), existing);
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl, "rect_rotation", ctrl->get_rotation_degrees(), existing);
if (key_scale)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl, "rect_size", ctrl->get_size(), existing);
}
@@ -4373,11 +4373,11 @@ void CanvasItemEditorViewport::_on_mouse_exit() {
void CanvasItemEditorViewport::_on_select_type(Object *selected) {
CheckBox *check = Object::cast_to<CheckBox>(selected);
String type = check->get_text();
- selector_label->set_text(vformat(TTR("Add %s"), type));
+ selector->set_title(vformat(TTR("Add %s"), type));
label->set_text(vformat(TTR("Adding %s..."), type));
}
-void CanvasItemEditorViewport::_on_change_type() {
+void CanvasItemEditorViewport::_on_change_type_confirmed() {
if (!button_group->get_pressed_button())
return;
@@ -4387,6 +4387,11 @@ void CanvasItemEditorViewport::_on_change_type() {
selector->hide();
}
+void CanvasItemEditorViewport::_on_change_type_closed() {
+
+ _remove_preview();
+}
+
void CanvasItemEditorViewport::_create_preview(const Vector<String> &files) const {
label->set_position(get_global_position() + Point2(14, 14) * EDSCALE);
label_desc->set_position(label->get_position() + Point2(0, label->get_size().height));
@@ -4698,7 +4703,7 @@ void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p
CheckBox *check = Object::cast_to<CheckBox>(btn_list[i]);
check->set_pressed(check->get_text() == default_type);
}
- selector_label->set_text(vformat(TTR("Add %s"), default_type));
+ selector->set_title(vformat(TTR("Add %s"), default_type));
selector->popup_centered_minsize();
} else {
_perform_drop_data();
@@ -4721,7 +4726,8 @@ void CanvasItemEditorViewport::_notification(int p_what) {
void CanvasItemEditorViewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("_on_select_type"), &CanvasItemEditorViewport::_on_select_type);
- ClassDB::bind_method(D_METHOD("_on_change_type"), &CanvasItemEditorViewport::_on_change_type);
+ ClassDB::bind_method(D_METHOD("_on_change_type_confirmed"), &CanvasItemEditorViewport::_on_change_type_confirmed);
+ ClassDB::bind_method(D_METHOD("_on_change_type_closed"), &CanvasItemEditorViewport::_on_change_type_closed);
ClassDB::bind_method(D_METHOD("_on_mouse_exit"), &CanvasItemEditorViewport::_on_mouse_exit);
}
@@ -4749,7 +4755,8 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte
selector = memnew(AcceptDialog);
editor->get_gui_base()->add_child(selector);
selector->set_title(TTR("Change default type"));
- selector->connect("confirmed", this, "_on_change_type");
+ selector->connect("confirmed", this, "_on_change_type_confirmed");
+ selector->connect("popup_hide", this, "_on_change_type_closed");
VBoxContainer *vbc = memnew(VBoxContainer);
selector->add_child(vbc);
@@ -4757,12 +4764,6 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte
vbc->set_v_size_flags(SIZE_EXPAND_FILL);
vbc->set_custom_minimum_size(Size2(200, 260) * EDSCALE);
- selector_label = memnew(Label);
- vbc->add_child(selector_label);
- selector_label->set_align(Label::ALIGN_CENTER);
- selector_label->set_valign(Label::VALIGN_BOTTOM);
- selector_label->set_custom_minimum_size(Size2(0, 30) * EDSCALE);
-
btn_group = memnew(VBoxContainer);
vbc->add_child(btn_group);
btn_group->set_h_size_flags(0);
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index 97e3b03569..457833e1a7 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -568,7 +568,8 @@ class CanvasItemEditorViewport : public Control {
void _on_mouse_exit();
void _on_select_type(Object *selected);
- void _on_change_type();
+ void _on_change_type_confirmed();
+ void _on_change_type_closed();
void _create_preview(const Vector<String> &files) const;
void _remove_preview();
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index c48a241e4d..5f73d0b465 100644
--- a/editor/plugins/editor_preview_plugins.cpp
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -278,11 +278,11 @@ EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() {
VS::get_singleton()->camera_set_transform(camera, Transform(Basis(), Vector3(0, 0, 3)));
VS::get_singleton()->camera_set_perspective(camera, 45, 0.1, 10);
- light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+ light = VS::get_singleton()->directional_light_create();
light_instance = VS::get_singleton()->instance_create2(light, scenario);
VS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
- light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+ light2 = VS::get_singleton()->directional_light_create();
VS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7));
//VS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7));
@@ -850,11 +850,11 @@ EditorMeshPreviewPlugin::EditorMeshPreviewPlugin() {
//VS::get_singleton()->camera_set_perspective(camera,45,0.1,10);
VS::get_singleton()->camera_set_orthogonal(camera, 1.0, 0.01, 1000.0);
- light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+ light = VS::get_singleton()->directional_light_create();
light_instance = VS::get_singleton()->instance_create2(light, scenario);
VS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
- light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+ light2 = VS::get_singleton()->directional_light_create();
VS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7));
//VS::get_singleton()->light_set_color(light2, VS::LIGHT_COLOR_SPECULAR, Color(0.0, 0.0, 0.0));
light_instance2 = VS::get_singleton()->instance_create2(light2, scenario);
diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp
index bd4891ccb7..1fc112896d 100644
--- a/editor/plugins/material_editor_plugin.cpp
+++ b/editor/plugins/material_editor_plugin.cpp
@@ -503,3 +503,41 @@ Ref<Resource> ParticlesMaterialConversionPlugin::convert(const Ref<Resource> &p_
smat->set_render_priority(mat->get_render_priority());
return smat;
}
+
+String CanvasItemMaterialConversionPlugin::converts_to() const {
+
+ return "ShaderMaterial";
+}
+bool CanvasItemMaterialConversionPlugin::handles(const Ref<Resource> &p_resource) const {
+
+ Ref<CanvasItemMaterial> mat = p_resource;
+ return mat.is_valid();
+}
+Ref<Resource> CanvasItemMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) {
+
+ Ref<CanvasItemMaterial> mat = p_resource;
+ ERR_FAIL_COND_V(!mat.is_valid(), Ref<Resource>());
+
+ Ref<ShaderMaterial> smat;
+ smat.instance();
+
+ Ref<Shader> shader;
+ shader.instance();
+
+ String code = VS::get_singleton()->shader_get_code(mat->get_shader_rid());
+
+ shader->set_code(code);
+
+ smat->set_shader(shader);
+
+ List<PropertyInfo> params;
+ VS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
+
+ for (List<PropertyInfo>::Element *E = params.front(); E; E = E->next()) {
+ Variant value = VS::get_singleton()->material_get_param(mat->get_rid(), E->get().name);
+ smat->set_shader_param(E->get().name, value);
+ }
+
+ smat->set_render_priority(mat->get_render_priority());
+ return smat;
+}
diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h
index 52c73cb7d8..2cc24be33a 100644
--- a/editor/plugins/material_editor_plugin.h
+++ b/editor/plugins/material_editor_plugin.h
@@ -119,4 +119,12 @@ public:
virtual Ref<Resource> convert(const Ref<Resource> &p_resource);
};
+class CanvasItemMaterialConversionPlugin : public EditorResourceConversionPlugin {
+ GDCLASS(CanvasItemMaterialConversionPlugin, EditorResourceConversionPlugin)
+public:
+ virtual String converts_to() const;
+ virtual bool handles(const Ref<Resource> &p_resource) const;
+ virtual Ref<Resource> convert(const Ref<Resource> &p_resource);
+};
+
#endif // MATERIAL_EDITOR_PLUGIN_H
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
index d421b3798b..3210af1433 100644
--- a/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -43,7 +43,7 @@ void ResourcePreloaderEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
load->set_icon(get_icon("Folder", "EditorIcons"));
- _delete->set_icon(get_icon("Del", "EditorIcons"));
+ _delete->set_icon(get_icon("Remove", "EditorIcons"));
}
if (p_what == NOTIFICATION_READY) {
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index a1183307fb..607ccaa4e7 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -865,20 +865,7 @@ void ScriptEditor::_menu_option(int p_option) {
} break;
case SEARCH_CLASSES: {
- String current;
-
- if (tab_container->get_tab_count() > 0) {
- EditorHelp *eh = Object::cast_to<EditorHelp>(tab_container->get_child(tab_container->get_current_tab()));
- if (eh) {
- current = eh->get_class();
- }
- }
-
help_index->popup();
-
- if (current != "") {
- help_index->call_deferred("select_class", current);
- }
} break;
case SEARCH_WEBSITE: {
@@ -890,8 +877,13 @@ void ScriptEditor::_menu_option(int p_option) {
_history_forward();
} break;
case WINDOW_PREV: {
+
_history_back();
} break;
+ case WINDOW_SORT: {
+ _sort_list_on_update = true;
+ _update_script_names();
+ } break;
case DEBUG_SHOW: {
if (debugger) {
bool visible = debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(DEBUG_SHOW));
@@ -926,10 +918,6 @@ void ScriptEditor::_menu_option(int p_option) {
if (current) {
switch (p_option) {
- case FILE_NEW: {
- script_create_dialog->config("Node", ".gd");
- script_create_dialog->popup_centered(Size2(300, 300) * EDSCALE);
- } break;
case FILE_SAVE: {
if (_test_script_times_on_disk())
@@ -1041,26 +1029,22 @@ void ScriptEditor::_menu_option(int p_option) {
debugger->debug_continue();
} break;
- case WINDOW_MOVE_LEFT: {
+ case WINDOW_MOVE_UP: {
if (tab_container->get_current_tab() > 0) {
- tab_container->call_deferred("set_current_tab", tab_container->get_current_tab() - 1);
- script_list->call_deferred("select", tab_container->get_current_tab() - 1);
tab_container->move_child(current, tab_container->get_current_tab() - 1);
+ tab_container->set_current_tab(tab_container->get_current_tab() - 1);
_update_script_names();
}
} break;
- case WINDOW_MOVE_RIGHT: {
+ case WINDOW_MOVE_DOWN: {
if (tab_container->get_current_tab() < tab_container->get_child_count() - 1) {
- tab_container->call_deferred("set_current_tab", tab_container->get_current_tab() + 1);
- script_list->call_deferred("select", tab_container->get_current_tab() + 1);
tab_container->move_child(current, tab_container->get_current_tab() + 1);
+ tab_container->set_current_tab(tab_container->get_current_tab() + 1);
_update_script_names();
}
-
} break;
-
default: {
if (p_option >= WINDOW_SELECT_BASE) {
@@ -1077,6 +1061,11 @@ void ScriptEditor::_menu_option(int p_option) {
switch (p_option) {
+ case SEARCH_CLASSES: {
+
+ help_index->popup();
+ help_index->call_deferred("select_class", help->get_class());
+ } break;
case HELP_SEARCH_FIND: {
help->popup_search();
} break;
@@ -1092,6 +1081,22 @@ void ScriptEditor::_menu_option(int p_option) {
case CLOSE_ALL: {
_close_all_tabs();
} break;
+ case WINDOW_MOVE_UP: {
+
+ if (tab_container->get_current_tab() > 0) {
+ tab_container->move_child(help, tab_container->get_current_tab() - 1);
+ tab_container->set_current_tab(tab_container->get_current_tab() - 1);
+ _update_script_names();
+ }
+ } break;
+ case WINDOW_MOVE_DOWN: {
+
+ if (tab_container->get_current_tab() < tab_container->get_child_count() - 1) {
+ tab_container->move_child(help, tab_container->get_current_tab() + 1);
+ tab_container->set_current_tab(tab_container->get_current_tab() + 1);
+ _update_script_names();
+ }
+ } break;
}
}
}
@@ -1361,6 +1366,7 @@ struct _ScriptEditorItemData {
String tooltip;
bool used;
int category;
+ Node *ref;
bool operator<(const _ScriptEditorItemData &id) const {
@@ -1526,6 +1532,7 @@ void ScriptEditor::_update_script_names() {
sd.index = i;
sd.used = used.has(se->get_edited_script());
sd.category = 0;
+ sd.ref = se;
switch (sort_by) {
case SORT_BY_NAME: {
@@ -1565,16 +1572,38 @@ void ScriptEditor::_update_script_names() {
_ScriptEditorItemData sd;
sd.icon = icon;
sd.name = name;
- sd.sort_key = name;
+ sd.sort_key = name.to_lower();
sd.tooltip = tooltip;
sd.index = i;
sd.used = false;
sd.category = split_script_help ? 1 : 0;
+ sd.ref = eh;
+
sedata.push_back(sd);
}
}
- sedata.sort();
+ if (_sort_list_on_update) {
+ sedata.sort();
+
+ // change actual order of tab_container so that the order can be rearranged by user
+ int cur_tab = tab_container->get_current_tab();
+ int prev_tab = tab_container->get_previous_tab();
+ int new_cur_tab = -1;
+ int new_prev_tab = -1;
+ for (int i = 0; i < sedata.size(); i++) {
+ tab_container->move_child(sedata[i].ref, i);
+ if (new_prev_tab == -1 && sedata[i].index == prev_tab) {
+ new_prev_tab = i;
+ }
+ if (new_cur_tab == -1 && sedata[i].index == cur_tab) {
+ new_cur_tab = i;
+ }
+ }
+ tab_container->call_deferred("set_current_tab", new_prev_tab);
+ tab_container->call_deferred("set_current_tab", new_cur_tab);
+ _sort_list_on_update = false;
+ }
for (int i = 0; i < sedata.size(); i++) {
@@ -1903,8 +1932,171 @@ void ScriptEditor::_script_split_dragged(float) {
_save_layout();
}
+Variant ScriptEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
+
+ // return Variant(); // return this if drag disabled
+
+ Node *cur_node = tab_container->get_child(tab_container->get_current_tab());
+
+ HBoxContainer *drag_preview = memnew(HBoxContainer);
+ String preview_name = "";
+ Ref<Texture> preview_icon;
+
+ ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(cur_node);
+ if (se) {
+ preview_name = se->get_name();
+ preview_icon = se->get_icon();
+ }
+ EditorHelp *eh = Object::cast_to<EditorHelp>(cur_node);
+ if (eh) {
+ preview_name = eh->get_class();
+ preview_icon = get_icon("Help", "EditorIcons");
+ }
+
+ if (!preview_icon.is_null()) {
+ TextureRect *tf = memnew(TextureRect);
+ tf->set_texture(preview_icon);
+ drag_preview->add_child(tf);
+ }
+ Label *label = memnew(Label(preview_name));
+ drag_preview->add_child(label);
+ set_drag_preview(drag_preview);
+
+ Dictionary drag_data;
+ drag_data["type"] = "script_list_element"; // using a custom type because node caused problems when dragging to scene tree
+ drag_data["script_list_element"] = cur_node;
+
+ return drag_data;
+}
+
+bool ScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
+
+ Dictionary d = p_data;
+ if (!d.has("type"))
+ return false;
+
+ if (String(d["type"]) == "script_list_element") {
+
+ Node *node = d["script_list_element"];
+
+ ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(node);
+ if (se) {
+ return true;
+ }
+ EditorHelp *eh = Object::cast_to<EditorHelp>(node);
+ if (eh) {
+ return true;
+ }
+ }
+
+ if (String(d["type"]) == "nodes") {
+
+ Array nodes = d["nodes"];
+ if (nodes.size() == 0)
+ return false;
+ Node *node = get_node((nodes[0]));
+
+ ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(node);
+ if (se) {
+ return true;
+ }
+ EditorHelp *eh = Object::cast_to<EditorHelp>(node);
+ if (eh) {
+ return true;
+ }
+ }
+
+ if (String(d["type"]) == "files") {
+
+ Vector<String> files = d["files"];
+
+ if (files.size() == 0)
+ return false; //weird
+
+ for (int i = 0; i < files.size(); i++) {
+ String file = files[i];
+ if (file == "" || !FileAccess::exists(file))
+ continue;
+ Ref<Script> scr = ResourceLoader::load(file);
+ if (scr.is_valid()) {
+ return true;
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
+
+void ScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
+
+ if (!can_drop_data_fw(p_point, p_data, p_from))
+ return;
+
+ Dictionary d = p_data;
+ if (!d.has("type"))
+ return;
+
+ if (String(d["type"]) == "script_list_element") {
+
+ Node *node = d["script_list_element"];
+
+ ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(node);
+ EditorHelp *eh = Object::cast_to<EditorHelp>(node);
+ if (se || eh) {
+ int new_index = script_list->get_item_at_position(p_point);
+ tab_container->move_child(node, new_index);
+ tab_container->set_current_tab(new_index);
+ _update_script_names();
+ }
+ }
+
+ if (String(d["type"]) == "nodes") {
+
+ Array nodes = d["nodes"];
+ if (nodes.size() == 0)
+ return;
+ Node *node = get_node(nodes[0]);
+
+ ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(node);
+ EditorHelp *eh = Object::cast_to<EditorHelp>(node);
+ if (se || eh) {
+ int new_index = script_list->get_item_at_position(p_point);
+ tab_container->move_child(node, new_index);
+ tab_container->set_current_tab(new_index);
+ _update_script_names();
+ }
+ }
+
+ if (String(d["type"]) == "files") {
+
+ Vector<String> files = d["files"];
+
+ int new_index = script_list->get_item_at_position(p_point);
+ int num_tabs_before = tab_container->get_child_count();
+ for (int i = 0; i < files.size(); i++) {
+ String file = files[i];
+ if (file == "" || !FileAccess::exists(file))
+ continue;
+ Ref<Script> scr = ResourceLoader::load(file);
+ if (scr.is_valid()) {
+ edit(scr);
+ if (tab_container->get_child_count() > num_tabs_before) {
+ tab_container->move_child(tab_container->get_child(tab_container->get_child_count() - 1), new_index);
+ num_tabs_before = tab_container->get_child_count();
+ } else {
+ tab_container->move_child(tab_container->get_child(tab_container->get_current_tab()), new_index);
+ }
+ }
+ }
+ tab_container->set_current_tab(new_index);
+ _update_script_names();
+ }
+}
+
void ScriptEditor::_unhandled_input(const Ref<InputEvent> &p_event) {
- if (p_event->is_pressed() || !is_visible_in_tree()) return;
+ if (!is_visible_in_tree() || !p_event->is_pressed() || p_event->is_echo())
+ return;
if (ED_IS_SHORTCUT("script_editor/next_script", p_event)) {
int next_tab = script_list->get_current() + 1;
next_tab %= script_list->get_item_count();
@@ -1917,6 +2109,62 @@ void ScriptEditor::_unhandled_input(const Ref<InputEvent> &p_event) {
_go_to_tab(script_list->get_item_metadata(next_tab));
_update_script_names();
}
+ if (ED_IS_SHORTCUT("script_editor/window_move_up", p_event)) {
+ _menu_option(WINDOW_MOVE_UP);
+ }
+ if (ED_IS_SHORTCUT("script_editor/window_move_down", p_event)) {
+ _menu_option(WINDOW_MOVE_DOWN);
+ }
+}
+
+void ScriptEditor::_script_list_gui_input(const Ref<InputEvent> &ev) {
+
+ Ref<InputEventMouseButton> mb = ev;
+ if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
+
+ _make_script_list_context_menu();
+ }
+}
+
+void ScriptEditor::_make_script_list_context_menu() {
+
+ context_menu->clear();
+
+ int selected = tab_container->get_current_tab();
+ if (selected < 0 || selected >= tab_container->get_child_count())
+ return;
+
+ ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_child(selected));
+ 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_separator();
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/reload_script_soft"), FILE_TOOL_RELOAD_SOFT);
+
+ Ref<Script> scr = se->get_edited_script();
+ if (!scr.is_null() && scr->is_tool()) {
+ context_menu->add_separator();
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/run_file"), FILE_RUN);
+ }
+ } else {
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/close_file"), FILE_CLOSE);
+ }
+
+ EditorHelp *eh = Object::cast_to<EditorHelp>(tab_container->get_child(selected));
+ if (eh) {
+ // nothing
+ }
+
+ 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);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/toggle_scripts_panel"), TOGGLE_SCRIPTS_PANEL);
+
+ context_menu->set_position(get_global_transform().xform(get_local_mouse_position()));
+ context_menu->set_size(Vector2(1, 1));
+ context_menu->popup();
}
void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {
@@ -2243,9 +2491,14 @@ void ScriptEditor::_bind_methods() {
ClassDB::bind_method("_history_back", &ScriptEditor::_history_back);
ClassDB::bind_method("_live_auto_reload_running_scripts", &ScriptEditor::_live_auto_reload_running_scripts);
ClassDB::bind_method("_unhandled_input", &ScriptEditor::_unhandled_input);
+ ClassDB::bind_method("_script_list_gui_input", &ScriptEditor::_script_list_gui_input);
ClassDB::bind_method("_script_changed", &ScriptEditor::_script_changed);
ClassDB::bind_method("_update_recent_scripts", &ScriptEditor::_update_recent_scripts);
+ ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &ScriptEditor::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &ScriptEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("drop_data_fw"), &ScriptEditor::drop_data_fw);
+
ClassDB::bind_method(D_METHOD("get_current_script"), &ScriptEditor::_get_current_script);
ClassDB::bind_method(D_METHOD("get_open_scripts"), &ScriptEditor::_get_open_scripts);
@@ -2287,6 +2540,15 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
script_split->set_split_offset(140);
//list_split->set_split_offset(500);
+ _sort_list_on_update = true;
+ script_list->connect("gui_input", this, "_script_list_gui_input");
+ 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");
+
members_overview = memnew(ItemList);
list_split->add_child(members_overview);
members_overview->set_custom_minimum_size(Size2(0, 100)); //need to give a bit of limit to avoid it from disappearing
@@ -2303,8 +2565,11 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
tab_container->set_h_size_flags(SIZE_EXPAND_FILL);
- ED_SHORTCUT("script_editor/next_script", TTR("Next script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_GREATER);
- ED_SHORTCUT("script_editor/prev_script", TTR("Previous script"), KEY_MASK_CMD | KEY_LESS);
+ ED_SHORTCUT("script_editor/window_sort", TTR("Sort"));
+ ED_SHORTCUT("script_editor/window_move_up", TTR("Move Up"), KEY_MASK_SHIFT | KEY_MASK_ALT | KEY_UP);
+ ED_SHORTCUT("script_editor/window_move_down", TTR("Move Down"), KEY_MASK_SHIFT | KEY_MASK_ALT | KEY_DOWN);
+ ED_SHORTCUT("script_editor/next_script", TTR("Next script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_PERIOD); // these should be KEY_GREATER and KEY_LESS but those don't work
+ ED_SHORTCUT("script_editor/prev_script", TTR("Previous script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_COLON);
set_process_unhandled_input(true);
file_menu = memnew(MenuButton);
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index 03fc4da7ce..b8317f9e86 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -150,10 +150,11 @@ class ScriptEditor : public PanelContainer {
SEARCH_WEBSITE,
HELP_SEARCH_FIND,
HELP_SEARCH_FIND_NEXT,
- WINDOW_MOVE_LEFT,
- WINDOW_MOVE_RIGHT,
+ WINDOW_MOVE_UP,
+ WINDOW_MOVE_DOWN,
WINDOW_NEXT,
WINDOW_PREV,
+ WINDOW_SORT,
WINDOW_SELECT_BASE = 100
};
@@ -173,6 +174,7 @@ class ScriptEditor : public PanelContainer {
MenuButton *edit_menu;
MenuButton *script_search_menu;
MenuButton *debug_menu;
+ PopupMenu *context_menu;
Timer *autosave_timer;
uint64_t idle;
@@ -292,6 +294,7 @@ class ScriptEditor : public PanelContainer {
void _update_members_overview_visibility();
void _update_members_overview();
void _update_script_names();
+ bool _sort_list_on_update;
void _members_overview_selected(int p_idx);
void _script_selected(int p_idx);
@@ -306,8 +309,15 @@ class ScriptEditor : public PanelContainer {
void _script_split_dragged(float);
+ Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
+ bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
+ void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+
void _unhandled_input(const Ref<InputEvent> &p_event);
+ void _script_list_gui_input(const Ref<InputEvent> &ev);
+ void _make_script_list_context_menu();
+
void _help_search(String p_text);
void _help_index(String p_text);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index adf65c11e1..6b945157e8 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -850,7 +850,8 @@ void ScriptTextEditor::_edit_option(int p_op) {
if (line_id == 0 || next_id < 0)
return;
- swap_lines(tx, line_id, next_id);
+ tx->swap_lines(line_id, next_id);
+ tx->cursor_set_line(next_id);
}
int from_line_up = from_line > 0 ? from_line - 1 : from_line;
int to_line_up = to_line > 0 ? to_line - 1 : to_line;
@@ -862,7 +863,8 @@ void ScriptTextEditor::_edit_option(int p_op) {
if (line_id == 0 || next_id < 0)
return;
- swap_lines(tx, line_id, next_id);
+ tx->swap_lines(line_id, next_id);
+ tx->cursor_set_line(next_id);
}
tx->end_complex_operation();
tx->update();
@@ -889,7 +891,8 @@ void ScriptTextEditor::_edit_option(int p_op) {
if (line_id == tx->get_line_count() - 1 || next_id > tx->get_line_count())
return;
- swap_lines(tx, line_id, next_id);
+ tx->swap_lines(line_id, next_id);
+ tx->cursor_set_line(next_id);
}
int from_line_down = from_line < tx->get_line_count() ? from_line + 1 : from_line;
int to_line_down = to_line < tx->get_line_count() ? to_line + 1 : to_line;
@@ -901,7 +904,8 @@ void ScriptTextEditor::_edit_option(int p_op) {
if (line_id == tx->get_line_count() - 1 || next_id > tx->get_line_count())
return;
- swap_lines(tx, line_id, next_id);
+ tx->swap_lines(line_id, next_id);
+ tx->cursor_set_line(next_id);
}
tx->end_complex_operation();
tx->update();
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index f7dcc4b52d..49e4642049 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -248,6 +248,8 @@ void ShaderTextEditor::_validate_script() {
if (err != OK) {
String error_text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text();
set_error(error_text);
+ for (int i = 0; i < get_text_edit()->get_line_count(); i++)
+ get_text_edit()->set_line_as_marked(i, false);
get_text_edit()->set_line_as_marked(sl.get_error_line() - 1, true);
} else {
@@ -269,55 +271,284 @@ ShaderTextEditor::ShaderTextEditor() {
void ShaderEditor::_menu_option(int p_option) {
- ShaderTextEditor *current = shader_editor;
-
switch (p_option) {
case EDIT_UNDO: {
-
- current->get_text_edit()->undo();
+ shader_editor->get_text_edit()->undo();
} break;
case EDIT_REDO: {
- current->get_text_edit()->redo();
-
+ shader_editor->get_text_edit()->redo();
} break;
case EDIT_CUT: {
-
- current->get_text_edit()->cut();
+ shader_editor->get_text_edit()->cut();
} break;
case EDIT_COPY: {
- current->get_text_edit()->copy();
-
+ shader_editor->get_text_edit()->copy();
} break;
case EDIT_PASTE: {
- current->get_text_edit()->paste();
-
+ shader_editor->get_text_edit()->paste();
} break;
case EDIT_SELECT_ALL: {
+ shader_editor->get_text_edit()->select_all();
+ } break;
+ case EDIT_MOVE_LINE_UP: {
+
+ TextEdit *tx = shader_editor->get_text_edit();
+ if (shader.is_null())
+ return;
+
+ tx->begin_complex_operation();
+ if (tx->is_selection_active()) {
+ int from_line = tx->get_selection_from_line();
+ int from_col = tx->get_selection_from_column();
+ int to_line = tx->get_selection_to_line();
+ int to_column = tx->get_selection_to_column();
+
+ for (int i = from_line; i <= to_line; i++) {
+ int line_id = i;
+ int next_id = i - 1;
+
+ if (line_id == 0 || next_id < 0)
+ return;
+
+ tx->swap_lines(line_id, next_id);
+ tx->cursor_set_line(next_id);
+ }
+ int from_line_up = from_line > 0 ? from_line - 1 : from_line;
+ int to_line_up = to_line > 0 ? to_line - 1 : to_line;
+ tx->select(from_line_up, from_col, to_line_up, to_column);
+ } else {
+ int line_id = tx->cursor_get_line();
+ int next_id = line_id - 1;
+
+ if (line_id == 0 || next_id < 0)
+ return;
+
+ tx->swap_lines(line_id, next_id);
+ tx->cursor_set_line(next_id);
+ }
+ tx->end_complex_operation();
+ tx->update();
+
+ } break;
+ case EDIT_MOVE_LINE_DOWN: {
+
+ TextEdit *tx = shader_editor->get_text_edit();
+ if (shader.is_null())
+ return;
+
+ tx->begin_complex_operation();
+ if (tx->is_selection_active()) {
+ int from_line = tx->get_selection_from_line();
+ int from_col = tx->get_selection_from_column();
+ int to_line = tx->get_selection_to_line();
+ int to_column = tx->get_selection_to_column();
+
+ for (int i = to_line; i >= from_line; i--) {
+ int line_id = i;
+ int next_id = i + 1;
+
+ if (line_id == tx->get_line_count() - 1 || next_id > tx->get_line_count())
+ return;
+
+ tx->swap_lines(line_id, next_id);
+ tx->cursor_set_line(next_id);
+ }
+ int from_line_down = from_line < tx->get_line_count() ? from_line + 1 : from_line;
+ int to_line_down = to_line < tx->get_line_count() ? to_line + 1 : to_line;
+ tx->select(from_line_down, from_col, to_line_down, to_column);
+ } else {
+ int line_id = tx->cursor_get_line();
+ int next_id = line_id + 1;
+
+ if (line_id == tx->get_line_count() - 1 || next_id > tx->get_line_count())
+ return;
+
+ tx->swap_lines(line_id, next_id);
+ tx->cursor_set_line(next_id);
+ }
+ tx->end_complex_operation();
+ tx->update();
+
+ } break;
+ case EDIT_INDENT_LEFT: {
+
+ TextEdit *tx = shader_editor->get_text_edit();
+ if (shader.is_null())
+ return;
+
+ tx->begin_complex_operation();
+ if (tx->is_selection_active()) {
+ tx->indent_selection_left();
+ } else {
+ int begin = tx->cursor_get_line();
+ String line_text = tx->get_line(begin);
+ // begins with tab
+ if (line_text.begins_with("\t")) {
+ line_text = line_text.substr(1, line_text.length());
+ tx->set_line(begin, line_text);
+ }
+ // begins with 4 spaces
+ else if (line_text.begins_with(" ")) {
+ line_text = line_text.substr(4, line_text.length());
+ tx->set_line(begin, line_text);
+ }
+ }
+ tx->end_complex_operation();
+ tx->update();
+ //tx->deselect();
+
+ } break;
+ case EDIT_INDENT_RIGHT: {
+
+ TextEdit *tx = shader_editor->get_text_edit();
+ if (shader.is_null())
+ return;
+
+ tx->begin_complex_operation();
+ if (tx->is_selection_active()) {
+ tx->indent_selection_right();
+ } else {
+ int begin = tx->cursor_get_line();
+ String line_text = tx->get_line(begin);
+ line_text = '\t' + line_text;
+ tx->set_line(begin, line_text);
+ }
+ tx->end_complex_operation();
+ tx->update();
+ //tx->deselect();
+
+ } break;
+ case EDIT_DELETE_LINE: {
- current->get_text_edit()->select_all();
+ TextEdit *tx = shader_editor->get_text_edit();
+ if (shader.is_null())
+ return;
+
+ tx->begin_complex_operation();
+ int line = tx->cursor_get_line();
+ tx->set_line(tx->cursor_get_line(), "");
+ tx->backspace_at_cursor();
+ tx->cursor_set_line(line);
+ tx->end_complex_operation();
} break;
+ case EDIT_CLONE_DOWN: {
+
+ TextEdit *tx = shader_editor->get_text_edit();
+ if (shader.is_null())
+ return;
+
+ int from_line = tx->cursor_get_line();
+ int to_line = tx->cursor_get_line();
+ int column = tx->cursor_get_column();
+
+ if (tx->is_selection_active()) {
+ from_line = tx->get_selection_from_line();
+ to_line = tx->get_selection_to_line();
+ column = tx->cursor_get_column();
+ }
+ int next_line = to_line + 1;
+
+ tx->begin_complex_operation();
+ for (int i = from_line; i <= to_line; i++) {
+
+ if (i >= tx->get_line_count() - 1) {
+ tx->set_line(i, tx->get_line(i) + "\n");
+ }
+ String line_clone = tx->get_line(i);
+ tx->insert_at(line_clone, next_line);
+ next_line++;
+ }
+
+ tx->cursor_set_column(column);
+ if (tx->is_selection_active()) {
+ tx->select(to_line + 1, tx->get_selection_from_column(), next_line - 1, tx->get_selection_to_column());
+ }
+
+ tx->end_complex_operation();
+ tx->update();
+
+ } break;
+ case EDIT_TOGGLE_COMMENT: {
+
+ TextEdit *tx = shader_editor->get_text_edit();
+ if (shader.is_null())
+ return;
+
+ tx->begin_complex_operation();
+ if (tx->is_selection_active()) {
+ int begin = tx->get_selection_from_line();
+ int end = tx->get_selection_to_line();
+
+ // End of selection ends on the first column of the last line, ignore it.
+ if (tx->get_selection_to_column() == 0)
+ end -= 1;
+
+ // Check if all lines in the selected block are commented
+ bool is_commented = true;
+ for (int i = begin; i <= end; i++) {
+ if (!tx->get_line(i).begins_with("//")) {
+ is_commented = false;
+ break;
+ }
+ }
+ for (int i = begin; i <= end; i++) {
+ String line_text = tx->get_line(i);
+
+ if (line_text.strip_edges().empty()) {
+ line_text = "//";
+ } else {
+ if (is_commented) {
+ line_text = line_text.substr(2, line_text.length());
+ } else {
+ line_text = "//" + line_text;
+ }
+ }
+ tx->set_line(i, line_text);
+ }
+ } else {
+ int begin = tx->cursor_get_line();
+ String line_text = tx->get_line(begin);
+
+ if (line_text.begins_with("//"))
+ line_text = line_text.substr(2, line_text.length());
+ else
+ line_text = "//" + line_text;
+ tx->set_line(begin, line_text);
+ }
+ tx->end_complex_operation();
+ tx->update();
+ //tx->deselect();
+
+ } break;
+ case EDIT_COMPLETE: {
+
+ shader_editor->get_text_edit()->query_code_comple();
+ } break;
case SEARCH_FIND: {
- current->get_find_replace_bar()->popup_search();
+ shader_editor->get_find_replace_bar()->popup_search();
} break;
case SEARCH_FIND_NEXT: {
- current->get_find_replace_bar()->search_next();
+ shader_editor->get_find_replace_bar()->search_next();
} break;
case SEARCH_FIND_PREV: {
- current->get_find_replace_bar()->search_prev();
+ shader_editor->get_find_replace_bar()->search_prev();
} break;
case SEARCH_REPLACE: {
- current->get_find_replace_bar()->popup_replace();
+ shader_editor->get_find_replace_bar()->popup_replace();
} break;
case SEARCH_GOTO_LINE: {
- goto_line_dialog->popup_find_line(current->get_text_edit());
+ goto_line_dialog->popup_find_line(shader_editor->get_text_edit());
} break;
}
+ if (p_option != SEARCH_FIND && p_option != SEARCH_REPLACE && p_option != SEARCH_GOTO_LINE) {
+ shader_editor->get_text_edit()->call_deferred("grab_focus");
+ }
}
void ShaderEditor::_notification(int p_what) {
@@ -325,10 +556,6 @@ void ShaderEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
}
if (p_what == NOTIFICATION_DRAW) {
-
- RID ci = get_canvas_item();
- Ref<StyleBox> style = get_stylebox("panel", "Panel");
- style->draw(ci, Rect2(Point2(), get_size()));
}
}
@@ -360,6 +587,7 @@ void ShaderEditor::_editor_settings_changed() {
void ShaderEditor::_bind_methods() {
ClassDB::bind_method("_editor_settings_changed", &ShaderEditor::_editor_settings_changed);
+ ClassDB::bind_method("_text_edit_gui_input", &ShaderEditor::_text_edit_gui_input);
ClassDB::bind_method("_menu_option", &ShaderEditor::_menu_option);
ClassDB::bind_method("_params_changed", &ShaderEditor::_params_changed);
@@ -413,49 +641,122 @@ void ShaderEditor::apply_shaders() {
}
}
-ShaderEditor::ShaderEditor() {
+void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
- HBoxContainer *hbc = memnew(HBoxContainer);
+ Ref<InputEventMouseButton> mb = ev;
- add_child(hbc);
+ if (mb.is_valid()) {
+
+ if (mb->get_button_index() == BUTTON_RIGHT && !mb->is_pressed()) {
+
+ int col, row;
+ TextEdit *tx = shader_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();
+ bool have_selection = (tx->get_selection_text().length() > 0);
+ _make_context_menu(have_selection);
+ }
+ }
+}
+
+void ShaderEditor::_make_context_menu(bool p_selection) {
+
+ context_menu->clear();
+ if (p_selection) {
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/cut"), EDIT_CUT);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/copy"), EDIT_COPY);
+ }
+
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/paste"), EDIT_PASTE);
+ context_menu->add_separator();
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/select_all"), EDIT_SELECT_ALL);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO);
+
+ context_menu->add_separator();
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_left"), EDIT_INDENT_LEFT);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_right"), EDIT_INDENT_RIGHT);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT);
+
+ context_menu->set_position(get_global_transform().xform(get_local_mouse_position()));
+ context_menu->set_size(Vector2(1, 1));
+ context_menu->popup();
+}
+
+ShaderEditor::ShaderEditor(EditorNode *p_node) {
+
+ shader_editor = memnew(ShaderTextEditor);
+ shader_editor->set_v_size_flags(SIZE_EXPAND_FILL);
+ shader_editor->add_constant_override("separation", 0);
+ shader_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+
+ shader_editor->connect("script_changed", this, "apply_shaders");
+ EditorSettings::get_singleton()->connect("settings_changed", this, "_editor_settings_changed");
+
+ shader_editor->get_text_edit()->set_callhint_settings(
+ EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"),
+ EditorSettings::get_singleton()->get("text_editor/completion/callhint_tooltip_offset"));
+
+ shader_editor->get_text_edit()->set_select_identifiers_on_hover(true);
+ shader_editor->get_text_edit()->set_context_menu_enabled(false);
+ shader_editor->get_text_edit()->connect("gui_input", this, "_text_edit_gui_input");
+
+ shader_editor->update_editor_settings();
+
+ context_menu = memnew(PopupMenu);
+ add_child(context_menu);
+ context_menu->connect("id_pressed", this, "_menu_option");
+
+ VBoxContainer *main_container = memnew(VBoxContainer);
+ HBoxContainer *hbc = memnew(HBoxContainer);
edit_menu = memnew(MenuButton);
- hbc->add_child(edit_menu);
- edit_menu->set_position(Point2(5, -1));
+ //edit_menu->set_position(Point2(5, -1));
edit_menu->set_text(TTR("Edit"));
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/undo", TTR("Undo"), KEY_MASK_CMD | KEY_Z), EDIT_UNDO);
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/redo", TTR("Redo"), KEY_MASK_CMD | KEY_Y), EDIT_REDO);
+
+ 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();
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/cut"), EDIT_CUT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/copy"), EDIT_COPY);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/paste"), EDIT_PASTE);
+ edit_menu->get_popup()->add_separator();
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/select_all"), EDIT_SELECT_ALL);
edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/cut", TTR("Cut"), KEY_MASK_CMD | KEY_X), EDIT_CUT);
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/copy", TTR("Copy"), KEY_MASK_CMD | KEY_C), EDIT_COPY);
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/paste", TTR("Paste"), KEY_MASK_CMD | KEY_V), EDIT_PASTE);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/move_up"), EDIT_MOVE_LINE_UP);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/move_down"), EDIT_MOVE_LINE_DOWN);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_left"), EDIT_INDENT_LEFT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_right"), EDIT_INDENT_RIGHT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/delete_line"), EDIT_DELETE_LINE);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/clone_down"), EDIT_CLONE_DOWN);
edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/select_all", TTR("Select All"), KEY_MASK_CMD | KEY_A), EDIT_SELECT_ALL);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/complete_symbol"), EDIT_COMPLETE);
+
edit_menu->get_popup()->connect("id_pressed", this, "_menu_option");
search_menu = memnew(MenuButton);
- hbc->add_child(search_menu);
- search_menu->set_position(Point2(38, -1));
+ //search_menu->set_position(Point2(38, -1));
search_menu->set_text(TTR("Search"));
- search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find", TTR("Find.."), KEY_MASK_CMD | KEY_F), SEARCH_FIND);
- search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_next", TTR("Find Next"), KEY_F3), SEARCH_FIND_NEXT);
- search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_previous", TTR("Find Previous"), KEY_MASK_SHIFT | KEY_F3), SEARCH_FIND_PREV);
- search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/replace", TTR("Replace.."), KEY_MASK_CMD | KEY_R), SEARCH_REPLACE);
+
+ 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);
+ search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/replace"), SEARCH_REPLACE);
search_menu->get_popup()->add_separator();
- //search_menu->get_popup()->add_item("Locate Symbol..",SEARCH_LOCATE_SYMBOL,KEY_MASK_CMD|KEY_K);
- search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/goto_line", TTR("Goto Line.."), KEY_MASK_CMD | KEY_L), SEARCH_GOTO_LINE);
+ search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_line"), SEARCH_GOTO_LINE);
search_menu->get_popup()->connect("id_pressed", this, "_menu_option");
+ add_child(main_container);
+ main_container->add_child(hbc);
+ hbc->add_child(search_menu);
+ hbc->add_child(edit_menu);
+ hbc->add_style_override("panel", p_node->get_gui_base()->get_stylebox("ScriptEditorPanel", "EditorStyles"));
+ main_container->add_child(shader_editor);
+
goto_line_dialog = memnew(GotoLineDialog);
add_child(goto_line_dialog);
- shader_editor = memnew(ShaderTextEditor);
- add_child(shader_editor);
- shader_editor->set_v_size_flags(SIZE_EXPAND_FILL);
-
- shader_editor->connect("script_changed", this, "apply_shaders");
- EditorSettings::get_singleton()->connect("settings_changed", this, "_editor_settings_changed");
-
_editor_settings_changed();
}
@@ -504,7 +805,7 @@ void ShaderEditorPlugin::apply_changes() {
ShaderEditorPlugin::ShaderEditorPlugin(EditorNode *p_node) {
editor = p_node;
- shader_editor = memnew(ShaderEditor);
+ shader_editor = memnew(ShaderEditor(p_node));
shader_editor->set_custom_minimum_size(Size2(0, 300));
button = editor->add_bottom_panel_item(TTR("Shader"), shader_editor);
diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h
index ab18784d9f..b191f5700f 100644
--- a/editor/plugins/shader_editor_plugin.h
+++ b/editor/plugins/shader_editor_plugin.h
@@ -33,6 +33,7 @@
#include "editor/code_editor.h"
#include "editor/editor_plugin.h"
#include "scene/gui/menu_button.h"
+#include "scene/gui/panel_container.h"
#include "scene/gui/tab_container.h"
#include "scene/gui/text_edit.h"
#include "scene/main/timer.h"
@@ -61,9 +62,9 @@ public:
ShaderTextEditor();
};
-class ShaderEditor : public VBoxContainer {
+class ShaderEditor : public PanelContainer {
- GDCLASS(ShaderEditor, VBoxContainer);
+ GDCLASS(ShaderEditor, PanelContainer);
enum {
@@ -73,6 +74,14 @@ class ShaderEditor : public VBoxContainer {
EDIT_COPY,
EDIT_PASTE,
EDIT_SELECT_ALL,
+ EDIT_MOVE_LINE_UP,
+ EDIT_MOVE_LINE_DOWN,
+ EDIT_INDENT_LEFT,
+ EDIT_INDENT_RIGHT,
+ EDIT_DELETE_LINE,
+ EDIT_CLONE_DOWN,
+ EDIT_TOGGLE_COMMENT,
+ EDIT_COMPLETE,
SEARCH_FIND,
SEARCH_FIND_NEXT,
SEARCH_FIND_PREV,
@@ -84,6 +93,7 @@ class ShaderEditor : public VBoxContainer {
MenuButton *edit_menu;
MenuButton *search_menu;
MenuButton *settings_menu;
+ PopupMenu *context_menu;
uint64_t idle;
GotoLineDialog *goto_line_dialog;
@@ -100,6 +110,8 @@ class ShaderEditor : public VBoxContainer {
protected:
void _notification(int p_what);
static void _bind_methods();
+ void _make_context_menu(bool p_selection);
+ void _text_edit_gui_input(const Ref<InputEvent> &ev);
public:
void apply_shaders();
@@ -110,7 +122,7 @@ public:
virtual Size2 get_minimum_size() const { return Size2(0, 200); }
void save_external_data();
- ShaderEditor();
+ ShaderEditor(EditorNode *p_node);
};
class ShaderEditorPlugin : public EditorPlugin {
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index 25ca2d731e..ca80908ab5 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -1255,7 +1255,6 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
Vector3 motion_mask;
Plane plane;
- bool plane_mv;
switch (_edit.plane) {
case TRANSFORM_VIEW:
@@ -1285,12 +1284,10 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
break;
Vector3 motion = intersection - click;
- print_line(String(intersection) + " --- " + String(click));
if (motion_mask != Vector3()) {
-
motion = motion_mask.dot(motion) * motion_mask;
- } else {
+ } else {
float center_click_dist = click.distance_to(_edit.center);
float center_inters_dist = intersection.distance_to(_edit.center);
if (center_click_dist == 0)
@@ -1302,12 +1299,19 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
List<Node *> &selection = editor_selection->get_selected_node_list();
- bool local_coords = (spatial_editor->are_local_coords_enabled() && motion_mask != Vector3()); // Disable local transformation for TRANSFORM_VIEW
+ bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); // Disable local transformation for TRANSFORM_VIEW
float snap = 0;
if (_edit.snap || spatial_editor->is_snap_enabled()) {
snap = spatial_editor->get_scale_snap() / 100;
+
+ Vector3 motion_snapped = motion;
+ motion_snapped.snap(Vector3(snap, snap, snap));
+ set_message(TTR("Scaling: ") + motion_snapped);
+
+ } else {
+ set_message(TTR("Scaling: ") + motion);
}
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
@@ -1339,6 +1343,15 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
local_scale = original_local.basis.get_scale() * (local_motion + Vector3(1, 1, 1));
+ // Prevent scaling to 0 it would break the gizmo
+ Basis check = original_local.basis;
+ check.scale(local_scale);
+ if (check.determinant() != 0) {
+
+ // Apply scale
+ sp->set_scale(local_scale);
+ }
+
} else {
if (_edit.snap || spatial_editor->is_snap_enabled()) {
@@ -1348,12 +1361,8 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
Transform r;
r.basis.scale(motion + Vector3(1, 1, 1));
t = base * (r * (base.inverse() * original));
- }
- // Apply scale
- if (local_coords) {
- sp->set_scale(local_scale);
- } else {
+ // Apply scale
sp->set_global_transform(t);
}
}
@@ -1366,7 +1375,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
Vector3 motion_mask;
Plane plane;
- bool plane_mv;
+ bool plane_mv = false;
switch (_edit.plane) {
case TRANSFORM_VIEW:
@@ -1386,17 +1395,14 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
plane = Plane(_edit.center, motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized());
break;
case TRANSFORM_YZ:
- motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2) + spatial_editor->get_gizmo_transform().basis.get_axis(1);
plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(0));
plane_mv = true;
break;
case TRANSFORM_XZ:
- motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2) + spatial_editor->get_gizmo_transform().basis.get_axis(0);
plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(1));
plane_mv = true;
break;
case TRANSFORM_XY:
- motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0) + spatial_editor->get_gizmo_transform().basis.get_axis(1);
plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(2));
plane_mv = true;
break;
@@ -1410,55 +1416,27 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (!plane.intersects_ray(_edit.click_ray_pos, _edit.click_ray, &click))
break;
- //_validate_selection();
Vector3 motion = intersection - click;
if (motion_mask != Vector3()) {
- if (plane_mv)
- motion *= motion_mask;
- else
+ if (!plane_mv) {
motion = motion_mask.dot(motion) * motion_mask;
+ }
}
- //set_message("Translating: "+motion);
-
List<Node *> &selection = editor_selection->get_selected_node_list();
- float snap = 0;
+ bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); // Disable local transformation for TRANSFORM_VIEW
+ float snap = 0;
if (_edit.snap || spatial_editor->is_snap_enabled()) {
snap = spatial_editor->get_translate_snap();
- bool local_coords = spatial_editor->are_local_coords_enabled();
-
- if (local_coords) {
- bool multiple = false;
- Spatial *node = NULL;
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
-
- Spatial *sp = Object::cast_to<Spatial>(E->get());
- if (!sp) {
- continue;
- }
- if (node) {
- multiple = true;
- break;
- } else {
- node = sp;
- }
- }
-
- if (multiple) {
- motion.snap(Vector3(snap, snap, snap));
- } else {
- Basis b = node->get_global_transform().basis.orthonormalized();
- Vector3 local_motion = b.inverse().xform(motion);
- local_motion.snap(Vector3(snap, snap, snap));
- motion = b.xform(local_motion);
- }
- } else {
- motion.snap(Vector3(snap, snap, snap));
- }
+ Vector3 motion_snapped = motion;
+ motion_snapped.snap(Vector3(snap, snap, snap));
+ set_message(TTR("Translating: ") + motion_snapped);
+ } else {
+ set_message(TTR("Translating: ") + motion);
}
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
@@ -1473,10 +1451,34 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
continue;
}
- Transform t = se->original;
+ Transform original = se->original;
+ Transform t;
+
+ if (local_coords) {
+
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+ Basis g = original.basis.orthonormalized();
+ Vector3 local_motion = g.inverse().xform(motion);
+ local_motion.snap(Vector3(snap, snap, snap));
+
+ motion = g.xform(local_motion);
+ }
+
+ } else {
+
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+ motion.snap(Vector3(snap, snap, snap));
+ }
+ }
+
+ // Apply translation
+ t = original;
t.origin += motion;
sp->set_global_transform(t);
}
+
+ surface->update();
+
} break;
case TRANSFORM_ROTATE: {
@@ -1533,7 +1535,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
List<Node *> &selection = editor_selection->get_selected_node_list();
- bool local_coords = spatial_editor->are_local_coords_enabled();
+ bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); // Disable local transformation for TRANSFORM_VIEW
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
@@ -1552,10 +1554,12 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
Transform original_local = se->original_local;
Basis rot = Basis(axis, angle);
- t.basis = original_local.get_basis() * rot;
+ t.basis = original_local.get_basis().orthonormalized() * rot;
t.origin = original_local.origin;
+ // Apply rotation
sp->set_transform(t);
+ sp->set_scale(original_local.basis.get_scale()); // re-apply original scale
} else {
@@ -1566,6 +1570,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
r.basis.rotate(plane.normal, angle);
t = base * r * base.inverse() * original;
+ // Apply rotation
sp->set_global_transform(t);
}
}
@@ -1803,6 +1808,11 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (!k->is_pressed()) emit_signal("toggle_maximize_view", this);
}
}
+
+ // freelook uses most of the useful shortcuts, like save, so its ok
+ // to consider freelook active as end of the line for future events.
+ if (freelook_active)
+ accept_event();
}
void SpatialEditorViewport::set_freelook_active(bool active_now) {
@@ -2911,7 +2921,9 @@ bool SpatialEditorViewport::_create_instance(Node *parent, String &path, const P
}
}
- instanced_scene->set_filename(ProjectSettings::get_singleton()->localize_path(path));
+ if (scene != NULL) {
+ instanced_scene->set_filename(ProjectSettings::get_singleton()->localize_path(path));
+ }
editor_data->get_undo_redo().add_do_method(parent, "add_child", instanced_scene);
editor_data->get_undo_redo().add_do_method(instanced_scene, "set_owner", editor->get_edited_scene());
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index 8870166dba..48aed0cf6c 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -860,6 +860,7 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) {
hb_tools->add_child(separator);
icon_zoom = memnew(TextureRect);
+ icon_zoom->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
hb_tools->add_child(icon_zoom);
zoom_out = memnew(ToolButton);
diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp
index 9235dafaa6..0ee0eed3a2 100644
--- a/editor/plugins/tile_map_editor_plugin.cpp
+++ b/editor/plugins/tile_map_editor_plugin.cpp
@@ -973,7 +973,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
Point2i pos = points[i];
- if (!paint_undo.has(over_tile)) {
+ if (!paint_undo.has(pos)) {
paint_undo[pos] = _get_op_from_cell(pos);
}
@@ -993,7 +993,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
Point2i pos = points[i];
- if (!paint_undo.has(over_tile)) {
+ if (!paint_undo.has(pos)) {
paint_undo[pos] = _get_op_from_cell(pos);
}
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index eac5720b43..dda2851166 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -308,7 +308,7 @@ void ProjectExportDialog::_patch_button_pressed(Object *p_item, int p_column, in
if (p_id == 0) {
Vector<String> patches = current->get_patches();
ERR_FAIL_INDEX(patch_index, patches.size());
- patch_erase->set_text(vformat(TTR("Delete patch '" + patches[patch_index].get_file() + "' from list?")));
+ patch_erase->set_text(vformat(TTR("Delete patch '%s' from list?"), patches[patch_index].get_file()));
patch_erase->popup_centered_minsize();
} else {
patch_dialog->popup_centered_ratio();
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 18416868ec..cc9de3e44d 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -284,7 +284,6 @@ private:
}
ProjectSettings *current = memnew(ProjectSettings);
- current->add_singleton(ProjectSettings::Singleton("Current"));
if (current->setup(dir, "")) {
set_message(TTR("Couldn't get project.godot in project path."), MESSAGE_ERROR);
@@ -503,7 +502,6 @@ public:
name_container->show();
ProjectSettings *current = memnew(ProjectSettings);
- current->add_singleton(ProjectSettings::Singleton("Current"));
if (current->setup(project_path->get_text(), "")) {
set_message(TTR("Couldn't get project.godot in the project path."), MESSAGE_ERROR);
@@ -1053,7 +1051,7 @@ void ProjectManager::_load_recent_projects() {
ec->set_custom_minimum_size(Size2(0, 1));
vb->add_child(ec);
Label *title = memnew(Label(project_name));
- title->add_font_override("font", gui_base->get_font("large", "Fonts"));
+ title->add_font_override("font", gui_base->get_font("title", "EditorFonts"));
title->add_color_override("font_color", font_color);
title->set_clip_text(true);
vb->add_child(title);
@@ -1492,7 +1490,6 @@ ProjectManager::ProjectManager() {
CenterContainer *ccl = memnew(CenterContainer);
Label *l = memnew(Label);
l->set_text(_MKSTR(VERSION_NAME) + String(" - ") + TTR("Project Manager"));
- l->add_font_override("font", gui_base->get_font("doc", "EditorFonts"));
ccl->add_child(l);
top_hb->add_child(ccl);
top_hb->add_spacer();
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index b21c176543..b07280a4cd 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -785,12 +785,12 @@ void ProjectSettingsEditor::_item_del() {
String property = globals_editor->get_current_section().plus_file(path);
if (!ProjectSettings::get_singleton()->has_setting(property)) {
- EditorNode::get_singleton()->show_warning(TTR("No property '" + property + "' exists."));
+ EditorNode::get_singleton()->show_warning(vformat(TTR("No property '%s' exists."), property));
return;
}
if (ProjectSettings::get_singleton()->get_order(property) < ProjectSettings::NO_BUILTIN_ORDER_BASE) {
- EditorNode::get_singleton()->show_warning(TTR("Setting '" + property + "' is internal, and it can't be deleted."));
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Setting '%s' is internal, and it can't be deleted."), property));
return;
}
@@ -1318,7 +1318,7 @@ void ProjectSettingsEditor::_update_translations() {
t->set_text(0, translations[i].replace_first("res://", ""));
t->set_tooltip(0, translations[i]);
t->set_metadata(0, i);
- t->add_button(0, get_icon("Del", "EditorIcons"), 0, false, TTR("Remove"));
+ t->add_button(0, get_icon("Remove", "EditorIcons"), 0, false, TTR("Remove"));
}
}
@@ -1436,7 +1436,7 @@ void ProjectSettingsEditor::_update_translations() {
t->set_text(0, keys[i].replace_first("res://", ""));
t->set_tooltip(0, keys[i]);
t->set_metadata(0, keys[i]);
- t->add_button(0, get_icon("Del", "EditorIcons"), 0, false, TTR("Remove"));
+ t->add_button(0, get_icon("Remove", "EditorIcons"), 0, false, TTR("Remove"));
if (keys[i] == remap_selected) {
t->select(0);
translation_res_option_add_button->set_disabled(false);
@@ -1454,7 +1454,7 @@ void ProjectSettingsEditor::_update_translations() {
t2->set_text(0, path.replace_first("res://", ""));
t2->set_tooltip(0, path);
t2->set_metadata(0, j);
- t2->add_button(0, get_icon("Del", "EditorIcons"), 0, false, TTR("Remove"));
+ t2->add_button(0, get_icon("Remove", "EditorIcons"), 0, false, TTR("Remove"));
t2->set_cell_mode(1, TreeItem::CELL_MODE_RANGE);
t2->set_text(1, langnames);
t2->set_editable(1, true);
@@ -1782,6 +1782,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
tab_container->add_child(translations);
//remap for properly select language in popup
translation_locales_idxs_remap = Vector<int>();
+ translation_locales_list_created = false;
{
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index f4d5530faa..002ae568ff 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -4258,7 +4258,7 @@ PropertyEditor::PropertyEditor() {
use_filter = false;
subsection_selectable = false;
property_selectable = false;
- show_type_icons = EDITOR_DEF("interface/editor/show_type_icons", false);
+ show_type_icons = false; // maybe one day will return.
}
PropertyEditor::~PropertyEditor() {
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 58f70ce11e..816156ef00 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -860,6 +860,14 @@ Node *SceneTreeDock::_duplicate(Node *p_node, Map<Node *, Node *> &duplimap) {
node->set(name, value);
}
+ List<Connection> conns;
+ p_node->get_all_signal_connections(&conns);
+ for (List<Connection>::Element *E = conns.front(); E; E = E->next()) {
+ if (E->get().flags & CONNECT_PERSIST) {
+ node->connect(E->get().signal, E->get().target, E->get().method, E->get().binds, E->get().flags);
+ }
+ }
+
List<Node::GroupInfo> group_info;
p_node->get_groups(&group_info);
for (List<Node::GroupInfo>::Element *E = group_info.front(); E; E = E->next()) {
@@ -1296,6 +1304,7 @@ void SceneTreeDock::_delete_confirm() {
editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", (Object *)NULL);
editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", edited_scene);
editor_data->get_undo_redo().add_undo_method(edited_scene, "set_owner", edited_scene->get_owner());
+ editor_data->get_undo_redo().add_undo_method(scene_tree, "update_tree");
editor_data->get_undo_redo().add_undo_reference(edited_scene);
} else {
@@ -1414,6 +1423,7 @@ void SceneTreeDock::_create() {
} else {
editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", child);
+ editor_data->get_undo_redo().add_do_method(scene_tree, "update_tree");
editor_data->get_undo_redo().add_do_reference(child);
editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", (Object *)NULL);
}
@@ -1878,6 +1888,43 @@ void SceneTreeDock::open_script_dialog(Node *p_for_node) {
_tool_selected(TOOL_ATTACH_SCRIPT);
}
+void SceneTreeDock::add_remote_tree_editor(Control *p_remote) {
+ ERR_FAIL_COND(remote_tree != NULL);
+ add_child(p_remote);
+ remote_tree = p_remote;
+ remote_tree->hide();
+}
+
+void SceneTreeDock::show_remote_tree() {
+
+ button_hb->show();
+ _remote_tree_selected();
+}
+
+void SceneTreeDock::hide_remote_tree() {
+
+ button_hb->hide();
+ _local_tree_selected();
+}
+
+void SceneTreeDock::_remote_tree_selected() {
+
+ scene_tree->hide();
+ if (remote_tree)
+ remote_tree->show();
+ edit_remote->set_pressed(true);
+ edit_local->set_pressed(false);
+}
+
+void SceneTreeDock::_local_tree_selected() {
+
+ scene_tree->show();
+ if (remote_tree)
+ remote_tree->hide();
+ edit_remote->set_pressed(false);
+ edit_local->set_pressed(true);
+}
+
void SceneTreeDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_tool_selected"), &SceneTreeDock::_tool_selected, DEFVAL(false));
@@ -1903,6 +1950,8 @@ void SceneTreeDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_tree_rmb"), &SceneTreeDock::_tree_rmb);
ClassDB::bind_method(D_METHOD("_filter_changed"), &SceneTreeDock::_filter_changed);
ClassDB::bind_method(D_METHOD("_focus_node"), &SceneTreeDock::_focus_node);
+ 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("instance"), &SceneTreeDock::instance);
}
@@ -1973,7 +2022,28 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
button_clear_script = tb;
tb->hide();
+ button_hb = memnew(HBoxContainer);
+ vbc->add_child(button_hb);
+
+ edit_remote = memnew(ToolButton);
+ button_hb->add_child(edit_remote);
+ edit_remote->set_h_size_flags(SIZE_EXPAND_FILL);
+ edit_remote->set_text(TTR("Remote"));
+ edit_remote->set_toggle_mode(true);
+ edit_remote->connect("pressed", this, "_remote_tree_selected");
+
+ edit_local = memnew(ToolButton);
+ button_hb->add_child(edit_local);
+ edit_local->set_h_size_flags(SIZE_EXPAND_FILL);
+ edit_local->set_text(TTR("Local"));
+ edit_local->set_toggle_mode(true);
+ edit_local->connect("pressed", this, "_local_tree_selected");
+
+ remote_tree = NULL;
+ button_hb->hide();
+
scene_tree = memnew(SceneTreeEditor(false, true, true));
+
vbc->add_child(scene_tree);
scene_tree->set_v_size_flags(SIZE_EXPAND | SIZE_FILL);
scene_tree->connect("rmb_pressed", this, "_tree_rmb");
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index f61c67bb13..97d3c4748a 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -95,7 +95,10 @@ class SceneTreeDock : public VBoxContainer {
ToolButton *button_create_script;
ToolButton *button_clear_script;
+ HBoxContainer *button_hb;
+ ToolButton *edit_local, *edit_remote;
SceneTreeEditor *scene_tree;
+ Control *remote_tree;
HBoxContainer *tool_hbc;
void _tool_selected(int p_tool, bool p_confirm_override = false);
@@ -174,6 +177,9 @@ class SceneTreeDock : public VBoxContainer {
void _file_selected(String p_file);
+ void _remote_tree_selected();
+ void _local_tree_selected();
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -194,6 +200,10 @@ public:
SceneTreeEditor *get_tree_editor() { return scene_tree; }
EditorData *get_editor_data() { return editor_data; }
+ void add_remote_tree_editor(Control *p_remote);
+ void show_remote_tree();
+ void hide_remote_tree();
+
void open_script_dialog(Node *p_for_node);
SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSelection *p_editor_selection, EditorData &p_editor_data);
};
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index a6e0af05b2..c4b86c6b2b 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -354,7 +354,11 @@ void SceneTreeEditor::_update_visibility_color(Node *p_node, TreeItem *p_item) {
void SceneTreeEditor::_node_script_changed(Node *p_node) {
- _update_tree();
+ if (tree_dirty)
+ return;
+
+ MessageQueue::get_singleton()->push_call(this, "_update_tree");
+ tree_dirty = true;
/*
changes the order :|
TreeItem* item=p_node?_find(tree->get_root(),p_node->get_path()):NULL;
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index c19b80e649..0f1712c224 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -703,9 +703,7 @@ ScriptCreateDialog::ScriptCreateDialog() {
internal = memnew(CheckButton);
internal->connect("pressed", this, "_built_in_pressed");
hb = memnew(HBoxContainer);
- Control *empty = memnew(Control);
hb->add_child(internal);
- hb->add_child(empty);
l = memnew(Label);
l->set_text(TTR("Built-in Script"));
l->set_align(Label::ALIGN_RIGHT);