You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-12-02 16:48:55 +00:00
Separate visual shader code out of shader editor plugin and dialog
This commit is contained in:
@@ -2711,17 +2711,17 @@ void FileSystemDock::_resource_created() {
|
||||
fpath = fpath.get_base_dir();
|
||||
}
|
||||
|
||||
String type_name = new_resource_dialog->get_selected_type();
|
||||
const String type_name = new_resource_dialog->get_selected_type();
|
||||
if (type_name == "Shader") {
|
||||
make_shader_dialog->config(fpath.path_join("new_shader"), false, false, 0);
|
||||
make_shader_dialog->popup_centered();
|
||||
return;
|
||||
} else if (type_name == "VisualShader") {
|
||||
make_shader_dialog->config(fpath.path_join("new_shader"), false, false, 1);
|
||||
make_shader_dialog->config(fpath.path_join("new_shader"), false, false, type_name);
|
||||
make_shader_dialog->popup_centered();
|
||||
return;
|
||||
} else if (type_name == "ShaderInclude") {
|
||||
make_shader_dialog->config(fpath.path_join("new_shader_include"), false, false, 2);
|
||||
make_shader_dialog->config(fpath.path_join("new_shader_include"), false, false, type_name);
|
||||
make_shader_dialog->popup_centered();
|
||||
return;
|
||||
} else if (type_name == "VisualShader") {
|
||||
make_shader_dialog->config(fpath.path_join("new_shader"), false, false, type_name);
|
||||
make_shader_dialog->popup_centered();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4255,7 +4255,7 @@ void SceneTreeDock::attach_shader_to_selected(int p_preferred_mode) {
|
||||
shader_create_dialog->connect("shader_created", callable_mp(this, &SceneTreeDock::_shader_created));
|
||||
shader_create_dialog->connect(SceneStringName(confirmed), callable_mp(this, &SceneTreeDock::_shader_creation_closed));
|
||||
shader_create_dialog->connect("canceled", callable_mp(this, &SceneTreeDock::_shader_creation_closed));
|
||||
shader_create_dialog->config(path, true, true, -1, p_preferred_mode);
|
||||
shader_create_dialog->config(path, true, true, "", p_preferred_mode);
|
||||
shader_create_dialog->popup_centered();
|
||||
}
|
||||
|
||||
|
||||
70
editor/shader/editor_shader_language_plugin.cpp
Normal file
70
editor/shader/editor_shader_language_plugin.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/**************************************************************************/
|
||||
/* editor_shader_language_plugin.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "editor_shader_language_plugin.h"
|
||||
|
||||
Vector<Ref<EditorShaderLanguagePlugin>> EditorShaderLanguagePlugin::shader_languages;
|
||||
Vector<Vector2i> EditorShaderLanguagePlugin::language_variation_map;
|
||||
|
||||
void EditorShaderLanguagePlugin::register_shader_language(const Ref<EditorShaderLanguagePlugin> &p_shader_language) {
|
||||
// Allows one ShaderLanguageEditorPlugin to provide multiple dropdown options in
|
||||
// the language selection menu. For example, ShaderInclude is handled this way.
|
||||
// X is the plugin index, and Y is the language variation index.
|
||||
for (int i = 0; i < p_shader_language->get_language_variations().size(); i++) {
|
||||
language_variation_map.push_back(Vector2i(shader_languages.size(), i));
|
||||
}
|
||||
shader_languages.push_back(p_shader_language);
|
||||
}
|
||||
|
||||
void EditorShaderLanguagePlugin::clear_registered_shader_languages() {
|
||||
shader_languages.clear();
|
||||
language_variation_map.clear();
|
||||
}
|
||||
|
||||
const Vector<Ref<EditorShaderLanguagePlugin>> EditorShaderLanguagePlugin::get_shader_languages_read_only() {
|
||||
return shader_languages;
|
||||
}
|
||||
|
||||
int EditorShaderLanguagePlugin::get_shader_language_variation_count() {
|
||||
return language_variation_map.size();
|
||||
}
|
||||
|
||||
Ref<EditorShaderLanguagePlugin> EditorShaderLanguagePlugin::get_shader_language_for_index(int p_index) {
|
||||
ERR_FAIL_INDEX_V(p_index, language_variation_map.size(), nullptr);
|
||||
Vector2i lang_var_indices = language_variation_map[p_index];
|
||||
return shader_languages[lang_var_indices.x];
|
||||
}
|
||||
|
||||
String EditorShaderLanguagePlugin::get_file_extension_for_index(int p_index) {
|
||||
ERR_FAIL_INDEX_V(p_index, language_variation_map.size(), "tres");
|
||||
Vector2i lang_var_indices = language_variation_map[p_index];
|
||||
EditorShaderLanguagePlugin *lang = shader_languages[lang_var_indices.x].ptr();
|
||||
return lang->get_file_extension(lang_var_indices.y);
|
||||
}
|
||||
57
editor/shader/editor_shader_language_plugin.h
Normal file
57
editor/shader/editor_shader_language_plugin.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/**************************************************************************/
|
||||
/* editor_shader_language_plugin.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shader_editor.h"
|
||||
|
||||
class EditorShaderLanguagePlugin : public RefCounted {
|
||||
GDCLASS(EditorShaderLanguagePlugin, RefCounted);
|
||||
|
||||
static Vector<Ref<EditorShaderLanguagePlugin>> shader_languages;
|
||||
static Vector<Vector2i> language_variation_map;
|
||||
|
||||
public:
|
||||
static void register_shader_language(const Ref<EditorShaderLanguagePlugin> &p_shader_language);
|
||||
static void clear_registered_shader_languages();
|
||||
static const Vector<Ref<EditorShaderLanguagePlugin>> get_shader_languages_read_only();
|
||||
static int get_shader_language_variation_count();
|
||||
static Ref<EditorShaderLanguagePlugin> get_shader_language_for_index(int p_index);
|
||||
static String get_file_extension_for_index(int p_index);
|
||||
|
||||
virtual bool handles_shader(const Ref<Shader> &p_shader) const = 0;
|
||||
virtual bool handles_shader_include(const Ref<ShaderInclude> &p_shader_inc) const { return false; }
|
||||
virtual ShaderEditor *edit_shader(const Ref<Shader> &p_shader) = 0;
|
||||
virtual ShaderEditor *edit_shader_include(const Ref<ShaderInclude> &p_shader_inc) { return nullptr; }
|
||||
virtual Ref<Shader> create_new_shader(int p_variation_index, Shader::Mode p_shader_mode, int p_template_index) = 0;
|
||||
virtual Ref<ShaderInclude> create_new_shader_include() { return Ref<ShaderInclude>(); }
|
||||
virtual PackedStringArray get_language_variations() const = 0;
|
||||
virtual String get_file_extension(int p_variation_index) const { return "tres"; }
|
||||
};
|
||||
@@ -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,42 +407,15 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
if (!is_built_in && !is_path_valid) {
|
||||
@@ -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.
|
||||
|
||||
@@ -78,7 +78,6 @@ class ShaderCreateDialog : public ConfirmationDialog {
|
||||
bool load_enabled = false;
|
||||
bool re_check_path = false;
|
||||
int current_type = -1;
|
||||
int default_type = -1;
|
||||
int current_mode = 0;
|
||||
int current_template = 0;
|
||||
|
||||
@@ -105,6 +104,6 @@ protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void config(const String &p_base_path, bool p_built_in_enabled = true, bool p_load_enabled = true, int p_preferred_type = -1, int p_preferred_mode = -1);
|
||||
void config(const String &p_base_path, bool p_built_in_enabled = true, bool p_load_enabled = true, const String &p_preferred_type = "", int p_preferred_mode = -1);
|
||||
ShaderCreateDialog();
|
||||
};
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
#include "editor/settings/editor_command_palette.h"
|
||||
#include "editor/shader/shader_create_dialog.h"
|
||||
#include "editor/shader/text_shader_editor.h"
|
||||
#include "editor/shader/visual_shader_editor_plugin.h"
|
||||
#include "editor/shader/text_shader_language_plugin.h"
|
||||
#include "editor/shader/visual_shader_language_plugin.h"
|
||||
#include "editor/themes/editor_scale.h"
|
||||
#include "scene/gui/item_list.h"
|
||||
#include "scene/gui/tab_container.h"
|
||||
@@ -151,8 +152,12 @@ void ShaderEditorPlugin::edit(Object *p_object) {
|
||||
}
|
||||
}
|
||||
es.shader_inc = Ref<ShaderInclude>(shader_include);
|
||||
es.shader_editor = memnew(TextShaderEditor);
|
||||
es.shader_editor->edit_shader_include(shader_include);
|
||||
for (Ref<EditorShaderLanguagePlugin> shader_lang : EditorShaderLanguagePlugin::get_shader_languages_read_only()) {
|
||||
if (shader_lang->handles_shader_include(es.shader_inc)) {
|
||||
es.shader_editor = shader_lang->edit_shader_include(es.shader_inc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If it's not a ShaderInclude, check for Shader.
|
||||
Shader *shader = Object::cast_to<Shader>(p_object);
|
||||
@@ -168,15 +173,15 @@ void ShaderEditorPlugin::edit(Object *p_object) {
|
||||
}
|
||||
// If we did not return, the shader needs to be opened in a new shader editor.
|
||||
es.shader = Ref<Shader>(shader);
|
||||
Ref<VisualShader> vs = es.shader;
|
||||
if (vs.is_valid()) {
|
||||
es.shader_editor = memnew(VisualShaderEditor);
|
||||
} else {
|
||||
es.shader_editor = memnew(TextShaderEditor);
|
||||
for (Ref<EditorShaderLanguagePlugin> shader_lang : EditorShaderLanguagePlugin::get_shader_languages_read_only()) {
|
||||
if (shader_lang->handles_shader(es.shader)) {
|
||||
es.shader_editor = shader_lang->edit_shader(es.shader);
|
||||
break;
|
||||
}
|
||||
}
|
||||
es.shader_editor->edit_shader(es.shader);
|
||||
}
|
||||
|
||||
ERR_FAIL_NULL_MSG(es.shader_editor, "ShaderEditorPlugin: Unable to edit shader because no suitable editor was found.");
|
||||
// TextShaderEditor-specific setup code.
|
||||
TextShaderEditor *text_shader_editor = Object::cast_to<TextShaderEditor>(es.shader_editor);
|
||||
if (text_shader_editor) {
|
||||
@@ -511,12 +516,12 @@ void ShaderEditorPlugin::_menu_item_pressed(int p_index) {
|
||||
switch (p_index) {
|
||||
case FILE_MENU_NEW: {
|
||||
String base_path = FileSystemDock::get_singleton()->get_current_path().get_base_dir();
|
||||
shader_create_dialog->config(base_path.path_join("new_shader"), false, false, 0);
|
||||
shader_create_dialog->config(base_path.path_join("new_shader"), false, false, "Shader");
|
||||
shader_create_dialog->popup_centered();
|
||||
} break;
|
||||
case FILE_MENU_NEW_INCLUDE: {
|
||||
String base_path = FileSystemDock::get_singleton()->get_current_path().get_base_dir();
|
||||
shader_create_dialog->config(base_path.path_join("new_shader"), false, false, 2);
|
||||
shader_create_dialog->config(base_path.path_join("new_shader"), false, false, "ShaderInclude");
|
||||
shader_create_dialog->popup_centered();
|
||||
} break;
|
||||
case FILE_MENU_OPEN: {
|
||||
@@ -927,9 +932,18 @@ ShaderEditorPlugin::ShaderEditorPlugin() {
|
||||
files_split->add_child(shader_create_dialog);
|
||||
shader_create_dialog->connect("shader_created", callable_mp(this, &ShaderEditorPlugin::_shader_created));
|
||||
shader_create_dialog->connect("shader_include_created", callable_mp(this, &ShaderEditorPlugin::_shader_include_created));
|
||||
|
||||
Ref<TextShaderLanguagePlugin> text_shader_lang;
|
||||
text_shader_lang.instantiate();
|
||||
EditorShaderLanguagePlugin::register_shader_language(text_shader_lang);
|
||||
|
||||
Ref<VisualShaderLanguagePlugin> visual_shader_lang;
|
||||
visual_shader_lang.instantiate();
|
||||
EditorShaderLanguagePlugin::register_shader_language(visual_shader_lang);
|
||||
}
|
||||
|
||||
ShaderEditorPlugin::~ShaderEditorPlugin() {
|
||||
EditorShaderLanguagePlugin::clear_registered_shader_languages();
|
||||
memdelete(file_menu);
|
||||
memdelete(make_floating);
|
||||
}
|
||||
|
||||
@@ -39,10 +39,8 @@ class MenuButton;
|
||||
class ShaderCreateDialog;
|
||||
class ShaderEditor;
|
||||
class TabContainer;
|
||||
class TextShaderEditor;
|
||||
class VBoxContainer;
|
||||
class HBoxContainer;
|
||||
class VisualShaderEditor;
|
||||
class WindowWrapper;
|
||||
|
||||
class ShaderEditorPlugin : public EditorPlugin {
|
||||
|
||||
156
editor/shader/text_shader_language_plugin.cpp
Normal file
156
editor/shader/text_shader_language_plugin.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
/**************************************************************************/
|
||||
/* text_shader_language_plugin.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "text_shader_language_plugin.h"
|
||||
|
||||
#include "text_shader_editor.h"
|
||||
|
||||
#include "core/string/string_builder.h"
|
||||
#include "servers/rendering/shader_types.h"
|
||||
|
||||
bool TextShaderLanguagePlugin::handles_shader(const Ref<Shader> &p_shader) const {
|
||||
// The text shader editor only edits the base Shader class,
|
||||
// not classes that inherit from it like VisualShader.
|
||||
return p_shader->get_class_name() == Shader::get_class_static();
|
||||
}
|
||||
|
||||
bool TextShaderLanguagePlugin::handles_shader_include(const Ref<ShaderInclude> &p_shader_inc) const {
|
||||
return p_shader_inc->get_class_static() == ShaderInclude::get_class_static();
|
||||
}
|
||||
|
||||
ShaderEditor *TextShaderLanguagePlugin::edit_shader(const Ref<Shader> &p_shader) {
|
||||
TextShaderEditor *editor = memnew(TextShaderEditor);
|
||||
editor->edit_shader(p_shader);
|
||||
return editor;
|
||||
}
|
||||
|
||||
ShaderEditor *TextShaderLanguagePlugin::edit_shader_include(const Ref<ShaderInclude> &p_shader_inc) {
|
||||
TextShaderEditor *editor = memnew(TextShaderEditor);
|
||||
editor->edit_shader_include(p_shader_inc);
|
||||
return editor;
|
||||
}
|
||||
|
||||
Ref<Shader> TextShaderLanguagePlugin::create_new_shader(int p_variation_index, Shader::Mode p_shader_mode, int p_template_index) {
|
||||
Ref<Shader> shader;
|
||||
shader.instantiate();
|
||||
|
||||
StringBuilder code;
|
||||
const String &shader_type = ShaderTypes::get_singleton()->get_types_list().get(p_shader_mode);
|
||||
code += vformat("shader_type %s;\n", shader_type);
|
||||
|
||||
if (p_template_index == 0) { // Default template.
|
||||
switch (p_shader_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.
|
||||
}
|
||||
)";
|
||||
} break;
|
||||
case Shader::MODE_MAX: {
|
||||
ERR_FAIL_V_MSG(Ref<Shader>(), "Invalid shader mode for text shader editor.");
|
||||
} break;
|
||||
}
|
||||
}
|
||||
shader->set_code(code.as_string());
|
||||
return shader;
|
||||
}
|
||||
|
||||
Ref<ShaderInclude> TextShaderLanguagePlugin::create_new_shader_include() {
|
||||
Ref<ShaderInclude> shader_inc;
|
||||
shader_inc.instantiate();
|
||||
return shader_inc;
|
||||
}
|
||||
|
||||
PackedStringArray TextShaderLanguagePlugin::get_language_variations() const {
|
||||
return PackedStringArray{ "Shader", "ShaderInclude" };
|
||||
}
|
||||
|
||||
String TextShaderLanguagePlugin::get_file_extension(int p_variation_index) const {
|
||||
if (p_variation_index == 0) {
|
||||
return "gdshader";
|
||||
} else if (p_variation_index == 1) {
|
||||
return "gdshaderinc";
|
||||
}
|
||||
return "tres";
|
||||
}
|
||||
47
editor/shader/text_shader_language_plugin.h
Normal file
47
editor/shader/text_shader_language_plugin.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/**************************************************************************/
|
||||
/* text_shader_language_plugin.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "editor/shader/editor_shader_language_plugin.h"
|
||||
|
||||
class TextShaderLanguagePlugin : public EditorShaderLanguagePlugin {
|
||||
GDCLASS(TextShaderLanguagePlugin, EditorShaderLanguagePlugin);
|
||||
|
||||
public:
|
||||
virtual bool handles_shader(const Ref<Shader> &p_shader) const override;
|
||||
virtual bool handles_shader_include(const Ref<ShaderInclude> &p_shader_inc) const override;
|
||||
virtual ShaderEditor *edit_shader(const Ref<Shader> &p_shader) override;
|
||||
virtual ShaderEditor *edit_shader_include(const Ref<ShaderInclude> &p_shader_inc) override;
|
||||
virtual Ref<Shader> create_new_shader(int p_variation_index, Shader::Mode p_shader_mode, int p_template_index) override;
|
||||
virtual Ref<ShaderInclude> create_new_shader_include() override;
|
||||
virtual PackedStringArray get_language_variations() const override;
|
||||
virtual String get_file_extension(int p_variation_index) const override;
|
||||
};
|
||||
58
editor/shader/visual_shader_language_plugin.cpp
Normal file
58
editor/shader/visual_shader_language_plugin.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/**************************************************************************/
|
||||
/* visual_shader_language_plugin.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "visual_shader_language_plugin.h"
|
||||
|
||||
#include "visual_shader_editor_plugin.h"
|
||||
|
||||
bool VisualShaderLanguagePlugin::handles_shader(const Ref<Shader> &p_shader) const {
|
||||
return Object::cast_to<VisualShader>(p_shader.ptr()) != nullptr;
|
||||
}
|
||||
|
||||
ShaderEditor *VisualShaderLanguagePlugin::edit_shader(const Ref<Shader> &p_shader) {
|
||||
const Ref<VisualShader> shader = p_shader;
|
||||
ERR_FAIL_COND_V(shader.is_null(), nullptr);
|
||||
VisualShaderEditor *editor = memnew(VisualShaderEditor);
|
||||
editor->edit_shader(shader);
|
||||
return editor;
|
||||
}
|
||||
|
||||
Ref<Shader> VisualShaderLanguagePlugin::create_new_shader(int p_variation_index, Shader::Mode p_shader_mode, int p_template_index) {
|
||||
Ref<VisualShader> shader;
|
||||
shader.instantiate();
|
||||
shader->set_mode(p_shader_mode);
|
||||
return shader;
|
||||
}
|
||||
|
||||
PackedStringArray VisualShaderLanguagePlugin::get_language_variations() const {
|
||||
PackedStringArray variations;
|
||||
variations.push_back("VisualShader");
|
||||
return variations;
|
||||
}
|
||||
43
editor/shader/visual_shader_language_plugin.h
Normal file
43
editor/shader/visual_shader_language_plugin.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/**************************************************************************/
|
||||
/* visual_shader_language_plugin.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "editor/shader/editor_shader_language_plugin.h"
|
||||
|
||||
class VisualShaderLanguagePlugin : public EditorShaderLanguagePlugin {
|
||||
GDCLASS(VisualShaderLanguagePlugin, EditorShaderLanguagePlugin);
|
||||
|
||||
public:
|
||||
virtual bool handles_shader(const Ref<Shader> &p_shader) const override;
|
||||
virtual ShaderEditor *edit_shader(const Ref<Shader> &p_shader) override;
|
||||
virtual Ref<Shader> create_new_shader(int p_variation_index, Shader::Mode p_shader_mode, int p_template_index) override;
|
||||
virtual PackedStringArray get_language_variations() const override;
|
||||
};
|
||||
Reference in New Issue
Block a user