diff options
Diffstat (limited to 'scene')
44 files changed, 697 insertions, 259 deletions
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 80169bc80c..78b5199358 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -172,6 +172,7 @@ void Light2D::set_shadow_filter(ShadowFilter p_filter) { ERR_FAIL_INDEX(p_filter, SHADOW_FILTER_MAX); shadow_filter = p_filter; RS::get_singleton()->canvas_light_set_shadow_filter(canvas_light, RS::CanvasLightShadowFilter(p_filter)); + notify_property_list_changed(); } Light2D::ShadowFilter Light2D::get_shadow_filter() const { @@ -231,6 +232,10 @@ void Light2D::_validate_property(PropertyInfo &p_property) const { if (!shadow && (p_property.name == "shadow_color" || p_property.name == "shadow_filter" || p_property.name == "shadow_filter_smooth" || p_property.name == "shadow_item_cull_mask")) { p_property.usage = PROPERTY_USAGE_NO_EDITOR; } + + if (shadow && p_property.name == "shadow_filter_smooth" && shadow_filter == SHADOW_FILTER_NONE) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; + } } void Light2D::_bind_methods() { diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index f077f7f5e6..748fbbe2d1 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -104,7 +104,7 @@ void NavigationAgent2D::_bind_methods() { ADD_SIGNAL(MethodInfo("path_changed")); ADD_SIGNAL(MethodInfo("target_reached")); ADD_SIGNAL(MethodInfo("navigation_finished")); - ADD_SIGNAL(MethodInfo("velocity_computed", PropertyInfo(Variant::VECTOR3, "safe_velocity"))); + ADD_SIGNAL(MethodInfo("velocity_computed", PropertyInfo(Variant::VECTOR2, "safe_velocity"))); } void NavigationAgent2D::_notification(int p_what) { @@ -478,8 +478,8 @@ void NavigationAgent2D::_request_repath() { void NavigationAgent2D::_check_distance_to_target() { if (!target_reached) { if (distance_to_target() < target_desired_distance) { - emit_signal(SNAME("target_reached")); target_reached = true; + emit_signal(SNAME("target_reached")); } } } diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 26627a4fca..f7a66215b2 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -1097,8 +1097,8 @@ void TileMap::_rendering_update_layer(int p_layer) { rs->canvas_item_set_sort_children_by_y(ci, layers[p_layer].y_sort_enabled); rs->canvas_item_set_use_parent_material(ci, get_use_parent_material() || get_material().is_valid()); rs->canvas_item_set_z_index(ci, layers[p_layer].z_index); - rs->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(get_texture_filter())); - rs->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(get_texture_repeat())); + rs->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(get_texture_filter_in_tree())); + rs->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(get_texture_repeat_in_tree())); rs->canvas_item_set_light_mask(ci, get_light_mask()); } @@ -1208,8 +1208,8 @@ void TileMap::_rendering_update_dirty_quadrants(SelfList<TileMapQuadrant>::List rs->canvas_item_set_z_as_relative_to_parent(ci, true); rs->canvas_item_set_z_index(ci, tile_z_index); - rs->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(get_texture_filter())); - rs->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(get_texture_repeat())); + rs->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(get_texture_filter_in_tree())); + rs->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(get_texture_repeat_in_tree())); q.canvas_items.push_back(ci); @@ -1297,7 +1297,7 @@ void TileMap::_rendering_draw_quadrant_debug(TileMapQuadrant *p_quadrant) { return; } - // Draw a placeholder for scenes needing one. + // Draw a placeholder for tiles needing one. RenderingServer *rs = RenderingServer::get_singleton(); Vector2 quadrant_pos = map_to_local(p_quadrant->coords * get_effective_quadrant_size(p_quadrant->layer)); for (const Vector2i &E_cell : p_quadrant->cells) { @@ -1330,9 +1330,9 @@ void TileMap::_rendering_draw_quadrant_debug(TileMapQuadrant *p_quadrant) { 0.8); // Draw a placeholder tile. - Transform2D xform; - xform.set_origin(map_to_local(E_cell) - quadrant_pos); - rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, xform); + Transform2D cell_to_quadrant; + cell_to_quadrant.set_origin(map_to_local(E_cell) - quadrant_pos); + rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, cell_to_quadrant); rs->canvas_item_add_circle(p_quadrant->debug_canvas_item, Vector2(), MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 4.0, color); } } @@ -1632,13 +1632,13 @@ void TileMap::_physics_draw_quadrant_debug(TileMapQuadrant *p_quadrant) { color.push_back(debug_collision_color); Vector2 quadrant_pos = map_to_local(p_quadrant->coords * get_effective_quadrant_size(p_quadrant->layer)); - Transform2D qudrant_xform; - qudrant_xform.set_origin(quadrant_pos); - Transform2D global_transform_inv = (get_global_transform() * qudrant_xform).affine_inverse(); + Transform2D quadrant_to_local; + quadrant_to_local.set_origin(quadrant_pos); + Transform2D global_to_quadrant = (get_global_transform() * quadrant_to_local).affine_inverse(); for (RID body : p_quadrant->bodies) { - Transform2D xform = Transform2D(ps->body_get_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM)) * global_transform_inv; - rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, xform); + Transform2D body_to_quadrant = global_to_quadrant * Transform2D(ps->body_get_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM)); + rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, body_to_quadrant); for (int shape_index = 0; shape_index < ps->body_get_shape_count(body); shape_index++) { const RID &shape = ps->body_get_shape(body, shape_index); PhysicsServer2D::ShapeType type = ps->shape_get_type(shape); @@ -1815,9 +1815,9 @@ void TileMap::_navigation_draw_quadrant_debug(TileMapQuadrant *p_quadrant) { tile_data = atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile); } - Transform2D xform; - xform.set_origin(map_to_local(E_cell) - quadrant_pos); - rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, xform); + Transform2D cell_to_quadrant; + cell_to_quadrant.set_origin(map_to_local(E_cell) - quadrant_pos); + rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, cell_to_quadrant); for (int layer_index = 0; layer_index < tile_set->get_navigation_layers_count(); layer_index++) { Ref<NavigationPolygon> navpoly = tile_data->get_navigation_polygon(layer_index); @@ -1863,7 +1863,7 @@ void TileMap::_scenes_update_dirty_quadrants(SelfList<TileMapQuadrant>::List &r_ for (const KeyValue<Vector2i, String> &E : q.scenes) { Node *node = get_node_or_null(E.value); if (node) { - node->queue_delete(); + node->queue_free(); } } @@ -1911,7 +1911,7 @@ void TileMap::_scenes_cleanup_quadrant(TileMapQuadrant *p_quadrant) { for (const KeyValue<Vector2i, String> &E : p_quadrant->scenes) { Node *node = get_node_or_null(E.value); if (node) { - node->queue_delete(); + node->queue_free(); } } @@ -1956,9 +1956,9 @@ void TileMap::_scenes_draw_quadrant_debug(TileMapQuadrant *p_quadrant) { 0.8); // Draw a placeholder tile. - Transform2D xform; - xform.set_origin(map_to_local(E_cell) - quadrant_pos); - rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, xform); + Transform2D cell_to_quadrant; + cell_to_quadrant.set_origin(map_to_local(E_cell) - quadrant_pos); + rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, cell_to_quadrant); rs->canvas_item_add_circle(p_quadrant->debug_canvas_item, Vector2(), MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 4.0, color); } } @@ -2206,11 +2206,10 @@ void TileMap::set_pattern(int p_layer, Vector2i p_position, const Ref<TileMapPat } } -TileSet::TerrainsPattern TileMap::_get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, RBSet<TerrainConstraint> p_constraints) { +TileSet::TerrainsPattern TileMap::_get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, RBSet<TerrainConstraint> p_constraints, TileSet::TerrainsPattern p_current_pattern) { if (!tile_set.is_valid()) { return TileSet::TerrainsPattern(); } - // Returns all tiles compatible with the given constraints. RBMap<TileSet::TerrainsPattern, int> terrain_pattern_score; RBSet<TileSet::TerrainsPattern> pattern_set = tile_set->get_terrains_pattern_set(p_terrain_set); @@ -2221,28 +2220,41 @@ TileSet::TerrainsPattern TileMap::_get_best_terrain_pattern_for_constraints(int // Check the center bit constraint TerrainConstraint terrain_constraint = TerrainConstraint(this, p_position, terrain_pattern.get_terrain()); RBSet<TerrainConstraint>::Element *in_set_constraint_element = p_constraints.find(terrain_constraint); - if (in_set_constraint_element && in_set_constraint_element->get().get_terrain() != terrain_constraint.get_terrain()) { - score += in_set_constraint_element->get().get_priority(); + if (in_set_constraint_element) { + if (in_set_constraint_element->get().get_terrain() != terrain_constraint.get_terrain()) { + score += in_set_constraint_element->get().get_priority(); + } + } else if (p_current_pattern.get_terrain() != terrain_pattern.get_terrain()) { + continue; // Ignore a pattern that cannot keep bits without constraints unmodified. } // Check the surrounding bits + bool invalid_pattern = false; for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) { // Check if the bit is compatible with the constraints. TerrainConstraint terrain_bit_constraint = TerrainConstraint(this, p_position, bit, terrain_pattern.get_terrain_peering_bit(bit)); in_set_constraint_element = p_constraints.find(terrain_bit_constraint); - if (in_set_constraint_element && in_set_constraint_element->get().get_terrain() != terrain_bit_constraint.get_terrain()) { - score += in_set_constraint_element->get().get_priority(); + if (in_set_constraint_element) { + if (in_set_constraint_element->get().get_terrain() != terrain_bit_constraint.get_terrain()) { + score += in_set_constraint_element->get().get_priority(); + } + } else if (p_current_pattern.get_terrain_peering_bit(bit) != terrain_pattern.get_terrain_peering_bit(bit)) { + invalid_pattern = true; // Ignore a pattern that cannot keep bits without constraints unmodified. + break; } } } + if (invalid_pattern) { + continue; + } terrain_pattern_score[terrain_pattern] = score; } // Compute the minimum score - TileSet::TerrainsPattern min_score_pattern; + TileSet::TerrainsPattern min_score_pattern = p_current_pattern; int min_score = INT32_MAX; for (KeyValue<TileSet::TerrainsPattern, int> E : terrain_pattern_score) { if (E.value < min_score) { @@ -2274,7 +2286,7 @@ RBSet<TileMap::TerrainConstraint> TileMap::_get_terrain_constraints_from_added_p return output; } -RBSet<TileMap::TerrainConstraint> TileMap::_get_terrain_constraints_from_cells_list(int p_layer, const RBSet<Vector2i> &p_cell_list, int p_terrain_set, bool p_ignore_empty_terrains) const { +RBSet<TileMap::TerrainConstraint> TileMap::_get_terrain_constraints_from_painted_cells_list(int p_layer, const RBSet<Vector2i> &p_painted, int p_terrain_set, bool p_ignore_empty_terrains) const { if (!tile_set.is_valid()) { return RBSet<TerrainConstraint>(); } @@ -2284,8 +2296,8 @@ RBSet<TileMap::TerrainConstraint> TileMap::_get_terrain_constraints_from_cells_l // Build a set of dummy constraints to get the constrained points. RBSet<TerrainConstraint> dummy_constraints; - for (const Vector2i &E : p_cell_list) { - for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { // Iterates over sides. + for (const Vector2i &E : p_painted) { + for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { // Iterates over neighbor bits. TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) { dummy_constraints.insert(TerrainConstraint(this, E, bit, -1)); @@ -2342,7 +2354,7 @@ RBSet<TileMap::TerrainConstraint> TileMap::_get_terrain_constraints_from_cells_l } // Add the centers as constraints - for (Vector2i E_coords : p_cell_list) { + for (Vector2i E_coords : p_painted) { TileData *tile_data = nullptr; TileMapCell cell = get_cell(p_layer, E_coords); if (cell.source_id != TileSet::INVALID_SOURCE) { @@ -2362,7 +2374,7 @@ RBSet<TileMap::TerrainConstraint> TileMap::_get_terrain_constraints_from_cells_l return constraints; } -HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> p_constraints) { +HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_fill_constraints(int p_layer, const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> p_constraints) { if (!tile_set.is_valid()) { return HashMap<Vector2i, TileSet::TerrainsPattern>(); } @@ -2378,7 +2390,20 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_fill_constraints(co const Vector2i &coords = p_to_replace[i]; // Select the best pattern for the given constraints - TileSet::TerrainsPattern pattern = _get_best_terrain_pattern_for_constraints(p_terrain_set, coords, constraints); + TileSet::TerrainsPattern current_pattern = TileSet::TerrainsPattern(*tile_set, p_terrain_set); + TileMapCell cell = get_cell(p_layer, coords); + if (cell.source_id != TileSet::INVALID_SOURCE) { + TileSetSource *source = *tile_set->get_source(cell.source_id); + TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); + if (atlas_source) { + // Get tile data. + TileData *tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile); + if (tile_data && tile_data->get_terrain_set() == p_terrain_set) { + current_pattern = tile_data->get_terrains_pattern(); + } + } + } + TileSet::TerrainsPattern pattern = _get_best_terrain_pattern_for_constraints(p_terrain_set, coords, constraints, current_pattern); // Update the constraint set with the new ones RBSet<TerrainConstraint> new_constraints = _get_terrain_constraints_from_added_pattern(coords, p_terrain_set, pattern); @@ -2492,12 +2517,12 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_fill_connect(int p_ } // Fills in the constraint list from existing tiles. - for (TerrainConstraint c : _get_terrain_constraints_from_cells_list(p_layer, can_modify_set, p_terrain_set, p_ignore_empty_terrains)) { + for (TerrainConstraint c : _get_terrain_constraints_from_painted_cells_list(p_layer, painted_set, p_terrain_set, p_ignore_empty_terrains)) { constraints.insert(c); } // Fill the terrains. - output = terrain_fill_constraints(can_modify_list, p_terrain_set, constraints); + output = terrain_fill_constraints(p_layer, can_modify_list, p_terrain_set, constraints); return output; } @@ -2527,10 +2552,12 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_fill_path(int p_lay // Build list and set of tiles that can be modified (painted and their surroundings) Vector<Vector2i> can_modify_list; RBSet<Vector2i> can_modify_set; + RBSet<Vector2i> painted_set; for (int i = p_path.size() - 1; i >= 0; i--) { const Vector2i &coords = p_path[i]; can_modify_list.push_back(coords); can_modify_set.insert(coords); + painted_set.insert(coords); } for (Vector2i coords : p_path) { // Find the adequate neighbor @@ -2563,12 +2590,12 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_fill_path(int p_lay } // Fills in the constraint list from existing tiles. - for (TerrainConstraint c : _get_terrain_constraints_from_cells_list(p_layer, can_modify_set, p_terrain_set, p_ignore_empty_terrains)) { + for (TerrainConstraint c : _get_terrain_constraints_from_painted_cells_list(p_layer, painted_set, p_terrain_set, p_ignore_empty_terrains)) { constraints.insert(c); } // Fill the terrains. - output = terrain_fill_constraints(can_modify_list, p_terrain_set, constraints); + output = terrain_fill_constraints(p_layer, can_modify_list, p_terrain_set, constraints); return output; } @@ -2580,10 +2607,12 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_fill_pattern(int p_ // Build list and set of tiles that can be modified (painted and their surroundings). Vector<Vector2i> can_modify_list; RBSet<Vector2i> can_modify_set; + RBSet<Vector2i> painted_set; for (int i = p_coords_array.size() - 1; i >= 0; i--) { const Vector2i &coords = p_coords_array[i]; can_modify_list.push_back(coords); can_modify_set.insert(coords); + painted_set.insert(coords); } for (Vector2i coords : p_coords_array) { // Find the adequate neighbor @@ -2613,12 +2642,12 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_fill_pattern(int p_ } // Fills in the constraint list from modified tiles border. - for (TerrainConstraint c : _get_terrain_constraints_from_cells_list(p_layer, can_modify_set, p_terrain_set, p_ignore_empty_terrains)) { + for (TerrainConstraint c : _get_terrain_constraints_from_painted_cells_list(p_layer, painted_set, p_terrain_set, p_ignore_empty_terrains)) { constraints.insert(c); } // Fill the terrains. - output = terrain_fill_constraints(can_modify_list, p_terrain_set, constraints); + output = terrain_fill_constraints(p_layer, can_modify_list, p_terrain_set, constraints); return output; } @@ -2627,14 +2656,38 @@ void TileMap::set_cells_terrain_connect(int p_layer, TypedArray<Vector2i> p_cell ERR_FAIL_INDEX(p_layer, (int)layers.size()); ERR_FAIL_INDEX(p_terrain_set, tile_set->get_terrain_sets_count()); - Vector<Vector2i> vector_cells; + Vector<Vector2i> cells_vector; + HashSet<Vector2i> painted_set; for (int i = 0; i < p_cells.size(); i++) { - vector_cells.push_back(p_cells[i]); - } - HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_output = terrain_fill_connect(p_layer, vector_cells, p_terrain_set, p_terrain, p_ignore_empty_terrains); - for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E : terrain_fill_output) { - TileMapCell c = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, E.value); - set_cell(p_layer, E.key, c.source_id, c.get_atlas_coords(), c.alternative_tile); + cells_vector.push_back(p_cells[i]); + painted_set.insert(p_cells[i]); + } + HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_output = terrain_fill_connect(p_layer, cells_vector, p_terrain_set, p_terrain, p_ignore_empty_terrains); + for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &kv : terrain_fill_output) { + if (painted_set.has(kv.key)) { + // Paint a random tile with the correct terrain for the painted path. + TileMapCell c = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, kv.value); + set_cell(p_layer, kv.key, c.source_id, c.get_atlas_coords(), c.alternative_tile); + } else { + // Avoids updating the painted path from the output if the new pattern is the same as before. + TileSet::TerrainsPattern in_map_terrain_pattern = TileSet::TerrainsPattern(*tile_set, p_terrain_set); + TileMapCell cell = get_cell(p_layer, kv.key); + if (cell.source_id != TileSet::INVALID_SOURCE) { + TileSetSource *source = *tile_set->get_source(cell.source_id); + TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); + if (atlas_source) { + // Get tile data. + TileData *tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile); + if (tile_data && tile_data->get_terrain_set() == p_terrain_set) { + in_map_terrain_pattern = tile_data->get_terrains_pattern(); + } + } + } + if (in_map_terrain_pattern != kv.value) { + TileMapCell c = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, kv.value); + set_cell(p_layer, kv.key, c.source_id, c.get_atlas_coords(), c.alternative_tile); + } + } } } @@ -2644,13 +2697,38 @@ void TileMap::set_cells_terrain_path(int p_layer, TypedArray<Vector2i> p_path, i ERR_FAIL_INDEX(p_terrain_set, tile_set->get_terrain_sets_count()); Vector<Vector2i> vector_path; + HashSet<Vector2i> painted_set; for (int i = 0; i < p_path.size(); i++) { vector_path.push_back(p_path[i]); + painted_set.insert(p_path[i]); } + HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_output = terrain_fill_path(p_layer, vector_path, p_terrain_set, p_terrain, p_ignore_empty_terrains); - for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E : terrain_fill_output) { - TileMapCell c = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, E.value); - set_cell(p_layer, E.key, c.source_id, c.get_atlas_coords(), c.alternative_tile); + for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &kv : terrain_fill_output) { + if (painted_set.has(kv.key)) { + // Paint a random tile with the correct terrain for the painted path. + TileMapCell c = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, kv.value); + set_cell(p_layer, kv.key, c.source_id, c.get_atlas_coords(), c.alternative_tile); + } else { + // Avoids updating the painted path from the output if the new pattern is the same as before. + TileSet::TerrainsPattern in_map_terrain_pattern = TileSet::TerrainsPattern(*tile_set, p_terrain_set); + TileMapCell cell = get_cell(p_layer, kv.key); + if (cell.source_id != TileSet::INVALID_SOURCE) { + TileSetSource *source = *tile_set->get_source(cell.source_id); + TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); + if (atlas_source) { + // Get tile data. + TileData *tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile); + if (tile_data && tile_data->get_terrain_set() == p_terrain_set) { + in_map_terrain_pattern = tile_data->get_terrains_pattern(); + } + } + } + if (in_map_terrain_pattern != kv.value) { + TileMapCell c = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, kv.value); + set_cell(p_layer, kv.key, c.source_id, c.get_atlas_coords(), c.alternative_tile); + } + } } } @@ -3717,13 +3795,14 @@ void TileMap::set_use_parent_material(bool p_use_parent_material) { } void TileMap::set_texture_filter(TextureFilter p_texture_filter) { - // Set a default texture filter for the whole tilemap + // Set a default texture filter for the whole tilemap. CanvasItem::set_texture_filter(p_texture_filter); + TextureFilter target_filter = get_texture_filter_in_tree(); for (unsigned int layer = 0; layer < layers.size(); layer++) { for (HashMap<Vector2i, TileMapQuadrant>::Iterator F = layers[layer].quadrant_map.begin(); F; ++F) { TileMapQuadrant &q = F->value; for (const RID &ci : q.canvas_items) { - RenderingServer::get_singleton()->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(p_texture_filter)); + RenderingServer::get_singleton()->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(target_filter)); _make_quadrant_dirty(F); } } @@ -3732,13 +3811,14 @@ void TileMap::set_texture_filter(TextureFilter p_texture_filter) { } void TileMap::set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) { - // Set a default texture repeat for the whole tilemap + // Set a default texture repeat for the whole tilemap. CanvasItem::set_texture_repeat(p_texture_repeat); + TextureRepeat target_repeat = get_texture_repeat_in_tree(); for (unsigned int layer = 0; layer < layers.size(); layer++) { for (HashMap<Vector2i, TileMapQuadrant>::Iterator F = layers[layer].quadrant_map.begin(); F; ++F) { TileMapQuadrant &q = F->value; for (const RID &ci : q.canvas_items) { - RenderingServer::get_singleton()->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(p_texture_repeat)); + RenderingServer::get_singleton()->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(target_repeat)); _make_quadrant_dirty(F); } } @@ -3976,9 +4056,5 @@ TileMap::TileMap() { } TileMap::~TileMap() { - if (tile_set.is_valid()) { - tile_set->disconnect("changed", callable_mp(this, &TileMap::_tile_set_changed)); - } - _clear_internals(); } diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index d468675e91..7f3e241871 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -266,9 +266,9 @@ private: void _scenes_draw_quadrant_debug(TileMapQuadrant *p_quadrant); // Terrains. - TileSet::TerrainsPattern _get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, RBSet<TerrainConstraint> p_constraints); + TileSet::TerrainsPattern _get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, RBSet<TerrainConstraint> p_constraints, TileSet::TerrainsPattern p_current_pattern); RBSet<TerrainConstraint> _get_terrain_constraints_from_added_pattern(Vector2i p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const; - RBSet<TerrainConstraint> _get_terrain_constraints_from_cells_list(int p_layer, const RBSet<Vector2i> &p_on_map, int p_terrain_set, bool p_ignore_empty_terrains) const; + RBSet<TerrainConstraint> _get_terrain_constraints_from_painted_cells_list(int p_layer, const RBSet<Vector2i> &p_painted, int p_terrain_set, bool p_ignore_empty_terrains) const; // Set and get tiles from data arrays. void _set_tile_data(int p_layer, const Vector<int> &p_data); @@ -352,7 +352,7 @@ public: void set_pattern(int p_layer, Vector2i p_position, const Ref<TileMapPattern> p_pattern); // Terrains. - HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> p_constraints); // Not exposed. + HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_constraints(int p_layer, const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> p_constraints); // Not exposed. HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_connect(int p_layer, const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); // Not exposed. HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_path(int p_layer, const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); // Not exposed. HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_pattern(int p_layer, const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains = true); // Not exposed. diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp index 39068fe83c..f64cabb75c 100644 --- a/scene/3d/navigation_agent_3d.cpp +++ b/scene/3d/navigation_agent_3d.cpp @@ -495,8 +495,8 @@ void NavigationAgent3D::_request_repath() { void NavigationAgent3D::_check_distance_to_target() { if (!target_reached) { if (distance_to_target() < target_desired_distance) { - emit_signal(SNAME("target_reached")); target_reached = true; + emit_signal(SNAME("target_reached")); } } } diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index 5f515acead..1743fa1838 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -253,9 +253,7 @@ Vector3 Node3D::get_global_rotation() const { void Node3D::set_global_rotation(const Vector3 &p_euler_rad) { Transform3D transform = get_global_transform(); - Basis new_basis = transform.get_basis(); - new_basis.set_euler(p_euler_rad); - transform.set_basis(new_basis); + transform.basis = Basis::from_euler(p_euler_rad); set_global_transform(transform); } diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h index 04f73a4cbd..457f634c34 100644 --- a/scene/3d/node_3d.h +++ b/scene/3d/node_3d.h @@ -71,8 +71,8 @@ public: }; private: - // For the sake of ease of use, Node3D can operate with Transforms (Basis+Origin), Quaterinon/Scale and Euler Rotation/Scale. - // Transform and Quaterinon are stored in data.local_transform Basis (so quaternion is not really stored, but converted back/forth from 3x3 matrix on demand). + // For the sake of ease of use, Node3D can operate with Transforms (Basis+Origin), Quaternion/Scale and Euler Rotation/Scale. + // Transform and Quaternion are stored in data.local_transform Basis (so quaternion is not really stored, but converted back/forth from 3x3 matrix on demand). // Euler needs to be kept separate because converting to Basis and back may result in a different vector (which is troublesome for users // editing in the inspector, not only because of the numerical precision loss but because they expect these rotations to be consistent, or support // "redundant" rotations for animation interpolation, like going from 0 to 720 degrees). diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp index a45ef52452..45ff0a4b45 100644 --- a/scene/3d/ray_cast_3d.cpp +++ b/scene/3d/ray_cast_3d.cpp @@ -516,7 +516,7 @@ void RayCast3D::_clear_debug_shape() { MeshInstance3D *mi = static_cast<MeshInstance3D *>(debug_shape); if (mi->is_inside_tree()) { - mi->queue_delete(); + mi->queue_free(); } else { memdelete(mi); } diff --git a/scene/3d/shape_cast_3d.cpp b/scene/3d/shape_cast_3d.cpp index e7d1a8ec7d..03cbd984cd 100644 --- a/scene/3d/shape_cast_3d.cpp +++ b/scene/3d/shape_cast_3d.cpp @@ -619,7 +619,7 @@ void ShapeCast3D::_clear_debug_shape() { MeshInstance3D *mi = static_cast<MeshInstance3D *>(debug_shape); if (mi->is_inside_tree()) { - mi->queue_delete(); + mi->queue_free(); } else { memdelete(mi); } diff --git a/scene/3d/visible_on_screen_notifier_3d.cpp b/scene/3d/visible_on_screen_notifier_3d.cpp index 2013a93e26..6d4c18a69e 100644 --- a/scene/3d/visible_on_screen_notifier_3d.cpp +++ b/scene/3d/visible_on_screen_notifier_3d.cpp @@ -189,7 +189,7 @@ void VisibleOnScreenEnabler3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_enable_node_path"), &VisibleOnScreenEnabler3D::get_enable_node_path); ADD_GROUP("Enabling", "enable_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "enable_mode", PROPERTY_HINT_ENUM, "Inherit,Always,WhenPaused"), "set_enable_mode", "get_enable_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "enable_mode", PROPERTY_HINT_ENUM, "Inherit,Always,When Paused"), "set_enable_mode", "get_enable_mode"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "enable_node_path"), "set_enable_node_path", "get_enable_node_path"); BIND_ENUM_CONSTANT(ENABLE_MODE_INHERIT); diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp index e93ad5ecbf..3868d1e42e 100644 --- a/scene/3d/visual_instance_3d.cpp +++ b/scene/3d/visual_instance_3d.cpp @@ -40,10 +40,6 @@ AABB VisualInstance3D::get_aabb() const { return AABB(); } -AABB VisualInstance3D::get_transformed_aabb() const { - return get_global_transform().xform(get_aabb()); -} - void VisualInstance3D::_update_visibility() { if (!is_inside_tree()) { return; @@ -121,8 +117,6 @@ void VisualInstance3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_layer_mask_value", "layer_number", "value"), &VisualInstance3D::set_layer_mask_value); ClassDB::bind_method(D_METHOD("get_layer_mask_value", "layer_number"), &VisualInstance3D::get_layer_mask_value); - ClassDB::bind_method(D_METHOD("get_transformed_aabb"), &VisualInstance3D::get_transformed_aabb); - GDVIRTUAL_BIND(_get_aabb); ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_3D_RENDER), "set_layer_mask", "get_layer_mask"); } diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h index 4755545516..06a8c05faa 100644 --- a/scene/3d/visual_instance_3d.h +++ b/scene/3d/visual_instance_3d.h @@ -60,8 +60,6 @@ public: RID get_instance() const; virtual AABB get_aabb() const; - virtual AABB get_transformed_aabb() const; // helper - void set_base(const RID &p_base); RID get_base() const; diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp index fe4ccbc7dc..f5d30c584f 100644 --- a/scene/3d/xr_nodes.cpp +++ b/scene/3d/xr_nodes.cpp @@ -363,7 +363,7 @@ void XRNode3D::_unbind_tracker() { } void XRNode3D::_changed_tracker(const StringName p_tracker_name, int p_tracker_type) { - if (p_tracker_name == p_tracker_name) { + if (tracker_name == p_tracker_name) { // just in case unref our current tracker _unbind_tracker(); @@ -373,7 +373,7 @@ void XRNode3D::_changed_tracker(const StringName p_tracker_name, int p_tracker_t } void XRNode3D::_removed_tracker(const StringName p_tracker_name, int p_tracker_type) { - if (p_tracker_name == p_tracker_name) { + if (tracker_name == p_tracker_name) { // unref our tracker, it's no longer available _unbind_tracker(); } diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index e306d00a51..59930a3fbb 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -2066,7 +2066,7 @@ Ref<AnimatedValuesBackup> AnimationPlayer::apply_reset(bool p_user_initiated) { // Forcing the use of the original root because the scene where original player belongs may be not the active one Ref<AnimatedValuesBackup> old_values = aux_player->backup_animated_values(get_node(get_root())); aux_player->seek(0.0f, true); - aux_player->queue_delete(); + aux_player->queue_free(); if (p_user_initiated) { Ref<AnimatedValuesBackup> new_values = aux_player->backup_animated_values(); diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp index bfc3c25fe6..b4bdda9ecb 100644 --- a/scene/debugger/scene_debugger.cpp +++ b/scene/debugger/scene_debugger.cpp @@ -548,14 +548,36 @@ SceneDebuggerTree::SceneDebuggerTree(Node *p_root) { // Flatten tree into list, depth first, use stack to avoid recursion. List<Node *> stack; stack.push_back(p_root); + bool is_root = true; + const StringName &is_visible_sn = SNAME("is_visible"); + const StringName &is_visible_in_tree_sn = SNAME("is_visible_in_tree"); while (stack.size()) { Node *n = stack[0]; stack.pop_front(); + int count = n->get_child_count(); - nodes.push_back(RemoteNode(count, n->get_name(), n->get_class(), n->get_instance_id())); for (int i = 0; i < count; i++) { stack.push_front(n->get_child(count - i - 1)); } + + int view_flags = 0; + if (is_root) { + // Prevent root window visibility from being changed. + is_root = false; + } else if (n->has_method(is_visible_sn)) { + const Variant visible = n->call(is_visible_sn); + if (visible.get_type() == Variant::BOOL) { + view_flags = RemoteNode::VIEW_HAS_VISIBLE_METHOD; + view_flags |= uint8_t(visible) * RemoteNode::VIEW_VISIBLE; + } + if (n->has_method(is_visible_in_tree_sn)) { + const Variant visible_in_tree = n->call(is_visible_in_tree_sn); + if (visible_in_tree.get_type() == Variant::BOOL) { + view_flags |= uint8_t(visible_in_tree) * RemoteNode::VIEW_VISIBLE_IN_TREE; + } + } + } + nodes.push_back(RemoteNode(count, n->get_name(), n->get_class(), n->get_instance_id(), n->get_scene_file_path(), view_flags)); } } @@ -565,19 +587,23 @@ void SceneDebuggerTree::serialize(Array &p_arr) { p_arr.push_back(n.name); p_arr.push_back(n.type_name); p_arr.push_back(n.id); + p_arr.push_back(n.scene_file_path); + p_arr.push_back(n.view_flags); } } void SceneDebuggerTree::deserialize(const Array &p_arr) { int idx = 0; while (p_arr.size() > idx) { - ERR_FAIL_COND(p_arr.size() < 4); - CHECK_TYPE(p_arr[idx], INT); - CHECK_TYPE(p_arr[idx + 1], STRING); - CHECK_TYPE(p_arr[idx + 2], STRING); - CHECK_TYPE(p_arr[idx + 3], INT); - nodes.push_back(RemoteNode(p_arr[idx], p_arr[idx + 1], p_arr[idx + 2], p_arr[idx + 3])); - idx += 4; + ERR_FAIL_COND(p_arr.size() < 6); + CHECK_TYPE(p_arr[idx], INT); // child_count. + CHECK_TYPE(p_arr[idx + 1], STRING); // name. + CHECK_TYPE(p_arr[idx + 2], STRING); // type_name. + CHECK_TYPE(p_arr[idx + 3], INT); // id. + CHECK_TYPE(p_arr[idx + 4], STRING); // scene_file_path. + CHECK_TYPE(p_arr[idx + 5], INT); // view_flags. + nodes.push_back(RemoteNode(p_arr[idx], p_arr[idx + 1], p_arr[idx + 2], p_arr[idx + 3], p_arr[idx + 4], p_arr[idx + 5])); + idx += 6; } } diff --git a/scene/debugger/scene_debugger.h b/scene/debugger/scene_debugger.h index 911363f45d..fe35446aae 100644 --- a/scene/debugger/scene_debugger.h +++ b/scene/debugger/scene_debugger.h @@ -110,12 +110,23 @@ public: String name; String type_name; ObjectID id; + String scene_file_path; + uint8_t view_flags = 0; - RemoteNode(int p_child, const String &p_name, const String &p_type, ObjectID p_id) { + enum ViewFlags { + VIEW_HAS_VISIBLE_METHOD = 1 << 1, + VIEW_VISIBLE = 1 << 2, + VIEW_VISIBLE_IN_TREE = 1 << 3, + }; + + RemoteNode(int p_child, const String &p_name, const String &p_type, ObjectID p_id, const String p_scene_file_path, int p_view_flags) { child_count = p_child; name = p_name; type_name = p_type; id = p_id; + + scene_file_path = p_scene_file_path; + view_flags = p_view_flags; } RemoteNode() {} diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 8a5d04f49c..f61fa29a33 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -2859,7 +2859,9 @@ void CodeEdit::_filter_code_completion_candidates_impl() { offset = line_height; } - max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset); + if (font.is_valid()) { + max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset); + } code_completion_options.push_back(option); } @@ -2970,7 +2972,9 @@ void CodeEdit::_filter_code_completion_candidates_impl() { if (string_to_complete.length() == 0) { code_completion_options.push_back(option); - max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset); + if (font.is_valid()) { + max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset); + } continue; } @@ -3076,7 +3080,9 @@ void CodeEdit::_filter_code_completion_candidates_impl() { option.matches.append_array(ssq_matches); completion_options_subseq.push_back(option); } - max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset); + if (font.is_valid()) { + max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset); + } } else if (!*ssq_lower) { // Matched the whole subsequence in s_lower. option.matches.clear(); @@ -3093,7 +3099,9 @@ void CodeEdit::_filter_code_completion_candidates_impl() { option.matches.append_array(ssq_lower_matches); completion_options_subseq_casei.push_back(option); } - max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset); + if (font.is_valid()) { + max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset); + } } } diff --git a/scene/gui/color_mode.cpp b/scene/gui/color_mode.cpp index 3a5013dabe..a063cd344a 100644 --- a/scene/gui/color_mode.cpp +++ b/scene/gui/color_mode.cpp @@ -284,46 +284,68 @@ Color ColorModeOKHSL::get_color() const { } void ColorModeOKHSL::slider_draw(int p_which) { - Vector<Vector2> pos; - pos.resize(4); - Vector<Color> col; - col.resize(4); HSlider *slider = color_picker->get_slider(p_which); Size2 size = slider->get_size(); - Color left_color; - Color right_color; - Color color = color_picker->get_pick_color(); const real_t margin = 16 * color_picker->get_theme_default_base_scale(); - if (p_which == ColorPicker::SLIDER_COUNT) { - slider->draw_texture_rect(color_picker->get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), Rect2(Point2(0, 0), Size2(size.x, margin)), true); - - left_color = color; - left_color.a = 0; - right_color = color; - right_color.a = 1; - } else if (p_which == 0) { + if (p_which == 0) { // H Ref<Texture2D> hue = color_picker->get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker")); slider->draw_set_transform(Point2(), -Math_PI / 2, Size2(1.0, 1.0)); slider->draw_texture_rect(hue, Rect2(Vector2(margin * -1, 0), Vector2(margin, size.x)), false); return; - } else { - Color s_col; - Color v_col; - s_col.set_ok_hsl(color.get_h(), 0, color.get_v()); - left_color = (p_which == 1) ? s_col : Color(0, 0, 0); - s_col.set_ok_hsl(color.get_h(), 1, color.get_v()); - v_col.set_ok_hsl(color.get_h(), color.get_s(), 1); - right_color = (p_which == 1) ? s_col : v_col; } - col.set(0, left_color); - col.set(1, right_color); - col.set(2, right_color); - col.set(3, left_color); - pos.set(0, Vector2(0, 0)); - pos.set(1, Vector2(size.x, 0)); - pos.set(2, Vector2(size.x, margin)); - pos.set(3, Vector2(0, margin)); + + Vector<Vector2> pos; + Vector<Color> col; + Color left_color; + Color right_color; + Color color = color_picker->get_pick_color(); + + if (p_which == 2) { // L + pos.resize(6); + col.resize(6); + left_color = Color(0, 0, 0); + Color middle_color; + middle_color.set_ok_hsl(color.get_ok_hsl_h(), color.get_ok_hsl_s(), 0.5); + right_color.set_ok_hsl(color.get_ok_hsl_h(), color.get_ok_hsl_s(), 1); + + col.set(0, left_color); + col.set(1, middle_color); + col.set(2, right_color); + col.set(3, right_color); + col.set(4, middle_color); + col.set(5, left_color); + pos.set(0, Vector2(0, 0)); + pos.set(1, Vector2(size.x * 0.5, 0)); + pos.set(2, Vector2(size.x, 0)); + pos.set(3, Vector2(size.x, margin)); + pos.set(4, Vector2(size.x * 0.5, margin)); + pos.set(5, Vector2(0, margin)); + } else { // A / S + pos.resize(4); + col.resize(4); + + if (p_which == ColorPicker::SLIDER_COUNT) { + slider->draw_texture_rect(color_picker->get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), Rect2(Point2(0, 0), Size2(size.x, margin)), true); + + left_color = color; + left_color.a = 0; + right_color = color; + right_color.a = 1; + } else { + left_color.set_ok_hsl(color.get_ok_hsl_h(), 0, color.get_ok_hsl_l()); + right_color.set_ok_hsl(color.get_ok_hsl_h(), 1, color.get_ok_hsl_l()); + } + + col.set(0, left_color); + col.set(1, right_color); + col.set(2, right_color); + col.set(3, left_color); + pos.set(0, Vector2(0, 0)); + pos.set(1, Vector2(size.x, 0)); + pos.set(2, Vector2(size.x, margin)); + pos.set(3, Vector2(0, margin)); + } slider->draw_polygon(pos, col); } diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index a2c138c0b2..1009b36584 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -744,7 +744,7 @@ void ColorPicker::add_recent_preset(const Color &p_color) { if (recent_preset_hbc->get_child_count() >= PRESET_COLUMN_COUNT) { recent_preset_cache.pop_front(); recent_presets.pop_front(); - recent_preset_hbc->get_child(PRESET_COLUMN_COUNT - 1)->queue_delete(); + recent_preset_hbc->get_child(PRESET_COLUMN_COUNT - 1)->queue_free(); } recent_presets.push_back(p_color); recent_preset_cache.push_back(p_color); @@ -770,7 +770,7 @@ void ColorPicker::erase_preset(const Color &p_color) { for (int i = 1; i < preset_container->get_child_count(); i++) { ColorPresetButton *current_btn = Object::cast_to<ColorPresetButton>(preset_container->get_child(i)); if (current_btn && p_color == current_btn->get_preset_color()) { - current_btn->queue_delete(); + current_btn->queue_free(); break; } } @@ -794,7 +794,7 @@ void ColorPicker::erase_recent_preset(const Color &p_color) { for (int i = 1; i < recent_preset_hbc->get_child_count(); i++) { ColorPresetButton *current_btn = Object::cast_to<ColorPresetButton>(recent_preset_hbc->get_child(i)); if (current_btn && p_color == current_btn->get_preset_color()) { - current_btn->queue_delete(); + current_btn->queue_free(); break; } } @@ -1087,16 +1087,24 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { Vector<Color> colors; Color col; col.set_ok_hsl(h, s, 1); - points.resize(4); - colors.resize(4); - points.set(0, Vector2()); - points.set(1, Vector2(c->get_size().x, 0)); + Color col2; + col2.set_ok_hsl(h, s, 0.5); + Color col3; + col3.set_ok_hsl(h, s, 0); + points.resize(6); + colors.resize(6); + points.set(0, Vector2(c->get_size().x, 0)); + points.set(1, Vector2(c->get_size().x, c->get_size().y * 0.5)); points.set(2, c->get_size()); points.set(3, Vector2(0, c->get_size().y)); + points.set(4, Vector2(0, c->get_size().y * 0.5)); + points.set(5, Vector2()); colors.set(0, col); - colors.set(1, col); - colors.set(2, Color(0, 0, 0)); - colors.set(3, Color(0, 0, 0)); + colors.set(1, col2); + colors.set(2, col3); + colors.set(3, col3); + colors.set(4, col2); + colors.set(5, col); c->draw_polygon(points, colors); int y = c->get_size().y - c->get_size().y * CLAMP(v, 0, 1); col.set_ok_hsl(h, 1, v); @@ -1367,7 +1375,7 @@ void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) { Ref<Image> img = r->get_texture()->get_image(); if (img.is_valid() && !img->is_empty()) { - Vector2 ofs = mev->get_global_position() - r->get_visible_rect().get_position(); + Vector2 ofs = mev->get_global_position(); Color c = img->get_pixel(ofs.x, ofs.y); set_pick_color(c); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 565e450d60..2ec0a48278 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -1436,13 +1436,6 @@ Rect2 Control::get_screen_rect() const { return r; } -Rect2 Control::get_window_rect() const { - ERR_FAIL_COND_V(!is_inside_tree(), Rect2()); - Rect2 gr = get_global_rect(); - gr.position += get_viewport()->get_visible_rect().position; - return gr; -} - Rect2 Control::get_anchorable_rect() const { return Rect2(Point2(), get_size()); } @@ -1564,7 +1557,7 @@ Size2 Control::get_minimum_size() const { return Vector2(); } -void Control::set_custom_minimum_size(const Size2i &p_custom) { +void Control::set_custom_minimum_size(const Size2 &p_custom) { if (p_custom == data.custom_minimum_size) { return; } @@ -1572,7 +1565,7 @@ void Control::set_custom_minimum_size(const Size2i &p_custom) { update_minimum_size(); } -Size2i Control::get_custom_minimum_size() const { +Size2 Control::get_custom_minimum_size() const { return data.custom_minimum_size; } @@ -3175,7 +3168,7 @@ void Control::_bind_methods() { ADD_GROUP("Layout", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_contents"), "set_clip_contents", "is_clipping_contents"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "custom_minimum_size", PROPERTY_HINT_NONE, "suffix:px"), "set_custom_minimum_size", "get_custom_minimum_size"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "custom_minimum_size", PROPERTY_HINT_NONE, "suffix:px"), "set_custom_minimum_size", "get_custom_minimum_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_direction", PROPERTY_HINT_ENUM, "Inherited,Locale,Left-to-Right,Right-to-Left"), "set_layout_direction", "get_layout_direction"); ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_mode", PROPERTY_HINT_ENUM, "Position,Anchors,Container,Uncontrolled", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "_set_layout_mode", "_get_layout_mode"); ADD_PROPERTY_DEFAULT("layout_mode", LayoutMode::LAYOUT_MODE_POSITION); diff --git a/scene/gui/control.h b/scene/gui/control.h index e526690cbe..72e870930d 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -201,7 +201,7 @@ private: int h_size_flags = SIZE_FILL; int v_size_flags = SIZE_FILL; real_t expand = 1.0; - Point2i custom_minimum_size; + Point2 custom_minimum_size; // Input events and rendering. @@ -445,7 +445,6 @@ public: Rect2 get_rect() const; Rect2 get_global_rect() const; Rect2 get_screen_rect() const; - Rect2 get_window_rect() const; ///< use with care, as it blocks waiting for the rendering server Rect2 get_anchorable_rect() const override; void set_scale(const Vector2 &p_scale); @@ -463,8 +462,8 @@ public: virtual Size2 get_minimum_size() const; virtual Size2 get_combined_minimum_size() const; - void set_custom_minimum_size(const Size2i &p_custom); - Size2i get_custom_minimum_size() const; + void set_custom_minimum_size(const Size2 &p_custom); + Size2 get_custom_minimum_size() const; // Container sizing. diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index c96d3c763d..1167dbec54 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -1087,7 +1087,6 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o _draw_fbg_boxes(ci, rid, fbg_line_off, it_from, it_to, chr_range.x, chr_range.y, 0); // Draw main text. - Color selection_fg = theme_cache.font_selected_color; Color selection_bg = theme_cache.selection_color; int sel_start = -1; @@ -1276,8 +1275,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o } } - if (selected) { - font_color = override_selected_font_color ? selection_fg : font_color; + if (selected && use_selected_font_color) { + font_color = theme_cache.font_selected_color; } // Draw glyphs. @@ -1286,9 +1285,9 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o if (txt_visible) { if (!skip) { if (frid != RID()) { - TS->font_draw_glyph(frid, ci, glyphs[i].font_size, p_ofs + fx_offset + off, gl, selected ? selection_fg : font_color); + TS->font_draw_glyph(frid, ci, glyphs[i].font_size, p_ofs + fx_offset + off, gl, font_color); } else if ((glyphs[i].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) { - TS->draw_hex_code_box(ci, glyphs[i].font_size, p_ofs + fx_offset + off, gl, selected ? selection_fg : font_color); + TS->draw_hex_code_box(ci, glyphs[i].font_size, p_ofs + fx_offset + off, gl, font_color); } } r_processed_glyphs++; @@ -1688,6 +1687,7 @@ void RichTextLabel::_update_theme_item_cache() { theme_cache.default_color = get_theme_color(SNAME("default_color")); theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color")); + use_selected_font_color = theme_cache.font_selected_color != Color(0, 0, 0, 0); theme_cache.selection_color = get_theme_color(SNAME("selection_color")); theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color")); theme_cache.font_shadow_color = get_theme_color(SNAME("font_shadow_color")); @@ -3564,14 +3564,6 @@ bool RichTextLabel::is_hint_underlined() const { return underline_hint; } -void RichTextLabel::set_override_selected_font_color(bool p_override_selected_font_color) { - override_selected_font_color = p_override_selected_font_color; -} - -bool RichTextLabel::is_overriding_selected_font_color() const { - return override_selected_font_color; -} - void RichTextLabel::set_offset(int p_pixel) { vscroll->set_value(p_pixel); } @@ -5294,9 +5286,6 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("set_hint_underline", "enable"), &RichTextLabel::set_hint_underline); ClassDB::bind_method(D_METHOD("is_hint_underlined"), &RichTextLabel::is_hint_underlined); - ClassDB::bind_method(D_METHOD("set_override_selected_font_color", "override"), &RichTextLabel::set_override_selected_font_color); - ClassDB::bind_method(D_METHOD("is_overriding_selected_font_color"), &RichTextLabel::is_overriding_selected_font_color); - ClassDB::bind_method(D_METHOD("set_scroll_active", "active"), &RichTextLabel::set_scroll_active); ClassDB::bind_method(D_METHOD("is_scroll_active"), &RichTextLabel::is_scroll_active); @@ -5406,7 +5395,6 @@ void RichTextLabel::_bind_methods() { ADD_GROUP("Text Selection", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selection_enabled"), "set_selection_enabled", "is_selection_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deselect_on_focus_loss_enabled"), "set_deselect_on_focus_loss_enabled", "is_deselect_on_focus_loss_enabled"); ADD_GROUP("Displayed Text", ""); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 04a682349d..d30baaa8d3 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -396,7 +396,7 @@ private: int tab_size = 4; bool underline_meta = true; bool underline_hint = true; - bool override_selected_font_color = false; + bool use_selected_font_color = false; HorizontalAlignment default_alignment = HORIZONTAL_ALIGNMENT_LEFT; diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index 193c6f1ce7..6899178885 100644 --- a/scene/gui/scroll_bar.cpp +++ b/scene/gui/scroll_bar.cpp @@ -338,7 +338,7 @@ void ScrollBar::_notification(int p_what) { if (scrolling) { if (get_value() != target_scroll) { double target = target_scroll - get_value(); - double dist = sqrt(target * target); + double dist = abs(target); double vel = ((target / dist) * 500) * get_physics_process_delta_time(); if (Math::abs(vel) >= dist) { diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 4cd244306c..144aa2a1ef 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -464,7 +464,7 @@ void TextEdit::_notification(int p_what) { case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { if (scrolling && get_v_scroll() != target_v_scroll) { double target_y = target_v_scroll - get_v_scroll(); - double dist = sqrt(target_y * target_y); + double dist = abs(target_y); // To ensure minimap is responsive override the speed setting. double vel = ((target_y / dist) * ((minimap_clicked) ? 3000 : v_scroll_speed)) * get_physics_process_delta_time(); @@ -1219,7 +1219,7 @@ void TextEdit::_notification(int p_what) { int sel_from = (line > get_selection_from_line(c)) ? TS->shaped_text_get_range(rid).x : get_selection_from_column(c); int sel_to = (line < get_selection_to_line(c)) ? TS->shaped_text_get_range(rid).y : get_selection_to_column(c); - if (glyphs[j].start >= sel_from && glyphs[j].end <= sel_to && override_selected_font_color) { + if (glyphs[j].start >= sel_from && glyphs[j].end <= sel_to && use_selected_font_color) { gl_color = font_selected_color; } } @@ -2051,7 +2051,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } if (is_shortcut_keys_enabled()) { - // SELECT ALL, SELECT WORD UNDER CARET, CUT, COPY, PASTE. + // SELECT ALL, SELECT WORD UNDER CARET, ADD SELECTION FOR NEXT OCCURRENCE, CUT, COPY, PASTE. if (k->is_action("ui_text_select_all", true)) { select_all(); accept_event(); @@ -2062,6 +2062,11 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { accept_event(); return; } + if (k->is_action("ui_text_add_selection_for_next_occurrence", true)) { + add_selection_for_next_occurrence(); + accept_event(); + return; + } if (k->is_action("ui_cut", true)) { cut(); accept_event(); @@ -2089,6 +2094,17 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { accept_event(); return; } + + if (k->is_action("ui_text_caret_add_below", true)) { + add_caret_at_carets(true); + accept_event(); + return; + } + if (k->is_action("ui_text_caret_add_above", true)) { + add_caret_at_carets(false); + accept_event(); + return; + } } // MISC. @@ -2803,6 +2819,51 @@ void TextEdit::_move_caret_document_end(bool p_select) { } } +void TextEdit::_get_above_below_caret_line_column(int p_old_line, int p_old_wrap_index, int p_old_column, bool p_below, int &p_new_line, int &p_new_column, int p_last_fit_x) const { + if (p_last_fit_x == -1) { + p_last_fit_x = _get_column_x_offset_for_line(p_old_column, p_old_line, p_old_column); + } + + // Calculate the new line and wrap index + p_new_line = p_old_line; + int caret_wrap_index = p_old_wrap_index; + if (p_below) { + if (caret_wrap_index < get_line_wrap_count(p_new_line)) { + caret_wrap_index++; + } else { + p_new_line++; + caret_wrap_index = 0; + } + } else { + if (caret_wrap_index == 0) { + p_new_line--; + caret_wrap_index = get_line_wrap_count(p_new_line); + } else { + caret_wrap_index--; + } + } + + // Boundary checks + if (p_new_line < 0) { + p_new_line = 0; + } + if (p_new_line >= text.size()) { + p_new_line = text.size() - 1; + } + + p_new_column = _get_char_pos_for_line(p_last_fit_x, p_new_line, caret_wrap_index); + if (p_new_column != 0 && get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE && caret_wrap_index < get_line_wrap_count(p_new_line)) { + Vector<String> rows = get_line_wrapped_text(p_new_line); + int row_end_col = 0; + for (int i = 0; i < caret_wrap_index + 1; i++) { + row_end_col += rows[i].length(); + } + if (p_new_column >= row_end_col) { + p_new_column -= 1; + } + } +} + void TextEdit::_update_placeholder() { if (font.is_null() || font_size <= 0) { return; // Not in tree? @@ -2861,6 +2922,7 @@ void TextEdit::_update_caches() { /* Selection */ font_selected_color = get_theme_color(SNAME("font_selected_color")); selection_color = get_theme_color(SNAME("selection_color")); + use_selected_font_color = font_selected_color != Color(0, 0, 0, 0); /* Visual. */ style_normal = get_theme_stylebox(SNAME("normal")); @@ -3810,6 +3872,9 @@ void TextEdit::undo() { return; } + if (in_action) { + pending_action_end = true; + } _push_current_op(); if (undo_stack_pos == nullptr) { @@ -3863,7 +3928,7 @@ void TextEdit::undo() { } caret_pos_dirty = true; } - queue_redraw(); + adjust_viewport_to_caret(); } void TextEdit::redo() { @@ -3871,6 +3936,9 @@ void TextEdit::redo() { return; } + if (in_action) { + pending_action_end = true; + } _push_current_op(); if (undo_stack_pos == nullptr) { @@ -3915,7 +3983,7 @@ void TextEdit::redo() { } caret_pos_dirty = true; } - queue_redraw(); + adjust_viewport_to_caret(); } void TextEdit::clear_undo_history() { @@ -4504,6 +4572,68 @@ int TextEdit::get_caret_count() const { return carets.size(); } +void TextEdit::add_caret_at_carets(bool p_below) { + Vector<int> caret_edit_order = get_caret_index_edit_order(); + for (const int &caret_index : caret_edit_order) { + const int caret_line = get_caret_line(caret_index); + const int caret_column = get_caret_column(caret_index); + + // The last fit x will be cleared if the caret has a selection, + // but if it does not have a selection the last fit x will be + // transferred to the new caret + int caret_from_column = 0, caret_to_column = 0, caret_last_fit_x = carets[caret_index].last_fit_x; + if (has_selection(caret_index)) { + // If the selection goes over multiple lines, deselect it. + if (get_selection_from_line(caret_index) != get_selection_to_line(caret_index)) { + deselect(caret_index); + } else { + caret_from_column = get_selection_from_column(caret_index); + caret_to_column = get_selection_to_column(caret_index); + caret_last_fit_x = -1; + carets.write[caret_index].last_fit_x = _get_column_x_offset_for_line(caret_column, caret_line, caret_column); + } + } + + // Get the line and column of the new caret as if you would move the caret by pressing the arrow keys + int new_caret_line, new_caret_column, new_caret_from_column = 0, new_caret_to_column = 0; + _get_above_below_caret_line_column(caret_line, get_caret_wrap_index(caret_index), caret_column, p_below, new_caret_line, new_caret_column, caret_last_fit_x); + + // If the caret does have a selection calculate the new from and to columns + if (caret_from_column != caret_to_column) { + // We only need to calculate the selection columns if the column of the caret changed + if (caret_column != new_caret_column) { + int _; // unused placeholder for p_new_line + _get_above_below_caret_line_column(caret_line, get_caret_wrap_index(caret_index), caret_from_column, p_below, _, new_caret_from_column); + _get_above_below_caret_line_column(caret_line, get_caret_wrap_index(caret_index), caret_to_column, p_below, _, new_caret_to_column); + } else { + new_caret_from_column = caret_from_column; + new_caret_to_column = caret_to_column; + } + } + + // Add the new caret + const int new_caret_index = add_caret(new_caret_line, new_caret_column); + + if (new_caret_index == -1) { + continue; + } + // Also add the selection if there should be one + if (new_caret_from_column != new_caret_to_column) { + select(new_caret_line, new_caret_from_column, new_caret_line, new_caret_to_column, new_caret_index); + // Necessary to properly modify the selection after adding the new caret + carets.write[new_caret_index].selection.selecting_line = new_caret_line; + carets.write[new_caret_index].selection.selecting_column = new_caret_column == new_caret_from_column ? new_caret_to_column : new_caret_from_column; + continue; + } + + // Copy the last fit x over + carets.write[new_caret_index].last_fit_x = carets[caret_index].last_fit_x; + } + + merge_overlapping_carets(); + queue_redraw(); +} + Vector<int> TextEdit::get_caret_index_edit_order() { if (!caret_index_edit_dirty) { return caret_index_edit_order; @@ -4739,14 +4869,6 @@ bool TextEdit::is_drag_and_drop_selection_enabled() const { return drag_and_drop_selection_enabled; } -void TextEdit::set_override_selected_font_color(bool p_override_selected_font_color) { - override_selected_font_color = p_override_selected_font_color; -} - -bool TextEdit::is_overriding_selected_font_color() const { - return override_selected_font_color; -} - void TextEdit::set_selection_mode(SelectionMode p_mode, int p_line, int p_column, int p_caret) { ERR_FAIL_INDEX(p_caret, carets.size()); @@ -4832,6 +4954,45 @@ void TextEdit::select_word_under_caret(int p_caret) { merge_overlapping_carets(); } +void TextEdit::add_selection_for_next_occurrence() { + if (!selecting_enabled || !is_multiple_carets_enabled()) { + return; + } + + if (text.size() == 1 && text[0].length() == 0) { + return; + } + + // Always use the last caret, to correctly search for + // the next occurrence that comes after this caret. + int caret = get_caret_count() - 1; + + if (!has_selection(caret)) { + select_word_under_caret(caret); + return; + } + + const String &highlighted_text = get_selected_text(caret); + int column = get_selection_from_column(caret) + 1; + int line = get_caret_line(caret); + + const Point2i next_occurrence = search(highlighted_text, SEARCH_MATCH_CASE, line, column); + + if (next_occurrence.x == -1 || next_occurrence.y == -1) { + return; + } + + int to_column = get_selection_to_column(caret) + 1; + int end = next_occurrence.x + (to_column - column); + int new_caret = add_caret(next_occurrence.y, end); + + if (new_caret != -1) { + select(next_occurrence.y, next_occurrence.x, next_occurrence.y, end, new_caret); + adjust_viewport_to_caret(new_caret); + merge_overlapping_carets(); + } +} + void TextEdit::select(int p_from_line, int p_from_column, int p_to_line, int p_to_column, int p_caret) { ERR_FAIL_INDEX(p_caret, carets.size()); if (!selecting_enabled) { @@ -5959,6 +6120,7 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("remove_secondary_carets"), &TextEdit::remove_secondary_carets); ClassDB::bind_method(D_METHOD("merge_overlapping_carets"), &TextEdit::merge_overlapping_carets); ClassDB::bind_method(D_METHOD("get_caret_count"), &TextEdit::get_caret_count); + ClassDB::bind_method(D_METHOD("add_caret_at_carets", "below"), &TextEdit::add_caret_at_carets); ClassDB::bind_method(D_METHOD("get_caret_index_edit_order"), &TextEdit::get_caret_index_edit_order); ClassDB::bind_method(D_METHOD("adjust_carets_after_edit", "caret", "from_line", "from_col", "to_line", "to_col"), &TextEdit::adjust_carets_after_edit); @@ -5992,14 +6154,12 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("set_drag_and_drop_selection_enabled", "enable"), &TextEdit::set_drag_and_drop_selection_enabled); ClassDB::bind_method(D_METHOD("is_drag_and_drop_selection_enabled"), &TextEdit::is_drag_and_drop_selection_enabled); - ClassDB::bind_method(D_METHOD("set_override_selected_font_color", "override"), &TextEdit::set_override_selected_font_color); - ClassDB::bind_method(D_METHOD("is_overriding_selected_font_color"), &TextEdit::is_overriding_selected_font_color); - ClassDB::bind_method(D_METHOD("set_selection_mode", "mode", "line", "column", "caret_index"), &TextEdit::set_selection_mode, DEFVAL(-1), DEFVAL(-1), DEFVAL(0)); ClassDB::bind_method(D_METHOD("get_selection_mode"), &TextEdit::get_selection_mode); ClassDB::bind_method(D_METHOD("select_all"), &TextEdit::select_all); ClassDB::bind_method(D_METHOD("select_word_under_caret", "caret_index"), &TextEdit::select_word_under_caret, DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("add_selection_for_next_occurrence"), &TextEdit::add_selection_for_next_occurrence); ClassDB::bind_method(D_METHOD("select", "from_line", "from_column", "to_line", "to_column", "caret_index"), &TextEdit::select, DEFVAL(0)); ClassDB::bind_method(D_METHOD("has_selection", "caret_index"), &TextEdit::has_selection, DEFVAL(-1)); @@ -6163,7 +6323,6 @@ void TextEdit::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "middle_mouse_paste_enabled"), "set_middle_mouse_paste_enabled", "is_middle_mouse_paste_enabled"); ADD_PROPERTY(PropertyInfo(Variant::INT, "wrap_mode", PROPERTY_HINT_ENUM, "None,Boundary"), "set_line_wrapping_mode", "get_line_wrapping_mode"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), "set_highlight_all_occurrences", "is_highlight_all_occurrences_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_current_line"), "set_highlight_current_line", "is_highlight_current_line_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_control_chars"), "set_draw_control_chars", "get_draw_control_chars"); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index e4af621b73..935f2a7ce8 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -443,9 +443,9 @@ private: bool deselect_on_focus_loss_enabled = true; bool drag_and_drop_selection_enabled = true; - Color font_selected_color = Color(1, 1, 1); + Color font_selected_color = Color(0, 0, 0, 0); Color selection_color = Color(1, 1, 1); - bool override_selected_font_color = false; + bool use_selected_font_color = false; bool selection_drag_attempt = false; bool dragging_selection = false; @@ -598,6 +598,9 @@ private: void _move_caret_document_start(bool p_select); void _move_caret_document_end(bool p_select); + // Used in add_caret_at_carets + void _get_above_below_caret_line_column(int p_old_line, int p_old_wrap_index, int p_old_column, bool p_below, int &p_new_line, int &p_new_column, int p_last_fit_x = -1) const; + protected: void _notification(int p_what); @@ -816,6 +819,7 @@ public: void remove_secondary_carets(); void merge_overlapping_carets(); int get_caret_count() const; + void add_caret_at_carets(bool p_below); Vector<int> get_caret_index_edit_order(); void adjust_carets_after_edit(int p_caret, int p_from_line, int p_from_col, int p_to_line, int p_to_col); @@ -851,6 +855,7 @@ public: void select_all(); void select_word_under_caret(int p_caret = -1); + void add_selection_for_next_occurrence(); void select(int p_from_line, int p_from_column, int p_to_line, int p_to_column, int p_caret = 0); bool has_selection(int p_caret = -1) const; diff --git a/scene/gui/texture_progress_bar.cpp b/scene/gui/texture_progress_bar.cpp index a9982b3ece..48c6dc5cfc 100644 --- a/scene/gui/texture_progress_bar.cpp +++ b/scene/gui/texture_progress_bar.cpp @@ -510,18 +510,38 @@ void TextureProgressBar::_notification(int p_what) { } pts.append(to); + Ref<AtlasTexture> atlas_progress = progress; + bool valid_atlas_progress = atlas_progress.is_valid() && atlas_progress->get_atlas().is_valid(); + Rect2 region_rect; + Size2 atlas_size; + if (valid_atlas_progress) { + region_rect = atlas_progress->get_region(); + atlas_size = atlas_progress->get_atlas()->get_size(); + } + Vector<Point2> uvs; Vector<Point2> points; - uvs.push_back(get_relative_center()); - points.push_back(progress_offset + s * get_relative_center()); for (int i = 0; i < pts.size(); i++) { Point2 uv = unit_val_to_uv(pts[i]); if (uvs.find(uv) >= 0) { continue; } - uvs.push_back(uv); points.push_back(progress_offset + Point2(uv.x * s.x, uv.y * s.y)); + if (valid_atlas_progress) { + uv.x = Math::remap(uv.x, 0, 1, region_rect.position.x / atlas_size.x, (region_rect.position.x + region_rect.size.x) / atlas_size.x); + uv.y = Math::remap(uv.y, 0, 1, region_rect.position.y / atlas_size.y, (region_rect.position.y + region_rect.size.y) / atlas_size.y); + } + uvs.push_back(uv); + } + + Point2 center_point = get_relative_center(); + points.push_back(progress_offset + s * center_point); + if (valid_atlas_progress) { + center_point.x = Math::remap(center_point.x, 0, 1, region_rect.position.x / atlas_size.x, (region_rect.position.x + region_rect.size.x) / atlas_size.x); + center_point.y = Math::remap(center_point.y, 0, 1, region_rect.position.y / atlas_size.y, (region_rect.position.y + region_rect.size.y) / atlas_size.y); } + uvs.push_back(center_point); + Vector<Color> colors; colors.push_back(tint_progress); draw_polygon(points, colors, uvs, progress); diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 05d86f77f2..840913d466 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -986,8 +986,8 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("set_texture_repeat", "mode"), &CanvasItem::set_texture_repeat); ClassDB::bind_method(D_METHOD("get_texture_repeat"), &CanvasItem::get_texture_repeat); - ClassDB::bind_method(D_METHOD("set_clip_children", "enable"), &CanvasItem::set_clip_children); - ClassDB::bind_method(D_METHOD("is_clipping_children"), &CanvasItem::is_clipping_children); + ClassDB::bind_method(D_METHOD("set_clip_children_mode", "mode"), &CanvasItem::set_clip_children_mode); + ClassDB::bind_method(D_METHOD("get_clip_children_mode"), &CanvasItem::get_clip_children_mode); GDVIRTUAL_BIND(_draw); @@ -997,7 +997,7 @@ void CanvasItem::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::COLOR, "self_modulate"), "set_self_modulate", "get_self_modulate"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_behind_parent"), "set_draw_behind_parent", "is_draw_behind_parent_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "top_level"), "set_as_top_level", "is_set_as_top_level"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_children"), "set_clip_children", "is_clipping_children"); + 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_GROUP("Texture", "texture_"); @@ -1035,6 +1035,11 @@ void CanvasItem::_bind_methods() { BIND_ENUM_CONSTANT(TEXTURE_REPEAT_ENABLED); BIND_ENUM_CONSTANT(TEXTURE_REPEAT_MIRROR); BIND_ENUM_CONSTANT(TEXTURE_REPEAT_MAX); + + BIND_ENUM_CONSTANT(CLIP_CHILDREN_DISABLED); + BIND_ENUM_CONSTANT(CLIP_CHILDREN_ONLY); + BIND_ENUM_CONSTANT(CLIP_CHILDREN_AND_DRAW); + BIND_ENUM_CONSTANT(CLIP_CHILDREN_MAX); } Transform2D CanvasItem::get_canvas_transform() const { @@ -1092,7 +1097,7 @@ int CanvasItem::get_canvas_layer() const { } } -void CanvasItem::_update_texture_filter_changed(bool p_propagate) { +void CanvasItem::_refresh_texture_filter_cache() { if (!is_inside_tree()) { return; } @@ -1107,6 +1112,14 @@ void CanvasItem::_update_texture_filter_changed(bool p_propagate) { } else { texture_filter_cache = RS::CanvasItemTextureFilter(texture_filter); } +} + +void CanvasItem::_update_texture_filter_changed(bool p_propagate) { + if (!is_inside_tree()) { + return; + } + _refresh_texture_filter_cache(); + RS::get_singleton()->canvas_item_set_default_texture_filter(get_canvas_item(), texture_filter_cache); queue_redraw(); @@ -1133,7 +1146,7 @@ CanvasItem::TextureFilter CanvasItem::get_texture_filter() const { return texture_filter; } -void CanvasItem::_update_texture_repeat_changed(bool p_propagate) { +void CanvasItem::_refresh_texture_repeat_cache() { if (!is_inside_tree()) { return; } @@ -1148,6 +1161,14 @@ void CanvasItem::_update_texture_repeat_changed(bool p_propagate) { } else { texture_repeat_cache = RS::CanvasItemTextureRepeat(texture_repeat); } +} + +void CanvasItem::_update_texture_repeat_changed(bool p_propagate) { + if (!is_inside_tree()) { + return; + } + _refresh_texture_repeat_cache(); + RS::get_singleton()->canvas_item_set_default_texture_repeat(get_canvas_item(), texture_repeat_cache); queue_redraw(); if (p_propagate) { @@ -1169,26 +1190,39 @@ void CanvasItem::set_texture_repeat(TextureRepeat p_texture_repeat) { notify_property_list_changed(); } -void CanvasItem::set_clip_children(bool p_enabled) { - if (clip_children == p_enabled) { +void CanvasItem::set_clip_children_mode(ClipChildrenMode p_clip_mode) { + ERR_FAIL_COND(p_clip_mode >= CLIP_CHILDREN_MAX); + + if (clip_children_mode == p_clip_mode) { return; } - clip_children = p_enabled; + clip_children_mode = p_clip_mode; if (Object::cast_to<CanvasGroup>(this) != nullptr) { //avoid accidental bugs, make this not work on CanvasGroup return; } - RS::get_singleton()->canvas_item_set_canvas_group_mode(get_canvas_item(), clip_children ? RS::CANVAS_GROUP_MODE_OPAQUE : RS::CANVAS_GROUP_MODE_DISABLED); + + RS::get_singleton()->canvas_item_set_canvas_group_mode(get_canvas_item(), RS::CanvasGroupMode(clip_children_mode)); } -bool CanvasItem::is_clipping_children() const { - return clip_children; +CanvasItem::ClipChildrenMode CanvasItem::get_clip_children_mode() const { + return clip_children_mode; } CanvasItem::TextureRepeat CanvasItem::get_texture_repeat() const { return texture_repeat; } +CanvasItem::TextureFilter CanvasItem::get_texture_filter_in_tree() { + _refresh_texture_filter_cache(); + return (TextureFilter)texture_filter_cache; +} + +CanvasItem::TextureRepeat CanvasItem::get_texture_repeat_in_tree() { + _refresh_texture_repeat_cache(); + return (TextureRepeat)texture_repeat_cache; +} + CanvasItem::CanvasItem() : xform_change(this) { canvas_item = RenderingServer::get_singleton()->canvas_item_create(); diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index b80289fdb4..565ea930ce 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -66,8 +66,16 @@ public: TEXTURE_REPEAT_MAX, }; + enum ClipChildrenMode { + CLIP_CHILDREN_DISABLED, + CLIP_CHILDREN_ONLY, + CLIP_CHILDREN_AND_DRAW, + CLIP_CHILDREN_MAX, + }; + private: - mutable SelfList<Node> xform_change; + mutable SelfList<Node> + xform_change; RID canvas_item; StringName canvas_group; @@ -85,7 +93,6 @@ private: Window *window = nullptr; bool visible = true; bool parent_visible_in_tree = false; - bool clip_children = false; bool pending_update = false; bool top_level = false; bool drawing = false; @@ -95,6 +102,8 @@ private: bool notify_local_transform = false; bool notify_transform = false; + ClipChildrenMode clip_children_mode = CLIP_CHILDREN_DISABLED; + RS::CanvasItemTextureFilter texture_filter_cache = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; RS::CanvasItemTextureRepeat texture_repeat_cache = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; TextureFilter texture_filter = TEXTURE_FILTER_PARENT_NODE; @@ -121,7 +130,9 @@ private: static CanvasItem *current_item_drawn; friend class Viewport; + void _refresh_texture_repeat_cache(); void _update_texture_repeat_changed(bool p_propagate); + void _refresh_texture_filter_cache(); void _update_texture_filter_changed(bool p_propagate); protected: @@ -200,8 +211,8 @@ public: void queue_redraw(); void move_to_front(); - void set_clip_children(bool p_enabled); - bool is_clipping_children() const; + void set_clip_children_mode(ClipChildrenMode p_clip_mode); + ClipChildrenMode get_clip_children_mode() const; virtual void set_light_mask(int p_light_mask); int get_light_mask() const; @@ -310,6 +321,9 @@ public: virtual void set_texture_repeat(TextureRepeat p_texture_repeat); TextureRepeat get_texture_repeat() const; + TextureFilter get_texture_filter_in_tree(); + TextureRepeat get_texture_repeat_in_tree(); + // Used by control nodes to retrieve the parent's anchorable area virtual Rect2 get_anchorable_rect() const { return Rect2(0, 0, 0, 0); }; @@ -321,6 +335,7 @@ public: VARIANT_ENUM_CAST(CanvasItem::TextureFilter) VARIANT_ENUM_CAST(CanvasItem::TextureRepeat) +VARIANT_ENUM_CAST(CanvasItem::ClipChildrenMode) class CanvasTexture : public Texture2D { GDCLASS(CanvasTexture, Texture2D); diff --git a/scene/main/instance_placeholder.cpp b/scene/main/instance_placeholder.cpp index 6dd83e4636..56e719968b 100644 --- a/scene/main/instance_placeholder.cpp +++ b/scene/main/instance_placeholder.cpp @@ -100,7 +100,7 @@ Node *InstancePlaceholder::create_instance(bool p_replace, const Ref<PackedScene } if (p_replace) { - queue_delete(); + queue_free(); base->remove_child(this); } diff --git a/scene/main/multiplayer_peer.cpp b/scene/main/multiplayer_peer.cpp index 9b63118f7c..462dc1babb 100644 --- a/scene/main/multiplayer_peer.cpp +++ b/scene/main/multiplayer_peer.cpp @@ -78,6 +78,10 @@ bool MultiplayerPeer::is_refusing_new_connections() const { return refuse_connections; } +bool MultiplayerPeer::is_server_relay_supported() const { + return false; +} + void MultiplayerPeer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_transfer_channel", "channel"), &MultiplayerPeer::set_transfer_channel); ClassDB::bind_method(D_METHOD("get_transfer_channel"), &MultiplayerPeer::get_transfer_channel); @@ -86,6 +90,8 @@ void MultiplayerPeer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_target_peer", "id"), &MultiplayerPeer::set_target_peer); ClassDB::bind_method(D_METHOD("get_packet_peer"), &MultiplayerPeer::get_packet_peer); + ClassDB::bind_method(D_METHOD("get_packet_channel"), &MultiplayerPeer::get_packet_channel); + ClassDB::bind_method(D_METHOD("get_packet_mode"), &MultiplayerPeer::get_packet_mode); ClassDB::bind_method(D_METHOD("poll"), &MultiplayerPeer::poll); @@ -96,6 +102,8 @@ void MultiplayerPeer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_refuse_new_connections", "enable"), &MultiplayerPeer::set_refuse_new_connections); ClassDB::bind_method(D_METHOD("is_refusing_new_connections"), &MultiplayerPeer::is_refusing_new_connections); + ClassDB::bind_method(D_METHOD("is_server_relay_supported"), &MultiplayerPeer::is_server_relay_supported); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_connections"), "set_refuse_new_connections", "is_refusing_new_connections"); ADD_PROPERTY(PropertyInfo(Variant::INT, "transfer_mode", PROPERTY_HINT_ENUM, "Unreliable,Unreliable Ordered,Reliable"), "set_transfer_mode", "get_transfer_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "transfer_channel", PROPERTY_HINT_RANGE, "0,255,1"), "set_transfer_channel", "get_transfer_channel"); @@ -177,6 +185,14 @@ bool MultiplayerPeerExtension::is_refusing_new_connections() const { return MultiplayerPeer::is_refusing_new_connections(); } +bool MultiplayerPeerExtension::is_server_relay_supported() const { + bool can_relay; + if (GDVIRTUAL_CALL(_is_server_relay_supported, can_relay)) { + return can_relay; + } + return MultiplayerPeer::is_server_relay_supported(); +} + void MultiplayerPeerExtension::_bind_methods() { GDVIRTUAL_BIND(_get_packet, "r_buffer", "r_buffer_size"); GDVIRTUAL_BIND(_put_packet, "p_buffer", "p_buffer_size"); diff --git a/scene/main/multiplayer_peer.h b/scene/main/multiplayer_peer.h index ab7483ece5..63ce66871e 100644 --- a/scene/main/multiplayer_peer.h +++ b/scene/main/multiplayer_peer.h @@ -74,10 +74,13 @@ public: virtual TransferMode get_transfer_mode() const; virtual void set_refuse_new_connections(bool p_enable); virtual bool is_refusing_new_connections() const; + virtual bool is_server_relay_supported() const; virtual void set_target_peer(int p_peer_id) = 0; virtual int get_packet_peer() const = 0; + virtual TransferMode get_packet_mode() const = 0; + virtual int get_packet_channel() const = 0; virtual bool is_server() const = 0; @@ -123,12 +126,17 @@ public: virtual bool is_refusing_new_connections() const override; GDVIRTUAL0RC(bool, _is_refusing_new_connections); // Optional. + virtual bool is_server_relay_supported() const override; + GDVIRTUAL0RC(bool, _is_server_relay_supported); // Optional. + EXBIND1(set_transfer_channel, int); EXBIND0RC(int, get_transfer_channel); EXBIND1(set_transfer_mode, TransferMode); EXBIND0RC(TransferMode, get_transfer_mode); EXBIND1(set_target_peer, int); EXBIND0RC(int, get_packet_peer); + EXBIND0RC(TransferMode, get_packet_mode); + EXBIND0RC(int, get_packet_channel); EXBIND0RC(bool, is_server); EXBIND0(poll); EXBIND0RC(int, get_unique_id); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 2ea45df309..038f182e8b 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1341,12 +1341,23 @@ Node *Node::get_node(const NodePath &p_path) const { Node *node = get_node_or_null(p_path); if (unlikely(!node)) { + // Try to get a clear description of this node in the error message. + String desc; + if (is_inside_tree()) { + desc = get_path(); + } else { + desc = get_name(); + if (desc.is_empty()) { + desc = get_class(); + } + } + if (p_path.is_absolute()) { ERR_FAIL_V_MSG(nullptr, - vformat(R"(Node not found: "%s" (absolute path attempted from "%s").)", p_path, get_path())); + vformat(R"(Node not found: "%s" (absolute path attempted from "%s").)", p_path, desc)); } else { ERR_FAIL_V_MSG(nullptr, - vformat(R"(Node not found: "%s" (relative to "%s").)", p_path, get_path())); + vformat(R"(Node not found: "%s" (relative to "%s").)", p_path, desc)); } } @@ -2569,7 +2580,7 @@ void Node::print_orphan_nodes() { #endif } -void Node::queue_delete() { +void Node::queue_free() { if (is_inside_tree()) { get_tree()->queue_delete(this); } else { @@ -2811,7 +2822,7 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("get_viewport"), &Node::get_viewport); - ClassDB::bind_method(D_METHOD("queue_free"), &Node::queue_delete); + ClassDB::bind_method(D_METHOD("queue_free"), &Node::queue_free); ClassDB::bind_method(D_METHOD("request_ready"), &Node::request_ready); diff --git a/scene/main/node.h b/scene/main/node.h index c8c8c395ce..4a3ec253b1 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -460,7 +460,7 @@ public: #endif static String adjust_name_casing(const String &p_name); - void queue_delete(); + void queue_free(); //hacks for speed static void init_node_hrcr(); diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 270e5b7025..5ff9a29792 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -896,7 +896,7 @@ void SceneTree::_call_input_pause(const StringName &p_group, CallInputType p_cal call_lock++; - Vector<Node *> no_context_nodes; + Vector<ObjectID> no_context_node_ids; // Nodes may be deleted due to this shortcut input. for (int i = gr_node_count - 1; i >= 0; i--) { if (p_viewport->is_input_handled()) { @@ -922,7 +922,7 @@ void SceneTree::_call_input_pause(const StringName &p_group, CallInputType p_cal // If calling shortcut input on a control, ensure it respects the shortcut context. // Shortcut context (based on focus) only makes sense for controls (UI), so don't need to worry about it for nodes if (c->get_shortcut_context() == nullptr) { - no_context_nodes.append(n); + no_context_node_ids.append(n->get_instance_id()); continue; } if (!c->is_focus_owner_in_shortcut_context()) { @@ -941,8 +941,11 @@ void SceneTree::_call_input_pause(const StringName &p_group, CallInputType p_cal } } - for (Node *n : no_context_nodes) { - n->_call_shortcut_input(p_input); + for (const ObjectID &id : no_context_node_ids) { + Node *n = Object::cast_to<Node>(ObjectDB::get_instance(id)); + if (n) { + n->_call_shortcut_input(p_input); + } } call_lock--; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index f66337a2f9..f395ede409 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1161,7 +1161,7 @@ void Viewport::_gui_cancel_tooltip() { gui.tooltip_timer = Ref<SceneTreeTimer>(); } if (gui.tooltip_popup) { - gui.tooltip_popup->queue_delete(); + gui.tooltip_popup->queue_free(); } } @@ -1263,9 +1263,15 @@ void Viewport::_gui_show_tooltip() { Point2 tooltip_offset = ProjectSettings::get_singleton()->get("display/mouse_cursor/tooltip_position_offset"); Rect2 r(gui.tooltip_pos + tooltip_offset, gui.tooltip_popup->get_contents_minimum_size()); + r.size = r.size.min(panel->get_max_size()); Window *window = gui.tooltip_popup->get_parent_visible_window(); - Rect2i vr = window->get_usable_parent_rect(); + Rect2i vr; + if (gui.tooltip_popup->is_embedded()) { + vr = gui.tooltip_popup->_get_embedder()->get_visible_rect(); + } else { + vr = window->get_usable_parent_rect(); + } if (r.size.x + r.position.x > vr.size.x + vr.position.x) { // Place it in the opposite direction. If it fails, just hug the border. @@ -1403,10 +1409,6 @@ Control *Viewport::gui_find_control(const Point2 &p_global) { } Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_global, const Transform2D &p_xform, Transform2D &r_inv_xform) { - if (Object::cast_to<Viewport>(p_node)) { - return nullptr; - } - if (!p_node->is_visible()) { return nullptr; // Canvas item hidden, discard. } @@ -3729,6 +3731,7 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("set_global_canvas_transform", "xform"), &Viewport::set_global_canvas_transform); ClassDB::bind_method(D_METHOD("get_global_canvas_transform"), &Viewport::get_global_canvas_transform); ClassDB::bind_method(D_METHOD("get_final_transform"), &Viewport::get_final_transform); + ClassDB::bind_method(D_METHOD("get_screen_transform"), &Viewport::get_screen_transform); ClassDB::bind_method(D_METHOD("get_visible_rect"), &Viewport::get_visible_rect); ClassDB::bind_method(D_METHOD("set_transparent_background", "enable"), &Viewport::set_transparent_background); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 8fb497113d..ebb11ecee8 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -587,6 +587,18 @@ bool Window::is_visible() const { } void Window::_update_window_size() { + // Force window to respect size limitations of rendering server + RenderingServer *rendering_server = RenderingServer::get_singleton(); + if (rendering_server) { + Size2i max_window_size = rendering_server->get_maximum_viewport_size(); + + if (max_window_size != Size2i()) { + size = size.min(max_window_size); + min_size = min_size.min(max_window_size); + max_size = max_size.min(max_window_size); + } + } + Size2i size_limit; if (wrap_controls) { size_limit = get_contents_minimum_size(); @@ -1828,6 +1840,11 @@ void Window::_bind_methods() { } Window::Window() { + RenderingServer *rendering_server = RenderingServer::get_singleton(); + if (rendering_server) { + max_size = rendering_server->get_maximum_viewport_size(); + } + theme_owner = memnew(ThemeOwner); RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_DISABLED); } diff --git a/scene/property_utils.cpp b/scene/property_utils.cpp index a9b7e9acbe..f445634a45 100644 --- a/scene/property_utils.cpp +++ b/scene/property_utils.cpp @@ -169,8 +169,10 @@ static bool _collect_inheritance_chain(const Ref<SceneState> &p_state, const Nod state = state->get_base_scene_state(); } - for (int i = inheritance_states.size() - 1; i >= 0; --i) { - r_states_stack.push_back(inheritance_states[i]); + if (inheritance_states.size() > 0) { + for (int i = inheritance_states.size() - 1; i >= 0; --i) { + r_states_stack.push_back(inheritance_states[i]); + } } return found; @@ -214,10 +216,12 @@ Vector<SceneState::PackState> PropertyUtils::get_node_states_stack(const Node *p { states_stack_ret.resize(states_stack.size()); _FastPackState *ps = states_stack.ptr(); - for (int i = states_stack.size() - 1; i >= 0; --i) { - states_stack_ret.write[i].state.reference_ptr(ps->state); - states_stack_ret.write[i].node = ps->node; - ++ps; + if (states_stack.size() > 0) { + for (int i = states_stack.size() - 1; i >= 0; --i) { + states_stack_ret.write[i].state.reference_ptr(ps->state); + states_stack_ret.write[i].node = ps->node; + ++ps; + } } } return states_stack_ret; diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index c9d92cea3f..7f51903586 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -433,7 +433,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_color("background_color", "TextEdit", Color(0, 0, 0, 0)); theme->set_color("font_color", "TextEdit", control_font_color); - theme->set_color("font_selected_color", "TextEdit", control_font_pressed_color); + theme->set_color("font_selected_color", "TextEdit", Color(0, 0, 0, 0)); theme->set_color("font_readonly_color", "TextEdit", control_font_disabled_color); theme->set_color("font_placeholder_color", "TextEdit", control_font_placeholder_color); theme->set_color("font_outline_color", "TextEdit", Color(1, 1, 1)); @@ -476,7 +476,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_color("completion_scroll_hovered_color", "CodeEdit", control_font_pressed_color * Color(1, 1, 1, 0.4)); theme->set_color("completion_font_color", "CodeEdit", Color(0.67, 0.67, 0.67)); theme->set_color("font_color", "CodeEdit", control_font_color); - theme->set_color("font_selected_color", "CodeEdit", Color(0, 0, 0)); + theme->set_color("font_selected_color", "CodeEdit", Color(0, 0, 0, 0)); theme->set_color("font_readonly_color", "CodeEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f)); theme->set_color("font_placeholder_color", "CodeEdit", control_font_placeholder_color); theme->set_color("font_outline_color", "CodeEdit", Color(1, 1, 1)); @@ -959,7 +959,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_font_size("mono_font_size", "RichTextLabel", -1); theme->set_color("default_color", "RichTextLabel", Color(1, 1, 1)); - theme->set_color("font_selected_color", "RichTextLabel", Color(0, 0, 0)); + theme->set_color("font_selected_color", "RichTextLabel", Color(0, 0, 0, 0)); theme->set_color("selection_color", "RichTextLabel", Color(0.1, 0.1, 1, 0.8)); theme->set_color("font_shadow_color", "RichTextLabel", Color(0, 0, 0, 0)); diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index ebdaaaa95f..23bd8a4be4 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -78,7 +78,7 @@ float Environment::get_sky_custom_fov() const { void Environment::set_sky_rotation(const Vector3 &p_rotation) { bg_sky_rotation = p_rotation; - RS::get_singleton()->environment_set_sky_orientation(environment, Basis(p_rotation)); + RS::get_singleton()->environment_set_sky_orientation(environment, Basis::from_euler(p_rotation)); } Vector3 Environment::get_sky_rotation() const { diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp index fe43f345d4..61daf801e8 100644 --- a/scene/resources/shape_2d.cpp +++ b/scene/resources/shape_2d.cpp @@ -105,6 +105,7 @@ void Shape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("collide_and_get_contacts", "local_xform", "with_shape", "shape_xform"), &Shape2D::collide_and_get_contacts); ClassDB::bind_method(D_METHOD("collide_with_motion_and_get_contacts", "local_xform", "local_motion", "with_shape", "shape_xform", "shape_motion"), &Shape2D::collide_with_motion_and_get_contacts); ClassDB::bind_method(D_METHOD("draw", "canvas_item", "color"), &Shape2D::draw); + ClassDB::bind_method(D_METHOD("get_rect"), &Shape2D::get_rect); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_solver_bias", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_custom_solver_bias", "get_custom_solver_bias"); } diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 3a2b0ed9cb..b994498dbf 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -122,7 +122,7 @@ void Texture2D::_bind_methods() { GDVIRTUAL_BIND(_draw, "to_canvas_item", "pos", "modulate", "transpose") GDVIRTUAL_BIND(_draw_rect, "to_canvas_item", "rect", "tile", "modulate", "transpose") - GDVIRTUAL_BIND(_draw_rect_region, "tp_canvas_item", "rect", "src_rect", "modulate", "transpose", "clip_uv"); + GDVIRTUAL_BIND(_draw_rect_region, "to_canvas_item", "rect", "src_rect", "modulate", "transpose", "clip_uv"); } Texture2D::Texture2D() { @@ -653,7 +653,7 @@ Ref<Image> CompressedTexture2D::load_image_from_file(Ref<FileAccess> f, int p_si Image::Format format = Image::Format(f->get_32()); if (data_format == DATA_FORMAT_PNG || data_format == DATA_FORMAT_WEBP || data_format == DATA_FORMAT_BASIS_UNIVERSAL) { - //look for a PNG or WEBP file inside + //look for a PNG or WebP file inside int sw = w; int sh = h; diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index e156679711..8f175e99a6 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -277,6 +277,9 @@ public: bool operator<(const TerrainsPattern &p_terrains_pattern) const; bool operator==(const TerrainsPattern &p_terrains_pattern) const; + bool operator!=(const TerrainsPattern &p_terrains_pattern) const { + return !operator==(p_terrains_pattern); + }; void set_terrain(int p_terrain); int get_terrain() const; diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index de13912b75..04637983b5 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -1642,17 +1642,20 @@ bool VisualShaderNodeLinearSceneDepth::has_output_port_preview(int p_port) const String VisualShaderNodeLinearSceneDepth::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String code; + code += " {\n"; - code += " float _log_depth = textureLod(DEPTH_TEXTURE, SCREEN_UV, 0.0).x;\n"; - code += " vec3 _depth_ndc = vec3(SCREEN_UV * 2.0 - 1.0, _log_depth);\n"; - code += " vec4 _depth_view = INV_PROJECTION_MATRIX * vec4(_depth_ndc, 1.0);\n"; - code += " _depth_view.xyz /= _depth_view.w;"; - code += vformat(" %s = -_depth_view.z;", p_output_vars[0]); + code += " float __log_depth = textureLod(DEPTH_TEXTURE, SCREEN_UV, 0.0).x;\n"; + code += " vec3 __depth_ndc = vec3(SCREEN_UV * 2.0 - 1.0, __log_depth);\n"; + code += " vec4 __depth_view = INV_PROJECTION_MATRIX * vec4(__depth_ndc, 1.0);\n"; + code += " __depth_view.xyz /= __depth_view.w;\n"; + code += vformat(" %s = -__depth_view.z;\n", p_output_vars[0]); + code += " }\n"; return code; } VisualShaderNodeLinearSceneDepth::VisualShaderNodeLinearSceneDepth() { + simple_decl = false; } ////////////// Float Op @@ -3204,6 +3207,7 @@ String VisualShaderNodeUVPolarCoord::get_output_port_name(int p_port) const { String VisualShaderNodeUVPolarCoord::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String code; + code += " {\n"; String uv; if (p_input_vars[0].is_empty()) { @@ -3220,17 +3224,18 @@ String VisualShaderNodeUVPolarCoord::generate_code(Shader::Mode p_mode, VisualSh String repeat = vformat("%s", p_input_vars[3]); if (p_mode == Shader::MODE_CANVAS_ITEM) { - code += vformat(" vec2 __dir = %s - %s;\n", uv, center); - code += " float __radius = length(__dir) * 2.0;\n"; - code += " float __angle = atan(__dir.y, __dir.x) * 1.0/(PI * 2.0);\n"; - code += vformat(" %s = mod(vec2(__radius * %s, __angle * %s), 1.0);\n", p_output_vars[0], zoom, repeat); + code += vformat(" vec2 __dir = %s - %s;\n", uv, center); + code += " float __radius = length(__dir) * 2.0;\n"; + code += " float __angle = atan(__dir.y, __dir.x) * 1.0 / (PI * 2.0);\n"; + code += vformat(" %s = mod(vec2(__radius * %s, __angle * %s), 1.0);\n", p_output_vars[0], zoom, repeat); } else { - code += vformat(" vec2 __dir = %s - %s;\n", uv, center); - code += " float __radius = length(__dir) * 2.0;\n"; - code += " float __angle = atan(__dir.y, __dir.x) * 1.0/(PI * 2.0);\n"; - code += vformat(" %s = vec2(__radius * %s, __angle * %s);\n", p_output_vars[0], zoom, repeat); + code += vformat(" vec2 __dir = %s - %s;\n", uv, center); + code += " float __radius = length(__dir) * 2.0;\n"; + code += " float __angle = atan(__dir.y, __dir.x) * 1.0 / (PI * 2.0);\n"; + code += vformat(" %s = vec2(__radius * %s, __angle * %s);\n", p_output_vars[0], zoom, repeat); } + code += " }\n"; return code; } @@ -3238,6 +3243,8 @@ VisualShaderNodeUVPolarCoord::VisualShaderNodeUVPolarCoord() { set_input_port_default_value(1, Vector2(0.5, 0.5)); // center set_input_port_default_value(2, 1.0); // zoom set_input_port_default_value(3, 1.0); // repeat + + simple_decl = false; } ////////////// Dot Product @@ -7256,22 +7263,26 @@ bool VisualShaderNodeProximityFade::has_output_port_preview(int p_port) const { String VisualShaderNodeProximityFade::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String code; + code += " {\n"; String proximity_fade_distance = vformat("%s", p_input_vars[0]); - code += " float __depth_tex = textureLod(DEPTH_TEXTURE, SCREEN_UV, 0.0).r;\n"; + code += " float __depth_tex = textureLod(DEPTH_TEXTURE, SCREEN_UV, 0.0).r;\n"; if (!RenderingServer::get_singleton()->is_low_end()) { - code += " vec4 __depth_world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, __depth_tex, 1.0);\n"; + code += " vec4 __depth_world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, __depth_tex, 1.0);\n"; } else { - code += " vec4 __depth_world_pos = INV_PROJECTION_MATRIX * vec4(vec3(SCREEN_UV, __depth_tex) * 2.0 - 1.0, 1.0);\n"; + code += " vec4 __depth_world_pos = INV_PROJECTION_MATRIX * vec4(vec3(SCREEN_UV, __depth_tex) * 2.0 - 1.0, 1.0);\n"; } - code += " __depth_world_pos.xyz /= __depth_world_pos.z;\n"; - code += vformat(" %s = clamp(1.0 - smoothstep(__depth_world_pos.z + %s, __depth_world_pos.z, VERTEX.z), 0.0, 1.0);\n", p_output_vars[0], p_input_vars[0]); + code += " __depth_world_pos.xyz /= __depth_world_pos.w;\n"; + code += vformat(" %s = clamp(1.0 - smoothstep(__depth_world_pos.z + %s, __depth_world_pos.z, VERTEX.z), 0.0, 1.0);\n", p_output_vars[0], p_input_vars[0]); + code += " }\n"; return code; } VisualShaderNodeProximityFade::VisualShaderNodeProximityFade() { set_input_port_default_value(0, 1.0); + + simple_decl = false; } ////////////// Random Range @@ -7416,11 +7427,11 @@ String VisualShaderNodeRemap::get_output_port_name(int p_port) const { String VisualShaderNodeRemap::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String code; - - code += vformat(" float _input_range = %s - %s;\n", p_input_vars[2], p_input_vars[1]); - code += vformat(" float _output_range = %s - %s;\n", p_input_vars[4], p_input_vars[3]); - code += vformat(" %s = %s + _output_range * ((%s - %s) / _input_range);\n", p_output_vars[0], p_input_vars[3], p_input_vars[0], p_input_vars[1]); - + code += " {\n"; + code += vformat(" float __input_range = %s - %s;\n", p_input_vars[2], p_input_vars[1]); + code += vformat(" float __output_range = %s - %s;\n", p_input_vars[4], p_input_vars[3]); + code += vformat(" %s = %s + __output_range * ((%s - %s) / __input_range);\n", p_output_vars[0], p_input_vars[3], p_input_vars[0], p_input_vars[1]); + code += " }\n"; return code; } @@ -7429,4 +7440,6 @@ VisualShaderNodeRemap::VisualShaderNodeRemap() { set_input_port_default_value(2, 1.0); set_input_port_default_value(3, 0.0); set_input_port_default_value(4, 1.0); + + simple_decl = false; } |