1
0
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:
Aaron Franke
2025-08-26 15:46:32 -07:00
parent 8deb221829
commit d6d60845fe
12 changed files with 532 additions and 208 deletions

View File

@@ -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;
}

View File

@@ -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();
}

View 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);
}

View 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"; }
};

View File

@@ -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 &current_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.

View File

@@ -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();
};

View File

@@ -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);
}

View File

@@ -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 {

View 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";
}

View 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;
};

View 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;
}

View 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;
};