diff options
Diffstat (limited to 'scene')
-rw-r--r-- | scene/2d/camera_2d.cpp | 4 | ||||
-rw-r--r-- | scene/gui/code_edit.cpp | 2 | ||||
-rw-r--r-- | scene/gui/control.cpp | 12 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 23 | ||||
-rw-r--r-- | scene/gui/texture_button.cpp | 31 | ||||
-rw-r--r-- | scene/main/instance_placeholder.cpp | 131 | ||||
-rw-r--r-- | scene/main/instance_placeholder.h | 4 | ||||
-rw-r--r-- | scene/resources/2d/tile_set.cpp | 2 | ||||
-rw-r--r-- | scene/resources/packed_scene.cpp | 10 |
9 files changed, 170 insertions, 49 deletions
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index 822f1b58fd..18ef2d8505 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -54,16 +54,18 @@ void Camera2D::_update_scroll() { if (is_current()) { ERR_FAIL_COND(custom_viewport && !ObjectDB::get_instance(custom_viewport_id)); + Size2 screen_size = _get_camera_screen_size(); + Transform2D xform; if (is_physics_interpolated_and_enabled()) { xform = _interpolation_data.xform_prev.interpolate_with(_interpolation_data.xform_curr, Engine::get_singleton()->get_physics_interpolation_fraction()); + camera_screen_center = xform.affine_inverse().xform(0.5 * screen_size); } else { xform = get_camera_transform(); } viewport->set_canvas_transform(xform); - Size2 screen_size = _get_camera_screen_size(); Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5) : Point2()); Point2 adj_screen_pos = camera_screen_center - (screen_size * 0.5); diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 8131fe7aaa..c843bb8c44 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -3050,7 +3050,7 @@ void CodeEdit::_update_delimiter_cache(int p_from_line, int p_to_line) { } int CodeEdit::_is_in_delimiter(int p_line, int p_column, DelimiterType p_type) const { - if (delimiters.size() == 0) { + if (delimiters.size() == 0 || p_line >= delimiter_cache.size()) { return -1; } ERR_FAIL_INDEX_V(p_line, get_line_count(), 0); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 1c175f9f95..0d5c69b207 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -211,17 +211,17 @@ void Control::get_argument_options(const StringName &p_function, int p_idx, List const String pf = p_function; Theme::DataType type = Theme::DATA_TYPE_MAX; - if (pf == "add_theme_color_override" || pf == "has_theme_color" || pf == "has_theme_color_override" || pf == "get_theme_color") { + if (pf == "add_theme_color_override" || pf == "has_theme_color" || pf == "has_theme_color_override" || pf == "get_theme_color" || pf == "remove_theme_color_override") { type = Theme::DATA_TYPE_COLOR; - } else if (pf == "add_theme_constant_override" || pf == "has_theme_constant" || pf == "has_theme_constant_override" || pf == "get_theme_constant") { + } else if (pf == "add_theme_constant_override" || pf == "has_theme_constant" || pf == "has_theme_constant_override" || pf == "get_theme_constant" || pf == "remove_theme_constant_override") { type = Theme::DATA_TYPE_CONSTANT; - } else if (pf == "add_theme_font_override" || pf == "has_theme_font" || pf == "has_theme_font_override" || pf == "get_theme_font") { + } else if (pf == "add_theme_font_override" || pf == "has_theme_font" || pf == "has_theme_font_override" || pf == "get_theme_font" || pf == "remove_theme_font_override") { type = Theme::DATA_TYPE_FONT; - } else if (pf == "add_theme_font_size_override" || pf == "has_theme_font_size" || pf == "has_theme_font_size_override" || pf == "get_theme_font_size") { + } else if (pf == "add_theme_font_size_override" || pf == "has_theme_font_size" || pf == "has_theme_font_size_override" || pf == "get_theme_font_size" || pf == "remove_theme_font_size_override") { type = Theme::DATA_TYPE_FONT_SIZE; - } else if (pf == "add_theme_icon_override" || pf == "has_theme_icon" || pf == "has_theme_icon_override" || pf == "get_theme_icon") { + } else if (pf == "add_theme_icon_override" || pf == "has_theme_icon" || pf == "has_theme_icon_override" || pf == "get_theme_icon" || pf == "remove_theme_icon_override") { type = Theme::DATA_TYPE_ICON; - } else if (pf == "add_theme_style_override" || pf == "has_theme_style" || pf == "has_theme_style_override" || pf == "get_theme_style") { + } else if (pf == "add_theme_stylebox_override" || pf == "has_theme_stylebox" || pf == "has_theme_stylebox_override" || pf == "get_theme_stylebox" || pf == "remove_theme_stylebox_override") { type = Theme::DATA_TYPE_STYLEBOX; } diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 69b84da23d..a36eb0652e 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1003,23 +1003,12 @@ void TextEdit::_notification(int p_what) { } } - if (str.length() == 0) { - // Draw line background if empty as we won't loop at all. - if (caret_line_wrap_index_map.has(line) && caret_line_wrap_index_map[line].has(line_wrap_index) && highlight_current_line) { - if (rtl) { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end, row_height), theme_cache.current_line_color); - } else { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(ofs_x, ofs_y, xmargin_end, row_height), theme_cache.current_line_color); - } - } - } else { - // If it has text, then draw current line marker in the margin, as line number etc will draw over it, draw the rest of line marker later. - if (caret_line_wrap_index_map.has(line) && caret_line_wrap_index_map[line].has(line_wrap_index) && highlight_current_line) { - if (rtl) { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end, row_height), theme_cache.current_line_color); - } else { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(ofs_x, ofs_y, xmargin_end, row_height), theme_cache.current_line_color); - } + // Draw current line highlight. + if (highlight_current_line && caret_line_wrap_index_map.has(line) && caret_line_wrap_index_map[line].has(line_wrap_index)) { + if (rtl) { + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end, row_height), theme_cache.current_line_color); + } else { + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(ofs_x, ofs_y, xmargin_end, row_height), theme_cache.current_line_color); } } diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp index df90257e03..c267ff93c6 100644 --- a/scene/gui/texture_button.cpp +++ b/scene/gui/texture_button.cpp @@ -178,13 +178,14 @@ void TextureButton::_notification(int p_what) { texdraw = focused; } - if (texdraw.is_valid()) { - size = texdraw->get_size(); - _texture_region = Rect2(Point2(), texdraw->get_size()); + if (texdraw.is_valid() || click_mask.is_valid()) { + const Size2 texdraw_size = texdraw.is_valid() ? texdraw->get_size() : Size2(click_mask->get_size()); + + size = texdraw_size; + _texture_region = Rect2(Point2(), texdraw_size); _tile = false; switch (stretch_mode) { case STRETCH_KEEP: - size = texdraw->get_size(); break; case STRETCH_SCALE: size = get_size(); @@ -194,18 +195,17 @@ void TextureButton::_notification(int p_what) { _tile = true; break; case STRETCH_KEEP_CENTERED: - ofs = (get_size() - texdraw->get_size()) / 2; - size = texdraw->get_size(); + ofs = (get_size() - texdraw_size) / 2; break; case STRETCH_KEEP_ASPECT_CENTERED: case STRETCH_KEEP_ASPECT: { Size2 _size = get_size(); - float tex_width = texdraw->get_width() * _size.height / texdraw->get_height(); + float tex_width = texdraw_size.width * _size.height / texdraw_size.height; float tex_height = _size.height; if (tex_width > _size.width) { tex_width = _size.width; - tex_height = texdraw->get_height() * tex_width / texdraw->get_width(); + tex_height = texdraw_size.height * tex_width / texdraw_size.width; } if (stretch_mode == STRETCH_KEEP_ASPECT_CENTERED) { @@ -217,10 +217,9 @@ void TextureButton::_notification(int p_what) { } break; case STRETCH_KEEP_ASPECT_COVERED: { size = get_size(); - Size2 tex_size = texdraw->get_size(); - Size2 scale_size(size.width / tex_size.width, size.height / tex_size.height); + Size2 scale_size = size / texdraw_size; float scale = scale_size.width > scale_size.height ? scale_size.width : scale_size.height; - Size2 scaled_tex_size = tex_size * scale; + Size2 scaled_tex_size = texdraw_size * scale; Point2 ofs2 = ((scaled_tex_size - size) / scale).abs() / 2.0f; _texture_region = Rect2(ofs2, size / scale); } break; @@ -233,10 +232,12 @@ void TextureButton::_notification(int p_what) { if (draw_focus_only) { // Do nothing, we only needed to calculate the rectangle. - } else if (_tile) { - draw_texture_rect(texdraw, Rect2(ofs, size), _tile); - } else { - draw_texture_rect_region(texdraw, Rect2(ofs, size), _texture_region); + } else if (texdraw.is_valid()) { + if (_tile) { + draw_texture_rect(texdraw, Rect2(ofs, size), _tile); + } else { + draw_texture_rect_region(texdraw, Rect2(ofs, size), _texture_region); + } } } else { _position_rect = Rect2(); diff --git a/scene/main/instance_placeholder.cpp b/scene/main/instance_placeholder.cpp index fe23ca1800..f36bbe9395 100644 --- a/scene/main/instance_placeholder.cpp +++ b/scene/main/instance_placeholder.cpp @@ -88,16 +88,16 @@ Node *InstancePlaceholder::create_instance(bool p_replace, const Ref<PackedScene if (!ps.is_valid()) { return nullptr; } - Node *scene = ps->instantiate(); - if (!scene) { + Node *instance = ps->instantiate(); + if (!instance) { return nullptr; } - scene->set_name(get_name()); - scene->set_multiplayer_authority(get_multiplayer_authority()); + instance->set_name(get_name()); + instance->set_multiplayer_authority(get_multiplayer_authority()); int pos = get_index(); for (const PropSet &E : stored_values) { - scene->set(E.name, E.value); + set_value_on_instance(this, instance, E); } if (p_replace) { @@ -105,10 +105,125 @@ Node *InstancePlaceholder::create_instance(bool p_replace, const Ref<PackedScene base->remove_child(this); } - base->add_child(scene); - base->move_child(scene, pos); + base->add_child(instance); + base->move_child(instance, pos); - return scene; + return instance; +} + +// This method will attempt to set the correct values on the placeholder instance +// for regular types this is trivial and unnecessary. +// For nodes however this becomes a bit tricky because they might now have existed until the instantiation, +// so this method will try to find the correct nodes and resolve them. +void InstancePlaceholder::set_value_on_instance(InstancePlaceholder *p_placeholder, Node *p_instance, const PropSet &p_set) { + bool is_valid; + + // If we don't have any info, we can't do anything, + // so try setting the value directly. + Variant current = p_instance->get(p_set.name, &is_valid); + if (!is_valid) { + p_instance->set(p_set.name, p_set.value, &is_valid); + return; + } + + Variant::Type current_type = current.get_type(); + Variant::Type placeholder_type = p_set.value.get_type(); + + // Arrays are a special case, because their containing type might be different. + if (current_type != Variant::Type::ARRAY) { + // Check if the variant types match. + if (Variant::evaluate(Variant::OP_EQUAL, current_type, placeholder_type)) { + p_instance->set(p_set.name, p_set.value, &is_valid); + if (is_valid) { + return; + } + // Types match but setting failed? This is strange, so let's print a warning! + WARN_PRINT(vformat("Property '%s' with type '%s' could not be set when creating instance of '%s'.", p_set.name, Variant::get_type_name(current_type), p_placeholder->get_name())); + return; + } + } else { + // We are dealing with an Array. + // Let's check if the subtype of the array matches first. + // This is needed because the set method of ScriptInstance checks for type, + // but the ClassDB set method doesn't! So we cannot reliably know what actually happens. + Array current_array = current; + Array placeholder_array = p_set.value; + if (current_array.is_same_typed(placeholder_array)) { + p_instance->set(p_set.name, p_set.value, &is_valid); + if (is_valid) { + return; + } + // Internal array types match but setting failed? This is strange, so let's print a warning! + WARN_PRINT(vformat("Array Property '%s' with type '%s' could not be set when creating instance of '%s'.", p_set.name, Variant::get_type_name(Variant::Type(current_array.get_typed_builtin())), p_placeholder->get_name())); + } + // Arrays are not the same internal type. This should be happening because we have a NodePath Array, + // but the instance wants a Node Array. + } + + switch (current_type) { + case Variant::Type::NIL: + if (placeholder_type != Variant::Type::NODE_PATH) { + break; + } + // If it's nil but we have a NodePath, we guess what works. + + p_instance->set(p_set.name, p_set.value, &is_valid); + if (is_valid) { + break; + } + + p_instance->set(p_set.name, try_get_node(p_placeholder, p_instance, p_set.value), &is_valid); + break; + case Variant::Type::OBJECT: + if (placeholder_type != Variant::Type::NODE_PATH) { + break; + } + // Easiest case, we want a node, but we have a deferred NodePath. + p_instance->set(p_set.name, try_get_node(p_placeholder, p_instance, p_set.value)); + break; + case Variant::Type::ARRAY: { + // If we have reached here it means our array types don't match, + // so we will convert the placeholder array into the correct type + // and resolve nodes if necessary. + Array current_array = current; + Array converted_array; + Array placeholder_array = p_set.value; + converted_array = current_array.duplicate(); + converted_array.resize(placeholder_array.size()); + + if (Variant::evaluate(Variant::OP_EQUAL, current_array.get_typed_builtin(), Variant::Type::NODE_PATH)) { + // We want a typed NodePath array. + for (int i = 0; i < placeholder_array.size(); i++) { + converted_array.set(i, placeholder_array[i]); + } + } else { + // We want Nodes, convert NodePaths. + for (int i = 0; i < placeholder_array.size(); i++) { + converted_array.set(i, try_get_node(p_placeholder, p_instance, placeholder_array[i])); + } + } + + p_instance->set(p_set.name, converted_array, &is_valid); + if (!is_valid) { + WARN_PRINT(vformat("Property '%s' with type '%s' could not be set when creating instance of '%s'.", p_set.name, Variant::get_type_name(current_type), p_placeholder->get_name())); + } + break; + } + default: + WARN_PRINT(vformat("Property '%s' with type '%s' could not be set when creating instance of '%s'.", p_set.name, Variant::get_type_name(current_type), p_placeholder->get_name())); + break; + } +} + +Node *InstancePlaceholder::try_get_node(InstancePlaceholder *p_placeholder, Node *p_instance, const NodePath &p_path) { + // First try to resolve internally, + // if that fails try resolving externally. + Node *node = p_instance->get_node_or_null(p_path); + if (node == nullptr) { + node = p_placeholder->get_node_or_null(p_path); + } + + return node; } Dictionary InstancePlaceholder::get_stored_values(bool p_with_order) { diff --git a/scene/main/instance_placeholder.h b/scene/main/instance_placeholder.h index 480474d0bd..ccf1e63a16 100644 --- a/scene/main/instance_placeholder.h +++ b/scene/main/instance_placeholder.h @@ -46,6 +46,10 @@ class InstancePlaceholder : public Node { List<PropSet> stored_values; +private: + void set_value_on_instance(InstancePlaceholder *p_placeholder, Node *p_instance, const PropSet &p_set); + Node *try_get_node(InstancePlaceholder *p_placeholder, Node *p_instance, const NodePath &p_path); + protected: bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; diff --git a/scene/resources/2d/tile_set.cpp b/scene/resources/2d/tile_set.cpp index 0f73577768..6c3356a205 100644 --- a/scene/resources/2d/tile_set.cpp +++ b/scene/resources/2d/tile_set.cpp @@ -6378,7 +6378,7 @@ Ref<ConvexPolygonShape2D> TileData::get_collision_polygon_shape(int p_layer_id, for (int i = 0; i < size; i++) { Ref<ConvexPolygonShape2D> transformed_polygon; transformed_polygon.instantiate(); - transformed_polygon->set_points(get_transformed_vertices(shapes_data.shapes[shape_index]->get_points(), p_flip_h, p_flip_v, p_transpose)); + transformed_polygon->set_points(get_transformed_vertices(shapes_data.shapes[i]->get_points(), p_flip_h, p_flip_v, p_transpose)); shapes_data.transformed_shapes[key][i] = transformed_polygon; } return shapes_data.transformed_shapes[key][shape_index]; diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 5e50b9a240..0c57c6b7ba 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -314,6 +314,16 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { ERR_FAIL_INDEX_V(nprops[j].value, prop_count, nullptr); if (nprops[j].name & FLAG_PATH_PROPERTY_IS_NODE) { + if (!Engine::get_singleton()->is_editor_hint() && node->get_scene_instance_load_placeholder()) { + // We cannot know if the referenced nodes exist yet, so instead of deferring, we write the NodePaths directly. + + uint32_t name_idx = nprops[j].name & (FLAG_PATH_PROPERTY_IS_NODE - 1); + ERR_FAIL_UNSIGNED_INDEX_V(name_idx, (uint32_t)sname_count, nullptr); + + node->set(snames[name_idx], props[nprops[j].value], &valid); + continue; + } + uint32_t name_idx = nprops[j].name & (FLAG_PATH_PROPERTY_IS_NODE - 1); ERR_FAIL_UNSIGNED_INDEX_V(name_idx, (uint32_t)sname_count, nullptr); |