diff options
17 files changed, 69 insertions, 34 deletions
diff --git a/doc/classes/Button.xml b/doc/classes/Button.xml index d63bad7cad..055d5091c7 100644 --- a/doc/classes/Button.xml +++ b/doc/classes/Button.xml @@ -78,7 +78,7 @@ </member> <member name="icon" type="Texture2D" setter="set_button_icon" getter="get_button_icon"> Button's icon, if text is present the icon will be placed before the text. - To edit margin and spacing of the icon, use [code]hseparation[/code] theme property of [Button] and [code]content_margin_*[/code] properties of the used [StyleBox]es. + To edit margin and spacing of the icon, use [theme_item hseparation] theme property and [code]content_margin_*[/code] properties of the used [StyleBox]es. </member> <member name="icon_align" type="int" setter="set_icon_align" getter="get_icon_align" enum="Button.TextAlign" default="0"> Specifies if the icon should be aligned to the left, right, or center of a button. Uses the same [enum TextAlign] constants as the text alignment. If centered, text will draw on top of the icon. diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml index 673bf19122..e962992491 100644 --- a/doc/classes/GraphEdit.xml +++ b/doc/classes/GraphEdit.xml @@ -141,7 +141,7 @@ <argument index="3" name="to_port" type="int" /> <argument index="4" name="amount" type="float" /> <description> - Sets the coloration of the connection between [code]from[/code]'s [code]from_port[/code] and [code]to[/code]'s [code]to_port[/code] with the color provided in the [code]activity[/code] theme property. + Sets the coloration of the connection between [code]from[/code]'s [code]from_port[/code] and [code]to[/code]'s [code]to_port[/code] with the color provided in the [theme_item activity] theme property. </description> </method> <method name="set_selected"> diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml index ff6271d2aa..e9226f7c1d 100644 --- a/doc/classes/GraphNode.xml +++ b/doc/classes/GraphNode.xml @@ -285,10 +285,10 @@ No overlay is shown. </constant> <constant name="OVERLAY_BREAKPOINT" value="1" enum="Overlay"> - Show overlay set in the [code]breakpoint[/code] theme property. + Show overlay set in the [theme_item breakpoint] theme property. </constant> <constant name="OVERLAY_POSITION" value="2" enum="Overlay"> - Show overlay set in the [code]position[/code] theme property. + Show overlay set in the [theme_item position] theme property. </constant> </constants> <theme_items> diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py index 5d3167a773..0d88ce4998 100755 --- a/doc/tools/make_rst.py +++ b/doc/tools/make_rst.py @@ -328,7 +328,7 @@ class State: theme_item.text, default_value, ) - class_def.theme_items[theme_item_id] = theme_item_def + class_def.theme_items[theme_item_name] = theme_item_def tutorials = class_root.find("tutorials") if tutorials is not None: @@ -905,6 +905,7 @@ def rstize_text(text, state): # type: (str, State) -> str or cmd.startswith("member") or cmd.startswith("signal") or cmd.startswith("constant") + or cmd.startswith("theme_item") ): param = tag_text[space_pos + 1 :] @@ -941,6 +942,13 @@ def rstize_text(text, state): # type: (str, State) -> str print_error("Unresolved member '{}', file: {}".format(param, state.current_class), state) ref_type = "_property" + elif cmd.startswith("theme_item"): + if method_param not in class_def.theme_items: + print_error( + "Unresolved theme item '{}', file: {}".format(param, state.current_class), state + ) + ref_type = "_theme_item" + elif cmd.startswith("signal"): if method_param not in class_def.signals: print_error("Unresolved signal '{}', file: {}".format(param, state.current_class), state) diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 05f4e385c6..f520877256 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -109,6 +109,9 @@ void EditorHelp::_class_desc_select(const String &p_select) { } else if (tag == "constant") { topic = "class_constant"; table = &this->constant_line; + } else if (tag == "theme_item") { + topic = "theme_item"; + table = &this->theme_property_line; } else { return; } @@ -1538,7 +1541,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { p_rt->add_text("["); pos = brk_pos + 1; - } else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ")) { + } else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ") || tag.begins_with("theme_item ")) { int tag_end = tag.find(" "); String link_tag = tag.substr(0, tag_end); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 22e3bbdb00..6d85c1f4c1 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -334,6 +334,10 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i]; const RenderElementInfo &element_info = p_params->element_info[i]; + if ((p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_SPECULAR) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) { + continue; // Objects with "Depth-prepass" transparency are included in both render lists, but should only be rendered in the transparent pass + } + if (surf->owner->instance_count == 0) { continue; } @@ -958,20 +962,20 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con bool uses_gi = false; float fade_alpha = 1.0; - if (p_render_list == RENDER_LIST_OPAQUE) { - if (inst->fade_near || inst->fade_far) { - float fade_dist = inst->transform.origin.distance_to(p_render_data->cam_transform.origin); - if (inst->fade_far && fade_dist > inst->fade_far_begin) { - fade_alpha = MAX(0.0, 1.0 - (fade_dist - inst->fade_far_begin) / (inst->fade_far_end - inst->fade_far_begin)); - } else if (inst->fade_near && fade_dist < inst->fade_near_end) { - fade_alpha = MAX(0.0, (fade_dist - inst->fade_near_begin) / (inst->fade_near_end - inst->fade_near_begin)); - } + if (inst->fade_near || inst->fade_far) { + float fade_dist = inst->transform.origin.distance_to(p_render_data->cam_transform.origin); + if (inst->fade_far && fade_dist > inst->fade_far_begin) { + fade_alpha = MAX(0.0, 1.0 - (fade_dist - inst->fade_far_begin) / (inst->fade_far_end - inst->fade_far_begin)); + } else if (inst->fade_near && fade_dist < inst->fade_near_end) { + fade_alpha = MAX(0.0, (fade_dist - inst->fade_near_begin) / (inst->fade_near_end - inst->fade_near_begin)); } + } - fade_alpha *= inst->force_alpha * inst->parent_fade_alpha; + fade_alpha *= inst->force_alpha * inst->parent_fade_alpha; - flags = (flags & ~INSTANCE_DATA_FLAGS_FADE_MASK) | (uint32_t(fade_alpha * 255.0) << INSTANCE_DATA_FLAGS_FADE_SHIFT); + flags = (flags & ~INSTANCE_DATA_FLAGS_FADE_MASK) | (uint32_t(fade_alpha * 255.0) << INSTANCE_DATA_FLAGS_FADE_SHIFT); + if (p_render_list == RENDER_LIST_OPAQUE) { // Setup GI if (inst->lightmap_instance.is_valid()) { int32_t lightmap_cull_index = -1; @@ -1206,6 +1210,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co scene_state.ubo.viewport_size[0] = vp_he.x; scene_state.ubo.viewport_size[1] = vp_he.y; scene_state.ubo.directional_light_count = 0; + scene_state.ubo.opaque_prepass_threshold = 0.99f; Size2i screen_size; RID opaque_framebuffer; @@ -1449,6 +1454,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_begin_label("Render Opaque Pass"); scene_state.ubo.directional_light_count = p_render_data->directional_light_count; + scene_state.ubo.opaque_prepass_threshold = 0.0f; _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, p_render_data->render_buffers.is_valid()); @@ -1632,6 +1638,7 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page render_data.render_info = p_render_info; scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1; + scene_state.ubo.opaque_prepass_threshold = 0.1f; _setup_environment(&render_data, true, Vector2(1, 1), !p_flip_y, Color(), false, p_use_pancake, shadow_pass_index); @@ -1718,6 +1725,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con _update_render_base_uniform_set(); scene_state.ubo.dual_paraboloid_side = 0; + scene_state.ubo.opaque_prepass_threshold = 0.0; _setup_environment(&render_data, true, Vector2(1, 1), true, Color(), false, false); @@ -1755,6 +1763,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform scene_state.ubo.dual_paraboloid_side = 0; scene_state.ubo.material_uv2_mode = false; + scene_state.ubo.opaque_prepass_threshold = 0.0f; _setup_environment(&render_data, true, Vector2(1, 1), false, Color()); @@ -1798,6 +1807,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p scene_state.ubo.dual_paraboloid_side = 0; scene_state.ubo.material_uv2_mode = true; + scene_state.ubo.opaque_prepass_threshold = 0.0; _setup_environment(&render_data, true, Vector2(1, 1), false, Color()); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 2ba9558128..7707d77296 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -257,7 +257,8 @@ class RenderForwardClustered : public RendererSceneRenderRD { float roughness_limiter_amount; float roughness_limiter_limit; - uint32_t roughness_limiter_pad[2]; + float opaque_prepass_threshold; + uint32_t roughness_limiter_pad; float sdf_to_bounds[16]; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 61f2031a70..768bd1de9d 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -650,6 +650,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n"; actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n"; actions.render_mode_defines["particle_trails"] = "#define USE_PARTICLE_TRAILS\n"; + actions.render_mode_defines["depth_draw_opaque"] = "#define USE_OPAQUE_PREPASS\n"; bool force_lambert = GLOBAL_GET("rendering/shading/overrides/force_lambert_over_burley"); diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index f23a386acf..445623fb86 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -483,6 +483,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color scene_state.ubo.viewport_size[0] = vp_he.x; scene_state.ubo.viewport_size[1] = vp_he.y; scene_state.ubo.directional_light_count = 0; + scene_state.ubo.opaque_prepass_threshold = 0.0; // We can only use our full subpass approach if we're: // - not reading from SCREEN_TEXTURE/DEPTH_TEXTURE @@ -793,7 +794,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (using_subpass_transparent) { RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); - RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count); + RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR_TRANSPARENT, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count); render_list_params.framebuffer_format = fb_format; if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time @@ -897,6 +898,7 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr render_data.lod_distance_multiplier = p_lod_distance_multiplier; scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1; + scene_state.ubo.opaque_prepass_threshold = 0.1; _setup_environment(&render_data, true, Vector2(1, 1), !p_flip_y, Color(), false, p_use_pancake, shadow_pass_index); @@ -978,6 +980,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c scene_state.ubo.dual_paraboloid_side = 0; scene_state.ubo.material_uv2_mode = false; + scene_state.ubo.opaque_prepass_threshold = 0.0f; RenderDataRD render_data; render_data.cam_projection = p_cam_projection; @@ -1089,6 +1092,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const _update_render_base_uniform_set(); scene_state.ubo.dual_paraboloid_side = 0; + scene_state.ubo.opaque_prepass_threshold = 0.0; RenderDataRD render_data; render_data.cam_projection = p_cam_projection; @@ -1447,13 +1451,13 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const } // ADD Element - if (p_pass_mode == PASS_MODE_COLOR) { + if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) { #ifdef DEBUG_ENABLED bool force_alpha = unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW); #else bool force_alpha = false; #endif - if (!force_alpha && (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE))) { + if (!force_alpha && (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) { rl->add_element(surf); } if (force_alpha || (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA)) { diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index 74bfe16557..485d08b589 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -292,7 +292,8 @@ protected: float roughness_limiter_amount; float roughness_limiter_limit; - uint32_t roughness_limiter_pad[2]; + float opaque_prepass_threshold; + uint32_t roughness_limiter_pad; // Fog uint32_t fog_enabled; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 5d5cb7a6b7..e6d9a60f94 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -637,6 +637,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n"; actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n"; actions.render_mode_defines["particle_trails"] = "#define USE_PARTICLE_TRAILS\n"; + actions.render_mode_defines["depth_draw_opaque"] = "#define USE_OPAQUE_PREPASS\n"; bool force_lambert = GLOBAL_GET("rendering/shading/overrides/force_lambert_over_burley"); if (!force_lambert) { diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 20982a466c..8e33610ae2 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -695,7 +695,7 @@ void main() { #endif // ALPHA_ANTIALIASING_EDGE_USED #ifdef USE_OPAQUE_PREPASS - if (alpha < opaque_prepass_threshold) { + if (alpha < scene_data.opaque_prepass_threshold) { discard; } #endif // USE_OPAQUE_PREPASS @@ -1711,7 +1711,7 @@ void main() { #ifdef USE_OPAQUE_PREPASS - if (alpha < opaque_prepass_threshold) { + if (alpha < scene_data.opaque_prepass_threshold) { discard; } diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl index c8489f2137..be29cf4f58 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl @@ -208,7 +208,8 @@ layout(set = 1, binding = 0, std140) uniform SceneData { float roughness_limiter_amount; float roughness_limiter_limit; - uvec2 roughness_limiter_pad; + float opaque_prepass_threshold; + uint roughness_limiter_pad; mat4 sdf_to_bounds; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl index b6fd89d912..e92fbecfd0 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl @@ -705,7 +705,7 @@ void main() { #endif // ALPHA_ANTIALIASING_EDGE_USED #ifdef USE_OPAQUE_PREPASS - if (alpha < opaque_prepass_threshold) { + if (alpha < scene_data.opaque_prepass_threshold) { discard; } #endif // USE_OPAQUE_PREPASS @@ -1476,7 +1476,7 @@ void main() { #ifdef USE_OPAQUE_PREPASS - if (alpha < opaque_prepass_threshold) { + if (alpha < scene_data.opaque_prepass_threshold) { discard; } diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl index eb8fb49598..a9a4fce82a 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl @@ -168,7 +168,8 @@ layout(set = 1, binding = 0, std140) uniform SceneData { mediump float roughness_limiter_amount; mediump float roughness_limiter_limit; - uvec2 roughness_limiter_pad; + mediump float opaque_prepass_threshold; + uint roughness_limiter_pad; bool fog_enabled; highp float fog_density; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index e338e526a0..7b4e2d34df 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -644,6 +644,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, instance->dynamic_gi); scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED); scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index); + scene_render->geometry_instance_set_transparency(geom->geometry_instance, instance->transparency); if (instance->lightmap_sh.size() == 9) { scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, instance->lightmap_sh.ptr()); } @@ -839,6 +840,8 @@ void RendererSceneCull::instance_geometry_set_transparency(RID p_instance, float Instance *instance = instance_owner.get_or_null(p_instance); ERR_FAIL_COND(!instance); + instance->transparency = p_transparency; + if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); scene_render->geometry_instance_set_transparency(geom->geometry_instance, p_transparency); diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index de22bc1328..2bfcfd462c 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -439,17 +439,18 @@ public: RID self; //scenario stuff DynamicBVH::ID indexer_id; - int32_t array_index; + int32_t array_index = -1; int32_t visibility_index = -1; - float visibility_range_begin; - float visibility_range_end; - float visibility_range_begin_margin; - float visibility_range_end_margin; + float visibility_range_begin = 0.0f; + float visibility_range_end = 0.0f; + float visibility_range_begin_margin = 0.0f; + float visibility_range_end_margin = 0.0f; RS::VisibilityRangeFadeMode visibility_range_fade_mode = RS::VISIBILITY_RANGE_FADE_DISABLED; Instance *visibility_parent = nullptr; Set<Instance *> visibility_dependencies; - uint32_t visibility_dependencies_depth; - Scenario *scenario; + uint32_t visibility_dependencies_depth = 0; + float transparency = 0.0f; + Scenario *scenario = nullptr; SelfList<Instance> scenario_item; //aabb stuff |