Allow configuring the script filename casing rule
Defaults to "Auto", which detects the casing based on the preference of the currently selected language (C# for example prefers PascalCase whereas GDScript prefers snake_case).
This commit is contained in:
parent
a07dd0d6a5
commit
2bd714e34e
|
@ -535,6 +535,13 @@ TypedArray<int> ScriptLanguage::CodeCompletionOption::get_option_cached_characte
|
|||
return charac;
|
||||
}
|
||||
|
||||
void ScriptLanguage::_bind_methods() {
|
||||
BIND_ENUM_CONSTANT(SCRIPT_NAME_CASING_AUTO);
|
||||
BIND_ENUM_CONSTANT(SCRIPT_NAME_CASING_PASCAL_CASE);
|
||||
BIND_ENUM_CONSTANT(SCRIPT_NAME_CASING_SNAKE_CASE);
|
||||
BIND_ENUM_CONSTANT(SCRIPT_NAME_CASING_KEBAB_CASE);
|
||||
}
|
||||
|
||||
bool PlaceHolderScriptInstance::set(const StringName &p_name, const Variant &p_value) {
|
||||
if (script->is_placeholder_fallback_enabled()) {
|
||||
return false;
|
||||
|
|
|
@ -193,6 +193,10 @@ public:
|
|||
|
||||
class ScriptLanguage : public Object {
|
||||
GDCLASS(ScriptLanguage, Object)
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual String get_name() const = 0;
|
||||
|
||||
|
@ -224,6 +228,13 @@ public:
|
|||
TEMPLATE_PROJECT
|
||||
};
|
||||
|
||||
enum ScriptNameCasing {
|
||||
SCRIPT_NAME_CASING_AUTO,
|
||||
SCRIPT_NAME_CASING_PASCAL_CASE,
|
||||
SCRIPT_NAME_CASING_SNAKE_CASE,
|
||||
SCRIPT_NAME_CASING_KEBAB_CASE,
|
||||
};
|
||||
|
||||
struct ScriptTemplate {
|
||||
String inherit = "Object";
|
||||
String name;
|
||||
|
@ -260,6 +271,7 @@ public:
|
|||
virtual bool can_make_function() const { return true; }
|
||||
virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; }
|
||||
virtual bool overrides_external_editor() { return false; }
|
||||
virtual ScriptNameCasing preferred_file_name_casing() const { return SCRIPT_NAME_CASING_SNAKE_CASE; }
|
||||
|
||||
// Keep enums in sync with:
|
||||
// scene/gui/code_edit.h - CodeEdit::CodeCompletionKind
|
||||
|
@ -405,6 +417,8 @@ public:
|
|||
virtual ~ScriptLanguage() {}
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(ScriptLanguage::ScriptNameCasing);
|
||||
|
||||
extern uint8_t script_encryption_key[32];
|
||||
|
||||
class PlaceHolderScriptInstance : public ScriptInstance {
|
||||
|
|
|
@ -112,6 +112,7 @@ void ScriptLanguageExtension::_bind_methods() {
|
|||
GDVIRTUAL_BIND(_can_make_function);
|
||||
GDVIRTUAL_BIND(_open_in_external_editor, "script", "line", "column");
|
||||
GDVIRTUAL_BIND(_overrides_external_editor);
|
||||
GDVIRTUAL_BIND(_preferred_file_name_casing);
|
||||
|
||||
GDVIRTUAL_BIND(_complete_code, "code", "path", "owner");
|
||||
GDVIRTUAL_BIND(_lookup_code, "code", "symbol", "path", "owner");
|
||||
|
|
|
@ -376,6 +376,7 @@ public:
|
|||
EXBIND0RC(bool, can_make_function)
|
||||
EXBIND3R(Error, open_in_external_editor, const Ref<Script> &, int, int)
|
||||
EXBIND0R(bool, overrides_external_editor)
|
||||
EXBIND0RC(ScriptNameCasing, preferred_file_name_casing)
|
||||
|
||||
GDVIRTUAL3RC(Dictionary, _complete_code, const String &, const String &, Object *)
|
||||
|
||||
|
|
|
@ -948,13 +948,16 @@
|
|||
The format of the default signal callback name when a signal connects to the same node that emits it (in the Signal Connection Dialog). The following substitutions are available: [code]{NodeName}[/code], [code]{nodeName}[/code], [code]{node_name}[/code], [code]{SignalName}[/code], [code]{signalName}[/code], and [code]{signal_name}[/code].
|
||||
</member>
|
||||
<member name="editor/naming/node_name_casing" type="int" setter="" getter="" default="0">
|
||||
When creating node names automatically, set the type of casing in this project. This is mostly an editor setting.
|
||||
When creating node names automatically, set the type of casing to use in this project. This is mostly an editor setting.
|
||||
</member>
|
||||
<member name="editor/naming/node_name_num_separator" type="int" setter="" getter="" default="0">
|
||||
What to use to separate node name from number. This is mostly an editor setting.
|
||||
</member>
|
||||
<member name="editor/naming/scene_name_casing" type="int" setter="" getter="" default="2">
|
||||
When generating file names from scene root node, set the type of casing in this project. This is mostly an editor setting.
|
||||
When generating scene file names from scene root node, set the type of casing to use in this project. This is mostly an editor setting.
|
||||
</member>
|
||||
<member name="editor/naming/script_name_casing" type="int" setter="" getter="" default="0">
|
||||
When generating script file names from the selected node, set the type of casing to use in this project. This is mostly an editor setting.
|
||||
</member>
|
||||
<member name="editor/run/main_run_args" type="String" setter="" getter="" default="""">
|
||||
The command-line arguments to append to Godot's own command line when running the project. This doesn't affect the editor itself.
|
||||
|
|
|
@ -6,4 +6,14 @@
|
|||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<constants>
|
||||
<constant name="SCRIPT_NAME_CASING_AUTO" value="0" enum="ScriptNameCasing">
|
||||
</constant>
|
||||
<constant name="SCRIPT_NAME_CASING_PASCAL_CASE" value="1" enum="ScriptNameCasing">
|
||||
</constant>
|
||||
<constant name="SCRIPT_NAME_CASING_SNAKE_CASE" value="2" enum="ScriptNameCasing">
|
||||
</constant>
|
||||
<constant name="SCRIPT_NAME_CASING_KEBAB_CASE" value="3" enum="ScriptNameCasing">
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
|
|
|
@ -267,6 +267,11 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="_preferred_file_name_casing" qualifiers="virtual const">
|
||||
<return type="int" enum="ScriptLanguage.ScriptNameCasing" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="_profiling_get_accumulated_data" qualifiers="virtual">
|
||||
<return type="int" />
|
||||
<param index="0" name="info_array" type="ScriptLanguageExtensionProfilingInfo*" />
|
||||
|
|
|
@ -166,7 +166,7 @@ void EditorAutoloadSettings::_autoload_add() {
|
|||
if (!fpath.ends_with("/")) {
|
||||
fpath = fpath.get_base_dir();
|
||||
}
|
||||
dialog->config("Node", fpath.path_join(vformat("%s.gd", autoload_add_name->get_text().to_snake_case())), false, false);
|
||||
dialog->config("Node", fpath.path_join(vformat("%s.gd", autoload_add_name->get_text())), false, false);
|
||||
dialog->popup_centered();
|
||||
} else {
|
||||
if (autoload_add(autoload_add_name->get_text(), autoload_add_path->get_text())) {
|
||||
|
|
|
@ -3089,17 +3089,40 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
|
|||
}
|
||||
}
|
||||
|
||||
String EditorNode::adjust_scene_name_casing(const String &root_name) {
|
||||
String EditorNode::adjust_scene_name_casing(const String &p_root_name) {
|
||||
switch (GLOBAL_GET("editor/naming/scene_name_casing").operator int()) {
|
||||
case SCENE_NAME_CASING_AUTO:
|
||||
// Use casing of the root node.
|
||||
break;
|
||||
case SCENE_NAME_CASING_PASCAL_CASE:
|
||||
return root_name.to_pascal_case();
|
||||
return p_root_name.replace("-", "_").to_pascal_case();
|
||||
case SCENE_NAME_CASING_SNAKE_CASE:
|
||||
return root_name.replace("-", "_").to_snake_case();
|
||||
return p_root_name.replace("-", "_").to_snake_case();
|
||||
case SCENE_NAME_CASING_KEBAB_CASE:
|
||||
return p_root_name.to_snake_case().replace("_", "-");
|
||||
}
|
||||
return root_name;
|
||||
return p_root_name;
|
||||
}
|
||||
|
||||
String EditorNode::adjust_script_name_casing(const String &p_file_name, ScriptLanguage::ScriptNameCasing p_auto_casing) {
|
||||
int editor_casing = GLOBAL_GET("editor/naming/script_name_casing");
|
||||
if (editor_casing == ScriptLanguage::SCRIPT_NAME_CASING_AUTO) {
|
||||
// Use the script language's preferred casing.
|
||||
editor_casing = p_auto_casing;
|
||||
}
|
||||
|
||||
switch (editor_casing) {
|
||||
case ScriptLanguage::SCRIPT_NAME_CASING_AUTO:
|
||||
// Script language has no preference, so do not adjust.
|
||||
break;
|
||||
case ScriptLanguage::SCRIPT_NAME_CASING_PASCAL_CASE:
|
||||
return p_file_name.replace("-", "_").to_pascal_case();
|
||||
case ScriptLanguage::SCRIPT_NAME_CASING_SNAKE_CASE:
|
||||
return p_file_name.replace("-", "_").to_snake_case();
|
||||
case ScriptLanguage::SCRIPT_NAME_CASING_KEBAB_CASE:
|
||||
return p_file_name.to_snake_case().replace("_", "-");
|
||||
}
|
||||
return p_file_name;
|
||||
}
|
||||
|
||||
void EditorNode::_request_screenshot() {
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#ifndef EDITOR_NODE_H
|
||||
#define EDITOR_NODE_H
|
||||
|
||||
#include "core/object/script_language.h"
|
||||
#include "core/templates/safe_refcount.h"
|
||||
#include "editor/editor_data.h"
|
||||
#include "editor/editor_folding.h"
|
||||
|
@ -135,7 +136,8 @@ public:
|
|||
enum SceneNameCasing {
|
||||
SCENE_NAME_CASING_AUTO,
|
||||
SCENE_NAME_CASING_PASCAL_CASE,
|
||||
SCENE_NAME_CASING_SNAKE_CASE
|
||||
SCENE_NAME_CASING_SNAKE_CASE,
|
||||
SCENE_NAME_CASING_KEBAB_CASE,
|
||||
};
|
||||
|
||||
struct ExecuteThreadArgs {
|
||||
|
@ -689,7 +691,8 @@ public:
|
|||
static VSplitContainer *get_top_split() { return singleton->top_split; }
|
||||
static EditorBottomPanel *get_bottom_panel() { return singleton->bottom_panel; }
|
||||
|
||||
static String adjust_scene_name_casing(const String &root_name);
|
||||
static String adjust_scene_name_casing(const String &p_root_name);
|
||||
static String adjust_script_name_casing(const String &p_file_name, ScriptLanguage::ScriptNameCasing p_auto_casing);
|
||||
|
||||
static bool has_unsaved_changes() { return singleton->unsaved_cache; }
|
||||
static void disambiguate_filenames(const Vector<String> p_full_paths, Vector<String> &r_filenames);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "register_editor_types.h"
|
||||
|
||||
#include "core/object/script_language.h"
|
||||
#include "editor/debugger/debug_adapter/debug_adapter_server.h"
|
||||
#include "editor/editor_command_palette.h"
|
||||
#include "editor/editor_feature_profile.h"
|
||||
|
@ -269,7 +270,8 @@ void register_editor_types() {
|
|||
|
||||
GLOBAL_DEF("editor/naming/default_signal_callback_name", "_on_{node_name}_{signal_name}");
|
||||
GLOBAL_DEF("editor/naming/default_signal_callback_to_self_name", "_on_{signal_name}");
|
||||
GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/naming/scene_name_casing", PROPERTY_HINT_ENUM, "Auto,PascalCase,snake_case"), EditorNode::SCENE_NAME_CASING_SNAKE_CASE);
|
||||
GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/naming/scene_name_casing", PROPERTY_HINT_ENUM, "Auto,PascalCase,snake_case,kebab-case"), EditorNode::SCENE_NAME_CASING_SNAKE_CASE);
|
||||
GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/naming/script_name_casing", PROPERTY_HINT_ENUM, "Auto,PascalCase,snake_case,kebab-case"), ScriptLanguage::SCRIPT_NAME_CASING_AUTO);
|
||||
|
||||
GLOBAL_DEF("editor/import/reimport_missing_imported_files", true);
|
||||
GLOBAL_DEF("editor/import/use_multiple_threads", true);
|
||||
|
|
|
@ -125,7 +125,6 @@ void ScriptCreateDialog::_notification(int p_what) {
|
|||
for (int i = 0; i < language_menu->get_item_count(); i++) {
|
||||
if (language_menu->get_item_text(i) == last_language) {
|
||||
language_menu->select(i);
|
||||
current_language = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -146,8 +145,8 @@ void ScriptCreateDialog::_notification(int p_what) {
|
|||
|
||||
void ScriptCreateDialog::_path_hbox_sorted() {
|
||||
if (is_visible()) {
|
||||
int filename_start_pos = initial_bp.rfind("/") + 1;
|
||||
int filename_end_pos = initial_bp.length();
|
||||
int filename_start_pos = file_path->get_text().rfind("/") + 1;
|
||||
int filename_end_pos = file_path->get_text().length();
|
||||
|
||||
if (!is_built_in) {
|
||||
file_path->select(filename_start_pos, filename_end_pos);
|
||||
|
@ -166,26 +165,30 @@ bool ScriptCreateDialog::_can_be_built_in() {
|
|||
return (supports_built_in && built_in_enabled);
|
||||
}
|
||||
|
||||
String ScriptCreateDialog::_adjust_file_path(const String &p_base_path) const {
|
||||
if (p_base_path.is_empty()) {
|
||||
return p_base_path;
|
||||
}
|
||||
|
||||
String base_dir = p_base_path.get_base_dir();
|
||||
String file_name = p_base_path.get_file().get_basename();
|
||||
file_name = EditorNode::adjust_script_name_casing(file_name, language->preferred_file_name_casing());
|
||||
String extension = language->get_extension();
|
||||
return base_dir.path_join(file_name + "." + extension);
|
||||
}
|
||||
|
||||
void ScriptCreateDialog::config(const String &p_base_name, const String &p_base_path, bool p_built_in_enabled, bool p_load_enabled) {
|
||||
parent_name->set_text(p_base_name);
|
||||
parent_name->deselect();
|
||||
built_in_name->set_text("");
|
||||
|
||||
if (!p_base_path.is_empty()) {
|
||||
initial_bp = p_base_path.get_basename();
|
||||
file_path->set_text(initial_bp + "." + ScriptServer::get_language(language_menu->get_selected())->get_extension());
|
||||
current_language = language_menu->get_selected();
|
||||
} else {
|
||||
initial_bp = "";
|
||||
file_path->set_text("");
|
||||
}
|
||||
file_path->set_text(p_base_path);
|
||||
file_path->deselect();
|
||||
|
||||
built_in_enabled = p_built_in_enabled;
|
||||
load_enabled = p_load_enabled;
|
||||
|
||||
_language_changed(current_language);
|
||||
_path_changed(file_path->get_text());
|
||||
_language_changed(language_menu->get_selected());
|
||||
}
|
||||
|
||||
void ScriptCreateDialog::set_inheritance_base_type(const String &p_base) {
|
||||
|
@ -388,38 +391,9 @@ void ScriptCreateDialog::_language_changed(int l) {
|
|||
is_built_in = false;
|
||||
}
|
||||
|
||||
String selected_ext = "." + language->get_extension();
|
||||
String path = file_path->get_text();
|
||||
String extension = "";
|
||||
if (!path.is_empty()) {
|
||||
if (path.contains(".")) {
|
||||
extension = path.get_extension();
|
||||
}
|
||||
|
||||
if (extension.length() == 0) {
|
||||
// Add extension if none.
|
||||
path += selected_ext;
|
||||
path = _adjust_file_path(path);
|
||||
_path_changed(path);
|
||||
} else {
|
||||
// Change extension by selected language.
|
||||
List<String> extensions;
|
||||
// Get all possible extensions for script.
|
||||
for (int m = 0; m < language_menu->get_item_count(); m++) {
|
||||
ScriptServer::get_language(m)->get_recognized_extensions(&extensions);
|
||||
}
|
||||
|
||||
for (const String &E : extensions) {
|
||||
if (E.nocasecmp_to(extension) == 0) {
|
||||
path = path.get_basename() + selected_ext;
|
||||
_path_changed(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
path = "class" + selected_ext;
|
||||
_path_changed(path);
|
||||
}
|
||||
file_path->set_text(path);
|
||||
|
||||
EditorSettings::get_singleton()->set_project_metadata("script_setup", "last_selected_language", language_menu->get_item_text(language_menu->get_selected()));
|
||||
|
@ -896,7 +870,6 @@ ScriptCreateDialog::ScriptCreateDialog() {
|
|||
if (default_language >= 0) {
|
||||
language_menu->select(default_language);
|
||||
}
|
||||
current_language = default_language;
|
||||
|
||||
language_menu->connect("item_selected", callable_mp(this, &ScriptCreateDialog::_language_changed));
|
||||
|
||||
|
|
|
@ -71,7 +71,6 @@ class ScriptCreateDialog : public ConfirmationDialog {
|
|||
bool is_browsing_parent = false;
|
||||
String path_error;
|
||||
String template_inactive_message;
|
||||
String initial_bp;
|
||||
bool is_new_script_created = true;
|
||||
bool is_path_valid = false;
|
||||
bool supports_built_in = false;
|
||||
|
@ -82,7 +81,6 @@ class ScriptCreateDialog : public ConfirmationDialog {
|
|||
bool is_using_templates = true;
|
||||
bool built_in_enabled = true;
|
||||
bool load_enabled = true;
|
||||
int current_language;
|
||||
int default_language;
|
||||
bool re_check_path = false;
|
||||
|
||||
|
@ -117,6 +115,7 @@ class ScriptCreateDialog : public ConfirmationDialog {
|
|||
Vector<ScriptLanguage::ScriptTemplate> _get_user_templates(const ScriptLanguage *p_language, const StringName &p_object, const String &p_dir, const ScriptLanguage::TemplateLocation &p_origin) const;
|
||||
ScriptLanguage::ScriptTemplate _parse_template(const ScriptLanguage *p_language, const String &p_path, const String &p_filename, const ScriptLanguage::TemplateLocation &p_origin, const String &p_inherits) const;
|
||||
String _get_script_origin_label(const ScriptLanguage::TemplateLocation &p_origin) const;
|
||||
String _adjust_file_path(const String &p_base_path) const;
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
|
|
@ -405,6 +405,10 @@ bool CSharpLanguage::supports_builtin_mode() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
ScriptLanguage::ScriptNameCasing CSharpLanguage::preferred_file_name_casing() const {
|
||||
return SCRIPT_NAME_CASING_PASCAL_CASE;
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
struct VariantCsName {
|
||||
Variant::Type variant_type;
|
||||
|
|
|
@ -518,6 +518,7 @@ public:
|
|||
virtual String _get_indentation() const;
|
||||
/* TODO? */ void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const override {}
|
||||
/* TODO */ void add_global_constant(const StringName &p_variable, const Variant &p_value) override {}
|
||||
virtual ScriptNameCasing preferred_file_name_casing() const override;
|
||||
|
||||
/* SCRIPT GLOBAL CLASS FUNCTIONS */
|
||||
virtual bool handles_global_class_type(const String &p_type) const override;
|
||||
|
|
Loading…
Reference in New Issue