Skip to content

Commit

Permalink
Add basic require shader support
Browse files Browse the repository at this point in the history
Co-authored-by: bitsawer <sawerduster@gmail.com>
  • Loading branch information
2 people authored and SaracenOne committed Feb 14, 2021
1 parent a1222e4 commit 2961cb3
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 3 deletions.
18 changes: 18 additions & 0 deletions editor/plugins/shader_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,24 @@ void ShaderEditor::apply_shaders() {
shader->set_code(editor_code);
shader->set_edited(true);
}
refresh_shader_dependencies();
}
}

void ShaderEditor::refresh_shader_dependencies() {
//We could use the arguments to find exactly what shaders we should update that depend on the argument shader.
//For now go through cached shaders, which are usually(?) all shaders that are currently used in editor
//Best solution would be to create a dependency graph about all #includes and use it

List<RES> cached;
ResourceCache::get_cached_resources(&cached);

for (int i = 0; i < cached.size(); i++) {
Shader *shader = Object::cast_to<Shader>(*cached[i]);
if (shader) {
// Workaround to refreshing code
shader->set_code(shader->get_code());
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions editor/plugins/shader_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ class ShaderEditor : public PanelContainer {

public:
void apply_shaders();

static void refresh_shader_dependencies();

void ensure_select_current();
void edit(const Ref<Shader> &p_shader);
Expand Down
94 changes: 91 additions & 3 deletions servers/visual/shader_language.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,15 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/

#include "shader_language.h"
#include "servers/visual/shader_language.h"
#include "core/engine.h"
#include "core/os/os.h"
#include "core/print_string.h"
#include "servers/visual_server.h"
#include "core/io/resource_loader.h"
#include "servers/visual/shader_language.h"
#include "servers/visual/rasterizer.h"
#include "scene/resources/shader.h"

static bool _is_text_char(CharType c) {

Expand Down Expand Up @@ -209,6 +214,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"HINT_COLOR",
"HINT_RANGE",
"SHADER_TYPE",
"IMPORT_SHADER",
"CURSOR",
"ERROR",
"EOF",
Expand Down Expand Up @@ -307,6 +313,8 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_HINT_COLOR, "hint_color" },
{ TK_HINT_RANGE, "hint_range" },
{ TK_SHADER_TYPE, "shader_type" },
{ TK_IMPORT, "import" },
{ TK_QUOTE, "\"" },

{ TK_ERROR, NULL }
};
Expand Down Expand Up @@ -431,7 +439,13 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
return _make_token(TK_OP_NOT);

} break;
//case '"' //string - no strings in shader
case '"': {
int end_quote = code.find_char('"', char_idx);
String quoted = code.substr(char_idx, end_quote - char_idx);
char_idx = end_quote + 1;
char_idx++;
return _make_token(TK_QUOTE, quoted);
}
//case '\'' //string - no strings in shader
case '{':
return _make_token(TK_CURLY_BRACKET_OPEN);
Expand Down Expand Up @@ -4865,10 +4879,85 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct

int texture_uniforms = 0;
int uniforms = 0;

Set<String> includes;
int include_depth = 0;

while (tk.type != TK_EOF) {

switch (tk.type) {
case TK_IMPORT: {
tk = _get_token();

if (tk.type != TK_QUOTE) {
_set_error("Expected quote.");
return ERR_PARSE_ERROR;
}

String path = tk.text;

if (path.empty()) {
_set_error("Invalid path");
return ERR_PARSE_ERROR;
}

RES res = ResourceLoader::load(path);
if (res.is_null()) {
_set_error("Shader include load failed");
return ERR_PARSE_ERROR;
}

String replacement = String("import \"") + tk.text + String("\"");
String empty;
for(int i = 0; i < replacement.size(); i++) {
empty += " ";
}
code = code.replace_first(replacement, empty);

tk = _get_token();
if (tk.type != TK_SEMICOLON) {
_set_error("Expected semicolon.");
return ERR_PARSE_ERROR;
}

Ref<Shader> shader = res;
if (shader.is_null()) {
_set_error("Shader include resource type is wrong");
return ERR_PARSE_ERROR;
}

String included = shader->get_code();
if (included.empty()) {
_set_error("Shader include not found");
return ERR_PARSE_ERROR;
}

int type_end = included.find(";");
if (type_end == -1) {
_set_error("Shader include shader_type not found");
return ERR_PARSE_ERROR;
}

const String real_path = shader->get_path();
if (includes.has(real_path)) {
//Already included, skip.
return ERR_PARSE_ERROR;
}

//Mark as included
includes.insert(real_path);

include_depth++;
if (include_depth > 25) {
_set_error("Shader max include depth exceeded");
return ERR_PARSE_ERROR;
}

//Remove "shader_type xyz;" prefix from included files
included = included.substr(type_end + 1, included.length());

code = code.insert(char_idx, included);
} break;
case TK_RENDER_MODE: {

while (true) {
Expand Down Expand Up @@ -5925,7 +6014,6 @@ ShaderLanguage::ShaderNode *ShaderLanguage::get_shader() {
}

ShaderLanguage::ShaderLanguage() {

nodes = NULL;
completion_class = TAG_GLOBAL;
}
Expand Down
2 changes: 2 additions & 0 deletions servers/visual/shader_language.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ class ShaderLanguage {
TK_ARG_OUT,
TK_ARG_INOUT,
TK_RENDER_MODE,
TK_IMPORT,
TK_QUOTE,
TK_HINT_WHITE_TEXTURE,
TK_HINT_BLACK_TEXTURE,
TK_HINT_NORMAL_TEXTURE,
Expand Down

0 comments on commit 2961cb3

Please sign in to comment.