diff options
Diffstat (limited to 'servers')
-rw-r--r-- | servers/display_server.cpp | 38 | ||||
-rw-r--r-- | servers/display_server.h | 20 | ||||
-rw-r--r-- | servers/navigation_server_2d.cpp | 2 | ||||
-rw-r--r-- | servers/navigation_server_3d.cpp | 2 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp | 5 | ||||
-rw-r--r-- | servers/rendering/shader_preprocessor.cpp | 165 | ||||
-rw-r--r-- | servers/rendering/shader_preprocessor.h | 37 |
7 files changed, 196 insertions, 73 deletions
diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 4e7db7d0a5..ff6d769a86 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -44,40 +44,49 @@ DisplayServer::DisplayServerCreate DisplayServer::server_create_functions[Displa int DisplayServer::server_create_count = 1; -void DisplayServer::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) { +int DisplayServer::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_separator(const String &p_menu_root, int p_index) { +int DisplayServer::global_menu_add_separator(const String &p_menu_root, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } int DisplayServer::global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const { @@ -159,6 +168,11 @@ Ref<Texture2D> DisplayServer::global_menu_get_item_icon(const String &p_menu_roo return Ref<Texture2D>(); } +int DisplayServer::global_menu_get_item_indentation_level(const String &p_menu_root, int p_idx) const { + WARN_PRINT("Global menus not supported by this display server."); + return 0; +} + void DisplayServer::global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked) { WARN_PRINT("Global menus not supported by this display server."); } @@ -207,6 +221,10 @@ void DisplayServer::global_menu_set_item_icon(const String &p_menu_root, int p_i WARN_PRINT("Global menus not supported by this display server."); } +void DisplayServer::global_menu_set_item_indentation_level(const String &p_menu_root, int p_idx, int p_level) { + WARN_PRINT("Global menus not supported by this display server."); +} + int DisplayServer::global_menu_get_item_count(const String &p_menu_root) const { WARN_PRINT("Global menus not supported by this display server."); return 0; @@ -535,6 +553,7 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("global_menu_get_item_state", "menu_root", "idx"), &DisplayServer::global_menu_get_item_state); ClassDB::bind_method(D_METHOD("global_menu_get_item_max_states", "menu_root", "idx"), &DisplayServer::global_menu_get_item_max_states); ClassDB::bind_method(D_METHOD("global_menu_get_item_icon", "menu_root", "idx"), &DisplayServer::global_menu_get_item_icon); + ClassDB::bind_method(D_METHOD("global_menu_get_item_indentation_level", "menu_root", "idx"), &DisplayServer::global_menu_get_item_indentation_level); ClassDB::bind_method(D_METHOD("global_menu_set_item_checked", "menu_root", "idx", "checked"), &DisplayServer::global_menu_set_item_checked); ClassDB::bind_method(D_METHOD("global_menu_set_item_checkable", "menu_root", "idx", "checkable"), &DisplayServer::global_menu_set_item_checkable); @@ -549,6 +568,7 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("global_menu_set_item_state", "menu_root", "idx", "state"), &DisplayServer::global_menu_set_item_state); ClassDB::bind_method(D_METHOD("global_menu_set_item_max_states", "menu_root", "idx", "max_states"), &DisplayServer::global_menu_set_item_max_states); ClassDB::bind_method(D_METHOD("global_menu_set_item_icon", "menu_root", "idx", "icon"), &DisplayServer::global_menu_set_item_icon); + ClassDB::bind_method(D_METHOD("global_menu_set_item_indentation_level", "menu_root", "idx", "level"), &DisplayServer::global_menu_set_item_indentation_level); ClassDB::bind_method(D_METHOD("global_menu_remove_item", "menu_root", "idx"), &DisplayServer::global_menu_remove_item); ClassDB::bind_method(D_METHOD("global_menu_clear", "menu_root"), &DisplayServer::global_menu_clear); diff --git a/servers/display_server.h b/servers/display_server.h index 8632b53f7b..a5c42617af 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -127,15 +127,15 @@ public: virtual bool has_feature(Feature p_feature) const = 0; virtual String get_name() const = 0; - virtual void global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index = -1); - virtual void global_menu_add_separator(const String &p_menu_root, int p_index = -1); + virtual int global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index = -1); + virtual int global_menu_add_separator(const String &p_menu_root, int p_index = -1); virtual int global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const; virtual int global_menu_get_item_index_from_tag(const String &p_menu_root, const Variant &p_tag) const; @@ -153,6 +153,7 @@ public: virtual int global_menu_get_item_state(const String &p_menu_root, int p_idx) const; virtual int global_menu_get_item_max_states(const String &p_menu_root, int p_idx) const; virtual Ref<Texture2D> global_menu_get_item_icon(const String &p_menu_root, int p_idx) const; + virtual int global_menu_get_item_indentation_level(const String &p_menu_root, int p_idx) const; virtual void global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked); virtual void global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable); @@ -167,6 +168,7 @@ public: virtual void global_menu_set_item_state(const String &p_menu_root, int p_idx, int p_state); virtual void global_menu_set_item_max_states(const String &p_menu_root, int p_idx, int p_max_states); virtual void global_menu_set_item_icon(const String &p_menu_root, int p_idx, const Ref<Texture2D> &p_icon); + virtual void global_menu_set_item_indentation_level(const String &p_menu_root, int p_idx, int p_level); virtual int global_menu_get_item_count(const String &p_menu_root) const; diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp index 126bb08c94..27b49014d8 100644 --- a/servers/navigation_server_2d.cpp +++ b/servers/navigation_server_2d.cpp @@ -204,7 +204,7 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_create"), &NavigationServer2D::map_create); ClassDB::bind_method(D_METHOD("map_set_active", "map", "active"), &NavigationServer2D::map_set_active); - ClassDB::bind_method(D_METHOD("map_is_active", "nap"), &NavigationServer2D::map_is_active); + ClassDB::bind_method(D_METHOD("map_is_active", "map"), &NavigationServer2D::map_is_active); ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &NavigationServer2D::map_set_cell_size); ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer2D::map_get_cell_size); ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer2D::map_set_edge_connection_margin); diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index 115eda7b30..206698f97c 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -41,7 +41,7 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_create"), &NavigationServer3D::map_create); ClassDB::bind_method(D_METHOD("map_set_active", "map", "active"), &NavigationServer3D::map_set_active); - ClassDB::bind_method(D_METHOD("map_is_active", "nap"), &NavigationServer3D::map_is_active); + ClassDB::bind_method(D_METHOD("map_is_active", "map"), &NavigationServer3D::map_is_active); ClassDB::bind_method(D_METHOD("map_set_up", "map", "up"), &NavigationServer3D::map_set_up); ClassDB::bind_method(D_METHOD("map_get_up", "map"), &NavigationServer3D::map_get_up); ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &NavigationServer3D::map_set_cell_size); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index dc3f35f942..585c42b2d8 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -416,7 +416,10 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) mesh->bone_aabbs.resize(p_surface.bone_aabbs.size()); } for (int i = 0; i < p_surface.bone_aabbs.size(); i++) { - mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]); + const AABB &bone = p_surface.bone_aabbs[i]; + if (!bone.has_no_volume()) { + mesh->bone_aabbs.write[i].merge_with(bone); + } } mesh->aabb.merge_with(p_surface.aabb); } diff --git a/servers/rendering/shader_preprocessor.cpp b/servers/rendering/shader_preprocessor.cpp index a7b274b3e2..8755ee61cc 100644 --- a/servers/rendering/shader_preprocessor.cpp +++ b/servers/rendering/shader_preprocessor.cpp @@ -349,6 +349,8 @@ void ShaderPreprocessor::process_directive(Tokenizer *p_tokenizer) { process_ifdef(p_tokenizer); } else if (directive == "ifndef") { process_ifndef(p_tokenizer); + } else if (directive == "elif") { + process_elif(p_tokenizer); } else if (directive == "else") { process_else(p_tokenizer); } else if (directive == "endif") { @@ -415,24 +417,83 @@ void ShaderPreprocessor::process_define(Tokenizer *p_tokenizer) { } } +void ShaderPreprocessor::process_elif(Tokenizer *p_tokenizer) { + const int line = p_tokenizer->get_line(); + + if (state->current_branch == nullptr || state->current_branch->else_defined) { + set_error(RTR("Unmatched elif."), line); + return; + } + if (state->previous_region != nullptr) { + state->previous_region->to_line = line - 1; + } + + String body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges(); + if (body.is_empty()) { + set_error(RTR("Missing condition."), line); + return; + } + + Error error = expand_macros(body, line, body); + if (error != OK) { + return; + } + + Expression expression; + Vector<String> names; + error = expression.parse(body, names); + if (error != OK) { + set_error(expression.get_error_text(), line); + return; + } + + Variant v = expression.execute(Array(), nullptr, false); + if (v.get_type() == Variant::NIL) { + set_error(RTR("Condition evaluation error."), line); + return; + } + + bool skip = false; + for (int i = 0; i < state->current_branch->conditions.size(); i++) { + if (state->current_branch->conditions[i]) { + skip = true; + break; + } + } + + bool success = !skip && v.booleanize(); + start_branch_condition(p_tokenizer, success, true); + + if (state->save_regions) { + add_region(line + 1, success, state->previous_region->parent); + } +} + void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) { - if (state->skip_stack_else.is_empty()) { - set_error(RTR("Unmatched else."), p_tokenizer->get_line()); + const int line = p_tokenizer->get_line(); + + if (state->current_branch == nullptr || state->current_branch->else_defined) { + set_error(RTR("Unmatched else."), line); return; } - p_tokenizer->advance('\n'); + if (state->previous_region != nullptr) { + state->previous_region->to_line = line - 1; + } - bool skip = state->skip_stack_else[state->skip_stack_else.size() - 1]; - state->skip_stack_else.remove_at(state->skip_stack_else.size() - 1); + p_tokenizer->advance('\n'); - Vector<SkippedCondition *> vec = state->skipped_conditions[state->current_include]; - int index = vec.size() - 1; - if (index >= 0) { - SkippedCondition *cond = vec[index]; - if (cond->end_line == -1) { - cond->end_line = p_tokenizer->get_line(); + bool skip = false; + for (int i = 0; i < state->current_branch->conditions.size(); i++) { + if (state->current_branch->conditions[i]) { + skip = true; + break; } } + state->current_branch->else_defined = true; + + if (state->save_regions) { + add_region(line + 1, !skip, state->previous_region->parent); + } if (skip) { Vector<String> ends; @@ -447,21 +508,19 @@ void ShaderPreprocessor::process_endif(Tokenizer *p_tokenizer) { set_error(RTR("Unmatched endif."), p_tokenizer->get_line()); return; } - - Vector<SkippedCondition *> vec = state->skipped_conditions[state->current_include]; - int index = vec.size() - 1; - if (index >= 0) { - SkippedCondition *cond = vec[index]; - if (cond->end_line == -1) { - cond->end_line = p_tokenizer->get_line(); - } + if (state->previous_region != nullptr) { + state->previous_region->to_line = p_tokenizer->get_line() - 1; + state->previous_region = state->previous_region->parent; } p_tokenizer->advance('\n'); + + state->current_branch = state->current_branch->parent; + state->branches.pop_back(); } void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) { - int line = p_tokenizer->get_line(); + const int line = p_tokenizer->get_line(); String body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges(); if (body.is_empty()) { @@ -490,6 +549,10 @@ void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) { bool success = v.booleanize(); start_branch_condition(p_tokenizer, success); + + if (state->save_regions) { + add_region(line + 1, success, state->previous_region); + } } void ShaderPreprocessor::process_ifdef(Tokenizer *p_tokenizer) { @@ -510,6 +573,10 @@ void ShaderPreprocessor::process_ifdef(Tokenizer *p_tokenizer) { bool success = state->defines.has(label); start_branch_condition(p_tokenizer, success); + + if (state->save_regions) { + add_region(line + 1, success, state->previous_region); + } } void ShaderPreprocessor::process_ifndef(Tokenizer *p_tokenizer) { @@ -530,6 +597,10 @@ void ShaderPreprocessor::process_ifndef(Tokenizer *p_tokenizer) { bool success = !state->defines.has(label); start_branch_condition(p_tokenizer, success); + + if (state->save_regions) { + add_region(line + 1, success, state->previous_region); + } } void ShaderPreprocessor::process_include(Tokenizer *p_tokenizer) { @@ -594,15 +665,15 @@ void ShaderPreprocessor::process_include(Tokenizer *p_tokenizer) { return; } - String old_include = state->current_include; - state->current_include = real_path; + String old_filename = state->current_filename; + state->current_filename = real_path; ShaderPreprocessor processor; int prev_condition_depth = state->condition_depth; state->condition_depth = 0; FilePosition fp; - fp.file = state->current_include; + fp.file = state->current_filename; fp.line = line; state->include_positions.push_back(fp); @@ -614,7 +685,7 @@ void ShaderPreprocessor::process_include(Tokenizer *p_tokenizer) { // Reset to last include if there are no errors. We want to use this as context. if (state->error.is_empty()) { - state->current_include = old_include; + state->current_filename = old_filename; state->include_positions.pop_back(); } else { return; @@ -668,24 +739,28 @@ void ShaderPreprocessor::process_undef(Tokenizer *p_tokenizer) { state->defines.erase(label); } -void ShaderPreprocessor::start_branch_condition(Tokenizer *p_tokenizer, bool p_success) { - state->condition_depth++; +void ShaderPreprocessor::add_region(int p_line, bool p_enabled, Region *p_parent_region) { + Region region; + region.file = state->current_filename; + region.enabled = p_enabled; + region.from_line = p_line; + region.parent = p_parent_region; + state->previous_region = &state->regions[region.file].push_back(region)->get(); +} - if (p_success) { - state->skip_stack_else.push_back(true); +void ShaderPreprocessor::start_branch_condition(Tokenizer *p_tokenizer, bool p_success, bool p_continue) { + if (!p_continue) { + state->condition_depth++; + state->current_branch = &state->branches.push_back(Branch(p_success, state->current_branch))->get(); } else { - SkippedCondition *cond = memnew(SkippedCondition()); - cond->start_line = p_tokenizer->get_line(); - state->skipped_conditions[state->current_include].push_back(cond); - + state->current_branch->conditions.push_back(p_success); + } + if (!p_success) { Vector<String> ends; + ends.push_back("elif"); ends.push_back("else"); ends.push_back("endif"); - if (next_directive(p_tokenizer, ends) == "else") { - state->skip_stack_else.push_back(false); - } else { - state->skip_stack_else.push_back(true); - } + next_directive(p_tokenizer, ends); } } @@ -874,12 +949,6 @@ void ShaderPreprocessor::clear() { memdelete(E->get()); } - for (const RBMap<String, Vector<SkippedCondition *>>::Element *E = state->skipped_conditions.front(); E; E = E->next()) { - for (SkippedCondition *condition : E->get()) { - memdelete(condition); - } - } - memdelete(state); } state_owner = false; @@ -969,8 +1038,12 @@ Error ShaderPreprocessor::preprocess(State *p_state, const String &p_code, Strin return OK; } -Error ShaderPreprocessor::preprocess(const String &p_code, String &r_result, String *r_error_text, List<FilePosition> *r_error_position, HashSet<Ref<ShaderInclude>> *r_includes, List<ScriptLanguage::CodeCompletionOption> *r_completion_options, IncludeCompletionFunction p_include_completion_func) { +Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filename, String &r_result, String *r_error_text, List<FilePosition> *r_error_position, List<Region> *r_regions, HashSet<Ref<ShaderInclude>> *r_includes, List<ScriptLanguage::CodeCompletionOption> *r_completion_options, IncludeCompletionFunction p_include_completion_func) { State pp_state; + if (!p_filename.is_empty()) { + pp_state.current_filename = p_filename; + pp_state.save_regions = r_regions != nullptr; + } Error err = preprocess(&pp_state, p_code, r_result); if (err != OK) { if (r_error_text) { @@ -980,6 +1053,9 @@ Error ShaderPreprocessor::preprocess(const String &p_code, String &r_result, Str *r_error_position = pp_state.include_positions; } } + if (r_regions) { + *r_regions = pp_state.regions[p_filename]; + } if (r_includes) { *r_includes = pp_state.shader_includes; } @@ -1022,6 +1098,7 @@ Error ShaderPreprocessor::preprocess(const String &p_code, String &r_result, Str void ShaderPreprocessor::get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords) { r_keywords->push_back("define"); + r_keywords->push_back("elif"); if (p_include_shader_keywords) { r_keywords->push_back("else"); } diff --git a/servers/rendering/shader_preprocessor.h b/servers/rendering/shader_preprocessor.h index a93fb680dd..71dd9a6ca8 100644 --- a/servers/rendering/shader_preprocessor.h +++ b/servers/rendering/shader_preprocessor.h @@ -58,6 +58,14 @@ public: int line = 0; }; + struct Region { + String file; + int from_line = -1; + int to_line = -1; + bool enabled = false; + Region *parent = nullptr; + }; + private: struct Token { char32_t text; @@ -122,23 +130,34 @@ private: String body; }; - struct SkippedCondition { - int start_line = -1; - int end_line = -1; + struct Branch { + Vector<bool> conditions; + Branch *parent = nullptr; + bool else_defined = false; + + Branch() {} + + Branch(bool p_condition, Branch *p_parent) : + parent(p_parent) { + conditions.push_back(p_condition); + } }; struct State { RBMap<String, Define *> defines; - Vector<bool> skip_stack_else; + List<Branch> branches; + Branch *current_branch = nullptr; int condition_depth = 0; RBSet<String> includes; List<uint64_t> cyclic_include_hashes; // Holds code hash of includes. int include_depth = 0; - String current_include; + String current_filename; String current_shader_type; String error; List<FilePosition> include_positions; - RBMap<String, Vector<SkippedCondition *>> skipped_conditions; + bool save_regions = false; + RBMap<String, List<Region>> regions; + Region *previous_region = nullptr; bool disabled = false; CompletionType completion_type = COMPLETION_TYPE_NONE; HashSet<Ref<ShaderInclude>> shader_includes; @@ -158,6 +177,7 @@ private: void process_directive(Tokenizer *p_tokenizer); void process_define(Tokenizer *p_tokenizer); + void process_elif(Tokenizer *p_tokenizer); void process_else(Tokenizer *p_tokenizer); void process_endif(Tokenizer *p_tokenizer); void process_if(Tokenizer *p_tokenizer); @@ -167,7 +187,8 @@ private: void process_pragma(Tokenizer *p_tokenizer); void process_undef(Tokenizer *p_tokenizer); - void start_branch_condition(Tokenizer *p_tokenizer, bool p_success); + void add_region(int p_line, bool p_enabled, Region *p_parent_region); + void start_branch_condition(Tokenizer *p_tokenizer, bool p_success, bool p_continue = false); void expand_output_macros(int p_start, int p_line); Error expand_macros(const String &p_string, int p_line, String &r_result); @@ -188,7 +209,7 @@ private: public: typedef void (*IncludeCompletionFunction)(List<ScriptLanguage::CodeCompletionOption> *); - Error preprocess(const String &p_code, String &r_result, String *r_error_text = nullptr, List<FilePosition> *r_error_position = nullptr, HashSet<Ref<ShaderInclude>> *r_includes = nullptr, List<ScriptLanguage::CodeCompletionOption> *r_completion_options = nullptr, IncludeCompletionFunction p_include_completion_func = nullptr); + Error preprocess(const String &p_code, const String &p_filename, String &r_result, String *r_error_text = nullptr, List<FilePosition> *r_error_position = nullptr, List<Region> *r_regions = nullptr, HashSet<Ref<ShaderInclude>> *r_includes = nullptr, List<ScriptLanguage::CodeCompletionOption> *r_completion_options = nullptr, IncludeCompletionFunction p_include_completion_func = nullptr); static void get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords); static void get_pragma_list(List<String> *r_pragmas); |