Skip to content

Commit

Permalink
Trait System
Browse files Browse the repository at this point in the history
  • Loading branch information
SeremTitus committed Dec 11, 2024
1 parent a40fc23 commit 20b3249
Show file tree
Hide file tree
Showing 77 changed files with 2,969 additions and 153 deletions.
1 change: 1 addition & 0 deletions core/object/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,7 @@ void Object::set_script(const Variant &p_script) {
if (!p_script.is_null()) {
ERR_FAIL_COND_MSG(s.is_null(), "Cannot set object script. Parameter should be null or a reference to a valid script.");
ERR_FAIL_COND_MSG(s->is_abstract(), vformat("Cannot set object script. Script '%s' should not be abstract.", s->get_path()));
ERR_FAIL_COND_MSG(!s->is_attachable(), vformat("Cannot set object script. Script '%s' is not attachable.", s->get_path()));
}

script = p_script;
Expand Down
1 change: 1 addition & 0 deletions core/object/script_language.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ void Script::_bind_methods() {

ClassDB::bind_method(D_METHOD("is_tool"), &Script::is_tool);
ClassDB::bind_method(D_METHOD("is_abstract"), &Script::is_abstract);
ClassDB::bind_method(D_METHOD("is_attachable"), &Script::is_attachable);

ClassDB::bind_method(D_METHOD("get_rpc_config"), &Script::get_rpc_config);

Expand Down
2 changes: 2 additions & 0 deletions core/object/script_language.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ class Script : public Resource {
virtual bool is_tool() const = 0;
virtual bool is_valid() const = 0;
virtual bool is_abstract() const = 0;
virtual bool is_attachable() const { return true; }

virtual ScriptLanguage *get_language() const = 0;

Expand Down Expand Up @@ -214,6 +215,7 @@ class ScriptLanguage : public Object {
virtual void init() = 0;
virtual String get_type() const = 0;
virtual String get_extension() const = 0;
virtual bool is_language_script_attachable() const { return true; }
virtual void finish() = 0;

/* EDITOR FUNCTIONS */
Expand Down
8 changes: 7 additions & 1 deletion doc/classes/Script.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<description>
A class stored as a resource. A script extends the functionality of all objects that instantiate it.
This is the base class for all scripts and should not be used directly. Trying to create a new script with this class will result in an error.
The [code]new[/code] method of a script subclass creates a new instance. [method Object.set_script] extends an existing object, if that object's class matches one of the script's base classes.
The [code]new[/code] method of a script subclass creates a new instance. [method Object.set_script] extends an existing object, if that object's class matches one of the script's base classes and if script is attachable check by [method is_attachable].
</description>
<tutorials>
<link title="Scripting documentation index">$DOCS_URL/tutorials/scripting/index.html</link>
Expand Down Expand Up @@ -115,6 +115,12 @@
Returns [code]true[/code] if the script is an abstract script. An abstract script does not have a constructor and cannot be instantiated.
</description>
</method>
<method name="is_attachable" qualifiers="const">
<return type="bool" />
<description>
Returns [code]true[/code] if the script is able to be attached to [Object].
</description>
</method>
<method name="is_tool" qualifiers="const">
<return type="bool" />
<description>
Expand Down
5 changes: 4 additions & 1 deletion editor/debugger/script_editor_debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,10 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, uint64_t p_thread
stack_dump_info.push_back(d);
s->set_metadata(0, d);

String line = itos(i) + " - " + String(d["file"]) + ":" + itos(d["line"]) + " - at function: " + String(d["function"]);
String line = itos(i) + " - " + String(d["file"]) + ":" + itos(d["line"]);
if (!String(d["function"]).is_empty()) {
line += " - at function: " + String(d["function"]);
}
s->set_text(0, line);

if (i == 0) {
Expand Down
1 change: 1 addition & 0 deletions editor/filesystem_dock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4266,6 +4266,7 @@ FileSystemDock::FileSystemDock() {
make_scene_dialog->connect(SceneStringName(confirmed), callable_mp(this, &FileSystemDock::_make_scene_confirm));

make_script_dialog = memnew(ScriptCreateDialog);
make_script_dialog->set_languages_list(false);
make_script_dialog->set_title(TTR("Create Script"));
add_child(make_script_dialog);

Expand Down
106 changes: 68 additions & 38 deletions editor/script_create_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,32 +129,16 @@ void ScriptCreateDialog::_notification(int p_what) {
} break;

case NOTIFICATION_THEME_CHANGED: {
const int icon_size = get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor));

EditorData &ed = EditorNode::get_editor_data();

for (int i = 0; i < ScriptServer::get_language_count(); i++) {
// Check if the extension has an icon first.
String script_type = ScriptServer::get_language(i)->get_type();
Ref<Texture2D> language_icon = get_editor_theme_icon(script_type);
if (language_icon.is_null() || language_icon == ThemeDB::get_singleton()->get_fallback_icon()) {
// The theme doesn't have an icon for this language, ask the extensions.
Ref<Texture2D> extension_language_icon = ed.extension_class_get_icon(script_type);
if (extension_language_icon.is_valid()) {
language_menu->get_popup()->set_item_icon_max_width(i, icon_size);
language_icon = extension_language_icon;
}
}

if (language_icon.is_valid()) {
language_menu->set_item_icon(i, language_icon);
}
}
set_languages_list(is_languages_list_only_attachable);

path_button->set_button_icon(get_editor_theme_icon(SNAME("Folder")));
parent_browse_button->set_button_icon(get_editor_theme_icon(SNAME("Folder")));
parent_search_button->set_button_icon(get_editor_theme_icon(SNAME("ClassList")));
} break;

case NOTIFICATION_POSTINITIALIZE: {
set_languages_list(is_languages_list_only_attachable);
} break;
}
}

Expand Down Expand Up @@ -210,6 +194,51 @@ void ScriptCreateDialog::set_inheritance_base_type(const String &p_base) {
base_type = p_base;
}

void ScriptCreateDialog::set_languages_list(const bool p_only_attachable) {
const int icon_size = get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor));
EditorData &ed = EditorNode::get_editor_data();
is_languages_list_only_attachable = p_only_attachable;
String previous_default;
if (language_menu->get_selected_id() > -1) {
previous_default = language_menu->get_item_text(language_menu->get_selected_id());
}
default_language = -1;
language_menu->clear();
language_list.clear();
int menu_location = 0;
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
ScriptLanguage *lang = ScriptServer::get_language(i);
if (p_only_attachable && !lang->is_language_script_attachable()) {
continue;
}
language_menu->add_item(lang->get_name());
String script_type = lang->get_type();
Ref<Texture2D> language_icon = get_editor_theme_icon(script_type);
if (language_icon.is_null() || language_icon == ThemeDB::get_singleton()->get_fallback_icon()) {
// The theme doesn't have an icon for this language, ask the extensions.
Ref<Texture2D> extension_language_icon = ed.extension_class_get_icon(script_type);
if (extension_language_icon.is_valid()) {
language_menu->get_popup()->set_item_icon_max_width(menu_location, icon_size);
language_icon = extension_language_icon;
}
}
if (language_icon.is_valid()) {
language_menu->set_item_icon(menu_location, language_icon);
}
if (lang->get_name() == previous_default) {
default_language = menu_location;
}
if (default_language == -1 && lang->get_name() == "GDScript") {
default_language = menu_location;
}
language_list.append(lang);
menu_location++;
}
if (default_language >= 0) {
language_menu->select(default_language);
}
}

bool ScriptCreateDialog::_validate_parent(const String &p_string) {
if (p_string.length() == 0) {
return false;
Expand Down Expand Up @@ -278,7 +307,7 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must
for (const String &E : extensions) {
if (E.nocasecmp_to(extension) == 0) {
found = true;
if (E == ScriptServer::get_language(language_menu->get_selected())->get_extension()) {
if (E == language->get_extension()) {
match = true;
}
break;
Expand All @@ -288,12 +317,25 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must
if (!found) {
return TTR("Invalid extension.");
}
if (!match) {
if (!match && _extention_update_selected_language(p.get_extension()) != OK) {
return TTR("Extension doesn't match chosen language.");
}

// Let ScriptLanguage do custom validation.
return ScriptServer::get_language(language_menu->get_selected())->validate_path(p);
return language->validate_path(p);
}

Error ScriptCreateDialog::_extention_update_selected_language(const String &p_extention) {
for (int i = 0; i < language_list.size(); i++) {
ScriptLanguage *lang = language_list[i];
if (p_extention == lang->get_extension()) {
language_menu->select(i);
_language_changed(i);
file_path->set_caret_column(file_path->get_text().length());
return OK;
}
}
return FAILED;
}

void ScriptCreateDialog::_parent_name_changed(const String &p_parent) {
Expand Down Expand Up @@ -360,7 +402,7 @@ void ScriptCreateDialog::_create_new() {
}

String class_name = file_path->get_text().get_file().get_basename();
scr = ScriptServer::get_language(language_menu->get_selected())->make_template(sinfo.content, class_name, parent_class);
scr = language->make_template(sinfo.content, class_name, parent_class);

if (is_built_in) {
scr->set_name(built_in_name->get_text());
Expand Down Expand Up @@ -396,7 +438,7 @@ void ScriptCreateDialog::_load_exist() {
}

void ScriptCreateDialog::_language_changed(int l) {
language = ScriptServer::get_language(l);
language = language_list[l];

can_inherit_from_file = language->can_inherit_from_file();
supports_built_in = language->supports_builtin_mode();
Expand Down Expand Up @@ -872,18 +914,6 @@ ScriptCreateDialog::ScriptCreateDialog() {
gc->add_child(memnew(Label(TTR("Language:"))));
gc->add_child(language_menu);

default_language = -1;
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
String lang = ScriptServer::get_language(i)->get_name();
language_menu->add_item(lang);
if (lang == "GDScript") {
default_language = i;
}
}
if (default_language >= 0) {
language_menu->select(default_language);
}

language_menu->connect(SceneStringName(item_selected), callable_mp(this, &ScriptCreateDialog::_language_changed));

/* Inherits */
Expand Down
4 changes: 4 additions & 0 deletions editor/script_create_dialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class ScriptCreateDialog : public ConfirmationDialog {
AcceptDialog *alert = nullptr;
CreateDialog *select_class = nullptr;

bool is_languages_list_only_attachable = true;
bool is_browsing_parent = false;
String path_error;
String template_inactive_message;
Expand All @@ -89,6 +90,7 @@ class ScriptCreateDialog : public ConfirmationDialog {

Vector<ScriptLanguage::ScriptTemplate> template_list;
ScriptLanguage *language = nullptr;
Vector<ScriptLanguage *> language_list;

String base_type;

Expand All @@ -100,6 +102,7 @@ class ScriptCreateDialog : public ConfirmationDialog {
void _use_template_pressed();
bool _validate_parent(const String &p_string);
String _validate_path(const String &p_path, bool p_file_must_exist);
Error _extention_update_selected_language(const String &p_extention);
void _parent_name_changed(const String &p_parent);
void _template_changed(int p_template = 0);
void _browse_path(bool browse_parent, bool p_save);
Expand All @@ -124,6 +127,7 @@ class ScriptCreateDialog : public ConfirmationDialog {
public:
void config(const String &p_base_name, const String &p_base_path, bool p_built_in_enabled = true, bool p_load_enabled = true);
void set_inheritance_base_type(const String &p_base);
void set_languages_list(const bool p_only_attachable);
ScriptCreateDialog();
};

Expand Down
4 changes: 4 additions & 0 deletions modules/gdscript/.editorconfig
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
[*.gd]
indent_size = 4
trim_trailing_whitespace = true

[*.gdt]
indent_size = 4
trim_trailing_whitespace = true
2 changes: 2 additions & 0 deletions modules/gdscript/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ def configure(env):
def get_doc_classes():
return [
"@GDScript",
"@GDTrait",
"GDScript",
"GDTrait",
"GDScriptSyntaxHighlighter",
]

Expand Down
Loading

0 comments on commit 20b3249

Please sign in to comment.