You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-12-03 16:55:53 +00:00
Separate visual shader code out of shader editor plugin and dialog
This commit is contained in:
@@ -34,41 +34,21 @@
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/gui/editor_file_dialog.h"
|
||||
#include "editor/gui/editor_validation_panel.h"
|
||||
#include "editor/shader/editor_shader_language_plugin.h"
|
||||
#include "editor/themes/editor_scale.h"
|
||||
#include "scene/resources/shader_include.h"
|
||||
#include "scene/resources/visual_shader.h"
|
||||
#include "servers/rendering/shader_types.h"
|
||||
|
||||
enum ShaderType {
|
||||
SHADER_TYPE_TEXT,
|
||||
SHADER_TYPE_VISUAL,
|
||||
SHADER_TYPE_INC,
|
||||
SHADER_TYPE_MAX,
|
||||
};
|
||||
|
||||
void ShaderCreateDialog::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
String last_lang = EditorSettings::get_singleton()->get_project_metadata("shader_setup", "last_selected_language", "");
|
||||
if (!last_lang.is_empty()) {
|
||||
for (int i = 0; i < type_menu->get_item_count(); i++) {
|
||||
if (type_menu->get_item_text(i) == last_lang) {
|
||||
type_menu->select(i);
|
||||
current_type = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
type_menu->select(default_type);
|
||||
}
|
||||
|
||||
current_mode = EditorSettings::get_singleton()->get_project_metadata("shader_setup", "last_selected_mode", 0);
|
||||
mode_menu->select(current_mode);
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
_refresh_type_icons();
|
||||
path_button->set_button_icon(get_editor_theme_icon(SNAME("Folder")));
|
||||
// Note that some of the theme logic happens in `config()` when opening the dialog.
|
||||
} break;
|
||||
}
|
||||
}
|
||||
@@ -91,16 +71,13 @@ void ShaderCreateDialog::_refresh_type_icons() {
|
||||
void ShaderCreateDialog::_update_language_info() {
|
||||
type_data.clear();
|
||||
|
||||
for (int i = 0; i < SHADER_TYPE_MAX; i++) {
|
||||
for (int i = 0; i < EditorShaderLanguagePlugin::get_shader_language_variation_count(); i++) {
|
||||
ShaderTypeData shader_type_data;
|
||||
if (i == int(SHADER_TYPE_TEXT)) {
|
||||
if (i == 0) {
|
||||
// HACK: The ShaderCreateDialog class currently only shows templates for text shaders. Generalize this later.
|
||||
shader_type_data.use_templates = true;
|
||||
shader_type_data.default_extension = "gdshader";
|
||||
} else if (i == int(SHADER_TYPE_INC)) {
|
||||
shader_type_data.default_extension = "gdshaderinc";
|
||||
} else {
|
||||
shader_type_data.default_extension = "tres";
|
||||
}
|
||||
shader_type_data.default_extension = EditorShaderLanguagePlugin::get_file_extension_for_index(i);
|
||||
shader_type_data.extensions.push_back(shader_type_data.default_extension);
|
||||
if (shader_type_data.default_extension != "tres") {
|
||||
shader_type_data.extensions.push_back("tres");
|
||||
@@ -155,93 +132,14 @@ void ShaderCreateDialog::_create_new() {
|
||||
Ref<Resource> shader;
|
||||
Ref<Resource> shader_inc;
|
||||
|
||||
switch (type_menu->get_selected()) {
|
||||
case SHADER_TYPE_TEXT: {
|
||||
Ref<Shader> text_shader;
|
||||
text_shader.instantiate();
|
||||
shader = text_shader;
|
||||
|
||||
StringBuilder code;
|
||||
code += vformat("shader_type %s;\n", mode_menu->get_text().to_snake_case());
|
||||
|
||||
if (current_template == 0) { // Default template.
|
||||
switch (current_mode) {
|
||||
case Shader::MODE_SPATIAL:
|
||||
code += R"(
|
||||
void vertex() {
|
||||
// Called for every vertex the material is visible on.
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
// Called for every pixel the material is visible on.
|
||||
}
|
||||
|
||||
//void light() {
|
||||
// // Called for every pixel for every light affecting the material.
|
||||
// // Uncomment to replace the default light processing function with this one.
|
||||
//}
|
||||
)";
|
||||
break;
|
||||
case Shader::MODE_CANVAS_ITEM:
|
||||
code += R"(
|
||||
void vertex() {
|
||||
// Called for every vertex the material is visible on.
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
// Called for every pixel the material is visible on.
|
||||
}
|
||||
|
||||
//void light() {
|
||||
// // Called for every pixel for every light affecting the CanvasItem.
|
||||
// // Uncomment to replace the default light processing function with this one.
|
||||
//}
|
||||
)";
|
||||
break;
|
||||
case Shader::MODE_PARTICLES:
|
||||
code += R"(
|
||||
void start() {
|
||||
// Called when a particle is spawned.
|
||||
}
|
||||
|
||||
void process() {
|
||||
// Called every frame on existing particles (according to the Fixed FPS property).
|
||||
}
|
||||
)";
|
||||
break;
|
||||
case Shader::MODE_SKY:
|
||||
code += R"(
|
||||
void sky() {
|
||||
// Called for every visible pixel in the sky background, as well as all pixels
|
||||
// in the radiance cubemap.
|
||||
}
|
||||
)";
|
||||
break;
|
||||
case Shader::MODE_FOG:
|
||||
code += R"(
|
||||
void fog() {
|
||||
// Called once for every froxel that is touched by an axis-aligned bounding box
|
||||
// of the associated FogVolume. This means that froxels that just barely touch
|
||||
// a given FogVolume will still be used.
|
||||
}
|
||||
)";
|
||||
}
|
||||
}
|
||||
text_shader->set_code(code.as_string());
|
||||
} break;
|
||||
case SHADER_TYPE_VISUAL: {
|
||||
Ref<VisualShader> visual_shader;
|
||||
visual_shader.instantiate();
|
||||
shader = visual_shader;
|
||||
visual_shader->set_mode(Shader::Mode(current_mode));
|
||||
} break;
|
||||
case SHADER_TYPE_INC: {
|
||||
Ref<ShaderInclude> include;
|
||||
include.instantiate();
|
||||
shader_inc = include;
|
||||
} break;
|
||||
default: {
|
||||
} break;
|
||||
const int type_index = type_menu->get_selected();
|
||||
Ref<EditorShaderLanguagePlugin> shader_lang = EditorShaderLanguagePlugin::get_shader_language_for_index(type_index);
|
||||
// A bit of an unfortunate hack because Shader and ShaderInclude do not share a common base class.
|
||||
// We need duplicate code paths for includes vs non-includes, so just check for the string "Include".
|
||||
if (type_menu->get_item_text(type_index).contains("Include")) {
|
||||
shader_inc = shader_lang->create_new_shader_include();
|
||||
} else {
|
||||
shader = shader_lang->create_new_shader(0, Shader::Mode(current_mode), current_template);
|
||||
}
|
||||
|
||||
if (shader.is_null()) {
|
||||
@@ -317,8 +215,18 @@ void ShaderCreateDialog::_type_changed(int p_language) {
|
||||
_path_changed(path);
|
||||
file_path->set_text(path);
|
||||
|
||||
type_menu->set_item_disabled(int(SHADER_TYPE_INC), load_enabled);
|
||||
mode_menu->set_disabled(p_language == SHADER_TYPE_INC);
|
||||
mode_menu->set_disabled(false);
|
||||
for (int i = 0; i < type_menu->get_item_count(); i++) {
|
||||
const String item_name = type_menu->get_item_text(i);
|
||||
if (item_name.contains("Include")) {
|
||||
type_menu->set_item_disabled(i, load_enabled);
|
||||
if (i == p_language) {
|
||||
mode_menu->set_disabled(true);
|
||||
}
|
||||
} else {
|
||||
type_menu->set_item_disabled(i, false);
|
||||
}
|
||||
}
|
||||
template_menu->set_disabled(!shader_type_data.use_templates);
|
||||
template_menu->clear();
|
||||
|
||||
@@ -408,7 +316,43 @@ void ShaderCreateDialog::_path_submitted(const String &p_path) {
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderCreateDialog::config(const String &p_base_path, bool p_built_in_enabled, bool p_load_enabled, int p_preferred_type, int p_preferred_mode) {
|
||||
void ShaderCreateDialog::config(const String &p_base_path, bool p_built_in_enabled, bool p_load_enabled, const String &p_preferred_type, int p_preferred_mode) {
|
||||
_update_language_info();
|
||||
type_menu->clear();
|
||||
const Vector<Ref<EditorShaderLanguagePlugin>> shader_langs = EditorShaderLanguagePlugin::get_shader_languages_read_only();
|
||||
ERR_FAIL_COND_MSG(shader_langs.is_empty(), "ShaderCreateDialog: Unable to load any shader languages!");
|
||||
for (Ref<EditorShaderLanguagePlugin> shader_lang : shader_langs) {
|
||||
const PackedStringArray variations = shader_lang->get_language_variations();
|
||||
for (const String &variation : variations) {
|
||||
type_menu->add_item(variation);
|
||||
}
|
||||
}
|
||||
_refresh_type_icons();
|
||||
|
||||
int preferred_type = -1;
|
||||
// Select preferred type if specified.
|
||||
for (int i = 0; i < type_menu->get_item_count(); i++) {
|
||||
if (type_menu->get_item_text(i) == p_preferred_type) {
|
||||
preferred_type = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (preferred_type < 0 || preferred_type >= type_menu->get_item_count()) {
|
||||
preferred_type = 0;
|
||||
// Select the last selected language if possible, otherwise default to the first language.
|
||||
String last_lang = EditorSettings::get_singleton()->get_project_metadata("shader_setup", "last_selected_language", "");
|
||||
if (!last_lang.is_empty()) {
|
||||
for (int i = 0; i < type_menu->get_item_count(); i++) {
|
||||
if (type_menu->get_item_text(i) == last_lang) {
|
||||
preferred_type = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type_menu->select(preferred_type);
|
||||
current_type = 0;
|
||||
|
||||
if (!p_base_path.is_empty()) {
|
||||
initial_base_path = p_base_path.get_basename();
|
||||
file_path->set_text(initial_base_path + "." + type_data.get(type_menu->get_selected()).default_extension);
|
||||
@@ -426,11 +370,6 @@ void ShaderCreateDialog::config(const String &p_base_path, bool p_built_in_enabl
|
||||
internal->set_pressed(EditorSettings::get_singleton()->get_project_metadata("shader_setup", "create_built_in_shader", false));
|
||||
}
|
||||
|
||||
if (p_preferred_type > -1) {
|
||||
type_menu->select(p_preferred_type);
|
||||
_type_changed(p_preferred_type);
|
||||
}
|
||||
|
||||
if (p_preferred_mode > -1) {
|
||||
mode_menu->select(p_preferred_mode);
|
||||
_mode_changed(p_preferred_mode);
|
||||
@@ -468,41 +407,14 @@ String ShaderCreateDialog::_validate_path(const String &p_path) {
|
||||
|
||||
const ShaderCreateDialog::ShaderTypeData ¤t_type_data = type_data.get(current_type);
|
||||
const String file_extension = stripped_file_path.get_extension();
|
||||
HashSet<String> extensions;
|
||||
|
||||
List<ShaderCreateDialog::ShaderTypeData>::ConstIterator itr = type_data.begin();
|
||||
for (int i = 0; i < SHADER_TYPE_MAX; ++itr, ++i) {
|
||||
for (const String &ext : itr->extensions) {
|
||||
if (!extensions.has(ext)) {
|
||||
extensions.insert(ext);
|
||||
}
|
||||
for (const String &type_ext : current_type_data.extensions) {
|
||||
if (type_ext.nocasecmp_to(file_extension) == 0) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
bool match = false;
|
||||
|
||||
for (const String &ext : extensions) {
|
||||
if (ext.nocasecmp_to(file_extension) == 0) {
|
||||
found = true;
|
||||
for (const String &type_ext : current_type_data.extensions) {
|
||||
if (type_ext.nocasecmp_to(file_extension) == 0) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
return TTR("Invalid extension.");
|
||||
}
|
||||
if (!match) {
|
||||
return TTR("Wrong extension chosen.");
|
||||
}
|
||||
|
||||
return "";
|
||||
return TTR("Invalid extension for selected shader type.");
|
||||
}
|
||||
|
||||
void ShaderCreateDialog::_update_dialog() {
|
||||
@@ -598,36 +510,6 @@ ShaderCreateDialog::ShaderCreateDialog() {
|
||||
gc->add_child(memnew(Label(TTR("Type:"))));
|
||||
gc->add_child(type_menu);
|
||||
|
||||
for (int i = 0; i < SHADER_TYPE_MAX; i++) {
|
||||
String type;
|
||||
bool invalid = false;
|
||||
switch (i) {
|
||||
case SHADER_TYPE_TEXT:
|
||||
type = "Shader";
|
||||
default_type = i;
|
||||
break;
|
||||
case SHADER_TYPE_VISUAL:
|
||||
type = "VisualShader";
|
||||
break;
|
||||
case SHADER_TYPE_INC:
|
||||
type = "ShaderInclude";
|
||||
break;
|
||||
case SHADER_TYPE_MAX:
|
||||
invalid = true;
|
||||
break;
|
||||
default:
|
||||
invalid = true;
|
||||
break;
|
||||
}
|
||||
if (invalid) {
|
||||
continue;
|
||||
}
|
||||
type_menu->add_item(type);
|
||||
}
|
||||
if (default_type >= 0) {
|
||||
type_menu->select(default_type);
|
||||
}
|
||||
current_type = default_type;
|
||||
type_menu->connect(SceneStringName(item_selected), callable_mp(this, &ShaderCreateDialog::_type_changed));
|
||||
|
||||
// Modes.
|
||||
|
||||
Reference in New Issue
Block a user