summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/animation_bezier_editor.cpp54
-rw-r--r--editor/animation_track_editor.cpp29
-rw-r--r--editor/editor_settings.cpp2
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp12
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp12
-rw-r--r--editor/project_manager.cpp2
-rw-r--r--editor/script_create_dialog.cpp169
-rw-r--r--editor/script_create_dialog.h1
8 files changed, 139 insertions, 142 deletions
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp
index f6d4a2665c..e524dffd43 100644
--- a/editor/animation_bezier_editor.cpp
+++ b/editor/animation_bezier_editor.cpp
@@ -453,6 +453,8 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
ep.point_rect.size = bezier_icon->get_size();
if (selection.has(i)) {
draw_texture(selected_icon, ep.point_rect.position);
+ draw_string(font, ep.point_rect.position + Vector2(8, -font->get_height() - 4), TTR("Time:") + " " + rtos(Math::stepify(offset, 0.001)), accent);
+ draw_string(font, ep.point_rect.position + Vector2(8, -8), TTR("Value:") + " " + rtos(Math::stepify(value, 0.001)), accent);
} else {
draw_texture(bezier_icon, ep.point_rect.position);
}
@@ -518,6 +520,12 @@ void AnimationBezierTrackEdit::set_animation_and_track(const Ref<Animation> &p_a
animation = p_animation;
track = p_track;
+ if (is_connected("select_key", editor, "_key_selected"))
+ disconnect("select_key", editor, "_key_selected");
+ if (is_connected("deselect_key", editor, "_key_deselected"))
+ disconnect("deselect_key", editor, "_key_deselected");
+ connect("select_key", editor, "_key_selected", varray(p_track), CONNECT_DEFERRED);
+ connect("deselect_key", editor, "_key_deselected", varray(p_track), CONNECT_DEFERRED);
update();
}
@@ -536,6 +544,7 @@ void AnimationBezierTrackEdit::set_timeline(AnimationTimelineEdit *p_timeline) {
}
void AnimationBezierTrackEdit::set_editor(AnimationTrackEditor *p_editor) {
editor = p_editor;
+ connect("clear_selection", editor, "_clear_selection");
}
void AnimationBezierTrackEdit::_play_position_draw() {
@@ -578,6 +587,7 @@ String AnimationBezierTrackEdit::get_tooltip(const Point2 &p_pos) const {
void AnimationBezierTrackEdit::_clear_selection() {
selection.clear();
+ emit_signal("clear_selection");
update();
}
@@ -598,6 +608,7 @@ void AnimationBezierTrackEdit::_select_at_anim(const Ref<Animation> &p_anim, int
ERR_FAIL_COND(idx < 0);
selection.insert(idx);
+ emit_signal("select_key", idx, true);
update();
}
@@ -653,20 +664,22 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
menu_insert_key = mb->get_position();
- Vector2 popup_pos = get_global_transform().xform(mb->get_position());
-
- menu->clear();
- menu->add_icon_item(bezier_icon, TTR("Insert Key Here"), MENU_KEY_INSERT);
- if (selection.size()) {
- menu->add_separator();
- menu->add_icon_item(get_icon("Duplicate", "EditorIcons"), TTR("Duplicate Selected Key(s)"), MENU_KEY_DUPLICATE);
- menu->add_separator();
- menu->add_icon_item(get_icon("Remove", "EditorIcons"), TTR("Delete Selected Key(s)"), MENU_KEY_DELETE);
- }
+ if (menu_insert_key.x >= timeline->get_name_limit() && menu_insert_key.x <= get_size().width - timeline->get_buttons_width()) {
+ Vector2 popup_pos = get_global_transform().xform(mb->get_position());
+
+ menu->clear();
+ menu->add_icon_item(bezier_icon, TTR("Insert Key Here"), MENU_KEY_INSERT);
+ if (selection.size()) {
+ menu->add_separator();
+ menu->add_icon_item(get_icon("Duplicate", "EditorIcons"), TTR("Duplicate Selected Key(s)"), MENU_KEY_DUPLICATE);
+ menu->add_separator();
+ menu->add_icon_item(get_icon("Remove", "EditorIcons"), TTR("Delete Selected Key(s)"), MENU_KEY_DELETE);
+ }
- menu->set_as_minsize();
- menu->set_position(popup_pos);
- menu->popup();
+ menu->set_as_minsize();
+ menu->set_position(popup_pos);
+ menu->popup();
+ }
}
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
@@ -678,6 +691,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
for (Map<int, Rect2>::Element *E = subtracks.front(); E; E = E->next()) {
if (E->get().has_point(mb->get_position())) {
set_animation_and_track(animation, E->key());
+ _clear_selection();
return;
}
}
@@ -850,7 +864,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
// 2- remove overlapped keys
for (Set<int>::Element *E = selection.back(); E; E = E->prev()) {
- float newtime = animation->track_get_key_time(track, E->get()) + moving_selection_offset.x;
+ float newtime = editor->snap_time(animation->track_get_key_time(track, E->get()) + moving_selection_offset.x);
int idx = animation->track_find_key(track, newtime, true);
if (idx == -1)
@@ -872,7 +886,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
// 3-move the keys (re insert them)
for (Set<int>::Element *E = selection.back(); E; E = E->prev()) {
- float newpos = animation->track_get_key_time(track, E->get()) + moving_selection_offset.x;
+ float newpos = editor->snap_time(animation->track_get_key_time(track, E->get()) + moving_selection_offset.x);
/*
if (newpos<0)
continue; //no add at the beginning
@@ -887,7 +901,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
// 4-(undo) remove inserted keys
for (Set<int>::Element *E = selection.back(); E; E = E->prev()) {
- float newpos = animation->track_get_key_time(track, E->get()) + moving_selection_offset.x;
+ float newpos = editor->snap_time(animation->track_get_key_time(track, E->get()) + moving_selection_offset.x);
/*
if (newpos<0)
continue; //no remove what no inserted
@@ -924,7 +938,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
for (Set<int>::Element *E = selection.back(); E; E = E->prev()) {
float oldpos = animation->track_get_key_time(track, E->get());
- float newpos = oldpos + moving_selection_offset.x;
+ float newpos = editor->snap_time(oldpos + moving_selection_offset.x);
undo_redo->add_do_method(this, "_select_at_anim", animation, track, newpos);
undo_redo->add_undo_method(this, "_select_at_anim", animation, track, oldpos);
@@ -965,7 +979,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
float y = (get_size().height / 2 - mm->get_position().y) * v_zoom + v_scroll;
- float x = ((mm->get_position().x - timeline->get_name_limit()) / timeline->get_zoom_scale()) + timeline->get_value();
+ float x = editor->snap_time(((mm->get_position().x - timeline->get_name_limit()) / timeline->get_zoom_scale()) + timeline->get_value());
moving_selection_offset = Vector2(x - animation->track_get_key_time(track, moving_selection_from_key), y - animation->bezier_track_get_key_value(track, moving_selection_from_key));
update();
@@ -1154,8 +1168,8 @@ void AnimationBezierTrackEdit::_bind_methods() {
ClassDB::bind_method("_play_position_draw", &AnimationBezierTrackEdit::_play_position_draw);
ClassDB::bind_method("_clear_selection", &AnimationBezierTrackEdit::_clear_selection);
- ClassDB::bind_method("_clear_selection_for_anim", &AnimationBezierTrackEdit::_clear_selection);
- ClassDB::bind_method("_select_at_anim", &AnimationBezierTrackEdit::_clear_selection);
+ ClassDB::bind_method("_clear_selection_for_anim", &AnimationBezierTrackEdit::_clear_selection_for_anim);
+ ClassDB::bind_method("_select_at_anim", &AnimationBezierTrackEdit::_select_at_anim);
ADD_SIGNAL(MethodInfo("timeline_changed", PropertyInfo(Variant::REAL, "position"), PropertyInfo(Variant::BOOL, "drag")));
ADD_SIGNAL(MethodInfo("remove_request", PropertyInfo(Variant::INT, "track")));
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 4dff7d5b69..61244ab78c 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -309,8 +309,8 @@ public:
setting = true;
undo_redo->create_action(TTR("Anim Change Keyframe Value"), UndoRedo::MERGE_ENDS);
Vector2 prev = animation->bezier_track_get_key_in_handle(track, key);
- undo_redo->add_do_method(animation.ptr(), "bezier_track_set_in_handle", track, key, value);
- undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_in_handle", track, key, prev);
+ undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_in_handle", track, key, value);
+ undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_key_in_handle", track, key, prev);
undo_redo->add_do_method(this, "_update_obj", animation);
undo_redo->add_undo_method(this, "_update_obj", animation);
undo_redo->commit_action();
@@ -325,8 +325,8 @@ public:
setting = true;
undo_redo->create_action(TTR("Anim Change Keyframe Value"), UndoRedo::MERGE_ENDS);
Vector2 prev = animation->bezier_track_get_key_out_handle(track, key);
- undo_redo->add_do_method(animation.ptr(), "bezier_track_set_out_handle", track, key, value);
- undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_out_handle", track, key, prev);
+ undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_out_handle", track, key, value);
+ undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_key_out_handle", track, key, prev);
undo_redo->add_do_method(this, "_update_obj", animation);
undo_redo->add_undo_method(this, "_update_obj", animation);
undo_redo->commit_action();
@@ -1274,13 +1274,7 @@ void AnimationTrackEdit::_notification(int p_what) {
} else if (animation->track_get_type(track) == Animation::TYPE_ANIMATION) {
text = TTR("Anim Clips:");
} else {
- Vector<StringName> sn = path.get_subnames();
- for (int i = 0; i < sn.size(); i++) {
- if (i > 0) {
- text += ".";
- }
- text += sn[i];
- }
+ text += path.get_concatenated_subnames();
}
text_color.a *= 0.7;
} else if (node) {
@@ -1294,14 +1288,10 @@ void AnimationTrackEdit::_notification(int p_what) {
draw_texture(icon, Point2(ofs, int(get_size().height - icon->get_height()) / 2));
icon_cache = icon;
- text = node->get_name();
+ text = String() + node->get_name() + ":" + path.get_concatenated_subnames();
ofs += hsep;
ofs += icon->get_width();
- Vector<StringName> sn = path.get_subnames();
- for (int i = 0; i < sn.size(); i++) {
- text += ".";
- text += sn[i];
- }
+
} else {
icon_cache = type_icon;
@@ -3536,7 +3526,10 @@ void AnimationTrackEditor::_animation_changed() {
if (key_edit && key_edit->setting) {
//if editing a key, just update the edited track, makes refresh less costly
if (key_edit->track < track_edits.size()) {
- track_edits[key_edit->track]->update();
+ if (animation->track_get_type(key_edit->track) == Animation::TYPE_BEZIER)
+ bezier_edit->update();
+ else
+ track_edits[key_edit->track]->update();
}
return;
}
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index b65a484b16..e80d3e1b37 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -407,6 +407,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/theme/color_theme", "Adaptive");
hints["text_editor/theme/color_theme"] = PropertyInfo(Variant::STRING, "text_editor/theme/color_theme", PROPERTY_HINT_ENUM, "Adaptive,Default,Custom");
_initial_set("text_editor/theme/line_spacing", 6);
+ hints["text_editor/theme/line_spacing"] = PropertyInfo(Variant::INT, "text_editor/theme/line_spacing", PROPERTY_HINT_RANGE, "0,50,1");
_load_default_text_editor_theme();
@@ -466,6 +467,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/completion/callhint_tooltip_offset", Vector2());
_initial_set("text_editor/completion/complete_file_paths", true);
_initial_set("text_editor/completion/add_type_hints", false);
+ _initial_set("text_editor/completion/use_single_quotes", false);
// Help
_initial_set("text_editor/help/show_help_index", true);
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 41f35c3bed..7c075b5635 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -846,6 +846,12 @@ void AnimationPlayerEditor::_update_player() {
onion_skinning->set_disabled(player == NULL);
pin->set_disabled(player == NULL);
+ if (!player) {
+ AnimationPlayerEditor::singleton->get_track_editor()->update_keying();
+ EditorNode::get_singleton()->update_keying();
+ return;
+ }
+
int active_idx = -1;
for (List<StringName>::Element *E = animlist.front(); E; E = E->next()) {
@@ -858,12 +864,6 @@ void AnimationPlayerEditor::_update_player() {
active_idx = animation->get_item_count() - 1;
}
- if (!player) {
- AnimationPlayerEditor::singleton->get_track_editor()->update_keying();
- EditorNode::get_singleton()->update_keying();
- return;
- }
-
updating = false;
if (active_idx != -1) {
animation->select(active_idx);
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 88bb8e38fe..c0f2410636 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -1471,10 +1471,14 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) {
if (!use_single_axis || use_y) control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, false);
break;
case DRAG_ANCHOR_ALL:
- if (!use_single_axis || !use_y) control->set_anchor(MARGIN_LEFT, new_anchor.x, false, true);
- if (!use_single_axis || !use_y) control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, true);
- if (!use_single_axis || use_y) control->set_anchor(MARGIN_TOP, new_anchor.y, false, true);
- if (!use_single_axis || use_y) control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, true);
+ if (!use_single_axis || !use_y) {
+ control->set_anchor(MARGIN_LEFT, new_anchor.x, false, true);
+ control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, true);
+ }
+ if (!use_single_axis || use_y) {
+ control->set_anchor(MARGIN_TOP, new_anchor.y, false, true);
+ control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, true);
+ }
break;
default:
break;
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 66766f7ccf..709c2caa96 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -765,7 +765,7 @@ public:
set_title(TTR("Install Project:") + " " + zip_title);
get_ok()->set_text(TTR("Install & Edit"));
- name_container->hide();
+ name_container->show();
install_path_container->hide();
rasterizer_container->hide();
project_path->grab_focus();
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index 292cb8ddc3..0f851c526d 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -105,8 +105,12 @@ bool ScriptCreateDialog::_validate(const String &p_string) {
if (p_string.length() == 0)
return false;
- String path_chars = "\"res://";
- bool is_val_path = ScriptServer::get_language(language_menu->get_selected())->can_inherit_from_file();
+ if (ScriptServer::get_language(language_menu->get_selected())->can_inherit_from_file() && p_string.is_quoted()) {
+ String p = p_string.substr(1, p_string.length() - 2);
+ if (_validate_path(p, true) == "")
+ return true;
+ }
+
for (int i = 0; i < p_string.length(); i++) {
if (i == 0) {
@@ -114,17 +118,7 @@ bool ScriptCreateDialog::_validate(const String &p_string) {
return false; // no start with number plz
}
- if (i == p_string.length() - 1 && is_val_path)
- return p_string[i] == '\"';
-
- if (is_val_path && i < path_chars.length()) {
- if (p_string[i] != path_chars[i])
- is_val_path = false;
- else
- continue;
- }
-
- bool valid_char = (p_string[i] >= '0' && p_string[i] <= '9') || (p_string[i] >= 'a' && p_string[i] <= 'z') || (p_string[i] >= 'A' && p_string[i] <= 'Z') || p_string[i] == '_' || p_string[i] == '-' || (is_val_path && (p_string[i] == '/' || p_string[i] == '.'));
+ bool valid_char = (p_string[i] >= '0' && p_string[i] <= '9') || (p_string[i] >= 'a' && p_string[i] <= 'z') || (p_string[i] >= 'A' && p_string[i] <= 'Z') || p_string[i] == '_' || p_string[i] == '-';
if (!valid_char)
return false;
@@ -133,6 +127,70 @@ bool ScriptCreateDialog::_validate(const String &p_string) {
return true;
}
+String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must_exist) {
+
+ String p = p_path.strip_edges();
+
+ if (p == "") return TTR("Path is empty.");
+ if (p.get_file().get_basename() == "") return TTR("Filename is empty.");
+
+ p = ProjectSettings::get_singleton()->localize_path(p);
+ if (!p.begins_with("res://")) return TTR("Path is not local.");
+
+ DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (d->change_dir(p.get_base_dir()) != OK) {
+ memdelete(d);
+ return TTR("Invalid base path.");
+ }
+ memdelete(d);
+
+ /* Does file already exist */
+ DirAccess *f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (f->dir_exists(p)) {
+ memdelete(f);
+ return TTR("A directory with the same name exists.");
+ } else if (p_file_must_exist && !f->file_exists(p)) {
+ memdelete(f);
+ return TTR("File does not exist.");
+ }
+ memdelete(f);
+
+ /* Check file extension */
+ String extension = p.get_extension();
+ List<String> extensions;
+
+ // get all possible extensions for script
+ for (int l = 0; l < language_menu->get_item_count(); l++) {
+ ScriptServer::get_language(l)->get_recognized_extensions(&extensions);
+ }
+
+ bool found = false;
+ bool match = false;
+ int index = 0;
+ for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
+ if (E->get().nocasecmp_to(extension) == 0) {
+ //FIXME (?) - changing language this way doesn't update controls, needs rework
+ //language_menu->select(index); // change Language option by extension
+ found = true;
+ if (E->get() == ScriptServer::get_language(language_menu->get_selected())->get_extension()) {
+ match = true;
+ }
+ break;
+ }
+ index++;
+ }
+
+ if (!found) return TTR("Invalid extension.");
+ if (!match) return TTR("Wrong extension chosen.");
+
+ /* Let ScriptLanguage do custom validation */
+ String path_error = ScriptServer::get_language(language_menu->get_selected())->validate_path(p);
+ if (path_error != "") return path_error;
+
+ /* All checks passed */
+ return "";
+}
+
void ScriptCreateDialog::_class_name_changed(const String &p_name) {
if (_validate(class_name->get_text())) {
@@ -400,97 +458,22 @@ void ScriptCreateDialog::_path_changed(const String &p_path) {
is_path_valid = false;
is_new_script_created = true;
- String p = p_path.strip_edges();
- if (p == "") {
- _msg_path_valid(false, TTR("Path is empty."));
- _update_dialog();
- return;
- }
-
- if (p.get_file().get_basename() == "") {
- _msg_path_valid(false, TTR("Filename is empty."));
- _update_dialog();
- return;
- }
-
- p = ProjectSettings::get_singleton()->localize_path(p);
- if (!p.begins_with("res://")) {
- _msg_path_valid(false, TTR("Path is not local."));
- _update_dialog();
- return;
- }
-
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- if (d->change_dir(p.get_base_dir()) != OK) {
- _msg_path_valid(false, TTR("Invalid base path."));
- memdelete(d);
+ String path_error = _validate_path(p_path, false);
+ if (path_error != "") {
+ _msg_path_valid(false, path_error);
_update_dialog();
return;
}
- memdelete(d);
/* Does file already exist */
-
DirAccess *f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- if (f->dir_exists(p)) {
+ String p = ProjectSettings::get_singleton()->localize_path(p_path.strip_edges());
+ if (f->file_exists(p)) {
is_new_script_created = false;
- is_path_valid = false;
- _msg_path_valid(false, TTR("A directory with the same name exists."));
- } else if (f->file_exists(p)) {
- is_new_script_created = false;
- is_path_valid = true;
_msg_path_valid(true, TTR("File exists, it will be reused."));
}
memdelete(f);
- _update_dialog();
-
- /* Check file extension */
-
- String extension = p.get_extension();
- List<String> extensions;
-
- // get all possible extensions for script
- for (int l = 0; l < language_menu->get_item_count(); l++) {
- ScriptServer::get_language(l)->get_recognized_extensions(&extensions);
- }
-
- bool found = false;
- bool match = false;
- int index = 0;
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- if (E->get().nocasecmp_to(extension) == 0) {
- //FIXME (?) - changing language this way doesn't update controls, needs rework
- //language_menu->select(index); // change Language option by extension
- found = true;
- if (E->get() == ScriptServer::get_language(language_menu->get_selected())->get_extension()) {
- match = true;
- }
- break;
- }
- index++;
- }
-
- if (!found) {
- _msg_path_valid(false, TTR("Invalid extension."));
- _update_dialog();
- return;
- }
-
- if (!match) {
- _msg_path_valid(false, TTR("Wrong extension chosen."));
- _update_dialog();
- return;
- }
-
- String path_error = ScriptServer::get_language(language_menu->get_selected())->validate_path(p);
- if (path_error != "") {
- _msg_path_valid(false, path_error);
- _update_dialog();
- return;
- }
-
- /* All checks passed */
is_path_valid = true;
_update_dialog();
diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h
index f5c335c00a..1a3ba3d371 100644
--- a/editor/script_create_dialog.h
+++ b/editor/script_create_dialog.h
@@ -87,6 +87,7 @@ class ScriptCreateDialog : public ConfirmationDialog {
void _lang_changed(int l = 0);
void _built_in_pressed();
bool _validate(const String &p_string);
+ String _validate_path(const String &p_path, bool p_file_must_exist);
void _class_name_changed(const String &p_name);
void _parent_name_changed(const String &p_parent);
void _template_changed(int p_template = 0);