diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml index b2d3e5cfdb6..22e2698de87 100644 --- a/doc/classes/CanvasItem.xml +++ b/doc/classes/CanvasItem.xml @@ -456,6 +456,13 @@ Returns this item's transform in relation to the viewport. + + + + + Returns an individual bit on the rendering visibility layer. + + @@ -527,6 +534,14 @@ If [param enable] is [code]true[/code], this node will receive [constant NOTIFICATION_TRANSFORM_CHANGED] when its global transform changes. + + + + + + Set/clear individual bits on the rendering visibility layer. This simplifies editing this [CanvasItem]'s visibility layer. + + @@ -565,6 +580,9 @@ If [code]true[/code], the parent [CanvasItem]'s [member material] property is used as this one's material. + + The rendering layer in which this [CanvasItem] is rendered by [Viewport] nodes. A [Viewport] will render a [CanvasItem] if it and all its parents share a layer with the [Viewport]'s canvas cull mask. + If [code]true[/code], this [CanvasItem] is drawn. The node is only visible if all of its antecedents are visible as well (in other words, [method is_visible_in_tree] must return [code]true[/code]). [b]Note:[/b] For controls that inherit [Popup], the correct way to make them visible is to call one of the multiple [code]popup*()[/code] functions instead. diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 376ba340562..cd8c082af28 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -498,6 +498,14 @@ Sets if the [CanvasItem] uses its parent's material. + + + + + + Sets the rendering visibility layer associated with this [CanvasItem]. Only [Viewport] nodes with a matching rendering mask will render this [CanvasItem]. + + @@ -3142,6 +3150,14 @@ If [code]true[/code], sets the viewport active, else sets it inactive. + + + + + + Sets the rendering mask associated with this [Viewport]. Only [CanvasItem] nodes with a matching rendering visibility layer will be rendered by this [Viewport]. + + diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index 5706d098e8a..78013a8f4bf 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -45,6 +45,13 @@ Returns the currently active 3D camera. + + + + + Returns an individual bit on the rendering layer mask. + + @@ -176,6 +183,14 @@ If none of the methods handle the event and [member physics_object_picking] is [code]true[/code], the event is used for physics object picking. + + + + + + Set/clear individual bits on the rendering layer mask. This simplifies editing this [Viewport]'s layers. + + @@ -205,6 +220,9 @@ If [code]true[/code], the viewport will process 3D audio streams. + + The rendering layers in which this [Viewport] renders [CanvasItem] nodes. + Sets the default filter mode used by [CanvasItem]s in this Viewport. See [enum DefaultCanvasItemTextureFilter] for options. diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 840913d4666..175ccd9485e 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -222,6 +222,7 @@ void CanvasItem::_enter_canvas() { } RenderingServer::get_singleton()->canvas_item_set_parent(canvas_item, canvas); + RenderingServer::get_singleton()->canvas_item_set_visibility_layer(canvas_item, visibility_layer); canvas_group = "root_canvas" + itos(canvas.get_id()); @@ -239,6 +240,7 @@ void CanvasItem::_enter_canvas() { canvas_layer = parent->canvas_layer; RenderingServer::get_singleton()->canvas_item_set_parent(canvas_item, parent->get_canvas_item()); RenderingServer::get_singleton()->canvas_item_set_draw_index(canvas_item, get_index()); + RenderingServer::get_singleton()->canvas_item_set_visibility_layer(canvas_item, visibility_layer); } pending_update = false; @@ -980,6 +982,11 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("make_canvas_position_local", "screen_point"), &CanvasItem::make_canvas_position_local); ClassDB::bind_method(D_METHOD("make_input_local", "event"), &CanvasItem::make_input_local); + ClassDB::bind_method(D_METHOD("set_visibility_layer", "layer"), &CanvasItem::set_visibility_layer); + ClassDB::bind_method(D_METHOD("get_visibility_layer"), &CanvasItem::get_visibility_layer); + ClassDB::bind_method(D_METHOD("set_visibility_layer_bit", "layer", "enabled"), &CanvasItem::set_visibility_layer_bit); + ClassDB::bind_method(D_METHOD("get_visibility_layer_bit", "layer"), &CanvasItem::get_visibility_layer_bit); + ClassDB::bind_method(D_METHOD("set_texture_filter", "mode"), &CanvasItem::set_texture_filter); ClassDB::bind_method(D_METHOD("get_texture_filter"), &CanvasItem::get_texture_filter); @@ -999,6 +1006,7 @@ void CanvasItem::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "top_level"), "set_as_top_level", "is_set_as_top_level"); ADD_PROPERTY(PropertyInfo(Variant::INT, "clip_children", PROPERTY_HINT_ENUM, "Disabled,Clip Only,Clip + Draw"), "set_clip_children_mode", "get_clip_children_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_light_mask", "get_light_mask"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "visibility_layer", PROPERTY_HINT_LAYERS_2D_RENDER), "set_visibility_layer", "get_visibility_layer"); ADD_GROUP("Texture", "texture_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Inherit,Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropic,Linear Mipmap Anisotropic"), "set_texture_filter", "get_texture_filter"); @@ -1097,6 +1105,29 @@ int CanvasItem::get_canvas_layer() const { } } +void CanvasItem::set_visibility_layer(uint32_t p_visibility_layer) { + visibility_layer = p_visibility_layer; + RenderingServer::get_singleton()->canvas_item_set_visibility_layer(canvas_item, p_visibility_layer); +} + +uint32_t CanvasItem::get_visibility_layer() const { + return visibility_layer; +} + +void CanvasItem::set_visibility_layer_bit(uint32_t p_visibility_layer, bool p_enable) { + ERR_FAIL_INDEX(p_visibility_layer, 32); + if (p_enable) { + set_visibility_layer(visibility_layer | (1 << p_visibility_layer)); + } else { + set_visibility_layer(visibility_layer & (~(1 << p_visibility_layer))); + } +} + +bool CanvasItem::get_visibility_layer_bit(uint32_t p_visibility_layer) const { + ERR_FAIL_INDEX_V(p_visibility_layer, 32, false); + return (visibility_layer & (1 << p_visibility_layer)); +} + void CanvasItem::_refresh_texture_filter_cache() { if (!is_inside_tree()) { return; diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index 565ea930ce7..4e78a175dc4 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -89,6 +89,7 @@ private: List::Element *C = nullptr; int light_mask = 1; + uint32_t visibility_layer = 1; Window *window = nullptr; bool visible = true; @@ -223,6 +224,12 @@ public: void set_self_modulate(const Color &p_self_modulate); Color get_self_modulate() const; + void set_visibility_layer(uint32_t p_visibility_layer); + uint32_t get_visibility_layer() const; + + void set_visibility_layer_bit(uint32_t p_visibility_layer, bool p_enable); + bool get_visibility_layer_bit(uint32_t p_visibility_layer) const; + /* DRAWING API */ void draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = 1.0, real_t p_dash = 2.0); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index ad40346c366..617c9bab228 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -362,6 +362,7 @@ void Viewport::_notification(int p_what) { current_canvas = find_world_2d()->get_canvas(); RenderingServer::get_singleton()->viewport_attach_canvas(viewport, current_canvas); + RenderingServer::get_singleton()->viewport_set_canvas_cull_mask(viewport, canvas_cull_mask); _update_audio_listener_2d(); #ifndef _3D_DISABLED RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario()); @@ -993,11 +994,6 @@ void Viewport::set_world_2d(const Ref &p_world_2d) { return; } - if (parent && parent->find_world_2d() == p_world_2d) { - WARN_PRINT("Unable to use parent world_2d as world_2d"); - return; - } - if (is_inside_tree()) { RenderingServer::get_singleton()->viewport_remove_canvas(viewport, current_canvas); } @@ -3244,6 +3240,29 @@ Transform2D Viewport::get_screen_transform() const { return _get_input_pre_xform().affine_inverse() * get_final_transform(); } +void Viewport::set_canvas_cull_mask(uint32_t p_canvas_cull_mask) { + canvas_cull_mask = p_canvas_cull_mask; + RenderingServer::get_singleton()->viewport_set_canvas_cull_mask(viewport, canvas_cull_mask); +} + +uint32_t Viewport::get_canvas_cull_mask() const { + return canvas_cull_mask; +} + +void Viewport::set_canvas_cull_mask_bit(uint32_t p_layer, bool p_enable) { + ERR_FAIL_INDEX(p_layer, 32); + if (p_enable) { + set_canvas_cull_mask(canvas_cull_mask | (1 << p_layer)); + } else { + set_canvas_cull_mask(canvas_cull_mask & (~(1 << p_layer))); + } +} + +bool Viewport::get_canvas_cull_mask_bit(uint32_t p_layer) const { + ERR_FAIL_INDEX_V(p_layer, 32, false); + return (canvas_cull_mask & (1 << p_layer)); +} + #ifndef _3D_DISABLED AudioListener3D *Viewport::get_audio_listener_3d() const { return audio_listener_3d; @@ -3815,6 +3834,12 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("set_embedding_subwindows", "enable"), &Viewport::set_embedding_subwindows); ClassDB::bind_method(D_METHOD("is_embedding_subwindows"), &Viewport::is_embedding_subwindows); + ClassDB::bind_method(D_METHOD("set_canvas_cull_mask", "mask"), &Viewport::set_canvas_cull_mask); + ClassDB::bind_method(D_METHOD("get_canvas_cull_mask"), &Viewport::get_canvas_cull_mask); + + ClassDB::bind_method(D_METHOD("set_canvas_cull_mask_bit", "layer", "enable"), &Viewport::set_canvas_cull_mask_bit); + ClassDB::bind_method(D_METHOD("get_canvas_cull_mask_bit", "layer"), &Viewport::get_canvas_cull_mask_bit); + ClassDB::bind_method(D_METHOD("set_default_canvas_item_texture_repeat", "mode"), &Viewport::set_default_canvas_item_texture_repeat); ClassDB::bind_method(D_METHOD("get_default_canvas_item_texture_repeat"), &Viewport::get_default_canvas_item_texture_repeat); @@ -3920,6 +3945,7 @@ void Viewport::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::INT, "positional_shadow_atlas_quad_3", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_positional_shadow_atlas_quadrant_subdiv", "get_positional_shadow_atlas_quadrant_subdiv", 3); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "canvas_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_canvas_transform", "get_canvas_transform"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_canvas_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_canvas_transform", "get_global_canvas_transform"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_cull_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_canvas_cull_mask", "get_canvas_cull_mask"); ADD_SIGNAL(MethodInfo("size_changed")); ADD_SIGNAL(MethodInfo("gui_focus_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Control"))); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 6f67649ea37..8911aea3351 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -317,6 +317,8 @@ private: SDFOversize sdf_oversize = SDF_OVERSIZE_120_PERCENT; SDFScale sdf_scale = SDF_SCALE_50_PERCENT; + uint32_t canvas_cull_mask = 0xffffffff; // by default show everything + enum SubWindowDrag { SUB_WINDOW_DRAG_DISABLED, SUB_WINDOW_DRAG_MOVE, @@ -639,6 +641,12 @@ public: void pass_mouse_focus_to(Viewport *p_viewport, Control *p_control); + void set_canvas_cull_mask(uint32_t p_layers); + uint32_t get_canvas_cull_mask() const; + + void set_canvas_cull_mask_bit(uint32_t p_layer, bool p_enable); + bool get_canvas_cull_mask_bit(uint32_t p_layer) const; + virtual Transform2D get_screen_transform() const; #ifndef _3D_DISABLED diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index ffd8f695c69..41d4ca8d5e8 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -38,17 +38,17 @@ static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1; -void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel) { +void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask) { RENDER_TIMESTAMP("Cull CanvasItem Tree"); memset(z_list, 0, z_range * sizeof(RendererCanvasRender::Item *)); memset(z_last_list, 0, z_range * sizeof(RendererCanvasRender::Item *)); for (int i = 0; i < p_child_item_count; i++) { - _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true); + _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, canvas_cull_mask); } if (p_canvas_item) { - _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true); + _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, canvas_cull_mask); } RendererCanvasRender::Item *list = nullptr; @@ -223,13 +223,17 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item * } } -void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort) { +void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort, uint32_t canvas_cull_mask) { Item *ci = p_canvas_item; if (!ci->visible) { return; } + if (!(ci->visibility_layer & canvas_cull_mask)) { + return; + } + if (ci->children_order_dirty) { ci->child_items.sort_custom(); ci->children_order_dirty = false; @@ -313,7 +317,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 sorter.sort(child_items, child_item_count); for (i = 0; i < child_item_count; i++) { - _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, child_items[i]->ysort_parent_abs_z_index, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false); + _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, child_items[i]->ysort_parent_abs_z_index, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false, canvas_cull_mask); } } else { RendererCanvasRender::Item *canvas_group_from = nullptr; @@ -337,19 +341,19 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 if (!child_items[i]->behind && !use_canvas_group) { continue; } - _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true); + _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, canvas_cull_mask); } _attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from, xform); for (int i = 0; i < child_item_count; i++) { if (child_items[i]->behind || use_canvas_group) { continue; } - _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true); + _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, canvas_cull_mask); } } } -void RendererCanvasCull::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel) { +void RendererCanvasCull::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask) { RENDER_TIMESTAMP("> Render Canvas"); sdf_used = false; @@ -372,26 +376,26 @@ void RendererCanvasCull::render_canvas(RID p_render_target, Canvas *p_canvas, co } if (!has_mirror) { - _render_canvas_item_tree(p_render_target, ci, l, nullptr, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel); + _render_canvas_item_tree(p_render_target, ci, l, nullptr, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask); } else { //used for parallaxlayer mirroring for (int i = 0; i < l; i++) { const Canvas::ChildItem &ci2 = p_canvas->child_items[i]; - _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel); + _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask); //mirroring (useful for scrolling backgrounds) if (ci2.mirror.x != 0) { Transform2D xform2 = p_transform * Transform2D(0, Vector2(ci2.mirror.x, 0)); - _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel); + _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask); } if (ci2.mirror.y != 0) { Transform2D xform2 = p_transform * Transform2D(0, Vector2(0, ci2.mirror.y)); - _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel); + _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask); } if (ci2.mirror.y != 0 && ci2.mirror.x != 0) { Transform2D xform2 = p_transform * Transform2D(0, ci2.mirror); - _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel); + _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask); } } } @@ -513,6 +517,20 @@ void RendererCanvasCull::canvas_item_set_transform(RID p_item, const Transform2D canvas_item->xform = p_transform; } +void RendererCanvasCull::canvas_item_set_visibility_layer(RID p_item, uint32_t p_visibility_layer) { + Item *canvas_item = canvas_item_owner.get_or_null(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->visibility_layer = p_visibility_layer; +} + +uint32_t RendererCanvasCull::canvas_item_get_visibility_layer(RID p_item) { + Item *canvas_item = canvas_item_owner.get_or_null(p_item); + if (!canvas_item) + return 0; + return canvas_item->visibility_layer; +} + void RendererCanvasCull::canvas_item_set_clip(RID p_item, bool p_clip) { Item *canvas_item = canvas_item_owner.get_or_null(p_item); ERR_FAIL_COND(!canvas_item); diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index 7a01fad9deb..198e1020f0b 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -54,6 +54,7 @@ public: Vector2 ysort_pos; int ysort_index; int ysort_parent_abs_z_index; // Absolute Z index of parent. Only populated and used when y-sorting. + uint32_t visibility_layer = 0xffffffff; Vector child_items; @@ -179,14 +180,14 @@ public: _FORCE_INLINE_ void _attach_canvas_item_for_draw(Item *ci, Item *p_canvas_clip, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, const Transform2D &xform, const Rect2 &p_clip_rect, Rect2 global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool p_use_canvas_group, RendererCanvasRender::Item *canvas_group_from, const Transform2D &p_xform); private: - void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel); - void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort); + void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask); + void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort, uint32_t canvas_cull_mask); RendererCanvasRender::Item **z_list; RendererCanvasRender::Item **z_last_list; public: - void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel); + void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask); bool was_sdf_used(); @@ -206,6 +207,9 @@ public: void canvas_item_set_visible(RID p_item, bool p_visible); void canvas_item_set_light_mask(RID p_item, int p_mask); + void canvas_item_set_visibility_layer(RID p_item, uint32_t p_layer); + uint32_t canvas_item_get_visibility_layer(RID p_item); + void canvas_item_set_transform(RID p_item, const Transform2D &p_transform); void canvas_item_set_clip(RID p_item, bool p_clip); void canvas_item_set_distance_field_mode(RID p_item, bool p_enable); diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 4f7683493b4..9bbcb015bb1 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -530,7 +530,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { ptr = ptr->filter_next_ptr; } - RSG::canvas->render_canvas(p_viewport->render_target, canvas, xform, canvas_lights, canvas_directional_lights, clip_rect, p_viewport->texture_filter, p_viewport->texture_repeat, p_viewport->snap_2d_transforms_to_pixel, p_viewport->snap_2d_vertices_to_pixel); + RSG::canvas->render_canvas(p_viewport->render_target, canvas, xform, canvas_lights, canvas_directional_lights, clip_rect, p_viewport->texture_filter, p_viewport->texture_repeat, p_viewport->snap_2d_transforms_to_pixel, p_viewport->snap_2d_vertices_to_pixel, p_viewport->canvas_cull_mask); if (RSG::canvas->was_sdf_used()) { p_viewport->sdf_active = true; } @@ -1349,6 +1349,12 @@ void RendererViewport::set_default_clear_color(const Color &p_color) { RSG::texture_storage->set_default_clear_color(p_color); } +void RendererViewport::viewport_set_canvas_cull_mask(RID p_viewport, uint32_t p_canvas_cull_mask) { + Viewport *viewport = viewport_owner.get_or_null(p_viewport); + ERR_FAIL_COND(!viewport); + viewport->canvas_cull_mask = p_canvas_cull_mask; +} + // Workaround for setting this on thread. void RendererViewport::call_set_vsync_mode(DisplayServer::VSyncMode p_mode, DisplayServer::WindowID p_window) { DisplayServer::get_singleton()->window_set_vsync_mode(p_mode, p_window); diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h index 55058a30b8b..5e0c090ec07 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -117,6 +117,8 @@ public: bool transparent_bg = false; + uint32_t canvas_cull_mask = 0xffffffff; + struct CanvasKey { int64_t stacking; RID canvas; @@ -249,6 +251,8 @@ public: void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform); void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer); + void viewport_set_canvas_cull_mask(RID p_viewport, uint32_t p_canvas_cull_mask); + void viewport_set_positional_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits = true); void viewport_set_positional_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index a68c7ddf2c2..6d2d0d99063 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -610,6 +610,8 @@ public: FUNC2(viewport_set_disable_environment, RID, bool) FUNC2(viewport_set_disable_3d, RID, bool) + FUNC2(viewport_set_canvas_cull_mask, RID, uint32_t) + FUNC2(viewport_attach_camera, RID, RID) FUNC2(viewport_set_scenario, RID, RID) FUNC2(viewport_attach_canvas, RID, RID) @@ -828,6 +830,8 @@ public: FUNC2(canvas_item_set_visible, RID, bool) FUNC2(canvas_item_set_light_mask, RID, int) + FUNC2(canvas_item_set_visibility_layer, RID, uint32_t) + FUNC2(canvas_item_set_update_when_visible, RID, bool) FUNC2(canvas_item_set_transform, RID, const Transform2D &) diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index e1a3fe46bec..cf30d377b7c 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2182,6 +2182,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("viewport_set_parent_viewport", "viewport", "parent_viewport"), &RenderingServer::viewport_set_parent_viewport); ClassDB::bind_method(D_METHOD("viewport_attach_to_screen", "viewport", "rect", "screen"), &RenderingServer::viewport_attach_to_screen, DEFVAL(Rect2()), DEFVAL(DisplayServer::MAIN_WINDOW_ID)); ClassDB::bind_method(D_METHOD("viewport_set_render_direct_to_screen", "viewport", "enabled"), &RenderingServer::viewport_set_render_direct_to_screen); + ClassDB::bind_method(D_METHOD("viewport_set_canvas_cull_mask", "viewport", "canvas_cull_mask"), &RenderingServer::viewport_set_canvas_cull_mask); ClassDB::bind_method(D_METHOD("viewport_set_scaling_3d_mode", "viewport", "scaling_3d_mode"), &RenderingServer::viewport_set_scaling_3d_mode); ClassDB::bind_method(D_METHOD("viewport_set_scaling_3d_scale", "viewport", "scale"), &RenderingServer::viewport_set_scaling_3d_scale); @@ -2575,6 +2576,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("canvas_item_set_default_texture_repeat", "item", "repeat"), &RenderingServer::canvas_item_set_default_texture_repeat); ClassDB::bind_method(D_METHOD("canvas_item_set_visible", "item", "visible"), &RenderingServer::canvas_item_set_visible); ClassDB::bind_method(D_METHOD("canvas_item_set_light_mask", "item", "mask"), &RenderingServer::canvas_item_set_light_mask); + ClassDB::bind_method(D_METHOD("canvas_item_set_visibility_layer", "item", "visibility_layer"), &RenderingServer::canvas_item_set_visibility_layer); ClassDB::bind_method(D_METHOD("canvas_item_set_transform", "item", "transform"), &RenderingServer::canvas_item_set_transform); ClassDB::bind_method(D_METHOD("canvas_item_set_clip", "item", "clip"), &RenderingServer::canvas_item_set_clip); ClassDB::bind_method(D_METHOD("canvas_item_set_distance_field_mode", "item", "enabled"), &RenderingServer::canvas_item_set_distance_field_mode); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 36779690de7..97fafd1b14c 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -807,6 +807,7 @@ public: virtual void viewport_set_size(RID p_viewport, int p_width, int p_height) = 0; virtual void viewport_set_active(RID p_viewport, bool p_active) = 0; virtual void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) = 0; + virtual void viewport_set_canvas_cull_mask(RID p_viewport, uint32_t p_canvas_cull_mask) = 0; virtual void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) = 0; virtual void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) = 0; @@ -1320,6 +1321,7 @@ public: virtual void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect = Rect2()) = 0; virtual void canvas_item_set_modulate(RID p_item, const Color &p_color) = 0; virtual void canvas_item_set_self_modulate(RID p_item, const Color &p_color) = 0; + virtual void canvas_item_set_visibility_layer(RID p_item, uint32_t p_visibility_layer) = 0; virtual void canvas_item_set_draw_behind_parent(RID p_item, bool p_enable) = 0;