Improve handling of custom types
This commit is contained in:
parent
b5c053321c
commit
a3309215c2
@ -406,6 +406,7 @@
|
|||||||
When a given node or resource is selected, the base type will be instantiated (e.g. "Node3D", "Control", "Resource"), then the script will be loaded and set to this object.
|
When a given node or resource is selected, the base type will be instantiated (e.g. "Node3D", "Control", "Resource"), then the script will be loaded and set to this object.
|
||||||
You can use the virtual method [method _handles] to check if your custom object is being edited by checking the script or using the [code]is[/code] keyword.
|
You can use the virtual method [method _handles] to check if your custom object is being edited by checking the script or using the [code]is[/code] keyword.
|
||||||
During run-time, this will be a simple object with a script so this function does not need to be called then.
|
During run-time, this will be a simple object with a script so this function does not need to be called then.
|
||||||
|
[b]Note:[/b] Custom types added this way are not true classes. They are just a helper to create a node with specific script.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="add_debugger_plugin">
|
<method name="add_debugger_plugin">
|
||||||
|
@ -665,7 +665,7 @@ void CreateDialog::_save_and_update_favorite_list() {
|
|||||||
for (int i = 0; i < favorite_list.size(); i++) {
|
for (int i = 0; i < favorite_list.size(); i++) {
|
||||||
String l = favorite_list[i];
|
String l = favorite_list[i];
|
||||||
String name = l.get_slicec(' ', 0);
|
String name = l.get_slicec(' ', 0);
|
||||||
if (!(ClassDB::class_exists(name) || ScriptServer::is_global_class(name))) {
|
if (!EditorNode::get_editor_data().is_type_recognized(name)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
f->store_line(l);
|
f->store_line(l);
|
||||||
@ -692,7 +692,7 @@ void CreateDialog::_load_favorites_and_history() {
|
|||||||
String l = f->get_line().strip_edges();
|
String l = f->get_line().strip_edges();
|
||||||
String name = l.get_slicec(' ', 0);
|
String name = l.get_slicec(' ', 0);
|
||||||
|
|
||||||
if ((ClassDB::class_exists(name) || ScriptServer::is_global_class(name)) && !_is_class_disabled_by_feature_profile(name)) {
|
if (EditorNode::get_editor_data().is_type_recognized(name) && !_is_class_disabled_by_feature_profile(name)) {
|
||||||
recent->add_item(l, EditorNode::get_singleton()->get_class_icon(name, icon_fallback));
|
recent->add_item(l, EditorNode::get_singleton()->get_class_icon(name, icon_fallback));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -509,6 +509,32 @@ Variant EditorData::instance_custom_type(const String &p_type, const String &p_i
|
|||||||
return Variant();
|
return Variant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const EditorData::CustomType *EditorData::get_custom_type_by_name(const String &p_type) const {
|
||||||
|
for (const KeyValue<String, Vector<CustomType>> &E : custom_types) {
|
||||||
|
for (const CustomType &F : E.value) {
|
||||||
|
if (F.name == p_type) {
|
||||||
|
return &F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EditorData::CustomType *EditorData::get_custom_type_by_path(const String &p_path) const {
|
||||||
|
for (const KeyValue<String, Vector<CustomType>> &E : custom_types) {
|
||||||
|
for (const CustomType &F : E.value) {
|
||||||
|
if (F.script->get_path() == p_path) {
|
||||||
|
return &F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EditorData::is_type_recognized(const String &p_type) const {
|
||||||
|
return ClassDB::class_exists(p_type) || ScriptServer::is_global_class(p_type) || get_custom_type_by_name(p_type);
|
||||||
|
}
|
||||||
|
|
||||||
void EditorData::remove_custom_type(const String &p_type) {
|
void EditorData::remove_custom_type(const String &p_type) {
|
||||||
for (KeyValue<String, Vector<CustomType>> &E : custom_types) {
|
for (KeyValue<String, Vector<CustomType>> &E : custom_types) {
|
||||||
for (int i = 0; i < E.value.size(); i++) {
|
for (int i = 0; i < E.value.size(); i++) {
|
||||||
|
@ -184,6 +184,9 @@ public:
|
|||||||
Variant instance_custom_type(const String &p_type, const String &p_inherits);
|
Variant instance_custom_type(const String &p_type, const String &p_inherits);
|
||||||
void remove_custom_type(const String &p_type);
|
void remove_custom_type(const String &p_type);
|
||||||
const HashMap<String, Vector<CustomType>> &get_custom_types() const { return custom_types; }
|
const HashMap<String, Vector<CustomType>> &get_custom_types() const { return custom_types; }
|
||||||
|
const CustomType *get_custom_type_by_name(const String &p_name) const;
|
||||||
|
const CustomType *get_custom_type_by_path(const String &p_path) const;
|
||||||
|
bool is_type_recognized(const String &p_type) const;
|
||||||
|
|
||||||
void instantiate_object_properties(Object *p_object);
|
void instantiate_object_properties(Object *p_object);
|
||||||
|
|
||||||
|
@ -2738,7 +2738,7 @@ void EditorInspector::update_tree() {
|
|||||||
doc_name = p.name;
|
doc_name = p.name;
|
||||||
|
|
||||||
// Set the category icon.
|
// Set the category icon.
|
||||||
if (!ClassDB::class_exists(type) && !ScriptServer::is_global_class(type) && p.hint_string.length() && FileAccess::exists(p.hint_string)) {
|
if (!EditorNode::get_editor_data().is_type_recognized(type) && p.hint_string.length() && FileAccess::exists(p.hint_string)) {
|
||||||
// If we have a category inside a script, search for the first script with a valid icon.
|
// If we have a category inside a script, search for the first script with a valid icon.
|
||||||
Ref<Script> script = ResourceLoader::load(p.hint_string, "Script");
|
Ref<Script> script = ResourceLoader::load(p.hint_string, "Script");
|
||||||
StringName base_type;
|
StringName base_type;
|
||||||
@ -2757,10 +2757,16 @@ void EditorInspector::update_tree() {
|
|||||||
while (script.is_valid()) {
|
while (script.is_valid()) {
|
||||||
name = EditorNode::get_editor_data().script_class_get_name(script->get_path());
|
name = EditorNode::get_editor_data().script_class_get_name(script->get_path());
|
||||||
String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name);
|
String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name);
|
||||||
if (name != StringName() && icon_path.length()) {
|
if (name != StringName() && !icon_path.is_empty()) {
|
||||||
category->icon = ResourceLoader::load(icon_path, "Texture");
|
category->icon = ResourceLoader::load(icon_path, "Texture");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const EditorData::CustomType *ctype = EditorNode::get_editor_data().get_custom_type_by_path(script->get_path());
|
||||||
|
if (ctype) {
|
||||||
|
category->icon = ctype->icon;
|
||||||
|
break;
|
||||||
|
}
|
||||||
script = script->get_base_script();
|
script = script->get_base_script();
|
||||||
}
|
}
|
||||||
if (category->icon.is_null() && has_theme_icon(base_type, SNAME("EditorIcons"))) {
|
if (category->icon.is_null() && has_theme_icon(base_type, SNAME("EditorIcons"))) {
|
||||||
|
@ -4338,16 +4338,8 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const HashMap<String, Vector<EditorData::CustomType>> &p_map = EditorNode::get_editor_data().get_custom_types();
|
if (const EditorData::CustomType *ctype = EditorNode::get_editor_data().get_custom_type_by_name(p_class)) {
|
||||||
for (const KeyValue<String, Vector<EditorData::CustomType>> &E : p_map) {
|
return ctype->icon;
|
||||||
const Vector<EditorData::CustomType> &ct = E.value;
|
|
||||||
for (int i = 0; i < ct.size(); ++i) {
|
|
||||||
if (ct[i].name == p_class) {
|
|
||||||
if (ct[i].icon.is_valid()) {
|
|
||||||
return ct[i].icon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gui_base->has_theme_icon(p_class, SNAME("EditorIcons"))) {
|
if (gui_base->has_theme_icon(p_class, SNAME("EditorIcons"))) {
|
||||||
|
@ -202,7 +202,7 @@ bool ScriptCreateDialog::_validate_parent(const String &p_string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ClassDB::class_exists(p_string) || ScriptServer::is_global_class(p_string);
|
return EditorNode::get_editor_data().is_type_recognized(p_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptCreateDialog::_validate_class(const String &p_string) {
|
bool ScriptCreateDialog::_validate_class(const String &p_string) {
|
||||||
@ -372,7 +372,15 @@ void ScriptCreateDialog::_create_new() {
|
|||||||
|
|
||||||
const ScriptLanguage::ScriptTemplate sinfo = _get_current_template();
|
const ScriptLanguage::ScriptTemplate sinfo = _get_current_template();
|
||||||
|
|
||||||
scr = ScriptServer::get_language(language_menu->get_selected())->make_template(sinfo.content, cname_param, parent_name->get_text());
|
String parent_class = parent_name->get_text();
|
||||||
|
if (!ClassDB::class_exists(parent_class) && !ScriptServer::is_global_class(parent_class)) {
|
||||||
|
// If base is a custom type, replace with script path instead.
|
||||||
|
const EditorData::CustomType *type = EditorNode::get_editor_data().get_custom_type_by_name(parent_class);
|
||||||
|
ERR_FAIL_NULL(type);
|
||||||
|
parent_class = "\"" + type->script->get_path() + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
scr = ScriptServer::get_language(language_menu->get_selected())->make_template(sinfo.content, cname_param, parent_class);
|
||||||
|
|
||||||
if (has_named_classes) {
|
if (has_named_classes) {
|
||||||
String cname = class_name->get_text();
|
String cname = class_name->get_text();
|
||||||
|
Loading…
Reference in New Issue
Block a user