diff options
Diffstat (limited to 'scene')
-rw-r--r-- | scene/2d/navigation2d.cpp | 4 | ||||
-rw-r--r-- | scene/2d/navigation2d.h | 2 | ||||
-rw-r--r-- | scene/2d/navigation_polygon.cpp | 6 | ||||
-rw-r--r-- | scene/2d/tile_map.cpp | 25 | ||||
-rw-r--r-- | scene/2d/tile_map.h | 1 | ||||
-rw-r--r-- | scene/3d/baked_lightmap.cpp | 7 | ||||
-rw-r--r-- | scene/3d/camera.cpp | 198 | ||||
-rw-r--r-- | scene/3d/camera.h | 13 | ||||
-rw-r--r-- | scene/3d/navigation.cpp | 4 | ||||
-rw-r--r-- | scene/3d/navigation.h | 2 | ||||
-rw-r--r-- | scene/3d/navigation_mesh.cpp | 6 | ||||
-rw-r--r-- | scene/3d/particles.cpp | 34 | ||||
-rw-r--r-- | scene/3d/voxel_light_baker.cpp | 8 | ||||
-rw-r--r-- | scene/gui/dialogs.cpp | 13 | ||||
-rw-r--r-- | scene/gui/popup_menu.cpp | 37 | ||||
-rw-r--r-- | scene/gui/rich_text_label.cpp | 11 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 74 | ||||
-rw-r--r-- | scene/gui/text_edit.h | 4 | ||||
-rw-r--r-- | scene/gui/tree.cpp | 14 | ||||
-rw-r--r-- | scene/main/node.cpp | 38 | ||||
-rw-r--r-- | scene/main/viewport.cpp | 2 | ||||
-rw-r--r-- | scene/resources/packed_scene.cpp | 23 | ||||
-rw-r--r-- | scene/resources/packed_scene.h | 6 | ||||
-rw-r--r-- | scene/resources/scene_format_text.cpp | 11 |
24 files changed, 334 insertions, 209 deletions
diff --git a/scene/2d/navigation2d.cpp b/scene/2d/navigation2d.cpp index 9eff107827..40013814f8 100644 --- a/scene/2d/navigation2d.cpp +++ b/scene/2d/navigation2d.cpp @@ -205,7 +205,7 @@ void Navigation2D::_navpoly_unlink(int p_id) { nm.linked = false; } -int Navigation2D::navpoly_create(const Ref<NavigationPolygon> &p_mesh, const Transform2D &p_xform, Object *p_owner) { +int Navigation2D::navpoly_add(const Ref<NavigationPolygon> &p_mesh, const Transform2D &p_xform, Object *p_owner) { int id = last_id++; NavMesh nm; @@ -708,7 +708,7 @@ Object *Navigation2D::get_closest_point_owner(const Vector2 &p_point) { void Navigation2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("navpoly_create", "mesh", "xform", "owner"), &Navigation2D::navpoly_create, DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("navpoly_add", "mesh", "xform", "owner"), &Navigation2D::navpoly_add, DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("navpoly_set_transform", "id", "xform"), &Navigation2D::navpoly_set_transform); ClassDB::bind_method(D_METHOD("navpoly_remove", "id"), &Navigation2D::navpoly_remove); diff --git a/scene/2d/navigation2d.h b/scene/2d/navigation2d.h index bb97e1a9a9..02dbcb0f96 100644 --- a/scene/2d/navigation2d.h +++ b/scene/2d/navigation2d.h @@ -159,7 +159,7 @@ protected: public: //API should be as dynamic as possible - int navpoly_create(const Ref<NavigationPolygon> &p_mesh, const Transform2D &p_xform, Object *p_owner = NULL); + int navpoly_add(const Ref<NavigationPolygon> &p_mesh, const Transform2D &p_xform, Object *p_owner = NULL); void navpoly_set_transform(int p_id, const Transform2D &p_xform); void navpoly_remove(int p_id); diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp index c53241e985..5a6a5128e6 100644 --- a/scene/2d/navigation_polygon.cpp +++ b/scene/2d/navigation_polygon.cpp @@ -293,7 +293,7 @@ void NavigationPolygonInstance::set_enabled(bool p_enabled) { if (navpoly.is_valid()) { - nav_id = navigation->navpoly_create(navpoly, get_relative_transform_to_parent(navigation), this); + nav_id = navigation->navpoly_add(navpoly, get_relative_transform_to_parent(navigation), this); } } } @@ -324,7 +324,7 @@ void NavigationPolygonInstance::_notification(int p_what) { if (enabled && navpoly.is_valid()) { - nav_id = navigation->navpoly_create(navpoly, get_relative_transform_to_parent(navigation), this); + nav_id = navigation->navpoly_add(navpoly, get_relative_transform_to_parent(navigation), this); } break; } @@ -419,7 +419,7 @@ void NavigationPolygonInstance::set_navigation_polygon(const Ref<NavigationPolyg } if (navigation && navpoly.is_valid() && enabled) { - nav_id = navigation->navpoly_create(navpoly, get_relative_transform_to_parent(navigation), this); + nav_id = navigation->navpoly_add(navpoly, get_relative_transform_to_parent(navigation), this); } //update_gizmo(); _change_notify("navpoly"); diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 1e34372d1e..7b30ddaa56 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -486,7 +486,7 @@ void TileMap::_update_dirty_quadrants() { xform.set_origin(offset.floor() + q.pos); _fix_cell_transform(xform, c, npoly_ofs + center_ofs, s); - int pid = navigation->navpoly_create(navpoly, nav_rel * xform); + int pid = navigation->navpoly_add(navpoly, nav_rel * xform); Quadrant::NavPoly np; np.id = pid; @@ -739,6 +739,26 @@ void TileMap::update_bitmask_area(const Vector2 &p_pos) { } } +void TileMap::update_bitmask_region(const Vector2 &p_start, const Vector2 &p_end) { + + if ((p_end.x < p_start.x || p_end.y < p_start.y) || (p_end.x == p_start.x && p_end.y == p_start.y)) { + int i; + Array a = get_used_cells(); + for (i = 0; i < a.size(); i++) { + // update_bitmask_area() in order to update cells adjacent to the + // current cell, since ordering in array may not be reliable + Vector2 vector = (Vector2)a[i]; + update_bitmask_area(Vector2(vector.x, vector.y)); + } + return; + } + for (int x = p_start.x - 1; x <= p_end.x + 1; x++) { + for (int y = p_start.y - 1; y <= p_end.y + 1; y++) { + update_cell_bitmask(x, y); + } + } +} + void TileMap::update_cell_bitmask(int p_x, int p_y) { PosKey p(p_x, p_y); @@ -1507,6 +1527,9 @@ void TileMap::_bind_methods() { ClassDB::bind_method(D_METHOD("_recreate_quadrants"), &TileMap::_recreate_quadrants); ClassDB::bind_method(D_METHOD("_update_dirty_quadrants"), &TileMap::_update_dirty_quadrants); + ClassDB::bind_method(D_METHOD("update_bitmask_area"), &TileMap::update_bitmask_area); + ClassDB::bind_method(D_METHOD("update_bitmask_region", "start", "end"), &TileMap::update_bitmask_region, DEFVAL(Vector2()), DEFVAL(Vector2())); + ClassDB::bind_method(D_METHOD("_set_tile_data"), &TileMap::_set_tile_data); ClassDB::bind_method(D_METHOD("_get_tile_data"), &TileMap::_get_tile_data); diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index e5608884c4..8f0b2e6e4c 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -245,6 +245,7 @@ public: void make_bitmask_area_dirty(const Vector2 &p_pos); void update_bitmask_area(const Vector2 &p_pos); + void update_bitmask_region(const Vector2 &p_start = Vector2(), const Vector2 &p_end = Vector2()); void update_cell_bitmask(int p_x, int p_y); void update_dirty_bitmask(); diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp index 8af8c2f7da..99d14e7f74 100644 --- a/scene/3d/baked_lightmap.cpp +++ b/scene/3d/baked_lightmap.cpp @@ -175,6 +175,7 @@ BakedLightmap::Subdiv BakedLightmap::get_capture_subdiv() const { void BakedLightmap::set_extents(const Vector3 &p_extents) { extents = p_extents; + update_gizmo(); } Vector3 BakedLightmap::get_extents() const { @@ -701,6 +702,12 @@ void BakedLightmap::_bind_methods() { BIND_ENUM_CONSTANT(BAKE_QUALITY_HIGH); BIND_ENUM_CONSTANT(BAKE_MODE_CONE_TRACE); BIND_ENUM_CONSTANT(BAKE_MODE_RAY_TRACE); + + BIND_ENUM_CONSTANT(BAKE_ERROR_OK); + BIND_ENUM_CONSTANT(BAKE_ERROR_NO_SAVE_PATH); + BIND_ENUM_CONSTANT(BAKE_ERROR_NO_MESHES); + BIND_ENUM_CONSTANT(BAKE_ERROR_CANT_CREATE_IMAGE); + BIND_ENUM_CONSTANT(BAKE_ERROR_USER_ABORTED); } BakedLightmap::BakedLightmap() { diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index af210fff1c..72c0b979af 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -56,126 +56,16 @@ void Camera::_update_camera_mode() { } } -bool Camera::_set(const StringName &p_name, const Variant &p_value) { - - bool changed_all = false; - if (p_name == "projection") { - - int proj = p_value; - if (proj == PROJECTION_PERSPECTIVE) - mode = PROJECTION_PERSPECTIVE; - if (proj == PROJECTION_ORTHOGONAL) - mode = PROJECTION_ORTHOGONAL; - - changed_all = true; - } else if (p_name == "fov" || p_name == "fovy" || p_name == "fovx") - fov = p_value; - else if (p_name == "size" || p_name == "sizex" || p_name == "sizey") - size = p_value; - else if (p_name == "near") - near = p_value; - else if (p_name == "far") - far = p_value; - else if (p_name == "keep_aspect") - set_keep_aspect_mode(KeepAspect(int(p_value))); - else if (p_name == "vaspect") - set_keep_aspect_mode(p_value ? KEEP_WIDTH : KEEP_HEIGHT); - else if (p_name == "h_offset") - h_offset = p_value; - else if (p_name == "v_offset") - v_offset = p_value; - else if (p_name == "current") { - if (p_value.operator bool()) { - make_current(); - } else { - clear_current(); +void Camera::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "fov") { + if (mode == PROJECTION_ORTHOGONAL) { + p_property.usage = PROPERTY_USAGE_NOEDITOR; } - } else if (p_name == "cull_mask") { - set_cull_mask(p_value); - } else if (p_name == "environment") { - set_environment(p_value); - } else if (p_name == "doppler/tracking") { - set_doppler_tracking(DopplerTracking(int(p_value))); - } else - return false; - - _update_camera_mode(); - if (changed_all) - _change_notify(); - return true; -} -bool Camera::_get(const StringName &p_name, Variant &r_ret) const { - - if (p_name == "projection") { - r_ret = mode; - } else if (p_name == "fov" || p_name == "fovy" || p_name == "fovx") - r_ret = fov; - else if (p_name == "size" || p_name == "sizex" || p_name == "sizey") - r_ret = size; - else if (p_name == "near") - r_ret = near; - else if (p_name == "far") - r_ret = far; - else if (p_name == "keep_aspect") - r_ret = int(keep_aspect); - else if (p_name == "current") { - - if (is_inside_tree() && get_tree()->is_node_being_edited(this)) { - r_ret = current; - } else { - r_ret = is_current(); + } else if (p_property.name == "size") { + if (mode == PROJECTION_PERSPECTIVE) { + p_property.usage = PROPERTY_USAGE_NOEDITOR; } - } else if (p_name == "cull_mask") { - r_ret = get_cull_mask(); - } else if (p_name == "h_offset") { - r_ret = get_h_offset(); - } else if (p_name == "v_offset") { - r_ret = get_v_offset(); - } else if (p_name == "environment") { - r_ret = get_environment(); - } else if (p_name == "doppler/tracking") { - r_ret = get_doppler_tracking(); - } else - return false; - - return true; -} - -void Camera::_get_property_list(List<PropertyInfo> *p_list) const { - - p_list->push_back(PropertyInfo(Variant::INT, "projection", PROPERTY_HINT_ENUM, "Perspective,Orthogonal")); - - switch (mode) { - - case PROJECTION_PERSPECTIVE: { - - p_list->push_back(PropertyInfo(Variant::REAL, "fov", PROPERTY_HINT_RANGE, "1,179,0.1", PROPERTY_USAGE_NOEDITOR)); - if (keep_aspect == KEEP_WIDTH) - p_list->push_back(PropertyInfo(Variant::REAL, "fovx", PROPERTY_HINT_RANGE, "1,179,0.1", PROPERTY_USAGE_EDITOR)); - else - p_list->push_back(PropertyInfo(Variant::REAL, "fovy", PROPERTY_HINT_RANGE, "1,179,0.1", PROPERTY_USAGE_EDITOR)); - - } break; - case PROJECTION_ORTHOGONAL: { - - p_list->push_back(PropertyInfo(Variant::REAL, "size", PROPERTY_HINT_RANGE, "1,16384,0.01", PROPERTY_USAGE_NOEDITOR)); - if (keep_aspect == KEEP_WIDTH) - p_list->push_back(PropertyInfo(Variant::REAL, "sizex", PROPERTY_HINT_RANGE, "0.1,16384,0.01", PROPERTY_USAGE_EDITOR)); - else - p_list->push_back(PropertyInfo(Variant::REAL, "sizey", PROPERTY_HINT_RANGE, "0.1,16384,0.01", PROPERTY_USAGE_EDITOR)); - - } break; } - - p_list->push_back(PropertyInfo(Variant::REAL, "near", PROPERTY_HINT_EXP_RANGE, "0.01,4096.0,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "far", PROPERTY_HINT_EXP_RANGE, "0.01,4096.0,0.01")); - p_list->push_back(PropertyInfo(Variant::INT, "keep_aspect", PROPERTY_HINT_ENUM, "Keep Width,Keep Height")); - p_list->push_back(PropertyInfo(Variant::BOOL, "current")); - p_list->push_back(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER)); - p_list->push_back(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment")); - p_list->push_back(PropertyInfo(Variant::REAL, "h_offset")); - p_list->push_back(PropertyInfo(Variant::REAL, "v_offset")); - p_list->push_back(PropertyInfo(Variant::INT, "doppler/tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics")); } void Camera::_update_camera() { @@ -282,6 +172,14 @@ void Camera::set_orthogonal(float p_size, float p_z_near, float p_z_far) { update_gizmo(); } +void Camera::set_projection(Camera::Projection p_mode) { + if (p_mode == PROJECTION_PERSPECTIVE || p_mode == PROJECTION_ORTHOGONAL) { + mode = p_mode; + _update_camera_mode(); + _change_notify(); + } +} + RID Camera::get_camera() const { return camera; @@ -311,6 +209,14 @@ void Camera::clear_current() { } } +void Camera::set_current(bool p_current) { + if (p_current) { + make_current(); + } else { + clear_current(); + } +} + bool Camera::is_current() const { if (is_inside_tree() && !get_tree()->is_node_being_edited(this)) { @@ -481,6 +387,7 @@ void Camera::set_environment(const Ref<Environment> &p_environment) { VS::get_singleton()->camera_set_environment(camera, environment->get_rid()); else VS::get_singleton()->camera_set_environment(camera, RID()); + _update_camera_mode(); } Ref<Environment> Camera::get_environment() const { @@ -489,10 +396,9 @@ Ref<Environment> Camera::get_environment() const { } void Camera::set_keep_aspect_mode(KeepAspect p_aspect) { - keep_aspect = p_aspect; VisualServer::get_singleton()->camera_set_use_vertical_aspect(camera, p_aspect == KEEP_WIDTH); - + _update_camera_mode(); _change_notify(); } @@ -501,6 +407,15 @@ Camera::KeepAspect Camera::get_keep_aspect_mode() const { return keep_aspect; } +void Camera::set_vaspect(bool p_vaspect) { + set_keep_aspect_mode(p_vaspect ? KEEP_WIDTH : KEEP_HEIGHT); + _update_camera_mode(); +} + +bool Camera::get_vaspect() const { + return keep_aspect == KEEP_HEIGHT; +} + void Camera::set_doppler_tracking(DopplerTracking p_tracking) { if (doppler_tracking == p_tracking) @@ -511,6 +426,7 @@ void Camera::set_doppler_tracking(DopplerTracking p_tracking) { velocity_tracker->set_track_physics_step(doppler_tracking == DOPPLER_TRACKING_PHYSICS_STEP); velocity_tracker->reset(get_global_transform().origin); } + _update_camera_mode(); } Camera::DopplerTracking Camera::get_doppler_tracking() const { @@ -529,13 +445,19 @@ void Camera::_bind_methods() { ClassDB::bind_method(D_METHOD("set_orthogonal", "size", "z_near", "z_far"), &Camera::set_orthogonal); ClassDB::bind_method(D_METHOD("make_current"), &Camera::make_current); ClassDB::bind_method(D_METHOD("clear_current"), &Camera::clear_current); + ClassDB::bind_method(D_METHOD("set_current"), &Camera::set_current); ClassDB::bind_method(D_METHOD("is_current"), &Camera::is_current); ClassDB::bind_method(D_METHOD("get_camera_transform"), &Camera::get_camera_transform); ClassDB::bind_method(D_METHOD("get_fov"), &Camera::get_fov); ClassDB::bind_method(D_METHOD("get_size"), &Camera::get_size); ClassDB::bind_method(D_METHOD("get_zfar"), &Camera::get_zfar); ClassDB::bind_method(D_METHOD("get_znear"), &Camera::get_znear); + ClassDB::bind_method(D_METHOD("set_fov"), &Camera::set_fov); + ClassDB::bind_method(D_METHOD("set_size"), &Camera::set_size); + ClassDB::bind_method(D_METHOD("set_zfar"), &Camera::set_zfar); + ClassDB::bind_method(D_METHOD("set_znear"), &Camera::set_znear); ClassDB::bind_method(D_METHOD("get_projection"), &Camera::get_projection); + ClassDB::bind_method(D_METHOD("set_projection"), &Camera::set_projection); ClassDB::bind_method(D_METHOD("set_h_offset", "ofs"), &Camera::set_h_offset); ClassDB::bind_method(D_METHOD("get_h_offset"), &Camera::get_h_offset); ClassDB::bind_method(D_METHOD("set_v_offset", "ofs"), &Camera::set_v_offset); @@ -546,10 +468,26 @@ void Camera::_bind_methods() { ClassDB::bind_method(D_METHOD("get_environment"), &Camera::get_environment); ClassDB::bind_method(D_METHOD("set_keep_aspect_mode", "mode"), &Camera::set_keep_aspect_mode); ClassDB::bind_method(D_METHOD("get_keep_aspect_mode"), &Camera::get_keep_aspect_mode); + ClassDB::bind_method(D_METHOD("set_vaspect"), &Camera::set_vaspect); + ClassDB::bind_method(D_METHOD("get_vaspect"), &Camera::get_vaspect); ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &Camera::set_doppler_tracking); ClassDB::bind_method(D_METHOD("get_doppler_tracking"), &Camera::get_doppler_tracking); //ClassDB::bind_method(D_METHOD("_camera_make_current"),&Camera::_camera_make_current ); + ADD_PROPERTY(PropertyInfo(Variant::INT, "keep_aspect", PROPERTY_HINT_ENUM, "Keep Width,Keep Height"), "set_keep_aspect_mode", "get_keep_aspect_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vaspect"), "set_vaspect", "get_vaspect"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "h_offset"), "set_h_offset", "get_h_offset"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_offset"), "set_v_offset", "get_v_offset"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "projection", PROPERTY_HINT_ENUM, "Perspective,Orthogonal"), "set_projection", "get_projection"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "fov", PROPERTY_HINT_RANGE, "1,179,0.1"), "set_fov", "get_fov"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "size", PROPERTY_HINT_RANGE, "0.1,16384,0.01"), "set_size", "get_size"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "near"), "set_znear", "get_znear"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "far"), "set_zfar", "get_zfar"); + BIND_ENUM_CONSTANT(PROJECTION_PERSPECTIVE); BIND_ENUM_CONSTANT(PROJECTION_ORTHOGONAL); @@ -586,10 +524,30 @@ Camera::Projection Camera::get_projection() const { return mode; } -void Camera::set_cull_mask(uint32_t p_layers) { +void Camera::set_fov(float p_fov) { + fov = p_fov; + _update_camera_mode(); +} + +void Camera::set_size(float p_size) { + size = p_size; + _update_camera_mode(); +} + +void Camera::set_znear(float p_znear) { + near = p_znear; + _update_camera_mode(); +} +void Camera::set_zfar(float p_zfar) { + far = p_zfar; + _update_camera_mode(); +} + +void Camera::set_cull_mask(uint32_t p_layers) { layers = p_layers; VisualServer::get_singleton()->camera_set_cull_mask(camera, layers); + _update_camera_mode(); } uint32_t Camera::get_cull_mask() const { diff --git a/scene/3d/camera.h b/scene/3d/camera.h index 73c6844c1a..520afb962b 100644 --- a/scene/3d/camera.h +++ b/scene/3d/camera.h @@ -95,10 +95,8 @@ protected: virtual void _request_camera_update(); void _update_camera_mode(); - bool _set(const StringName &p_name, const Variant &p_value); - bool _get(const StringName &p_name, Variant &r_ret) const; - void _get_property_list(List<PropertyInfo> *p_list) const; void _notification(int p_what); + virtual void _validate_property(PropertyInfo &property) const; static void _bind_methods(); @@ -111,9 +109,11 @@ public: void set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far); void set_orthogonal(float p_size, float p_z_near, float p_z_far); + void set_projection(Camera::Projection p_mode); void make_current(); void clear_current(); + void set_current(bool p_current); bool is_current() const; RID get_camera() const; @@ -124,6 +124,11 @@ public: float get_znear() const; Projection get_projection() const; + void set_fov(float p_fov); + void set_size(float p_size); + void set_zfar(float p_zfar); + void set_znear(float p_znear); + virtual Transform get_camera_transform() const; Vector3 project_ray_normal(const Point2 &p_pos) const; @@ -143,6 +148,8 @@ public: void set_keep_aspect_mode(KeepAspect p_aspect); KeepAspect get_keep_aspect_mode() const; + void set_vaspect(bool p_vaspect); + bool get_vaspect() const; void set_v_offset(float p_offset); float get_v_offset() const; diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp index b6507aedb3..78cf75e3b3 100644 --- a/scene/3d/navigation.cpp +++ b/scene/3d/navigation.cpp @@ -202,7 +202,7 @@ void Navigation::_navmesh_unlink(int p_id) { nm.linked = false; } -int Navigation::navmesh_create(const Ref<NavigationMesh> &p_mesh, const Transform &p_xform, Object *p_owner) { +int Navigation::navmesh_add(const Ref<NavigationMesh> &p_mesh, const Transform &p_xform, Object *p_owner) { int id = last_id++; NavMesh nm; @@ -686,7 +686,7 @@ Vector3 Navigation::get_up_vector() const { void Navigation::_bind_methods() { - ClassDB::bind_method(D_METHOD("navmesh_create", "mesh", "xform", "owner"), &Navigation::navmesh_create, DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("navmesh_add", "mesh", "xform", "owner"), &Navigation::navmesh_add, DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("navmesh_set_transform", "id", "xform"), &Navigation::navmesh_set_transform); ClassDB::bind_method(D_METHOD("navmesh_remove", "id"), &Navigation::navmesh_remove); diff --git a/scene/3d/navigation.h b/scene/3d/navigation.h index d9a38f7b00..134afa2278 100644 --- a/scene/3d/navigation.h +++ b/scene/3d/navigation.h @@ -166,7 +166,7 @@ public: Vector3 get_up_vector() const; //API should be as dynamic as possible - int navmesh_create(const Ref<NavigationMesh> &p_mesh, const Transform &p_xform, Object *p_owner = NULL); + int navmesh_add(const Ref<NavigationMesh> &p_mesh, const Transform &p_xform, Object *p_owner = NULL); void navmesh_set_transform(int p_id, const Transform &p_xform); void navmesh_remove(int p_id); diff --git a/scene/3d/navigation_mesh.cpp b/scene/3d/navigation_mesh.cpp index 40750cdfe8..4fb12b8fac 100644 --- a/scene/3d/navigation_mesh.cpp +++ b/scene/3d/navigation_mesh.cpp @@ -471,7 +471,7 @@ void NavigationMeshInstance::set_enabled(bool p_enabled) { if (navmesh.is_valid()) { - nav_id = navigation->navmesh_create(navmesh, get_relative_transform(navigation), this); + nav_id = navigation->navmesh_add(navmesh, get_relative_transform(navigation), this); } } } @@ -508,7 +508,7 @@ void NavigationMeshInstance::_notification(int p_what) { if (enabled && navmesh.is_valid()) { - nav_id = navigation->navmesh_create(navmesh, get_relative_transform(navigation), this); + nav_id = navigation->navmesh_add(navmesh, get_relative_transform(navigation), this); } break; } @@ -568,7 +568,7 @@ void NavigationMeshInstance::set_navigation_mesh(const Ref<NavigationMesh> &p_na navmesh = p_navmesh; if (navigation && navmesh.is_valid() && enabled) { - nav_id = navigation->navmesh_create(navmesh, get_relative_transform(navigation), this); + nav_id = navigation->navmesh_add(navmesh, get_relative_transform(navigation), this); } if (debug_view && navmesh.is_valid()) { diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp index 821f1a5a78..b445ccc5a9 100644 --- a/scene/3d/particles.cpp +++ b/scene/3d/particles.cpp @@ -598,6 +598,11 @@ void ParticlesMaterial::_update_shader() { code += "}\n"; code += "\n"; + code += "float rand_from_seed_m1_p1(inout uint seed) {\n"; + code += " return rand_from_seed(seed)*2.0-1.0;\n"; + code += "}\n"; + code += "\n"; + //improve seed quality code += "uint hash(uint x) {\n"; code += " x = ((x >> uint(16)) ^ x) * uint(73244475);\n"; @@ -614,6 +619,8 @@ void ParticlesMaterial::_update_shader() { code += " float scale_rand = rand_from_seed(alt_seed);\n"; code += " float hue_rot_rand = rand_from_seed(alt_seed);\n"; code += " float anim_offset_rand = rand_from_seed(alt_seed);\n"; + code += " float pi = 3.14159;\n"; + code += " float degree_to_rad = pi / 180.0;\n"; code += "\n"; if (emission_shape >= EMISSION_SHAPE_POINTS) { @@ -638,23 +645,28 @@ void ParticlesMaterial::_update_shader() { else code += " float tex_anim_offset = 0.0;\n"; + code += " float spread_rad = spread*degree_to_rad;\n"; + if (flags[FLAG_DISABLE_Z]) { - code += " float angle1 = (rand_from_seed(alt_seed)*2.0-1.0)*spread/180.0*3.1416;\n"; - code += " vec3 rot = vec3( cos(angle1), sin(angle1),0.0 );\n"; + code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed)*spread_rad;\n"; + code += " vec3 rot = vec3( cos(angle1_rad), sin(angle1_rad),0.0 );\n"; code += " VELOCITY = rot*initial_linear_velocity*mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; } else { //initiate velocity spread in 3D - code += " float angle1 = rand_from_seed(alt_seed)*spread*3.1416;\n"; - code += " float angle2 = rand_from_seed(alt_seed)*20.0*3.1416; // make it more random like\n"; - code += " vec3 rot_xz = vec3( sin(angle1), 0.0, cos(angle1) );\n"; - code += " vec3 rot = vec3( cos(angle2)*rot_xz.x,sin(angle2)*rot_xz.x, rot_xz.z);\n"; - code += " VELOCITY = rot*initial_linear_velocity*mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; + code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed)*spread_rad;\n"; + code += " float angle2_rad = rand_from_seed_m1_p1(alt_seed)*spread_rad*(1.0-flatness);\n"; + code += " vec3 direction_xz = vec3( sin(angle1_rad), 0, cos(angle1_rad));\n"; + code += " vec3 direction_yz = vec3( 0, sin(angle2_rad), cos(angle2_rad));\n"; + code += " direction_yz.z = direction_yz.z / sqrt(direction_yz.z); //better uniform distribution\n"; + code += " vec3 direction = vec3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);\n"; + code += " direction = normalize(direction);\n"; + code += " VELOCITY = direction*initial_linear_velocity*mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; } code += " float base_angle = (initial_angle+tex_angle)*mix(1.0,angle_rand,initial_angle_random);\n"; - code += " CUSTOM.x = base_angle*3.1416/180.0;\n"; //angle + code += " CUSTOM.x = base_angle*degree_to_rad;\n"; //angle code += " CUSTOM.y = 0.0;\n"; //phase code += " CUSTOM.z = (anim_offset+tex_anim_offset)*mix(1.0,anim_offset_rand,anim_offset_random);\n"; //animation offset (0-1) switch (emission_shape) { @@ -777,7 +789,7 @@ void ParticlesMaterial::_update_shader() { code += " float orbit_amount = (orbit_velocity+tex_orbit_velocity)*mix(1.0,rand_from_seed(alt_seed),orbit_velocity_random);\n"; code += " if (orbit_amount!=0.0) {\n"; - code += " float ang = orbit_amount * DELTA * 3.1416 * 2.0;\n"; + code += " float ang = orbit_amount * DELTA * pi * 2.0;\n"; code += " mat2 rot = mat2(vec2(cos(ang),-sin(ang)),vec2(sin(ang),cos(ang)));\n"; code += " TRANSFORM[3].xy-=diff.xy;\n"; code += " TRANSFORM[3].xy+=rot * diff.xy;\n"; @@ -800,7 +812,7 @@ void ParticlesMaterial::_update_shader() { code += " }\n"; code += " float base_angle = (initial_angle+tex_angle)*mix(1.0,angle_rand,initial_angle_random);\n"; code += " base_angle += CUSTOM.y*LIFETIME*(angular_velocity+tex_angular_velocity)*mix(1.0,rand_from_seed(alt_seed)*2.0-1.0,angular_velocity_random);\n"; - code += " CUSTOM.x = base_angle*3.1416/180.0;\n"; //angle + code += " CUSTOM.x = base_angle*degree_to_rad;\n"; //angle code += " CUSTOM.z = (anim_offset+tex_anim_offset)*mix(1.0,anim_offset_rand,anim_offset_random)+CUSTOM.y*(anim_speed+tex_anim_speed)*mix(1.0,rand_from_seed(alt_seed),anim_speed_random);\n"; //angle if (flags[FLAG_ANIM_LOOP]) { code += " CUSTOM.z = mod(CUSTOM.z,1.0);\n"; //loop @@ -821,7 +833,7 @@ void ParticlesMaterial::_update_shader() { else code += " float tex_hue_variation = 0.0;\n"; - code += " float hue_rot_angle = (hue_variation+tex_hue_variation)*3.1416*2.0*mix(1.0,hue_rot_rand*2.0-1.0,hue_variation_random);\n"; + code += " float hue_rot_angle = (hue_variation+tex_hue_variation)*pi*2.0*mix(1.0,hue_rot_rand*2.0-1.0,hue_variation_random);\n"; code += " float hue_rot_c = cos(hue_rot_angle);\n"; code += " float hue_rot_s = sin(hue_rot_angle);\n"; code += " mat4 hue_rot_mat = mat4( vec4(0.299, 0.587, 0.114, 0.0),\n"; diff --git a/scene/3d/voxel_light_baker.cpp b/scene/3d/voxel_light_baker.cpp index 98dc1590d8..c05dfddeca 100644 --- a/scene/3d/voxel_light_baker.cpp +++ b/scene/3d/voxel_light_baker.cpp @@ -1781,7 +1781,7 @@ Error VoxelLightBaker::make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh //print_line("bake line " + itos(i) + " / " + itos(height)); #ifdef _OPENMP -#pragma omp parallel for +#pragma omp parallel for schedule(dynamic, 1) #endif for (int j = 0; j < width; j++) { @@ -1878,12 +1878,14 @@ Error VoxelLightBaker::make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh LightMap *lightmap_ptr = lightmap.ptrw(); const Cell *cells = bake_cells.ptr(); const Light *light = bake_light.ptr(); - +#ifdef _OPENMP +#pragma omp parallel +#endif for (int i = 0; i < height; i++) { //print_line("bake line " + itos(i) + " / " + itos(height)); #ifdef _OPENMP -#pragma omp parallel for +#pragma omp parallel for schedule(dynamic, 1) #endif for (int j = 0; j < width; j++) { diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index d4912339da..9a55073bb6 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -289,10 +289,17 @@ bool WindowDialog::get_resizable() const { Size2 WindowDialog::get_minimum_size() const { Ref<Font> font = get_font("title_font", "WindowDialog"); - int msx = close_button->get_combined_minimum_size().x; - msx += font->get_string_size(title).x; - return Size2(msx, 1); + const int button_width = close_button->get_combined_minimum_size().x; + const int title_width = font->get_string_size(title).x; + const int padding = button_width / 2; + const int button_area = button_width + padding; + + // as the title gets centered, title_width + close_button_width is not enough. + // we want a width w, such that w / 2 - title_width / 2 >= button_area, i.e. + // w >= 2 * button_area + title_width + + return Size2(2 * button_area + title_width, 1); } TextureButton *WindowDialog::get_close_button() { diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 32f889e826..698676cc39 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -42,24 +42,6 @@ String PopupMenu::_get_accel_text(int p_item) const { else if (items[p_item].accel) return keycode_get_string(items[p_item].accel); return String(); - - /* - String atxt; - if (p_accel&KEY_MASK_SHIFT) - atxt+="Shift+"; - if (p_accel&KEY_MASK_ALT) - atxt+="Alt+"; - if (p_accel&KEY_MASK_CTRL) - atxt+="Ctrl+"; - if (p_accel&KEY_MASK_META) - atxt+="Meta+"; - - p_accel&=KEY_CODE_MASK; - - atxt+=String::chr(p_accel).to_upper(); - - return atxt; -*/ } Size2 PopupMenu::get_minimum_size() const { @@ -136,7 +118,6 @@ int PopupMenu::_get_mouse_over(const Point2 &p_over) const { Ref<Font> font = get_font("font"); int vseparation = get_constant("vseparation"); - //int hseparation = get_constant("hseparation"); float font_h = font->get_height(); for (int i = 0; i < items.size(); i++) { @@ -230,6 +211,11 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { mouse_over = i; update(); + + if (items[i].submenu != "" && submenu_over != i) { + submenu_over = i; + submenu_timer->start(); + } break; } } @@ -245,6 +231,11 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { mouse_over = i; update(); + + if (items[i].submenu != "" && submenu_over != i) { + submenu_over = i; + submenu_timer->start(); + } break; } } @@ -500,6 +491,13 @@ void PopupMenu::_notification(int p_what) { } break; case NOTIFICATION_MOUSE_EXIT: { + if (mouse_over >= 0 && (items[mouse_over].submenu == "" || submenu_over != -1)) { + mouse_over = -1; + update(); + } + } break; + case NOTIFICATION_POPUP_HIDE: { + if (mouse_over >= 0) { mouse_over = -1; update(); @@ -1217,6 +1215,7 @@ void PopupMenu::set_invalidate_click_until_motion() { PopupMenu::PopupMenu() { mouse_over = -1; + submenu_over = -1; set_focus_mode(FOCUS_ALL); set_as_toplevel(true); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 05c6e9f77e..6fbc58a38a 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -31,6 +31,11 @@ #include "os/keyboard.h" #include "os/os.h" #include "scene/scene_string_names.h" + +#ifdef TOOLS_ENABLED +#include "editor/editor_node.h" +#endif + RichTextLabel::Item *RichTextLabel::_get_next_item(Item *p_item, bool p_free) { if (p_free) { @@ -370,7 +375,11 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & Color uc = color; uc.a *= 0.5; int uy = y + lh - fh + ascent + 2; - VS::get_singleton()->canvas_item_add_line(ci, p_ofs + Point2(align_ofs + pofs, uy), p_ofs + Point2(align_ofs + pofs + cw, uy), uc); + float underline_width = 1.0; +#ifdef TOOLS_ENABLED + underline_width *= EDSCALE; +#endif + VS::get_singleton()->canvas_item_add_line(ci, p_ofs + Point2(align_ofs + pofs, uy), p_ofs + Point2(align_ofs + pofs + cw, uy), uc, underline_width); } ofs += cw; } diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index e5169089f2..83aee5ca30 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1664,17 +1664,22 @@ void TextEdit::backspace_at_cursor() { cursor_set_column(prev_column); } -void TextEdit::indent_selection_right() { +void TextEdit::indent_right() { - if (!is_selection_active()) { - return; - } + int start_line; + int end_line; begin_complex_operation(); - int start_line = get_selection_from_line(); - int end_line = get_selection_to_line(); + + if (is_selection_active()) { + start_line = get_selection_from_line(); + end_line = get_selection_to_line(); + } else { + start_line = cursor.line; + end_line = start_line; + } // ignore if the cursor is not past the first column - if (get_selection_to_column() == 0) { + if (is_selection_active() && get_selection_to_column() == 0) { end_line--; } @@ -1688,23 +1693,32 @@ void TextEdit::indent_selection_right() { set_line(i, line_text); } - // fix selection being off by one on the last line - selection.to_column++; + // fix selection and cursor being off by one on the last line + if (is_selection_active()) { + selection.to_column++; + selection.from_column++; + } + cursor.column++; end_complex_operation(); update(); } -void TextEdit::indent_selection_left() { +void TextEdit::indent_left() { - if (!is_selection_active()) { - return; - } + int start_line; + int end_line; begin_complex_operation(); - int start_line = get_selection_from_line(); - int end_line = get_selection_to_line(); + + if (is_selection_active()) { + start_line = get_selection_from_line(); + end_line = get_selection_to_line(); + } else { + start_line = cursor.line; + end_line = start_line; + } // ignore if the cursor is not past the first column - if (get_selection_to_column() == 0) { + if (is_selection_active() && get_selection_to_column() == 0) { end_line--; } String last_line_text = get_line(end_line); @@ -1721,9 +1735,15 @@ void TextEdit::indent_selection_left() { } } - // fix selection being off by one on the last line - if (last_line_text != get_line(end_line) && selection.to_column > 0) { - selection.to_column--; + // fix selection and cursor being off by one on the last line + if (is_selection_active() && last_line_text != get_line(end_line)) { + if (selection.to_column > 0) + selection.to_column--; + if (selection.from_column > 0) + selection.from_column--; + } + if (cursor.column > 0) { + cursor.column--; } end_complex_operation(); update(); @@ -2216,9 +2236,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { case KEY_TAB: { if (k->get_shift()) { - indent_selection_left(); + indent_left(); } else { - indent_selection_right(); + indent_right(); } dobreak = true; accept_event(); @@ -2389,8 +2409,12 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { if (readonly) break; - if (selection.active) { - + if (is_selection_active()) { + if (k->get_shift()) { + indent_left(); + } else { + indent_right(); + } } else { if (k->get_shift()) { @@ -5444,8 +5468,10 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("cut"), &TextEdit::cut); ClassDB::bind_method(D_METHOD("copy"), &TextEdit::copy); ClassDB::bind_method(D_METHOD("paste"), &TextEdit::paste); - ClassDB::bind_method(D_METHOD("select_all"), &TextEdit::select_all); + ClassDB::bind_method(D_METHOD("select", "from_line", "from_column", "to_line", "to_column"), &TextEdit::select); + ClassDB::bind_method(D_METHOD("select_all"), &TextEdit::select_all); + ClassDB::bind_method(D_METHOD("deselect"), &TextEdit::deselect); ClassDB::bind_method(D_METHOD("is_selection_active"), &TextEdit::is_selection_active); ClassDB::bind_method(D_METHOD("get_selection_from_line"), &TextEdit::get_selection_from_line); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index dd305d5822..edef28cc25 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -443,8 +443,8 @@ public: void set_line(int line, String new_text); void backspace_at_cursor(); - void indent_selection_left(); - void indent_selection_right(); + void indent_left(); + void indent_right(); int get_indent_level(int p_line) const; inline void set_scroll_pass_end_of_file(bool p_enabled) { diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index ab12d123ba..b5b42e8f29 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -30,6 +30,7 @@ #include "tree.h" #include <limits.h> +#include "math_funcs.h" #include "os/input.h" #include "os/keyboard.h" #include "os/os.h" @@ -37,6 +38,10 @@ #include "project_settings.h" #include "scene/main/viewport.h" +#ifdef TOOLS_ENABLED +#include "editor/editor_node.h" +#endif + void TreeItem::move_to_top() { if (!parent || parent->childs == this) @@ -1412,9 +1417,14 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 if (c->get_children() != NULL) root_pos -= Point2i(cache.arrow->get_width(), 0); + float line_width = 1.0; +#ifdef TOOLS_ENABLED + line_width *= EDSCALE; +#endif + Point2i parent_pos = Point2i(parent_ofs - cache.arrow->get_width() / 2, p_pos.y + label_h / 2 + cache.arrow->get_height() / 2) - cache.offset + p_draw_ofs; - VisualServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x, root_pos.y), cache.relationship_line_color); - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y), parent_pos, cache.relationship_line_color); + VisualServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x - Math::floor(line_width / 2), root_pos.y), cache.relationship_line_color, line_width); + VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y), parent_pos, cache.relationship_line_color, line_width); } int child_h = draw_item(children_pos, p_draw_ofs, p_draw_size, c); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index efc5d269a6..af7a6bddd9 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2110,6 +2110,7 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const StringName script_property_name = CoreStringNames::get_singleton()->_script; + List<const Node *> hidden_roots; List<const Node *> node_tree; node_tree.push_front(this); @@ -2120,11 +2121,16 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const for (List<const Node *>::Element *N = node_tree.front(); N; N = N->next()) { for (int i = 0; i < N->get()->get_child_count(); ++i) { + Node *descendant = N->get()->get_child(i); // Skip nodes not really belonging to the instanced hierarchy; they'll be processed normally later - if (N->get()->get_child(i)->data.owner != this) + // but remember non-instanced nodes that are hidden below instanced ones + if (descendant->data.owner != this) { + if (descendant->get_parent() && descendant->get_parent() != this && descendant->get_parent()->data.owner == this) + hidden_roots.push_back(descendant); continue; + } - node_tree.push_back(N->get()->get_child(i)); + node_tree.push_back(descendant); } } } @@ -2201,6 +2207,34 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const } node->add_child(dup); + if (i < node->get_child_count() - 1) { + node->move_child(dup, i); + } + } + + for (List<const Node *>::Element *E = hidden_roots.front(); E; E = E->next()) { + + Node *parent = node->get_node(get_path_to(E->get()->data.parent)); + if (!parent) { + + memdelete(node); + return NULL; + } + + Node *dup = E->get()->_duplicate(p_flags, r_duplimap); + if (!dup) { + + memdelete(node); + return NULL; + } + + parent->add_child(dup); + int pos = E->get()->get_position_in_parent(); + + if (pos < parent->get_child_count() - 1) { + + parent->move_child(dup, pos); + } } return node; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 4635de81e8..f5d7043a40 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1421,7 +1421,7 @@ void Viewport::_gui_show_tooltip() { gui.tooltip_label->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, ttp->get_margin(MARGIN_TOP)); gui.tooltip_label->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -ttp->get_margin(MARGIN_RIGHT)); gui.tooltip_label->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -ttp->get_margin(MARGIN_BOTTOM)); - gui.tooltip_label->set_text(tooltip); + gui.tooltip_label->set_text(tooltip.strip_edges()); Rect2 r(gui.tooltip_pos + Point2(10, 10), gui.tooltip_label->get_combined_minimum_size() + ttp->get_minimum_size()); Rect2 vr = gui.tooltip_label->get_viewport_rect(); if (r.size.x + r.position.x > vr.size.x) diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 3a5cb7da2e..879f76e6d8 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -270,6 +270,8 @@ Node *SceneState::instance(GenEditState p_edit_state) const { if (i > 0) { if (parent) { parent->_add_child_nocheck(node, snames[n.name]); + if (n.index >= 0 && n.index < parent->get_child_count() - 1) + parent->move_child(node, n.index); } else { //it may be possible that an instanced scene has changed //and the node has nowhere to go anymore @@ -386,6 +388,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map nd.name = _nm_get_string(p_node->get_name(), name_map); nd.instance = -1; //not instanced by default + nd.index = p_node->get_index(); // if this node is part of an instanced scene or sub-instanced scene // we need to get the corresponding instance states. @@ -1114,7 +1117,10 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { nd.parent = r[idx++]; nd.owner = r[idx++]; nd.type = r[idx++]; - nd.name = r[idx++]; + uint32_t name_index = r[idx++]; + nd.name = name_index & ((1 << NAME_INDEX_BITS) - 1); + nd.index = (name_index >> NAME_INDEX_BITS); + nd.index--; //0 is invaild, stored as 1 nd.instance = r[idx++]; nd.properties.resize(r[idx++]); for (int j = 0; j < nd.properties.size(); j++) { @@ -1206,7 +1212,11 @@ Dictionary SceneState::get_bundled_scene() const { rnodes.push_back(nd.parent); rnodes.push_back(nd.owner); rnodes.push_back(nd.type); - rnodes.push_back(nd.name); + uint32_t name_index = nd.name; + if (nd.index < (1 << (32 - NAME_INDEX_BITS)) - 1) { //save if less than 16k childs + name_index |= uint32_t(nd.index + 1) << NAME_INDEX_BITS; //for backwards compatibility, index 0 is no index + } + rnodes.push_back(name_index); rnodes.push_back(nd.instance); rnodes.push_back(nd.properties.size()); for (int j = 0; j < nd.properties.size(); j++) { @@ -1284,6 +1294,11 @@ StringName SceneState::get_node_name(int p_idx) const { return names[nodes[p_idx].name]; } +int SceneState::get_node_index(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, nodes.size(), -1); + return nodes[p_idx].index; +} + bool SceneState::is_node_instance_placeholder(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, nodes.size(), false); @@ -1524,7 +1539,7 @@ int SceneState::add_node_path(const NodePath &p_path) { node_paths.push_back(p_path); return (node_paths.size() - 1) | FLAG_ID_IS_PATH; } -int SceneState::add_node(int p_parent, int p_owner, int p_type, int p_name, int p_instance) { +int SceneState::add_node(int p_parent, int p_owner, int p_type, int p_name, int p_instance, int p_index) { NodeData nd; nd.parent = p_parent; @@ -1532,6 +1547,7 @@ int SceneState::add_node(int p_parent, int p_owner, int p_type, int p_name, int nd.type = p_type; nd.name = p_name; nd.instance = p_instance; + nd.index = p_index; nodes.push_back(nd); @@ -1605,6 +1621,7 @@ void SceneState::_bind_methods() { ClassDB::bind_method(D_METHOD("get_node_instance_placeholder", "idx"), &SceneState::get_node_instance_placeholder); ClassDB::bind_method(D_METHOD("get_node_instance", "idx"), &SceneState::get_node_instance); ClassDB::bind_method(D_METHOD("get_node_groups", "idx"), &SceneState::_get_node_groups); + ClassDB::bind_method(D_METHOD("get_node_index", "idx"), &SceneState::get_node_index); ClassDB::bind_method(D_METHOD("get_node_property_count", "idx"), &SceneState::get_node_property_count); ClassDB::bind_method(D_METHOD("get_node_property_name", "idx", "prop_idx"), &SceneState::get_node_property_name); ClassDB::bind_method(D_METHOD("get_node_property_value", "idx", "prop_idx"), &SceneState::get_node_property_value); diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h index 20bfb19b1f..70deea24ff 100644 --- a/scene/resources/packed_scene.h +++ b/scene/resources/packed_scene.h @@ -48,6 +48,8 @@ class SceneState : public Reference { enum { NO_PARENT_SAVED = 0x7FFFFFFF, + NAME_INDEX_BITS = 18, + NAME_MASK = (1 << NAME_INDEX_BITS) - 1, }; struct NodeData { @@ -57,6 +59,7 @@ class SceneState : public Reference { int type; int name; int instance; + int index; struct Property { @@ -151,6 +154,7 @@ public: String get_node_instance_placeholder(int p_idx) const; bool is_node_instance_placeholder(int p_idx) const; Vector<StringName> get_node_groups(int p_idx) const; + int get_node_index(int p_idx) const; int get_node_property_count(int p_idx) const; StringName get_node_property_name(int p_idx, int p_prop) const; @@ -174,7 +178,7 @@ public: int find_name(const StringName &p_name) const; int add_value(const Variant &p_value); int add_node_path(const NodePath &p_path); - int add_node(int p_parent, int p_owner, int p_type, int p_name, int p_instance); + int add_node(int p_parent, int p_owner, int p_type, int p_name, int p_instance, int p_index); void add_node_property(int p_node, int p_name, int p_value); void add_node_group(int p_node, int p_group); void set_base_scene(int p_idx); diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp index aebbb5b562..7bf5f24269 100644 --- a/scene/resources/scene_format_text.cpp +++ b/scene/resources/scene_format_text.cpp @@ -198,6 +198,7 @@ Ref<PackedScene> ResourceInteractiveLoaderText::_parse_node_tag(VariantParser::R int type = -1; int name = -1; int instance = -1; + int index = -1; //int base_scene=-1; if (next_tag.fields.has("name")) { @@ -249,7 +250,11 @@ Ref<PackedScene> ResourceInteractiveLoaderText::_parse_node_tag(VariantParser::R owner = 0; //if no owner, owner is root } - int node_id = packed_scene->get_state()->add_node(parent, owner, type, name, instance); + if (next_tag.fields.has("index")) { + index = next_tag.fields["index"]; + } + + int node_id = packed_scene->get_state()->add_node(parent, owner, type, name, instance, index); if (next_tag.fields.has("groups")) { @@ -1609,6 +1614,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r StringName type = state->get_node_type(i); StringName name = state->get_node_name(i); + int index = state->get_node_index(i); NodePath path = state->get_node_path(i, true); NodePath owner = state->get_node_owner_path(i); Ref<PackedScene> instance = state->get_node_instance(i); @@ -1626,6 +1632,9 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r if (owner != NodePath() && owner != NodePath(".")) { header += " owner=\"" + String(owner.simplified()) + "\""; } + if (index >= 0) { + header += " index=\"" + itos(index) + "\""; + } if (groups.size()) { String sgroups = " groups=[\n"; |