|
@@ -135,6 +135,7 @@ void ShaderTextEditor::set_edited_code(const String &p_code) {
|
|
get_text_editor()->clear_undo_history();
|
|
get_text_editor()->clear_undo_history();
|
|
get_text_editor()->call_deferred(SNAME("set_h_scroll"), 0);
|
|
get_text_editor()->call_deferred(SNAME("set_h_scroll"), 0);
|
|
get_text_editor()->call_deferred(SNAME("set_v_scroll"), 0);
|
|
get_text_editor()->call_deferred(SNAME("set_v_scroll"), 0);
|
|
|
|
+ get_text_editor()->tag_saved_version();
|
|
|
|
|
|
_validate_script();
|
|
_validate_script();
|
|
_line_col_changed();
|
|
_line_col_changed();
|
|
@@ -844,6 +845,7 @@ void ShaderEditor::save_external_data(const String &p_str) {
|
|
if (shader_inc.is_valid() && shader_inc != edited_shader_inc) {
|
|
if (shader_inc.is_valid() && shader_inc != edited_shader_inc) {
|
|
ResourceSaver::save(shader_inc->get_path(), shader_inc);
|
|
ResourceSaver::save(shader_inc->get_path(), shader_inc);
|
|
}
|
|
}
|
|
|
|
+ shader_editor->get_text_editor()->tag_saved_version();
|
|
|
|
|
|
disk_changed->hide();
|
|
disk_changed->hide();
|
|
}
|
|
}
|
|
@@ -852,6 +854,10 @@ void ShaderEditor::validate_script() {
|
|
shader_editor->_validate_script();
|
|
shader_editor->_validate_script();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+bool ShaderEditor::is_unsaved() const {
|
|
|
|
+ return shader_editor->get_text_editor()->get_saved_version() != shader_editor->get_text_editor()->get_version();
|
|
|
|
+}
|
|
|
|
+
|
|
void ShaderEditor::apply_shaders() {
|
|
void ShaderEditor::apply_shaders() {
|
|
String editor_code = shader_editor->get_text_editor()->get_text();
|
|
String editor_code = shader_editor->get_text_editor()->get_text();
|
|
if (shader.is_valid()) {
|
|
if (shader.is_valid()) {
|
|
@@ -1128,36 +1134,34 @@ ShaderEditor::ShaderEditor() {
|
|
void ShaderEditorPlugin::_update_shader_list() {
|
|
void ShaderEditorPlugin::_update_shader_list() {
|
|
shader_list->clear();
|
|
shader_list->clear();
|
|
for (uint32_t i = 0; i < edited_shaders.size(); i++) {
|
|
for (uint32_t i = 0; i < edited_shaders.size(); i++) {
|
|
- String text;
|
|
|
|
- String path;
|
|
|
|
- String _class;
|
|
|
|
- String shader_name;
|
|
|
|
- if (edited_shaders[i].shader.is_valid()) {
|
|
|
|
- Ref<Shader> shader = edited_shaders[i].shader;
|
|
|
|
-
|
|
|
|
- path = shader->get_path();
|
|
|
|
- _class = shader->get_class();
|
|
|
|
- shader_name = shader->get_name();
|
|
|
|
- } else {
|
|
|
|
- Ref<ShaderInclude> shader_inc = edited_shaders[i].shader_inc;
|
|
|
|
-
|
|
|
|
- path = shader_inc->get_path();
|
|
|
|
- _class = shader_inc->get_class();
|
|
|
|
- shader_name = shader_inc->get_name();
|
|
|
|
|
|
+ Ref<Resource> shader = edited_shaders[i].shader;
|
|
|
|
+ if (shader.is_null()) {
|
|
|
|
+ shader = edited_shaders[i].shader_inc;
|
|
}
|
|
}
|
|
|
|
|
|
- if (path.is_resource_file()) {
|
|
|
|
- text = path.get_file();
|
|
|
|
- } else if (shader_name != "") {
|
|
|
|
- text = shader_name;
|
|
|
|
- } else {
|
|
|
|
- if (edited_shaders[i].shader.is_valid()) {
|
|
|
|
- text = _class + ":" + itos(edited_shaders[i].shader->get_instance_id());
|
|
|
|
- } else {
|
|
|
|
- text = _class + ":" + itos(edited_shaders[i].shader_inc->get_instance_id());
|
|
|
|
|
|
+ String path = shader->get_path();
|
|
|
|
+ String text = path.get_file();
|
|
|
|
+ if (text.is_empty()) {
|
|
|
|
+ // This appears for newly created built-in shaders before saving the scene.
|
|
|
|
+ text = TTR("[unsaved]");
|
|
|
|
+ } else if (shader->is_built_in()) {
|
|
|
|
+ const String &shader_name = shader->get_name();
|
|
|
|
+ if (!shader_name.is_empty()) {
|
|
|
|
+ text = vformat("%s (%s)", shader_name, text.get_slice("::", 0));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ bool unsaved = false;
|
|
|
|
+ if (edited_shaders[i].shader_editor) {
|
|
|
|
+ unsaved = edited_shaders[i].shader_editor->is_unsaved();
|
|
|
|
+ }
|
|
|
|
+ // TODO: Handle visual shaders too.
|
|
|
|
+
|
|
|
|
+ if (unsaved) {
|
|
|
|
+ text += "(*)";
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ String _class = shader->get_class();
|
|
if (!shader_list->has_theme_icon(_class, SNAME("EditorIcons"))) {
|
|
if (!shader_list->has_theme_icon(_class, SNAME("EditorIcons"))) {
|
|
_class = "TextFile";
|
|
_class = "TextFile";
|
|
}
|
|
}
|
|
@@ -1207,7 +1211,7 @@ void ShaderEditorPlugin::edit(Object *p_object) {
|
|
es.shader_editor = memnew(ShaderEditor);
|
|
es.shader_editor = memnew(ShaderEditor);
|
|
es.shader_editor->edit(si);
|
|
es.shader_editor->edit(si);
|
|
shader_tabs->add_child(es.shader_editor);
|
|
shader_tabs->add_child(es.shader_editor);
|
|
- es.shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list_status));
|
|
|
|
|
|
+ es.shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list));
|
|
} else {
|
|
} else {
|
|
Shader *s = Object::cast_to<Shader>(p_object);
|
|
Shader *s = Object::cast_to<Shader>(p_object);
|
|
for (uint32_t i = 0; i < edited_shaders.size(); i++) {
|
|
for (uint32_t i = 0; i < edited_shaders.size(); i++) {
|
|
@@ -1227,7 +1231,7 @@ void ShaderEditorPlugin::edit(Object *p_object) {
|
|
es.shader_editor = memnew(ShaderEditor);
|
|
es.shader_editor = memnew(ShaderEditor);
|
|
shader_tabs->add_child(es.shader_editor);
|
|
shader_tabs->add_child(es.shader_editor);
|
|
es.shader_editor->edit(s);
|
|
es.shader_editor->edit(s);
|
|
- es.shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list_status));
|
|
|
|
|
|
+ es.shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1273,6 +1277,7 @@ void ShaderEditorPlugin::save_external_data() {
|
|
edited_shaders[i].shader_editor->save_external_data();
|
|
edited_shaders[i].shader_editor->save_external_data();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ _update_shader_list();
|
|
}
|
|
}
|
|
|
|
|
|
void ShaderEditorPlugin::apply_changes() {
|
|
void ShaderEditorPlugin::apply_changes() {
|
|
@@ -1290,6 +1295,12 @@ void ShaderEditorPlugin::_shader_selected(int p_index) {
|
|
shader_tabs->set_current_tab(p_index);
|
|
shader_tabs->set_current_tab(p_index);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void ShaderEditorPlugin::_shader_list_clicked(int p_item, Vector2 p_local_mouse_pos, MouseButton p_mouse_button_index) {
|
|
|
|
+ if (p_mouse_button_index == MouseButton::MIDDLE) {
|
|
|
|
+ _close_shader(p_item);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
void ShaderEditorPlugin::_close_shader(int p_index) {
|
|
void ShaderEditorPlugin::_close_shader(int p_index) {
|
|
int index = shader_tabs->get_current_tab();
|
|
int index = shader_tabs->get_current_tab();
|
|
ERR_FAIL_INDEX(index, shader_tabs->get_tab_count());
|
|
ERR_FAIL_INDEX(index, shader_tabs->get_tab_count());
|
|
@@ -1409,6 +1420,7 @@ ShaderEditorPlugin::ShaderEditorPlugin() {
|
|
shader_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
|
shader_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
|
vb->add_child(shader_list);
|
|
vb->add_child(shader_list);
|
|
shader_list->connect("item_selected", callable_mp(this, &ShaderEditorPlugin::_shader_selected));
|
|
shader_list->connect("item_selected", callable_mp(this, &ShaderEditorPlugin::_shader_selected));
|
|
|
|
+ shader_list->connect("item_clicked", callable_mp(this, &ShaderEditorPlugin::_shader_list_clicked));
|
|
|
|
|
|
main_split->add_child(vb);
|
|
main_split->add_child(vb);
|
|
vb->set_custom_minimum_size(Size2(200, 300) * EDSCALE);
|
|
vb->set_custom_minimum_size(Size2(200, 300) * EDSCALE);
|