Make custom types more subtle and more useful
Implements #6067 (aaronfranke's idea) Fixes #26980
This commit is contained in:
parent
22c843b0c4
commit
4f72178868
6 changed files with 104 additions and 31 deletions
|
@ -1274,12 +1274,7 @@ void AnimationTrackEdit::_notification(int p_what) {
|
|||
}
|
||||
text_color.a *= 0.7;
|
||||
} else if (node) {
|
||||
Ref<Texture> icon;
|
||||
if (has_icon(node->get_class(), "EditorIcons")) {
|
||||
icon = get_icon(node->get_class(), "EditorIcons");
|
||||
} else {
|
||||
icon = get_icon("Node", "EditorIcons");
|
||||
}
|
||||
Ref<Texture> icon = EditorNode::get_singleton()->get_object_icon(node, "Node");
|
||||
|
||||
draw_texture(icon, Point2(ofs, int(get_size().height - icon->get_height()) / 2));
|
||||
icon_cache = icon;
|
||||
|
@ -3500,9 +3495,7 @@ void AnimationTrackEditor::_update_tracks() {
|
|||
if (root && root->has_node(base_path)) {
|
||||
Node *n = root->get_node(base_path);
|
||||
if (n) {
|
||||
if (has_icon(n->get_class(), "EditorIcons")) {
|
||||
icon = get_icon(n->get_class(), "EditorIcons");
|
||||
}
|
||||
icon = EditorNode::get_singleton()->get_object_icon(n, "Node");
|
||||
name = n->get_name();
|
||||
tooltip = root->get_path_to(n);
|
||||
}
|
||||
|
|
|
@ -499,7 +499,6 @@ Object *EditorData::instance_custom_type(const String &p_type, const String &p_i
|
|||
|
||||
for (int i = 0; i < get_custom_types()[p_inherits].size(); i++) {
|
||||
if (get_custom_types()[p_inherits][i].name == p_type) {
|
||||
Ref<Texture> icon = get_custom_types()[p_inherits][i].icon;
|
||||
Ref<Script> script = get_custom_types()[p_inherits][i].script;
|
||||
|
||||
Object *ob = ClassDB::instance(p_inherits);
|
||||
|
@ -508,8 +507,6 @@ Object *EditorData::instance_custom_type(const String &p_type, const String &p_i
|
|||
ob->call("set_name", p_type);
|
||||
}
|
||||
ob->set_script(script.get_ref_ptr());
|
||||
if (icon.is_valid())
|
||||
ob->set_meta("_editor_icon", icon);
|
||||
return ob;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3488,6 +3488,69 @@ void EditorNode::stop_child_process() {
|
|||
_menu_option_confirm(RUN_STOP, false);
|
||||
}
|
||||
|
||||
Ref<Script> EditorNode::get_object_custom_type_base(const Object *p_object) const {
|
||||
ERR_FAIL_COND_V(!p_object, NULL);
|
||||
|
||||
Ref<Script> script = p_object->get_script();
|
||||
|
||||
if (script.is_valid()) {
|
||||
// Uncommenting would break things! Consider adding a parameter if you need it.
|
||||
// StringName name = EditorNode::get_editor_data().script_class_get_name(base_script->get_path());
|
||||
// if (name != StringName())
|
||||
// return name;
|
||||
|
||||
// should probably be deprecated in 4.x
|
||||
StringName base = script->get_instance_base_type();
|
||||
if (base != StringName() && EditorNode::get_editor_data().get_custom_types().has(base)) {
|
||||
const Vector<EditorData::CustomType> &types = EditorNode::get_editor_data().get_custom_types()[base];
|
||||
|
||||
Ref<Script> base_script = script;
|
||||
while (base_script.is_valid()) {
|
||||
for (int i = 0; i < types.size(); ++i) {
|
||||
if (types[i].script == base_script) {
|
||||
return types[i].script;
|
||||
}
|
||||
}
|
||||
base_script = base_script->get_base_script();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
StringName EditorNode::get_object_custom_type_name(const Object *p_object) const {
|
||||
ERR_FAIL_COND_V(!p_object, StringName());
|
||||
|
||||
Ref<Script> script = p_object->get_script();
|
||||
if (script.is_null() && p_object->is_class("Script")) {
|
||||
script = p_object;
|
||||
}
|
||||
|
||||
if (script.is_valid()) {
|
||||
Ref<Script> base_script = script;
|
||||
while (base_script.is_valid()) {
|
||||
StringName name = EditorNode::get_editor_data().script_class_get_name(base_script->get_path());
|
||||
if (name != StringName())
|
||||
return name;
|
||||
|
||||
// should probably be deprecated in 4.x
|
||||
StringName base = base_script->get_instance_base_type();
|
||||
if (base != StringName() && EditorNode::get_editor_data().get_custom_types().has(base)) {
|
||||
const Vector<EditorData::CustomType> &types = EditorNode::get_editor_data().get_custom_types()[base];
|
||||
for (int i = 0; i < types.size(); ++i) {
|
||||
if (types[i].script == base_script) {
|
||||
return types[i].name;
|
||||
}
|
||||
}
|
||||
}
|
||||
base_script = base_script->get_base_script();
|
||||
}
|
||||
}
|
||||
|
||||
return StringName();
|
||||
}
|
||||
|
||||
Ref<Texture> EditorNode::get_object_icon(const Object *p_object, const String &p_fallback) const {
|
||||
ERR_FAIL_COND_V(!p_object || !gui_base, NULL);
|
||||
|
||||
|
@ -3497,23 +3560,24 @@ Ref<Texture> EditorNode::get_object_icon(const Object *p_object, const String &p
|
|||
}
|
||||
|
||||
if (script.is_valid()) {
|
||||
StringName 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);
|
||||
if (icon_path.length())
|
||||
return ResourceLoader::load(icon_path);
|
||||
Ref<Script> base_script = script;
|
||||
while (base_script.is_valid()) {
|
||||
StringName name = EditorNode::get_editor_data().script_class_get_name(base_script->get_path());
|
||||
String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name);
|
||||
if (icon_path.length())
|
||||
return ResourceLoader::load(icon_path);
|
||||
|
||||
// should probably be deprecated in 4.x
|
||||
StringName base = script->get_instance_base_type();
|
||||
if (base != StringName()) {
|
||||
const Map<String, Vector<EditorData::CustomType> > &p_map = EditorNode::get_editor_data().get_custom_types();
|
||||
for (const Map<String, Vector<EditorData::CustomType> >::Element *E = p_map.front(); E; E = E->next()) {
|
||||
const Vector<EditorData::CustomType> &ct = E->value();
|
||||
for (int i = 0; i < ct.size(); ++i) {
|
||||
if (ct[i].name == base && ct[i].icon.is_valid()) {
|
||||
return ct[i].icon;
|
||||
// should probably be deprecated in 4.x
|
||||
StringName base = base_script->get_instance_base_type();
|
||||
if (base != StringName() && EditorNode::get_editor_data().get_custom_types().has(base)) {
|
||||
const Vector<EditorData::CustomType> &types = EditorNode::get_editor_data().get_custom_types()[base];
|
||||
for (int i = 0; i < types.size(); ++i) {
|
||||
if (types[i].script == base_script && types[i].icon.is_valid()) {
|
||||
return types[i].icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
base_script = base_script->get_base_script();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -776,6 +776,8 @@ public:
|
|||
void stop_child_process();
|
||||
|
||||
Ref<Theme> get_editor_theme() const { return theme; }
|
||||
Ref<Script> get_object_custom_type_base(const Object *p_object) const;
|
||||
StringName get_object_custom_type_name(const Object *p_object) const;
|
||||
Ref<Texture> get_object_icon(const Object *p_object, const String &p_fallback = "Object") const;
|
||||
Ref<Texture> get_class_icon(const String &p_class, const String &p_fallback = "Object") const;
|
||||
|
||||
|
|
|
@ -466,8 +466,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
|
|||
|
||||
Node *n = Object::cast_to<Node>(selection[i]);
|
||||
Ref<Script> existing = n->get_script();
|
||||
if (existing.is_valid()) {
|
||||
const RefPtr empty;
|
||||
Ref<Script> empty = EditorNode::get_singleton()->get_object_custom_type_base(n);
|
||||
if (existing != empty) {
|
||||
editor_data->get_undo_redo().add_do_method(n, "set_script", empty);
|
||||
editor_data->get_undo_redo().add_undo_method(n, "set_script", existing);
|
||||
}
|
||||
|
@ -2329,6 +2329,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
|
|||
menu->clear();
|
||||
|
||||
Ref<Script> existing_script;
|
||||
bool exisiting_script_removable = true;
|
||||
if (selection.size() == 1) {
|
||||
|
||||
Node *selected = selection[0];
|
||||
|
@ -2348,6 +2349,10 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
|
|||
menu->add_separator();
|
||||
|
||||
existing_script = selected->get_script();
|
||||
|
||||
if (EditorNode::get_singleton()->get_object_custom_type_base(selected) == existing_script) {
|
||||
exisiting_script_removable = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (profile_allow_script_editing) {
|
||||
|
@ -2359,7 +2364,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
|
|||
menu->add_icon_shortcut(get_icon("ScriptExtend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/extend_script"), TOOL_ATTACH_SCRIPT);
|
||||
}
|
||||
}
|
||||
if (selection.size() > 1 || existing_script.is_valid()) {
|
||||
if (selection.size() > 1 || (existing_script.is_valid() && exisiting_script_removable)) {
|
||||
menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT);
|
||||
}
|
||||
menu->add_separator();
|
||||
|
|
|
@ -212,13 +212,19 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
|
|||
Color accent = get_color("accent_color", "Editor");
|
||||
|
||||
Ref<Script> script = p_node->get_script();
|
||||
if (!script.is_null()) {
|
||||
if (!script.is_null() && EditorNode::get_singleton()->get_object_custom_type_base(p_node) != script) {
|
||||
//has script
|
||||
item->add_button(0, get_icon("Script", "EditorIcons"), BUTTON_SCRIPT);
|
||||
} else {
|
||||
//has no script
|
||||
//has no script (or script is a custom type)
|
||||
item->set_custom_color(0, get_color("disabled_font_color", "Editor"));
|
||||
item->set_selectable(0, false);
|
||||
|
||||
if (!script.is_null()) { // make sure to mark the script if a custom type
|
||||
item->add_button(0, get_icon("Script", "EditorIcons"), BUTTON_SCRIPT);
|
||||
item->set_button_disabled(0, item->get_button_count(0) - 1, true);
|
||||
}
|
||||
|
||||
accent.a *= 0.7;
|
||||
}
|
||||
|
||||
|
@ -284,7 +290,10 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
|
|||
item->add_button(0, get_icon("InstanceOptions", "EditorIcons"), BUTTON_SUBSCENE, false, TTR("Open in Editor"));
|
||||
item->set_tooltip(0, TTR("Instance:") + " " + p_node->get_filename() + "\n" + TTR("Type:") + " " + p_node->get_class());
|
||||
} else {
|
||||
item->set_tooltip(0, String(p_node->get_name()) + "\n" + TTR("Type:") + " " + p_node->get_class());
|
||||
StringName type = EditorNode::get_singleton()->get_object_custom_type_name(p_node);
|
||||
if (type == StringName())
|
||||
type = p_node->get_class();
|
||||
item->set_tooltip(0, String(p_node->get_name()) + "\n" + TTR("Type:") + " " + type);
|
||||
}
|
||||
|
||||
if (can_open_instance && undo_redo) { //Show buttons only when necessary(SceneTreeDock) to avoid crashes
|
||||
|
@ -295,6 +304,9 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
|
|||
Ref<Script> script = p_node->get_script();
|
||||
if (!script.is_null()) {
|
||||
item->add_button(0, get_icon("Script", "EditorIcons"), BUTTON_SCRIPT, false, TTR("Open Script:") + " " + script->get_path());
|
||||
if (EditorNode::get_singleton()->get_object_custom_type_base(p_node) == script) {
|
||||
item->set_button_color(0, item->get_button_count(0) - 1, Color(1, 1, 1, 0.5));
|
||||
}
|
||||
}
|
||||
|
||||
if (p_node->is_class("CanvasItem")) {
|
||||
|
|
Loading…
Reference in a new issue