diff options
Diffstat (limited to 'scene')
92 files changed, 2630 insertions, 806 deletions
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index b56eedabc7..85e7f8df92 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -235,7 +235,7 @@ void SpriteFrames::_set_frames(const Array &p_frames) { E->get().frames.resize(p_frames.size()); for (int i = 0; i < E->get().frames.size(); i++) - E->get().frames[i] = p_frames[i]; + E->get().frames.write[i] = p_frames[i]; } Array SpriteFrames::_get_frames() const { diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h index f6586aff36..cc49465403 100644 --- a/scene/2d/animated_sprite.h +++ b/scene/2d/animated_sprite.h @@ -113,7 +113,7 @@ public: ERR_FAIL_COND(p_idx < 0); if (p_idx >= E->get().frames.size()) return; - E->get().frames[p_idx] = p_frame; + E->get().frames.write[p_idx] = p_frame; } void remove_frame(const StringName &p_anim, int p_idx); void clear(const StringName &p_anim); diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 47326b9be2..a035d9021f 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -411,6 +411,9 @@ void CanvasItem::_enter_canvas() { if (canvas_layer) { break; } + if (Object::cast_to<Viewport>(n)) { + break; + } n = n->get_parent(); } diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index cabd7fddc2..1e2184bd41 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -259,7 +259,7 @@ void CollisionObject2D::shape_owner_remove_shape(uint32_t p_owner, int p_shape) for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { for (int i = 0; i < E->get().shapes.size(); i++) { if (E->get().shapes[i].index > index_to_remove) { - E->get().shapes[i].index -= 1; + E->get().shapes.write[i].index -= 1; } } } diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index 9d2a83fda7..9f19f56e75 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -102,11 +102,11 @@ Vector<Vector<Vector2> > CollisionPolygon2D::_decompose_in_convex() { TriangulatorPoly &tp = I->get(); - decomp[idx].resize(tp.GetNumPoints()); + decomp.write[idx].resize(tp.GetNumPoints()); for (int i = 0; i < tp.GetNumPoints(); i++) { - decomp[idx][i] = tp.GetPoint(i); + decomp.write[idx].write[i] = tp.GetPoint(i); } idx++; diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp index e9e895b5bb..ad9775c0b7 100644 --- a/scene/2d/line_2d.cpp +++ b/scene/2d/line_2d.cpp @@ -239,7 +239,7 @@ void Line2D::_draw() { { PoolVector<Vector2>::Read points_read = _points.read(); for (int i = 0; i < len; ++i) { - points[i] = points_read[i]; + points.write[i] = points_read[i]; } } diff --git a/scene/2d/line_builder.cpp b/scene/2d/line_builder.cpp index 74ad3e79d0..a3f1b25e05 100644 --- a/scene/2d/line_builder.cpp +++ b/scene/2d/line_builder.cpp @@ -292,7 +292,6 @@ void LineBuilder::build() { color1 = gradient->get_color_at_offset(current_distance1 / total_distance); } if (texture_mode == Line2D::LINE_TEXTURE_TILE) { - uvx0 = current_distance0 / (width * tile_aspect); uvx1 = current_distance1 / (width * tile_aspect); } else if (texture_mode == Line2D::LINE_TEXTURE_STRETCH) { uvx0 = current_distance0 / total_distance; @@ -306,7 +305,6 @@ void LineBuilder::build() { u0 = u1; f0 = f1; pos0 = pos1; - current_distance0 = current_distance1; if (intersection_result == SEGMENT_INTERSECT) { if (current_joint_mode == Line2D::LINE_JOINT_SHARP) { pos_up0 = pos_up1; diff --git a/scene/2d/navigation2d.cpp b/scene/2d/navigation2d.cpp index 16e0386952..e3b048fd74 100644 --- a/scene/2d/navigation2d.cpp +++ b/scene/2d/navigation2d.cpp @@ -74,7 +74,7 @@ void Navigation2D::_navpoly_link(int p_id) { Vector2 ep = nm.xform.xform(r[idx]); center += ep; e.point = _get_point(ep); - p.edges[j] = e; + p.edges.write[j] = e; int idxn = indices[(j + 1) % plen]; if (idxn < 0 || idxn >= len) { @@ -119,17 +119,17 @@ void Navigation2D::_navpoly_link(int p_id) { ConnectionPending pending; pending.polygon = &p; pending.edge = j; - p.edges[j].P = C->get().pending.push_back(pending); + p.edges.write[j].P = C->get().pending.push_back(pending); continue; //print_line(String()+_get_vertex(ek.a)+" -> "+_get_vertex(ek.b)); } C->get().B = &p; C->get().B_edge = j; - C->get().A->edges[C->get().A_edge].C = &p; - C->get().A->edges[C->get().A_edge].C_edge = j; - p.edges[j].C = C->get().A; - p.edges[j].C_edge = C->get().A_edge; + C->get().A->edges.write[C->get().A_edge].C = &p; + C->get().A->edges.write[C->get().A_edge].C_edge = j; + p.edges.write[j].C = C->get().A; + p.edges.write[j].C_edge = C->get().A_edge; //connection successful. } } @@ -167,10 +167,10 @@ void Navigation2D::_navpoly_unlink(int p_id) { } else if (C->get().B) { //disconnect - C->get().B->edges[C->get().B_edge].C = NULL; - C->get().B->edges[C->get().B_edge].C_edge = -1; - C->get().A->edges[C->get().A_edge].C = NULL; - C->get().A->edges[C->get().A_edge].C_edge = -1; + C->get().B->edges.write[C->get().B_edge].C = NULL; + C->get().B->edges.write[C->get().B_edge].C_edge = -1; + C->get().A->edges.write[C->get().A_edge].C = NULL; + C->get().A->edges.write[C->get().A_edge].C_edge = -1; if (C->get().A == &E->get()) { @@ -187,11 +187,11 @@ void Navigation2D::_navpoly_unlink(int p_id) { C->get().B = cp.polygon; C->get().B_edge = cp.edge; - C->get().A->edges[C->get().A_edge].C = cp.polygon; - C->get().A->edges[C->get().A_edge].C_edge = cp.edge; - cp.polygon->edges[cp.edge].C = C->get().A; - cp.polygon->edges[cp.edge].C_edge = C->get().A_edge; - cp.polygon->edges[cp.edge].P = NULL; + C->get().A->edges.write[C->get().A_edge].C = cp.polygon; + C->get().A->edges.write[C->get().A_edge].C_edge = cp.edge; + cp.polygon->edges.write[cp.edge].C = C->get().A; + cp.polygon->edges.write[cp.edge].C_edge = C->get().A_edge; + cp.polygon->edges.write[cp.edge].P = NULL; } } else { @@ -339,8 +339,8 @@ Vector<Vector2> Navigation2D::get_simple_path(const Vector2 &p_start, const Vect Vector<Vector2> path; path.resize(2); - path[0] = begin_point; - path[1] = end_point; + path.write[0] = begin_point; + path.write[1] = end_point; //print_line("Direct Path"); return path; } @@ -408,7 +408,7 @@ Vector<Vector2> Navigation2D::get_simple_path(const Vector2 &p_start, const Vect for (int i = 0; i < es; i++) { - Polygon::Edge &e = p->edges[i]; + Polygon::Edge &e = p->edges.write[i]; if (!e.C) continue; @@ -586,7 +586,7 @@ Vector<Vector2> Navigation2D::get_simple_path(const Vector2 &p_start, const Vect if (!path.size() || path[path.size() - 1].distance_squared_to(begin_point) > CMP_EPSILON) { path.push_back(begin_point); // Add the begin point } else { - path[path.size() - 1] = begin_point; // Replace first midpoint by the exact begin point + path.write[path.size() - 1] = begin_point; // Replace first midpoint by the exact begin point } path.invert(); @@ -594,7 +594,7 @@ Vector<Vector2> Navigation2D::get_simple_path(const Vector2 &p_start, const Vect if (path.size() <= 1 || path[path.size() - 1].distance_squared_to(end_point) > CMP_EPSILON) { path.push_back(end_point); // Add the end point } else { - path[path.size() - 1] = end_point; // Replace last midpoint by the exact end point + path.write[path.size() - 1] = end_point; // Replace last midpoint by the exact end point } return path; diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp index 6e27bf1c1d..2d6679272a 100644 --- a/scene/2d/navigation_polygon.cpp +++ b/scene/2d/navigation_polygon.cpp @@ -91,7 +91,7 @@ void NavigationPolygon::_set_polygons(const Array &p_array) { polygons.resize(p_array.size()); for (int i = 0; i < p_array.size(); i++) { - polygons[i].indices = p_array[i]; + polygons.write[i].indices = p_array[i]; } } @@ -110,7 +110,7 @@ void NavigationPolygon::_set_outlines(const Array &p_array) { outlines.resize(p_array.size()); for (int i = 0; i < p_array.size(); i++) { - outlines[i] = p_array[i]; + outlines.write[i] = p_array[i]; } rect_cache_dirty = true; } @@ -166,7 +166,7 @@ int NavigationPolygon::get_outline_count() const { void NavigationPolygon::set_outline(int p_idx, const PoolVector<Vector2> &p_outline) { ERR_FAIL_INDEX(p_idx, outlines.size()); - outlines[p_idx] = p_outline; + outlines.write[p_idx] = p_outline; rect_cache_dirty = true; } @@ -432,8 +432,8 @@ void NavigationPolygonInstance::_notification(int p_what) { { PoolVector<Vector2>::Read vr = verts.read(); for (int i = 0; i < vsize; i++) { - vertices[i] = vr[i]; - colors[i] = color; + vertices.write[i] = vr[i]; + colors.write[i] = color; } } diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 8787a2c735..9879f43877 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -30,6 +30,7 @@ #include "physics_body_2d.h" +#include "core/core_string_names.h" #include "core/method_bind_ext.gen.inc" #include "engine.h" #include "math_funcs.h" @@ -186,28 +187,75 @@ real_t StaticBody2D::get_constant_angular_velocity() const { return constant_angular_velocity; } +#ifndef DISABLE_DEPRECATED void StaticBody2D::set_friction(real_t p_friction) { + ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physical material") + WARN_DEPRECATED + ERR_FAIL_COND(p_friction < 0 || p_friction > 1); - friction = p_friction; - Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_FRICTION, friction); + if (physics_material_override.is_null()) { + physics_material_override.instance(); + } + physics_material_override->set_friction(p_friction); + _reload_physics_characteristics(); } + real_t StaticBody2D::get_friction() const { - return friction; + ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physical material") + WARN_DEPRECATED + + if (physics_material_override.is_null()) { + return 1; + } + + return physics_material_override->get_friction(); } void StaticBody2D::set_bounce(real_t p_bounce) { + ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physical material") + WARN_DEPRECATED + ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1); - bounce = p_bounce; - Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_BOUNCE, bounce); + if (physics_material_override.is_null()) { + physics_material_override.instance(); + } + physics_material_override->set_bounce(p_bounce); + _reload_physics_characteristics(); } + real_t StaticBody2D::get_bounce() const { - return bounce; + ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physical material") + WARN_DEPRECATED + + if (physics_material_override.is_null()) { + return 0; + } + + return physics_material_override->get_bounce(); +} +#endif + +void StaticBody2D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) { + if (physics_material_override.is_valid()) { + physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics"); + } + + physics_material_override = p_physics_material_override; + + if (physics_material_override.is_valid()) { + physics_material_override->connect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics"); + } + _reload_physics_characteristics(); +} + +Ref<PhysicsMaterial> StaticBody2D::get_physics_material_override() const { + return physics_material_override; } void StaticBody2D::_bind_methods() { @@ -222,23 +270,41 @@ void StaticBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bounce", "bounce"), &StaticBody2D::set_bounce); ClassDB::bind_method(D_METHOD("get_bounce"), &StaticBody2D::get_bounce); + ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody2D::set_physics_material_override); + ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody2D::get_physics_material_override); + + ClassDB::bind_method(D_METHOD("_reload_physics_characteristics"), &StaticBody2D::_reload_physics_characteristics); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); } StaticBody2D::StaticBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_STATIC) { constant_angular_velocity = 0; - bounce = 0; - friction = 1; } StaticBody2D::~StaticBody2D() { } +void StaticBody2D::_reload_physics_characteristics() { + if (physics_material_override.is_null()) { + Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_BOUNCE, 0); + Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_FRICTION, 1); + Physics2DServer::get_singleton()->body_set_combine_mode(get_rid(), Physics2DServer::BODY_PARAM_BOUNCE, Physics2DServer::COMBINE_MODE_INHERIT); + Physics2DServer::get_singleton()->body_set_combine_mode(get_rid(), Physics2DServer::BODY_PARAM_FRICTION, Physics2DServer::COMBINE_MODE_INHERIT); + } else { + Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_BOUNCE, physics_material_override->get_bounce()); + Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_FRICTION, physics_material_override->get_friction()); + Physics2DServer::get_singleton()->body_set_combine_mode(get_rid(), Physics2DServer::BODY_PARAM_BOUNCE, (Physics2DServer::CombineMode)physics_material_override->get_bounce_combine_mode()); + Physics2DServer::get_singleton()->body_set_combine_mode(get_rid(), Physics2DServer::BODY_PARAM_FRICTION, (Physics2DServer::CombineMode)physics_material_override->get_friction_combine_mode()); + } +} + void RigidBody2D::_body_enter_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); @@ -545,28 +611,72 @@ real_t RigidBody2D::get_weight() const { return mass * real_t(GLOBAL_DEF("physics/2d/default_gravity", 98)) / 10; } +#ifndef DISABLE_DEPRECATED void RigidBody2D::set_friction(real_t p_friction) { + ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physical material") + WARN_DEPRECATED ERR_FAIL_COND(p_friction < 0 || p_friction > 1); - friction = p_friction; - Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_FRICTION, friction); + if (physics_material_override.is_null()) { + physics_material_override.instance(); + } + physics_material_override->set_friction(p_friction); + _reload_physics_characteristics(); } real_t RigidBody2D::get_friction() const { - return friction; + ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physical material") + WARN_DEPRECATED + + if (physics_material_override.is_null()) { + return 1; + } + + return physics_material_override->get_friction(); } void RigidBody2D::set_bounce(real_t p_bounce) { + ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physical material") + WARN_DEPRECATED + ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1); - bounce = p_bounce; - Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_BOUNCE, bounce); + if (physics_material_override.is_null()) { + physics_material_override.instance(); + } + physics_material_override->set_bounce(p_bounce); + _reload_physics_characteristics(); } real_t RigidBody2D::get_bounce() const { - return bounce; + ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physical material") + WARN_DEPRECATED + + if (physics_material_override.is_null()) { + return 0; + } + + return physics_material_override->get_bounce(); +} +#endif + +void RigidBody2D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) { + if (physics_material_override.is_valid()) { + physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics"); + } + + physics_material_override = p_physics_material_override; + + if (physics_material_override.is_valid()) { + physics_material_override->connect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics"); + } + _reload_physics_characteristics(); +} + +Ref<PhysicsMaterial> RigidBody2D::get_physics_material_override() const { + return physics_material_override; } void RigidBody2D::set_gravity_scale(real_t p_gravity_scale) { @@ -690,11 +800,19 @@ int RigidBody2D::get_max_contacts_reported() const { return max_contacts_reported; } +void RigidBody2D::apply_central_impulse(const Vector2 &p_impulse) { + Physics2DServer::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); +} + void RigidBody2D::apply_impulse(const Vector2 &p_offset, const Vector2 &p_impulse) { Physics2DServer::get_singleton()->body_apply_impulse(get_rid(), p_offset, p_impulse); } +void RigidBody2D::apply_torque_impulse(float p_torque) { + Physics2DServer::get_singleton()->body_apply_torque_impulse(get_rid(), p_torque); +} + void RigidBody2D::set_applied_force(const Vector2 &p_force) { Physics2DServer::get_singleton()->body_set_applied_force(get_rid(), p_force); @@ -715,11 +833,19 @@ float RigidBody2D::get_applied_torque() const { return Physics2DServer::get_singleton()->body_get_applied_torque(get_rid()); }; +void RigidBody2D::add_central_force(const Vector2 &p_force) { + Physics2DServer::get_singleton()->body_add_central_force(get_rid(), p_force); +} + void RigidBody2D::add_force(const Vector2 &p_offset, const Vector2 &p_force) { Physics2DServer::get_singleton()->body_add_force(get_rid(), p_offset, p_force); } +void RigidBody2D::add_torque(const float p_torque) { + Physics2DServer::get_singleton()->body_add_torque(get_rid(), p_torque); +} + void RigidBody2D::set_continuous_collision_detection_mode(CCDMode p_mode) { ccd_mode = p_mode; @@ -843,6 +969,11 @@ void RigidBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bounce", "bounce"), &RigidBody2D::set_bounce); ClassDB::bind_method(D_METHOD("get_bounce"), &RigidBody2D::get_bounce); + ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidBody2D::set_physics_material_override); + ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidBody2D::get_physics_material_override); + + ClassDB::bind_method(D_METHOD("_reload_physics_characteristics"), &RigidBody2D::_reload_physics_characteristics); + ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidBody2D::set_gravity_scale); ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidBody2D::get_gravity_scale); @@ -871,7 +1002,9 @@ void RigidBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_continuous_collision_detection_mode"), &RigidBody2D::get_continuous_collision_detection_mode); ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidBody2D::set_axis_velocity); + ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody2D::apply_central_impulse); ClassDB::bind_method(D_METHOD("apply_impulse", "offset", "impulse"), &RigidBody2D::apply_impulse); + ClassDB::bind_method(D_METHOD("apply_torque_impulse", "torque"), &RigidBody2D::apply_torque_impulse); ClassDB::bind_method(D_METHOD("set_applied_force", "force"), &RigidBody2D::set_applied_force); ClassDB::bind_method(D_METHOD("get_applied_force"), &RigidBody2D::get_applied_force); @@ -879,7 +1012,9 @@ void RigidBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_applied_torque", "torque"), &RigidBody2D::set_applied_torque); ClassDB::bind_method(D_METHOD("get_applied_torque"), &RigidBody2D::get_applied_torque); + ClassDB::bind_method(D_METHOD("add_central_force", "force"), &RigidBody2D::add_central_force); ClassDB::bind_method(D_METHOD("add_force", "offset", "force"), &RigidBody2D::add_force); + ClassDB::bind_method(D_METHOD("add_torque", "torque"), &RigidBody2D::add_torque); ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidBody2D::set_sleeping); ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidBody2D::is_sleeping); @@ -903,6 +1038,7 @@ void RigidBody2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "weight", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01", PROPERTY_USAGE_EDITOR), "set_weight", "get_weight"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator"); ADD_PROPERTY(PropertyInfo(Variant::INT, "continuous_cd", PROPERTY_HINT_ENUM, "Disabled,Cast Ray,Cast Shape"), "set_continuous_collision_detection_mode", "get_continuous_collision_detection_mode"); @@ -941,9 +1077,7 @@ RigidBody2D::RigidBody2D() : mode = MODE_RIGID; - bounce = 0; mass = 1; - friction = 1; gravity_scale = 1; linear_damp = -1; @@ -969,6 +1103,20 @@ RigidBody2D::~RigidBody2D() { memdelete(contact_monitor); } +void RigidBody2D::_reload_physics_characteristics() { + if (physics_material_override.is_null()) { + Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_BOUNCE, 0); + Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_FRICTION, 1); + Physics2DServer::get_singleton()->body_set_combine_mode(get_rid(), Physics2DServer::BODY_PARAM_BOUNCE, Physics2DServer::COMBINE_MODE_INHERIT); + Physics2DServer::get_singleton()->body_set_combine_mode(get_rid(), Physics2DServer::BODY_PARAM_FRICTION, Physics2DServer::COMBINE_MODE_INHERIT); + } else { + Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_BOUNCE, physics_material_override->get_bounce()); + Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_FRICTION, physics_material_override->get_friction()); + Physics2DServer::get_singleton()->body_set_combine_mode(get_rid(), Physics2DServer::BODY_PARAM_BOUNCE, (Physics2DServer::CombineMode)physics_material_override->get_bounce_combine_mode()); + Physics2DServer::get_singleton()->body_set_combine_mode(get_rid(), Physics2DServer::BODY_PARAM_FRICTION, (Physics2DServer::CombineMode)physics_material_override->get_friction_combine_mode()); + } +} + ////////////////////////// Ref<KinematicCollision2D> KinematicBody2D::_move(const Vector2 &p_motion, bool p_infinite_inertia, bool p_exclude_raycast_shapes, bool p_test_only) { @@ -1225,11 +1373,11 @@ Ref<KinematicCollision2D> KinematicBody2D::_get_slide_collision(int p_bounce) { } if (slide_colliders[p_bounce].is_null()) { - slide_colliders[p_bounce].instance(); - slide_colliders[p_bounce]->owner = this; + slide_colliders.write[p_bounce].instance(); + slide_colliders.write[p_bounce]->owner = this; } - slide_colliders[p_bounce]->collision = colliders[p_bounce]; + slide_colliders.write[p_bounce]->collision = colliders[p_bounce]; return slide_colliders[p_bounce]; } @@ -1327,7 +1475,7 @@ KinematicBody2D::~KinematicBody2D() { for (int i = 0; i < slide_colliders.size(); i++) { if (slide_colliders[i].is_valid()) { - slide_colliders[i]->owner = NULL; + slide_colliders.write[i]->owner = NULL; } } } diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 7bda6ce817..0a2ce0918b 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -32,6 +32,7 @@ #define PHYSICS_BODY_2D_H #include "scene/2d/collision_object_2d.h" +#include "scene/resources/physics_material.h" #include "servers/physics_2d_server.h" #include "vset.h" @@ -79,18 +80,21 @@ class StaticBody2D : public PhysicsBody2D { Vector2 constant_linear_velocity; real_t constant_angular_velocity; - real_t bounce; - real_t friction; + Ref<PhysicsMaterial> physics_material_override; protected: static void _bind_methods(); public: +#ifndef DISABLE_DEPRECATED void set_friction(real_t p_friction); real_t get_friction() const; void set_bounce(real_t p_bounce); real_t get_bounce() const; +#endif + void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override); + Ref<PhysicsMaterial> get_physics_material_override() const; void set_constant_linear_velocity(const Vector2 &p_vel); void set_constant_angular_velocity(real_t p_vel); @@ -100,6 +104,9 @@ public: StaticBody2D(); ~StaticBody2D(); + +private: + void _reload_physics_characteristics(); }; class RigidBody2D : public PhysicsBody2D { @@ -125,9 +132,8 @@ private: Physics2DDirectBodyState *state; Mode mode; - real_t bounce; real_t mass; - real_t friction; + Ref<PhysicsMaterial> physics_material_override; real_t gravity_scale; real_t linear_damp; real_t angular_damp; @@ -204,11 +210,16 @@ public: void set_weight(real_t p_weight); real_t get_weight() const; +#ifndef DISABLE_DEPRECATED void set_friction(real_t p_friction); real_t get_friction() const; void set_bounce(real_t p_bounce); real_t get_bounce() const; +#endif + + void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override); + Ref<PhysicsMaterial> get_physics_material_override() const; void set_gravity_scale(real_t p_gravity_scale); real_t get_gravity_scale() const; @@ -245,7 +256,9 @@ public: void set_continuous_collision_detection_mode(CCDMode p_mode); CCDMode get_continuous_collision_detection_mode() const; + void apply_central_impulse(const Vector2 &p_impulse); void apply_impulse(const Vector2 &p_offset, const Vector2 &p_impulse); + void apply_torque_impulse(float p_torque); void set_applied_force(const Vector2 &p_force); Vector2 get_applied_force() const; @@ -253,7 +266,9 @@ public: void set_applied_torque(const float p_torque); float get_applied_torque() const; + void add_central_force(const Vector2 &p_force); void add_force(const Vector2 &p_offset, const Vector2 &p_force); + void add_torque(float p_torque); Array get_colliding_bodies() const; //function for script @@ -261,6 +276,9 @@ public: RigidBody2D(); ~RigidBody2D(); + +private: + void _reload_physics_characteristics(); }; VARIANT_ENUM_CAST(RigidBody2D::Mode); diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index 81ed3c63c3..c9e5408f06 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -113,7 +113,7 @@ void Polygon2D::_notification(int p_what) { PoolVector<Vector2>::Read polyr = polygon.read(); for (int i = 0; i < len; i++) { - points[i] = polyr[i] + offset; + points.write[i] = polyr[i] + offset; } } @@ -153,18 +153,18 @@ void Polygon2D::_notification(int p_what) { SWAP(ep[1], ep[4]); SWAP(ep[2], ep[3]); SWAP(ep[5], ep[0]); - SWAP(ep[6], points[highest_idx]); + SWAP(ep[6], points.write[highest_idx]); } points.resize(points.size() + 7); for (int i = points.size() - 1; i >= highest_idx + 7; i--) { - points[i] = points[i - 7]; + points.write[i] = points[i - 7]; } for (int i = 0; i < 7; i++) { - points[highest_idx + i + 1] = ep[i]; + points.write[highest_idx + i + 1] = ep[i]; } len = points.size(); @@ -182,12 +182,12 @@ void Polygon2D::_notification(int p_what) { PoolVector<Vector2>::Read uvr = uv.read(); for (int i = 0; i < len; i++) { - uvs[i] = texmat.xform(uvr[i]) / tex_size; + uvs.write[i] = texmat.xform(uvr[i]) / tex_size; } } else { for (int i = 0; i < len; i++) { - uvs[i] = texmat.xform(points[i]) / tex_size; + uvs.write[i] = texmat.xform(points[i]) / tex_size; } } } @@ -262,10 +262,10 @@ void Polygon2D::_notification(int p_what) { { PoolVector<Color>::Read color_r = vertex_colors.read(); for (int i = 0; i < color_len && i < len; i++) { - colors[i] = color_r[i]; + colors.write[i] = color_r[i]; } for (int i = color_len; i < len; i++) { - colors[i] = color; + colors.write[i] = color; } } @@ -333,13 +333,13 @@ void Polygon2D::_notification(int p_what) { Vector<Vector2> vertices; vertices.resize(loop.size()); for (int j = 0; j < vertices.size(); j++) { - vertices[j] = points[loop[j]]; + vertices.write[j] = points[loop[j]]; } Vector<int> sub_indices = Geometry::triangulate_polygon(vertices); int from = indices.size(); indices.resize(from + sub_indices.size()); for (int j = 0; j < sub_indices.size(); j++) { - indices[from + j] = loop[sub_indices[j]]; + indices.write[from + j] = loop[sub_indices[j]]; } } @@ -538,12 +538,12 @@ void Polygon2D::clear_bones() { void Polygon2D::set_bone_weights(int p_index, const PoolVector<float> &p_weights) { ERR_FAIL_INDEX(p_index, bone_weights.size()); - bone_weights[p_index].weights = p_weights; + bone_weights.write[p_index].weights = p_weights; update(); } void Polygon2D::set_bone_path(int p_index, const NodePath &p_path) { ERR_FAIL_INDEX(p_index, bone_weights.size()); - bone_weights[p_index].path = p_path; + bone_weights.write[p_index].path = p_path; update(); } diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index 8ceffb3c27..e6e9bde20a 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -191,13 +191,13 @@ void Skeleton2D::_update_bone_setup() { bones.sort(); //sorty so they are always in the same order/index for (int i = 0; i < bones.size(); i++) { - bones[i].rest_inverse = bones[i].bone->get_skeleton_rest().affine_inverse(); //bind pose - bones[i].bone->skeleton_index = i; + bones.write[i].rest_inverse = bones[i].bone->get_skeleton_rest().affine_inverse(); //bind pose + bones.write[i].bone->skeleton_index = i; Bone2D *parent_bone = Object::cast_to<Bone2D>(bones[i].bone->get_parent()); if (parent_bone) { - bones[i].parent_index = parent_bone->skeleton_index; + bones.write[i].parent_index = parent_bone->skeleton_index; } else { - bones[i].parent_index = -1; + bones.write[i].parent_index = -1; } } @@ -230,9 +230,9 @@ void Skeleton2D::_update_transform() { ERR_CONTINUE(bones[i].parent_index >= i); if (bones[i].parent_index >= 0) { - bones[i].accum_transform = bones[bones[i].parent_index].accum_transform * bones[i].bone->get_transform(); + bones.write[i].accum_transform = bones[bones[i].parent_index].accum_transform * bones[i].bone->get_transform(); } else { - bones[i].accum_transform = bones[i].bone->get_transform(); + bones.write[i].accum_transform = bones[i].bone->get_transform(); } } diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 9a343ca0f0..78637cc097 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -62,7 +62,7 @@ void TileMap::_notification(int p_what) { pending_update = true; _recreate_quadrants(); - _update_dirty_quadrants(); + update_dirty_quadrants(); RID space = get_world_2d()->get_space(); _update_quadrant_transform(); _update_quadrant_space(space); @@ -245,7 +245,7 @@ void TileMap::_fix_cell_transform(Transform2D &xform, const Cell &p_cell, const xform.elements[2].y += offset.y; } -void TileMap::_update_dirty_quadrants() { +void TileMap::update_dirty_quadrants() { if (!pending_update) return; @@ -529,8 +529,8 @@ void TileMap::_update_dirty_quadrants() { { PoolVector<Vector2>::Read vr = navigation_polygon_vertices.read(); for (int i = 0; i < vsize; i++) { - vertices[i] = vr[i]; - colors[i] = debug_navigation_color; + vertices.write[i] = vr[i]; + colors.write[i] = debug_navigation_color; } } @@ -721,7 +721,7 @@ void TileMap::_make_quadrant_dirty(Map<PosKey, Quadrant>::Element *Q, bool updat return; if (update) { - _update_dirty_quadrants(); + call_deferred("update_dirty_quadrants"); } } @@ -1026,7 +1026,7 @@ void TileMap::_recreate_quadrants() { Q->get().cells.insert(E->key()); _make_quadrant_dirty(Q, false); } - _update_dirty_quadrants(); + update_dirty_quadrants(); } void TileMap::_clear_quadrants() { @@ -1611,7 +1611,7 @@ void TileMap::_bind_methods() { ClassDB::bind_method(D_METHOD("set_cell", "x", "y", "tile", "flip_x", "flip_y", "transpose", "autotile_coord"), &TileMap::set_cell, DEFVAL(false), DEFVAL(false), DEFVAL(false), DEFVAL(Vector2())); ClassDB::bind_method(D_METHOD("set_cellv", "position", "tile", "flip_x", "flip_y", "transpose"), &TileMap::set_cellv, DEFVAL(false), DEFVAL(false), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("set_celld", "data"), &TileMap::set_celld); + ClassDB::bind_method(D_METHOD("set_celld", "position", "data"), &TileMap::set_celld); ClassDB::bind_method(D_METHOD("get_cell", "x", "y"), &TileMap::get_cell); ClassDB::bind_method(D_METHOD("get_cellv", "position"), &TileMap::get_cellv); ClassDB::bind_method(D_METHOD("is_cell_x_flipped", "x", "y"), &TileMap::is_cell_x_flipped); @@ -1630,7 +1630,7 @@ void TileMap::_bind_methods() { ClassDB::bind_method(D_METHOD("_clear_quadrants"), &TileMap::_clear_quadrants); 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_dirty_quadrants"), &TileMap::update_dirty_quadrants); ClassDB::bind_method(D_METHOD("update_bitmask_area", "position"), &TileMap::update_bitmask_area); ClassDB::bind_method(D_METHOD("update_bitmask_region", "start", "end"), &TileMap::update_bitmask_region, DEFVAL(Vector2()), DEFVAL(Vector2())); diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index 79d79ca59f..c8aceac17d 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -191,7 +191,6 @@ private: void _make_quadrant_dirty(Map<PosKey, Quadrant>::Element *Q, bool update = true); void _recreate_quadrants(); void _clear_quadrants(); - void _update_dirty_quadrants(); void _update_quadrant_space(const RID &p_space); void _update_quadrant_transform(); void _recompute_rect_cache(); @@ -251,6 +250,8 @@ public: void update_cell_bitmask(int p_x, int p_y); void update_dirty_bitmask(); + void update_dirty_quadrants(); + void set_collision_layer(uint32_t p_layer); uint32_t get_collision_layer() const; diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp index 1d5d1b2afe..e19e45b263 100644 --- a/scene/3d/collision_object.cpp +++ b/scene/3d/collision_object.cpp @@ -305,7 +305,7 @@ void CollisionObject::shape_owner_remove_shape(uint32_t p_owner, int p_shape) { for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { for (int i = 0; i < E->get().shapes.size(); i++) { if (E->get().shapes[i].index > index_to_remove) { - E->get().shapes[i].index -= 1; + E->get().shapes.write[i].index -= 1; } } } diff --git a/scene/3d/collision_object.h b/scene/3d/collision_object.h index f31d65e411..f8ef04b78f 100644 --- a/scene/3d/collision_object.h +++ b/scene/3d/collision_object.h @@ -39,6 +39,7 @@ class CollisionObject : public Spatial { GDCLASS(CollisionObject, Spatial); bool area; + RID rid; struct ShapeData { diff --git a/scene/3d/collision_shape.h b/scene/3d/collision_shape.h index c9c91a5824..6ca8e80ea1 100644 --- a/scene/3d/collision_shape.h +++ b/scene/3d/collision_shape.h @@ -49,6 +49,7 @@ class CollisionShape : public Spatial { void resource_changed(RES res); bool disabled; +protected: void _create_debug_shape(); void _update_in_shape_owner(bool p_xform_only = false); diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp index 2e897c1c73..c3b0196316 100644 --- a/scene/3d/cpu_particles.cpp +++ b/scene/3d/cpu_particles.cpp @@ -25,6 +25,8 @@ void CPUParticles::set_emitting(bool p_emitting) { update_mutex->lock(); #endif VS::get_singleton()->connect("frame_pre_draw", this, "_update_render_thread"); + VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_REDRAW_FRAME_IF_VISIBLE, true); + #ifndef NO_THREADS update_mutex->unlock(); #endif @@ -446,6 +448,8 @@ float rand_from_seed_m1_p1(uint32_t &seed) { void CPUParticles::_particles_process(float p_delta) { + p_delta *= speed_scale; + int pcount = particles.size(); PoolVector<Particle>::Write w = particles.write(); @@ -475,7 +479,7 @@ void CPUParticles::_particles_process(float p_delta) { if (!emitting && !p.active) continue; - float restart_time = float(i) / float(pcount); + float restart_time = (float(i) / float(pcount)) * lifetime; float local_delta = p_delta; if (randomness_ratio > 0.0) { @@ -643,7 +647,7 @@ void CPUParticles::_particles_process(float p_delta) { uint32_t alt_seed = p.seed; p.time += local_delta; - p.custom[1] += p.time / lifetime; + p.custom[1] = p.time / lifetime; float tex_linear_velocity = 0.0; if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { @@ -979,6 +983,7 @@ void CPUParticles::_notification(int p_what) { update_mutex->lock(); #endif VS::get_singleton()->connect("frame_pre_draw", this, "_update_render_thread"); + VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_REDRAW_FRAME_IF_VISIBLE, true); #ifndef NO_THREADS update_mutex->unlock(); #endif @@ -992,6 +997,7 @@ void CPUParticles::_notification(int p_what) { update_mutex->lock(); #endif VS::get_singleton()->disconnect("frame_pre_draw", this, "_update_render_thread"); + VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_REDRAW_FRAME_IF_VISIBLE, false); #ifndef NO_THREADS update_mutex->unlock(); #endif @@ -1018,6 +1024,8 @@ void CPUParticles::_notification(int p_what) { update_mutex->lock(); #endif VS::get_singleton()->disconnect("frame_pre_draw", this, "_update_render_thread"); + VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_REDRAW_FRAME_IF_VISIBLE, false); + #ifndef NO_THREADS update_mutex->unlock(); #endif diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp index e836a6154a..e277cae5b7 100644 --- a/scene/3d/mesh_instance.cpp +++ b/scene/3d/mesh_instance.cpp @@ -36,6 +36,7 @@ #include "scene/resources/material.h" #include "scene/scene_string_names.h" #include "skeleton.h" + bool MeshInstance::_set(const StringName &p_name, const Variant &p_value) { //this is not _too_ bad performance wise, really. it only arrives here if the property was not set anywhere else. @@ -256,7 +257,7 @@ void MeshInstance::set_surface_material(int p_surface, const Ref<Material> &p_ma ERR_FAIL_INDEX(p_surface, materials.size()); - materials[p_surface] = p_material; + materials.write[p_surface] = p_material; if (materials[p_surface].is_valid()) VS::get_singleton()->instance_set_surface_material(get_instance(), p_surface, materials[p_surface]->get_rid()); diff --git a/scene/3d/mesh_instance.h b/scene/3d/mesh_instance.h index 5d359cd4d5..0dfec538f9 100644 --- a/scene/3d/mesh_instance.h +++ b/scene/3d/mesh_instance.h @@ -41,6 +41,7 @@ class MeshInstance : public GeometryInstance { GDCLASS(MeshInstance, GeometryInstance); +protected: Ref<Mesh> mesh; NodePath skeleton_path; diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp index 77bf703706..f5b77d361c 100644 --- a/scene/3d/navigation.cpp +++ b/scene/3d/navigation.cpp @@ -73,7 +73,7 @@ void Navigation::_navmesh_link(int p_id) { Vector3 ep = nm.xform.xform(r[idx]); center += ep; e.point = _get_point(ep); - p.edges[j] = e; + p.edges.write[j] = e; if (j >= 2) { Vector3 epa = nm.xform.xform(r[indices[j - 2]]); @@ -118,7 +118,7 @@ void Navigation::_navmesh_link(int p_id) { ConnectionPending pending; pending.polygon = &p; pending.edge = j; - p.edges[j].P = C->get().pending.push_back(pending); + p.edges.write[j].P = C->get().pending.push_back(pending); continue; //print_line(String()+_get_vertex(ek.a)+" -> "+_get_vertex(ek.b)); } @@ -126,10 +126,10 @@ void Navigation::_navmesh_link(int p_id) { C->get().B = &p; C->get().B_edge = j; - C->get().A->edges[C->get().A_edge].C = &p; - C->get().A->edges[C->get().A_edge].C_edge = j; - p.edges[j].C = C->get().A; - p.edges[j].C_edge = C->get().A_edge; + C->get().A->edges.write[C->get().A_edge].C = &p; + C->get().A->edges.write[C->get().A_edge].C_edge = j; + p.edges.write[j].C = C->get().A; + p.edges.write[j].C_edge = C->get().A_edge; //connection successful. } } @@ -165,10 +165,10 @@ void Navigation::_navmesh_unlink(int p_id) { } else if (C->get().B) { //disconnect - C->get().B->edges[C->get().B_edge].C = NULL; - C->get().B->edges[C->get().B_edge].C_edge = -1; - C->get().A->edges[C->get().A_edge].C = NULL; - C->get().A->edges[C->get().A_edge].C_edge = -1; + C->get().B->edges.write[C->get().B_edge].C = NULL; + C->get().B->edges.write[C->get().B_edge].C_edge = -1; + C->get().A->edges.write[C->get().A_edge].C = NULL; + C->get().A->edges.write[C->get().A_edge].C_edge = -1; if (C->get().A == &E->get()) { @@ -185,11 +185,11 @@ void Navigation::_navmesh_unlink(int p_id) { C->get().B = cp.polygon; C->get().B_edge = cp.edge; - C->get().A->edges[C->get().A_edge].C = cp.polygon; - C->get().A->edges[C->get().A_edge].C_edge = cp.edge; - cp.polygon->edges[cp.edge].C = C->get().A; - cp.polygon->edges[cp.edge].C_edge = C->get().A_edge; - cp.polygon->edges[cp.edge].P = NULL; + C->get().A->edges.write[C->get().A_edge].C = cp.polygon; + C->get().A->edges.write[C->get().A_edge].C_edge = cp.edge; + cp.polygon->edges.write[cp.edge].C = C->get().A; + cp.polygon->edges.write[cp.edge].C_edge = C->get().A_edge; + cp.polygon->edges.write[cp.edge].P = NULL; } } else { @@ -320,8 +320,8 @@ Vector<Vector3> Navigation::get_simple_path(const Vector3 &p_start, const Vector Vector<Vector3> path; path.resize(2); - path[0] = begin_point; - path[1] = end_point; + path.write[0] = begin_point; + path.write[1] = end_point; //print_line("Direct Path"); return path; } @@ -375,7 +375,7 @@ Vector<Vector3> Navigation::get_simple_path(const Vector3 &p_start, const Vector for (int i = 0; i < p->edges.size(); i++) { - Polygon::Edge &e = p->edges[i]; + Polygon::Edge &e = p->edges.write[i]; if (!e.C) continue; diff --git a/scene/3d/navigation_mesh.cpp b/scene/3d/navigation_mesh.cpp index 073e56fdb4..99680b7273 100644 --- a/scene/3d/navigation_mesh.cpp +++ b/scene/3d/navigation_mesh.cpp @@ -55,9 +55,9 @@ void NavigationMesh::create_from_mesh(const Ref<Mesh> &p_mesh) { for (int j = 0; j < rlen; j += 3) { Vector<int> vi; vi.resize(3); - vi[0] = r[j + 0] + from; - vi[1] = r[j + 1] + from; - vi[2] = r[j + 2] + from; + vi.write[0] = r[j + 0] + from; + vi.write[1] = r[j + 1] + from; + vi.write[2] = r[j + 2] + from; add_polygon(vi); } @@ -215,7 +215,7 @@ void NavigationMesh::_set_polygons(const Array &p_array) { polygons.resize(p_array.size()); for (int i = 0; i < p_array.size(); i++) { - polygons[i].indices = p_array[i]; + polygons.write[i].indices = p_array[i]; } } diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp index 2b3a62fcdc..4900692155 100644 --- a/scene/3d/particles.cpp +++ b/scene/3d/particles.cpp @@ -185,7 +185,7 @@ void Particles::set_draw_pass_mesh(int p_pass, const Ref<Mesh> &p_mesh) { ERR_FAIL_INDEX(p_pass, draw_passes.size()); - draw_passes[p_pass] = p_mesh; + draw_passes.write[p_pass] = p_mesh; RID mesh_rid; if (p_mesh.is_valid()) diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index e851c8d643..9a78fcfa35 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -30,6 +30,7 @@ #include "physics_body.h" +#include "core/core_string_names.h" #include "engine.h" #include "method_bind_ext.gen.inc" #include "scene/scene_string_names.h" @@ -121,23 +122,23 @@ bool PhysicsBody::get_collision_layer_bit(int p_bit) const { void PhysicsBody::add_collision_exception_with(Node *p_node) { ERR_FAIL_NULL(p_node); - PhysicsBody *physics_body = Object::cast_to<PhysicsBody>(p_node); - if (!physics_body) { - ERR_EXPLAIN("Collision exception only works between two objects of PhysicsBody type"); + CollisionObject *collision_object = Object::cast_to<CollisionObject>(p_node); + if (!collision_object) { + ERR_EXPLAIN("Collision exception only works between two CollisionObject"); } - ERR_FAIL_COND(!physics_body); - PhysicsServer::get_singleton()->body_add_collision_exception(get_rid(), physics_body->get_rid()); + ERR_FAIL_COND(!collision_object); + PhysicsServer::get_singleton()->body_add_collision_exception(get_rid(), collision_object->get_rid()); } void PhysicsBody::remove_collision_exception_with(Node *p_node) { ERR_FAIL_NULL(p_node); - PhysicsBody *physics_body = Object::cast_to<PhysicsBody>(p_node); - if (!physics_body) { - ERR_EXPLAIN("Collision exception only works between two objects of PhysicsBody type"); + CollisionObject *collision_object = Object::cast_to<CollisionObject>(p_node); + if (!collision_object) { + ERR_EXPLAIN("Collision exception only works between two CollisionObject"); } - ERR_FAIL_COND(!physics_body); - PhysicsServer::get_singleton()->body_remove_collision_exception(get_rid(), physics_body->get_rid()); + ERR_FAIL_COND(!collision_object); + PhysicsServer::get_singleton()->body_remove_collision_exception(get_rid(), collision_object->get_rid()); } void PhysicsBody::_set_layers(uint32_t p_mask) { @@ -178,28 +179,75 @@ PhysicsBody::PhysicsBody(PhysicsServer::BodyMode p_mode) : collision_mask = 1; } +#ifndef DISABLE_DEPRECATED void StaticBody::set_friction(real_t p_friction) { + ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physical material") + WARN_DEPRECATED + ERR_FAIL_COND(p_friction < 0 || p_friction > 1); - friction = p_friction; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, friction); + if (physics_material_override.is_null()) { + physics_material_override.instance(); + } + physics_material_override->set_friction(p_friction); + _reload_physics_characteristics(); } + real_t StaticBody::get_friction() const { - return friction; + ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physical material") + WARN_DEPRECATED + + if (physics_material_override.is_null()) { + return 1; + } + + return physics_material_override->get_friction(); } void StaticBody::set_bounce(real_t p_bounce) { + ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physical material") + WARN_DEPRECATED + ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1); - bounce = p_bounce; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, bounce); + if (physics_material_override.is_null()) { + physics_material_override.instance(); + } + physics_material_override->set_bounce(p_bounce); + _reload_physics_characteristics(); } + real_t StaticBody::get_bounce() const { - return bounce; + ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physical material") + WARN_DEPRECATED + + if (physics_material_override.is_null()) { + return 0; + } + + return physics_material_override->get_bounce(); +} +#endif + +void StaticBody::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) { + if (physics_material_override.is_valid()) { + physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics"); + } + + physics_material_override = p_physics_material_override; + + if (physics_material_override.is_valid()) { + physics_material_override->connect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics"); + } + _reload_physics_characteristics(); +} + +Ref<PhysicsMaterial> StaticBody::get_physics_material_override() const { + return physics_material_override; } void StaticBody::set_constant_linear_velocity(const Vector3 &p_vel) { @@ -236,24 +284,39 @@ void StaticBody::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bounce", "bounce"), &StaticBody::set_bounce); ClassDB::bind_method(D_METHOD("get_bounce"), &StaticBody::get_bounce); + ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody::set_physics_material_override); + ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody::get_physics_material_override); + + ClassDB::bind_method(D_METHOD("_reload_physics_characteristics"), &StaticBody::_reload_physics_characteristics); + ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody::add_collision_exception_with); ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &PhysicsBody::remove_collision_exception_with); ADD_PROPERTY(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce"); - + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity"); } StaticBody::StaticBody() : PhysicsBody(PhysicsServer::BODY_MODE_STATIC) { - - bounce = 0; - friction = 1; } -StaticBody::~StaticBody() { +StaticBody::~StaticBody() {} + +void StaticBody::_reload_physics_characteristics() { + if (physics_material_override.is_null()) { + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, 0); + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, 1); + PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, PhysicsServer::COMBINE_MODE_INHERIT); + PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, PhysicsServer::COMBINE_MODE_INHERIT); + } else { + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->get_bounce()); + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->get_friction()); + PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->get_bounce_combine_mode()); + PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->get_friction_combine_mode()); + } } void RigidBody::_body_enter_tree(ObjectID p_id) { @@ -550,28 +613,67 @@ real_t RigidBody::get_weight() const { return mass * real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8)); } +#ifndef DISABLE_DEPRECATED void RigidBody::set_friction(real_t p_friction) { + ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physical material") + WARN_DEPRECATED ERR_FAIL_COND(p_friction < 0 || p_friction > 1); - friction = p_friction; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, friction); + if (physics_material_override.is_null()) { + physics_material_override.instance(); + } + physics_material_override->set_friction(p_friction); + _reload_physics_characteristics(); } real_t RigidBody::get_friction() const { - return friction; + ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physical material") + WARN_DEPRECATED + if (physics_material_override.is_null()) { + return 1; + } + + return physics_material_override->get_friction(); } void RigidBody::set_bounce(real_t p_bounce) { - + ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physical material") + WARN_DEPRECATED ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1); - bounce = p_bounce; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, bounce); + if (physics_material_override.is_null()) { + physics_material_override.instance(); + } + physics_material_override->set_bounce(p_bounce); + _reload_physics_characteristics(); } real_t RigidBody::get_bounce() const { + ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physical material") + WARN_DEPRECATED + if (physics_material_override.is_null()) { + return 0; + } - return bounce; + return physics_material_override->get_bounce(); +} +#endif + +void RigidBody::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) { + if (physics_material_override.is_valid()) { + physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics"); + } + + physics_material_override = p_physics_material_override; + + if (physics_material_override.is_valid()) { + physics_material_override->connect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics"); + } + _reload_physics_characteristics(); +} + +Ref<PhysicsMaterial> RigidBody::get_physics_material_override() const { + return physics_material_override; } void RigidBody::set_gravity_scale(real_t p_gravity_scale) { @@ -693,6 +795,22 @@ int RigidBody::get_max_contacts_reported() const { return max_contacts_reported; } +void RigidBody::add_central_force(const Vector3 &p_force) { + PhysicsServer::get_singleton()->body_add_central_force(get_rid(), p_force); +} + +void RigidBody::add_force(const Vector3 &p_force, const Vector3 &p_pos) { + PhysicsServer::get_singleton()->body_add_force(get_rid(), p_force, p_pos); +} + +void RigidBody::add_torque(const Vector3 &p_torque) { + PhysicsServer::get_singleton()->body_add_torque(get_rid(), p_torque); +} + +void RigidBody::apply_central_impulse(const Vector3 &p_impulse) { + PhysicsServer::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); +} + void RigidBody::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) { PhysicsServer::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse); @@ -812,6 +930,11 @@ void RigidBody::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bounce", "bounce"), &RigidBody::set_bounce); ClassDB::bind_method(D_METHOD("get_bounce"), &RigidBody::get_bounce); + ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidBody::set_physics_material_override); + ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidBody::get_physics_material_override); + + ClassDB::bind_method(D_METHOD("_reload_physics_characteristics"), &RigidBody::_reload_physics_characteristics); + ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &RigidBody::set_linear_velocity); ClassDB::bind_method(D_METHOD("get_linear_velocity"), &RigidBody::get_linear_velocity); @@ -840,6 +963,12 @@ void RigidBody::_bind_methods() { ClassDB::bind_method(D_METHOD("is_using_continuous_collision_detection"), &RigidBody::is_using_continuous_collision_detection); ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidBody::set_axis_velocity); + + ClassDB::bind_method(D_METHOD("add_central_force", "force"), &RigidBody::add_central_force); + ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &RigidBody::add_force); + ClassDB::bind_method(D_METHOD("add_torque", "torque"), &RigidBody::add_torque); + + ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody::apply_central_impulse); ClassDB::bind_method(D_METHOD("apply_impulse", "position", "impulse"), &RigidBody::apply_impulse); ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &RigidBody::apply_torque_impulse); @@ -865,6 +994,7 @@ void RigidBody::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "weight", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01", PROPERTY_USAGE_EDITOR), "set_weight", "get_weight"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "continuous_cd"), "set_use_continuous_collision_detection", "is_using_continuous_collision_detection"); @@ -903,9 +1033,7 @@ RigidBody::RigidBody() : mode = MODE_RIGID; - bounce = 0; mass = 1; - friction = 1; max_contacts_reported = 0; state = NULL; @@ -929,6 +1057,21 @@ RigidBody::~RigidBody() { if (contact_monitor) memdelete(contact_monitor); } + +void RigidBody::_reload_physics_characteristics() { + if (physics_material_override.is_null()) { + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, 0); + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, 1); + PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, PhysicsServer::COMBINE_MODE_INHERIT); + PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, PhysicsServer::COMBINE_MODE_INHERIT); + } else { + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->get_bounce()); + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->get_friction()); + PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->get_bounce_combine_mode()); + PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->get_friction_combine_mode()); + } +} + ////////////////////////////////////////////////////// ////////////////////////// @@ -1117,11 +1260,11 @@ Ref<KinematicCollision> KinematicBody::_get_slide_collision(int p_bounce) { } if (slide_colliders[p_bounce].is_null()) { - slide_colliders[p_bounce].instance(); - slide_colliders[p_bounce]->owner = this; + slide_colliders.write[p_bounce].instance(); + slide_colliders.write[p_bounce]->owner = this; } - slide_colliders[p_bounce]->collision = colliders[p_bounce]; + slide_colliders.write[p_bounce]->collision = colliders[p_bounce]; return slide_colliders[p_bounce]; } @@ -1174,7 +1317,7 @@ KinematicBody::~KinematicBody() { for (int i = 0; i < slide_colliders.size(); i++) { if (slide_colliders[i].is_valid()) { - slide_colliders[i]->owner = NULL; + slide_colliders.write[i]->owner = NULL; } } } @@ -2228,6 +2371,7 @@ void PhysicalBone::set_bounce(real_t p_bounce) { bounce = p_bounce; PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, bounce); } + real_t PhysicalBone::get_bounce() const { return bounce; diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index 7236eba685..4143989671 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -32,6 +32,7 @@ #define PHYSICS_BODY__H #include "scene/3d/collision_object.h" +#include "scene/resources/physics_material.h" #include "servers/physics_server.h" #include "skeleton.h" #include "vset.h" @@ -81,18 +82,22 @@ class StaticBody : public PhysicsBody { Vector3 constant_linear_velocity; Vector3 constant_angular_velocity; - real_t bounce; - real_t friction; + Ref<PhysicsMaterial> physics_material_override; protected: static void _bind_methods(); public: +#ifndef DISABLE_DEPRECATED void set_friction(real_t p_friction); real_t get_friction() const; void set_bounce(real_t p_bounce); real_t get_bounce() const; +#endif + + void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override); + Ref<PhysicsMaterial> get_physics_material_override() const; void set_constant_linear_velocity(const Vector3 &p_vel); void set_constant_angular_velocity(const Vector3 &p_vel); @@ -102,6 +107,9 @@ public: StaticBody(); ~StaticBody(); + +private: + void _reload_physics_characteristics(); }; class RigidBody : public PhysicsBody { @@ -121,9 +129,8 @@ protected: PhysicsDirectBodyState *state; Mode mode; - real_t bounce; real_t mass; - real_t friction; + Ref<PhysicsMaterial> physics_material_override; Vector3 linear_velocity; Vector3 angular_velocity; @@ -196,11 +203,16 @@ public: void set_weight(real_t p_weight); real_t get_weight() const; +#ifndef DISABLE_DEPRECATED void set_friction(real_t p_friction); real_t get_friction() const; void set_bounce(real_t p_bounce); real_t get_bounce() const; +#endif + + void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override); + Ref<PhysicsMaterial> get_physics_material_override() const; void set_linear_velocity(const Vector3 &p_velocity); Vector3 get_linear_velocity() const; @@ -242,6 +254,11 @@ public: Array get_colliding_bodies() const; + void add_central_force(const Vector3 &p_force); + void add_force(const Vector3 &p_force, const Vector3 &p_pos); + void add_torque(const Vector3 &p_torque); + + void apply_central_impulse(const Vector3 &p_impulse); void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse); void apply_torque_impulse(const Vector3 &p_impulse); @@ -249,6 +266,9 @@ public: RigidBody(); ~RigidBody(); + +private: + void _reload_physics_characteristics(); }; VARIANT_ENUM_CAST(RigidBody::Mode); diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index 8d91b6f09f..4b6b59b2d3 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -66,7 +66,7 @@ bool Skeleton::_set(const StringName &p_path, const Variant &p_value) { Array children = p_value; if (is_inside_tree()) { - bones[which].nodes_bound.clear(); + bones.write[which].nodes_bound.clear(); for (int i = 0; i < children.size(); i++) { @@ -176,7 +176,7 @@ void Skeleton::_notification(int p_what) { case NOTIFICATION_UPDATE_SKELETON: { VisualServer *vs = VisualServer::get_singleton(); - Bone *bonesptr = &bones[0]; + Bone *bonesptr = bones.ptrw(); int len = bones.size(); vs->skeleton_allocate(skeleton, len); // if same size, nothin really happens @@ -370,7 +370,7 @@ void Skeleton::set_bone_parent(int p_bone, int p_parent) { ERR_FAIL_INDEX(p_bone, bones.size()); ERR_FAIL_COND(p_parent != -1 && (p_parent < 0 || p_parent >= p_bone)); - bones[p_bone].parent = p_parent; + bones.write[p_bone].parent = p_parent; rest_global_inverse_dirty = true; _make_dirty(); } @@ -381,19 +381,19 @@ void Skeleton::unparent_bone_and_rest(int p_bone) { int parent = bones[p_bone].parent; while (parent >= 0) { - bones[p_bone].rest = bones[parent].rest * bones[p_bone].rest; + bones.write[p_bone].rest = bones[parent].rest * bones[p_bone].rest; parent = bones[parent].parent; } - bones[p_bone].parent = -1; - bones[p_bone].rest_global_inverse = bones[p_bone].rest.affine_inverse(); //same thing + bones.write[p_bone].parent = -1; + bones.write[p_bone].rest_global_inverse = bones[p_bone].rest.affine_inverse(); //same thing _make_dirty(); } void Skeleton::set_bone_ignore_animation(int p_bone, bool p_ignore) { ERR_FAIL_INDEX(p_bone, bones.size()); - bones[p_bone].ignore_animation = p_ignore; + bones.write[p_bone].ignore_animation = p_ignore; } bool Skeleton::is_bone_ignore_animation(int p_bone) const { @@ -405,7 +405,7 @@ bool Skeleton::is_bone_ignore_animation(int p_bone) const { void Skeleton::set_bone_disable_rest(int p_bone, bool p_disable) { ERR_FAIL_INDEX(p_bone, bones.size()); - bones[p_bone].disable_rest = p_disable; + bones.write[p_bone].disable_rest = p_disable; } bool Skeleton::is_bone_rest_disabled(int p_bone) const { @@ -425,7 +425,7 @@ void Skeleton::set_bone_rest(int p_bone, const Transform &p_rest) { ERR_FAIL_INDEX(p_bone, bones.size()); - bones[p_bone].rest = p_rest; + bones.write[p_bone].rest = p_rest; rest_global_inverse_dirty = true; _make_dirty(); } @@ -440,7 +440,7 @@ void Skeleton::set_bone_enabled(int p_bone, bool p_enabled) { ERR_FAIL_INDEX(p_bone, bones.size()); - bones[p_bone].enabled = p_enabled; + bones.write[p_bone].enabled = p_enabled; rest_global_inverse_dirty = true; _make_dirty(); } @@ -457,13 +457,13 @@ void Skeleton::bind_child_node_to_bone(int p_bone, Node *p_node) { uint32_t id = p_node->get_instance_id(); - for (List<uint32_t>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) { + for (const List<uint32_t>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) { if (E->get() == id) return; // already here } - bones[p_bone].nodes_bound.push_back(id); + bones.write[p_bone].nodes_bound.push_back(id); } void Skeleton::unbind_child_node_from_bone(int p_bone, Node *p_node) { @@ -471,7 +471,7 @@ void Skeleton::unbind_child_node_from_bone(int p_bone, Node *p_node) { ERR_FAIL_INDEX(p_bone, bones.size()); uint32_t id = p_node->get_instance_id(); - bones[p_bone].nodes_bound.erase(id); + bones.write[p_bone].nodes_bound.erase(id); } void Skeleton::get_bound_child_nodes_to_bone(int p_bone, List<Node *> *p_bound) const { @@ -499,7 +499,7 @@ void Skeleton::set_bone_pose(int p_bone, const Transform &p_pose) { ERR_FAIL_INDEX(p_bone, bones.size()); ERR_FAIL_COND(!is_inside_tree()); - bones[p_bone].pose = p_pose; + bones.write[p_bone].pose = p_pose; _make_dirty(); } Transform Skeleton::get_bone_pose(int p_bone) const { @@ -513,8 +513,8 @@ void Skeleton::set_bone_custom_pose(int p_bone, const Transform &p_custom_pose) ERR_FAIL_INDEX(p_bone, bones.size()); //ERR_FAIL_COND( !is_inside_scene() ); - bones[p_bone].custom_pose_enable = (p_custom_pose != Transform()); - bones[p_bone].custom_pose = p_custom_pose; + bones.write[p_bone].custom_pose_enable = (p_custom_pose != Transform()); + bones.write[p_bone].custom_pose = p_custom_pose; _make_dirty(); } @@ -553,14 +553,14 @@ void Skeleton::bind_physical_bone_to_bone(int p_bone, PhysicalBone *p_physical_b ERR_FAIL_INDEX(p_bone, bones.size()); ERR_FAIL_COND(bones[p_bone].physical_bone); ERR_FAIL_COND(!p_physical_bone); - bones[p_bone].physical_bone = p_physical_bone; + bones.write[p_bone].physical_bone = p_physical_bone; _rebuild_physical_bones_cache(); } void Skeleton::unbind_physical_bone_from_bone(int p_bone) { ERR_FAIL_INDEX(p_bone, bones.size()); - bones[p_bone].physical_bone = NULL; + bones.write[p_bone].physical_bone = NULL; _rebuild_physical_bones_cache(); } @@ -600,7 +600,7 @@ PhysicalBone *Skeleton::_get_physical_bone_parent(int p_bone) { void Skeleton::_rebuild_physical_bones_cache() { const int b_size = bones.size(); for (int i = 0; i < b_size; ++i) { - bones[i].cache_parent_physical_bone = _get_physical_bone_parent(i); + bones.write[i].cache_parent_physical_bone = _get_physical_bone_parent(i); if (bones[i].physical_bone) bones[i].physical_bone->_on_bone_parent_changed(); } @@ -660,7 +660,7 @@ void Skeleton::physical_bones_start_simulation_on(const Array &p_bones) { if (Variant::STRING == p_bones.get(i).get_type()) { int bone_id = find_bone(p_bones.get(i)); if (bone_id != -1) - sim_bones[c++] = bone_id; + sim_bones.write[c++] = bone_id; } } sim_bones.resize(c); diff --git a/scene/3d/soft_body.cpp b/scene/3d/soft_body.cpp new file mode 100644 index 0000000000..8498dc34c0 --- /dev/null +++ b/scene/3d/soft_body.cpp @@ -0,0 +1,740 @@ +/*************************************************************************/ +/* soft_physics_body.cpp */ +/* Author: AndreaCatania */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "soft_body.h" +#include "os/os.h" +#include "scene/3d/collision_object.h" +#include "scene/3d/skeleton.h" +#include "servers/physics_server.h" + +SoftBodyVisualServerHandler::SoftBodyVisualServerHandler() {} + +void SoftBodyVisualServerHandler::prepare(RID p_mesh, int p_surface) { + clear(); + + ERR_FAIL_COND(!p_mesh.is_valid()); + + mesh = p_mesh; + surface = p_surface; + + const uint32_t surface_format = VS::get_singleton()->mesh_surface_get_format(mesh, surface); + const int surface_vertex_len = VS::get_singleton()->mesh_surface_get_array_len(mesh, p_surface); + const int surface_index_len = VS::get_singleton()->mesh_surface_get_array_index_len(mesh, p_surface); + uint32_t surface_offsets[VS::ARRAY_MAX]; + + buffer = VS::get_singleton()->mesh_surface_get_array(mesh, surface); + stride = VS::get_singleton()->mesh_surface_make_offsets_from_format(surface_format, surface_vertex_len, surface_index_len, surface_offsets); + offset_vertices = surface_offsets[VS::ARRAY_VERTEX]; + offset_normal = surface_offsets[VS::ARRAY_NORMAL]; +} + +void SoftBodyVisualServerHandler::clear() { + + if (mesh.is_valid()) { + buffer.resize(0); + } + + mesh = RID(); +} + +void SoftBodyVisualServerHandler::open() { + write_buffer = buffer.write(); +} + +void SoftBodyVisualServerHandler::close() { + write_buffer = PoolVector<uint8_t>::Write(); +} + +void SoftBodyVisualServerHandler::commit_changes() { + VS::get_singleton()->mesh_surface_update_region(mesh, surface, 0, buffer); +} + +void SoftBodyVisualServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) { + copymem(&write_buffer[p_vertex_id * stride + offset_vertices], p_vector3, sizeof(float) * 3); +} + +void SoftBodyVisualServerHandler::set_normal(int p_vertex_id, const void *p_vector3) { + copymem(&write_buffer[p_vertex_id * stride + offset_normal], p_vector3, sizeof(float) * 3); +} + +void SoftBodyVisualServerHandler::set_aabb(const AABB &p_aabb) { + VS::get_singleton()->mesh_set_custom_aabb(mesh, p_aabb); +} + +SoftBody::PinnedPoint::PinnedPoint() : + point_index(-1), + spatial_attachment(NULL) { +} + +SoftBody::PinnedPoint::PinnedPoint(const PinnedPoint &obj_tocopy) { + point_index = obj_tocopy.point_index; + spatial_attachment_path = obj_tocopy.spatial_attachment_path; + spatial_attachment = obj_tocopy.spatial_attachment; + vertex_offset_transform = obj_tocopy.vertex_offset_transform; +} + +void SoftBody::_update_pickable() { + if (!is_inside_tree()) + return; + bool pickable = ray_pickable && is_inside_tree() && is_visible_in_tree(); + PhysicsServer::get_singleton()->soft_body_set_ray_pickable(physics_rid, pickable); +} + +bool SoftBody::_set(const StringName &p_name, const Variant &p_value) { + String name = p_name; + String which = name.get_slicec('/', 0); + + if ("pinned_points" == which) { + + return _set_property_pinned_points_indices(p_value); + + } else if ("attachments" == which) { + + int idx = name.get_slicec('/', 1).to_int(); + String what = name.get_slicec('/', 2); + + return _set_property_pinned_points_attachment(idx, what, p_value); + } + + return false; +} + +bool SoftBody::_get(const StringName &p_name, Variant &r_ret) const { + String name = p_name; + String which = name.get_slicec('/', 0); + + if ("pinned_points" == which) { + Array arr_ret; + const int pinned_points_indices_size = pinned_points_indices.size(); + PoolVector<PinnedPoint>::Read r = pinned_points_indices.read(); + arr_ret.resize(pinned_points_indices_size); + + for (int i = 0; i < pinned_points_indices_size; ++i) { + arr_ret[i] = r[i].point_index; + } + + r_ret = arr_ret; + return true; + + } else if ("attachments" == which) { + + int idx = name.get_slicec('/', 1).to_int(); + String what = name.get_slicec('/', 2); + + return _get_property_pinned_points(idx, what, r_ret); + } + + return false; +} + +void SoftBody::_get_property_list(List<PropertyInfo> *p_list) const { + + const int pinned_points_indices_size = pinned_points_indices.size(); + + p_list->push_back(PropertyInfo(Variant::POOL_INT_ARRAY, "pinned_points")); + + for (int i = 0; i < pinned_points_indices_size; ++i) { + p_list->push_back(PropertyInfo(Variant::INT, "attachments/" + itos(i) + "/point_index")); + p_list->push_back(PropertyInfo(Variant::NODE_PATH, "attachments/" + itos(i) + "/spatial_attachment_path")); + } +} + +bool SoftBody::_set_property_pinned_points_indices(const Array &p_indices) { + + const int p_indices_size = p_indices.size(); + + { // Remove the pined points on physics server that will be removed by resize + PoolVector<PinnedPoint>::Read r = pinned_points_indices.read(); + if (p_indices_size < pinned_points_indices.size()) { + for (int i = pinned_points_indices.size() - 1; i >= p_indices_size; --i) { + pin_point(r[i].point_index, false); + } + } + } + + pinned_points_indices.resize(p_indices_size); + + PoolVector<PinnedPoint>::Write w = pinned_points_indices.write(); + int point_index; + for (int i = 0; i < p_indices_size; ++i) { + point_index = p_indices.get(i); + if (w[i].point_index != point_index) { + if (-1 != w[i].point_index) + pin_point(w[i].point_index, false); + w[i].point_index = point_index; + pin_point(w[i].point_index, true); + } + } + return true; +} + +bool SoftBody::_set_property_pinned_points_attachment(int p_item, const String &p_what, const Variant &p_value) { + if (pinned_points_indices.size() <= p_item) { + return false; + } + + if ("spatial_attachment_path" == p_what) { + PoolVector<PinnedPoint>::Write w = pinned_points_indices.write(); + pin_point(w[p_item].point_index, true, p_value); + } else { + return false; + } + + return true; +} + +bool SoftBody::_get_property_pinned_points(int p_item, const String &p_what, Variant &r_ret) const { + if (pinned_points_indices.size() <= p_item) { + return false; + } + PoolVector<PinnedPoint>::Read r = pinned_points_indices.read(); + + if ("point_index" == p_what) { + r_ret = r[p_item].point_index; + } else if ("spatial_attachment_path" == p_what) { + r_ret = r[p_item].spatial_attachment_path; + } else { + return false; + } + + return true; +} + +void SoftBody::_changed_callback(Object *p_changed, const char *p_prop) { +#ifdef TOOLS_ENABLED + if (p_changed == this) { + update_configuration_warning(); + } +#endif +} + +void SoftBody::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_WORLD: { + + if (Engine::get_singleton()->is_editor_hint()) + add_change_receptor(this); + + RID space = get_world()->get_space(); + PhysicsServer::get_singleton()->soft_body_set_space(physics_rid, space); + PhysicsServer::get_singleton()->soft_body_set_transform(physics_rid, get_global_transform()); + update_physics_server(); + } break; + case NOTIFICATION_READY: { + if (!parent_collision_ignore.is_empty()) + add_collision_exception_with(get_node(parent_collision_ignore)); + + } break; + case NOTIFICATION_TRANSFORM_CHANGED: { + + if (!simulation_started) { + PhysicsServer::get_singleton()->soft_body_set_transform(physics_rid, get_global_transform()); + + _update_cache_pin_points_datas(); + // Submit bone attachment + const int pinned_points_indices_size = pinned_points_indices.size(); + PoolVector<PinnedPoint>::Read r = pinned_points_indices.read(); + for (int i = 0; i < pinned_points_indices_size; ++i) { + if (!r[i].spatial_attachment) { + // Use soft body position to update the point position + PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, (get_global_transform() * r[i].vertex_offset_transform).origin); + } else { + PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, (r[i].spatial_attachment->get_global_transform() * r[i].vertex_offset_transform).origin); + } + } + } + } break; + case NOTIFICATION_VISIBILITY_CHANGED: { + + _update_pickable(); + + } break; + case NOTIFICATION_EXIT_WORLD: { + + PhysicsServer::get_singleton()->soft_body_set_space(physics_rid, RID()); + + } break; + } + +#ifdef TOOLS_ENABLED + + if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { + if (Engine::get_singleton()->is_editor_hint()) { + update_configuration_warning(); + } + } + +#endif +} + +void SoftBody::_bind_methods() { + + ClassDB::bind_method(D_METHOD("_draw_soft_mesh"), &SoftBody::_draw_soft_mesh); + + ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &SoftBody::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &SoftBody::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_collision_layer", "collision_layer"), &SoftBody::set_collision_layer); + ClassDB::bind_method(D_METHOD("get_collision_layer"), &SoftBody::get_collision_layer); + + ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &SoftBody::set_collision_mask_bit); + ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &SoftBody::get_collision_mask_bit); + + ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &SoftBody::set_collision_layer_bit); + ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &SoftBody::get_collision_layer_bit); + + ClassDB::bind_method(D_METHOD("set_parent_collision_ignore", "parent_collision_ignore"), &SoftBody::set_parent_collision_ignore); + ClassDB::bind_method(D_METHOD("get_parent_collision_ignore"), &SoftBody::get_parent_collision_ignore); + + ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &SoftBody::add_collision_exception_with); + ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &SoftBody::remove_collision_exception_with); + + ClassDB::bind_method(D_METHOD("set_simulation_precision", "simulation_precision"), &SoftBody::set_simulation_precision); + ClassDB::bind_method(D_METHOD("get_simulation_precision"), &SoftBody::get_simulation_precision); + + ClassDB::bind_method(D_METHOD("set_total_mass", "mass"), &SoftBody::set_total_mass); + ClassDB::bind_method(D_METHOD("get_total_mass"), &SoftBody::get_total_mass); + + ClassDB::bind_method(D_METHOD("set_linear_stiffness", "linear_stiffness"), &SoftBody::set_linear_stiffness); + ClassDB::bind_method(D_METHOD("get_linear_stiffness"), &SoftBody::get_linear_stiffness); + + ClassDB::bind_method(D_METHOD("set_areaAngular_stiffness", "areaAngular_stiffness"), &SoftBody::set_areaAngular_stiffness); + ClassDB::bind_method(D_METHOD("get_areaAngular_stiffness"), &SoftBody::get_areaAngular_stiffness); + + ClassDB::bind_method(D_METHOD("set_volume_stiffness", "volume_stiffness"), &SoftBody::set_volume_stiffness); + ClassDB::bind_method(D_METHOD("get_volume_stiffness"), &SoftBody::get_volume_stiffness); + + ClassDB::bind_method(D_METHOD("set_pressure_coefficient", "pressure_coefficient"), &SoftBody::set_pressure_coefficient); + ClassDB::bind_method(D_METHOD("get_pressure_coefficient"), &SoftBody::get_pressure_coefficient); + + ClassDB::bind_method(D_METHOD("set_pose_matching_coefficient", "pose_matching_coefficient"), &SoftBody::set_pose_matching_coefficient); + ClassDB::bind_method(D_METHOD("get_pose_matching_coefficient"), &SoftBody::get_pose_matching_coefficient); + + ClassDB::bind_method(D_METHOD("set_damping_coefficient", "damping_coefficient"), &SoftBody::set_damping_coefficient); + ClassDB::bind_method(D_METHOD("get_damping_coefficient"), &SoftBody::get_damping_coefficient); + + ClassDB::bind_method(D_METHOD("set_drag_coefficient", "drag_coefficient"), &SoftBody::set_drag_coefficient); + ClassDB::bind_method(D_METHOD("get_drag_coefficient"), &SoftBody::get_drag_coefficient); + + ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &SoftBody::set_ray_pickable); + ClassDB::bind_method(D_METHOD("is_ray_pickable"), &SoftBody::is_ray_pickable); + + ADD_GROUP("Collision", "collision_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "parent_collision_ignore", PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE, "Parent collision object"), "set_parent_collision_ignore", "get_parent_collision_ignore"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "simulation_precision", PROPERTY_HINT_RANGE, "1,100,1"), "set_simulation_precision", "get_simulation_precision"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "total_mass", PROPERTY_HINT_RANGE, "0.01,10000,1"), "set_total_mass", "get_total_mass"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "linear_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_linear_stiffness", "get_linear_stiffness"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "areaAngular_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_areaAngular_stiffness", "get_areaAngular_stiffness"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "volume_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_volume_stiffness", "get_volume_stiffness"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "pressure_coefficient"), "set_pressure_coefficient", "get_pressure_coefficient"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "damping_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_damping_coefficient", "get_damping_coefficient"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "drag_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drag_coefficient", "get_drag_coefficient"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "pose_matching_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_pose_matching_coefficient", "get_pose_matching_coefficient"); +} + +String SoftBody::get_configuration_warning() const { + + String warning = MeshInstance::get_configuration_warning(); + + if (get_mesh().is_null()) { + if (!warning.empty()) + warning += "\n\n"; + + warning += TTR("This body will be ignored until you set a mesh"); + } + + Transform t = get_transform(); + if ((ABS(t.basis.get_axis(0).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(1).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(0).length() - 1.0) > 0.05)) { + if (!warning.empty()) + warning += "\n\n"; + + warning += TTR("Size changes to SoftBody will be overriden by the physics engine when running.\nChange the size in children collision shapes instead."); + } + + return warning; +} + +void SoftBody::_draw_soft_mesh() { + if (get_mesh().is_null()) + return; + + if (!visual_server_handler.is_ready()) { + + visual_server_handler.prepare(get_mesh()->get_rid(), 0); + + /// Necessary in order to render the mesh correctly (Soft body nodes are in global space) + simulation_started = true; + call_deferred("set_as_toplevel", true); + call_deferred("set_transform", Transform()); + } + + visual_server_handler.open(); + PhysicsServer::get_singleton()->soft_body_update_visual_server(physics_rid, &visual_server_handler); + visual_server_handler.close(); + + visual_server_handler.commit_changes(); +} + +void SoftBody::update_physics_server() { + + if (Engine::get_singleton()->is_editor_hint()) + return; + + if (get_mesh().is_valid()) { + + become_mesh_owner(); + PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh()); + VS::get_singleton()->connect("frame_pre_draw", this, "_draw_soft_mesh"); + } else { + + PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, NULL); + VS::get_singleton()->disconnect("frame_pre_draw", this, "_draw_soft_mesh"); + } +} + +void SoftBody::become_mesh_owner() { + if (mesh.is_null()) + return; + + if (!mesh_owner) { + mesh_owner = true; + + ERR_FAIL_COND(!mesh->get_surface_count()); + + // Get current mesh array and create new mesh array with necessary flag for softbody + Array surface_arrays = mesh->surface_get_arrays(0); + Array surface_blend_arrays = mesh->surface_get_blend_shape_arrays(0); + uint32_t surface_format = mesh->surface_get_format(0); + + surface_format &= ~(Mesh::ARRAY_COMPRESS_VERTEX | Mesh::ARRAY_COMPRESS_NORMAL); + surface_format |= Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE; + + Ref<ArrayMesh> soft_mesh; + soft_mesh.instance(); + soft_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, surface_arrays, surface_blend_arrays, surface_format); + + set_mesh(soft_mesh); + + Vector<Ref<Material> > copy_materials; + copy_materials.append_array(materials); + for (int i = copy_materials.size() - 1; 0 <= i; --i) { + set_surface_material(i, copy_materials[i]); + } + } +} + +void SoftBody::set_collision_mask(uint32_t p_mask) { + collision_mask = p_mask; + PhysicsServer::get_singleton()->soft_body_set_collision_mask(physics_rid, p_mask); +} + +uint32_t SoftBody::get_collision_mask() const { + return collision_mask; +} +void SoftBody::set_collision_layer(uint32_t p_layer) { + collision_layer = p_layer; + PhysicsServer::get_singleton()->soft_body_set_collision_layer(physics_rid, p_layer); +} + +uint32_t SoftBody::get_collision_layer() const { + return collision_layer; +} + +void SoftBody::set_collision_mask_bit(int p_bit, bool p_value) { + uint32_t mask = get_collision_mask(); + if (p_value) + mask |= 1 << p_bit; + else + mask &= ~(1 << p_bit); + set_collision_mask(mask); +} + +bool SoftBody::get_collision_mask_bit(int p_bit) const { + return get_collision_mask() & (1 << p_bit); +} + +void SoftBody::set_collision_layer_bit(int p_bit, bool p_value) { + uint32_t layer = get_collision_layer(); + if (p_value) + layer |= 1 << p_bit; + else + layer &= ~(1 << p_bit); + set_collision_layer(layer); +} + +bool SoftBody::get_collision_layer_bit(int p_bit) const { + return get_collision_layer() & (1 << p_bit); +} + +void SoftBody::set_parent_collision_ignore(const NodePath &p_parent_collision_ignore) { + parent_collision_ignore = p_parent_collision_ignore; +} + +const NodePath &SoftBody::get_parent_collision_ignore() const { + return parent_collision_ignore; +} + +void SoftBody::set_pinned_points_indices(PoolVector<SoftBody::PinnedPoint> p_pinned_points_indices) { + pinned_points_indices = p_pinned_points_indices; + PoolVector<PinnedPoint>::Read w = pinned_points_indices.read(); + for (int i = pinned_points_indices.size() - 1; 0 <= i; --i) { + pin_point(p_pinned_points_indices[i].point_index, true); + } +} + +PoolVector<SoftBody::PinnedPoint> SoftBody::get_pinned_points_indices() { + return pinned_points_indices; +} + +void SoftBody::add_collision_exception_with(Node *p_node) { + ERR_FAIL_NULL(p_node); + CollisionObject *collision_object = Object::cast_to<CollisionObject>(p_node); + if (!collision_object) { + ERR_EXPLAIN("Collision exception only works between two CollisionObject"); + } + ERR_FAIL_COND(!collision_object); + PhysicsServer::get_singleton()->soft_body_add_collision_exception(physics_rid, collision_object->get_rid()); +} + +void SoftBody::remove_collision_exception_with(Node *p_node) { + ERR_FAIL_NULL(p_node); + CollisionObject *collision_object = Object::cast_to<CollisionObject>(p_node); + if (!collision_object) { + ERR_EXPLAIN("Collision exception only works between two CollisionObject"); + } + ERR_FAIL_COND(!collision_object); + PhysicsServer::get_singleton()->soft_body_remove_collision_exception(physics_rid, collision_object->get_rid()); +} + +int SoftBody::get_simulation_precision() { + return PhysicsServer::get_singleton()->soft_body_get_simulation_precision(physics_rid); +} + +void SoftBody::set_simulation_precision(int p_simulation_precision) { + PhysicsServer::get_singleton()->soft_body_set_simulation_precision(physics_rid, p_simulation_precision); +} + +real_t SoftBody::get_total_mass() { + return PhysicsServer::get_singleton()->soft_body_get_total_mass(physics_rid); +} + +void SoftBody::set_total_mass(real_t p_total_mass) { + PhysicsServer::get_singleton()->soft_body_set_total_mass(physics_rid, p_total_mass); +} + +void SoftBody::set_linear_stiffness(real_t p_linear_stiffness) { + PhysicsServer::get_singleton()->soft_body_set_linear_stiffness(physics_rid, p_linear_stiffness); +} + +real_t SoftBody::get_linear_stiffness() { + return PhysicsServer::get_singleton()->soft_body_get_linear_stiffness(physics_rid); +} + +void SoftBody::set_areaAngular_stiffness(real_t p_areaAngular_stiffness) { + PhysicsServer::get_singleton()->soft_body_set_areaAngular_stiffness(physics_rid, p_areaAngular_stiffness); +} + +real_t SoftBody::get_areaAngular_stiffness() { + return PhysicsServer::get_singleton()->soft_body_get_areaAngular_stiffness(physics_rid); +} + +void SoftBody::set_volume_stiffness(real_t p_volume_stiffness) { + PhysicsServer::get_singleton()->soft_body_set_volume_stiffness(physics_rid, p_volume_stiffness); +} + +real_t SoftBody::get_volume_stiffness() { + return PhysicsServer::get_singleton()->soft_body_get_volume_stiffness(physics_rid); +} + +real_t SoftBody::get_pressure_coefficient() { + return PhysicsServer::get_singleton()->soft_body_get_pressure_coefficient(physics_rid); +} + +void SoftBody::set_pose_matching_coefficient(real_t p_pose_matching_coefficient) { + PhysicsServer::get_singleton()->soft_body_set_pose_matching_coefficient(physics_rid, p_pose_matching_coefficient); +} + +real_t SoftBody::get_pose_matching_coefficient() { + return PhysicsServer::get_singleton()->soft_body_get_pose_matching_coefficient(physics_rid); +} + +void SoftBody::set_pressure_coefficient(real_t p_pressure_coefficient) { + PhysicsServer::get_singleton()->soft_body_set_pressure_coefficient(physics_rid, p_pressure_coefficient); +} + +real_t SoftBody::get_damping_coefficient() { + return PhysicsServer::get_singleton()->soft_body_get_damping_coefficient(physics_rid); +} + +void SoftBody::set_damping_coefficient(real_t p_damping_coefficient) { + PhysicsServer::get_singleton()->soft_body_set_damping_coefficient(physics_rid, p_damping_coefficient); +} + +real_t SoftBody::get_drag_coefficient() { + return PhysicsServer::get_singleton()->soft_body_get_drag_coefficient(physics_rid); +} + +void SoftBody::set_drag_coefficient(real_t p_drag_coefficient) { + PhysicsServer::get_singleton()->soft_body_set_drag_coefficient(physics_rid, p_drag_coefficient); +} + +Vector3 SoftBody::get_point_transform(int p_point_index) { + return PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, p_point_index); +} + +void SoftBody::pin_point_toggle(int p_point_index) { + pin_point(p_point_index, !(-1 != _has_pinned_point(p_point_index))); +} + +void SoftBody::pin_point(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path) { + _pin_point_on_physics_server(p_point_index, pin); + if (pin) { + _add_pinned_point(p_point_index, p_spatial_attachment_path); + } else { + _remove_pinned_point(p_point_index); + } +} + +bool SoftBody::is_point_pinned(int p_point_index) const { + return -1 != _has_pinned_point(p_point_index); +} + +void SoftBody::set_ray_pickable(bool p_ray_pickable) { + + ray_pickable = p_ray_pickable; + _update_pickable(); +} + +bool SoftBody::is_ray_pickable() const { + + return ray_pickable; +} + +SoftBody::SoftBody() : + MeshInstance(), + physics_rid(PhysicsServer::get_singleton()->soft_body_create()), + mesh_owner(false), + collision_mask(1), + collision_layer(1), + simulation_started(false), + pinned_points_cache_dirty(true) { + + PhysicsServer::get_singleton()->body_attach_object_instance_id(physics_rid, get_instance_id()); +} + +SoftBody::~SoftBody() { +} + +void SoftBody::reset_softbody_pin() { + PhysicsServer::get_singleton()->soft_body_remove_all_pinned_points(physics_rid); + PoolVector<PinnedPoint>::Read pps = pinned_points_indices.read(); + for (int i = pinned_points_indices.size() - 1; 0 < i; --i) { + PhysicsServer::get_singleton()->soft_body_pin_point(physics_rid, pps[i].point_index, true); + } +} + +void SoftBody::_update_cache_pin_points_datas() { + if (pinned_points_cache_dirty) { + pinned_points_cache_dirty = false; + + PoolVector<PinnedPoint>::Write w = pinned_points_indices.write(); + for (int i = pinned_points_indices.size() - 1; 0 <= i; --i) { + + if (!w[i].spatial_attachment_path.is_empty()) { + w[i].spatial_attachment = Object::cast_to<Spatial>(get_node(w[i].spatial_attachment_path)); + if (w[i].spatial_attachment) { + + Transform point_global_transform(get_global_transform()); + point_global_transform.translate(PhysicsServer::get_singleton()->soft_body_get_point_offset(physics_rid, w[i].point_index)); + + // Local transform relative to spatial attachment node + w[i].vertex_offset_transform = w[i].spatial_attachment->get_global_transform().affine_inverse() * point_global_transform; + continue; + } else { + ERR_PRINTS("The node with path: " + String(w[i].spatial_attachment_path) + " was not found or is not a spatial node."); + } + } + // Local transform relative to Soft body + w[i].vertex_offset_transform.origin = PhysicsServer::get_singleton()->soft_body_get_point_offset(physics_rid, w[i].point_index); + w[i].vertex_offset_transform.basis = Basis(); + } + } +} + +void SoftBody::_pin_point_on_physics_server(int p_point_index, bool pin) { + PhysicsServer::get_singleton()->soft_body_pin_point(physics_rid, p_point_index, pin); +} + +void SoftBody::_add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path) { + SoftBody::PinnedPoint *pinned_point; + if (-1 == _get_pinned_point(p_point_index, pinned_point)) { + // Create new + PinnedPoint pp; + pp.point_index = p_point_index; + pp.spatial_attachment_path = p_spatial_attachment_path; + pinned_points_indices.push_back(pp); + } else { + // Update + pinned_point->point_index = p_point_index; + pinned_point->spatial_attachment_path = p_spatial_attachment_path; + } +} + +void SoftBody::_remove_pinned_point(int p_point_index) { + const int id(_has_pinned_point(p_point_index)); + if (-1 != id) { + pinned_points_indices.remove(id); + } +} + +int SoftBody::_get_pinned_point(int p_point_index, SoftBody::PinnedPoint *&r_point) const { + const int id = _has_pinned_point(p_point_index); + if (-1 == id) { + r_point = NULL; + return -1; + } else { + r_point = const_cast<SoftBody::PinnedPoint *>(&pinned_points_indices.read()[id]); + return id; + } +} + +int SoftBody::_has_pinned_point(int p_point_index) const { + PoolVector<PinnedPoint>::Read r = pinned_points_indices.read(); + for (int i = pinned_points_indices.size() - 1; 0 <= i; --i) { + if (p_point_index == r[i].point_index) { + return i; + } + } + return -1; +} diff --git a/scene/3d/soft_body.h b/scene/3d/soft_body.h new file mode 100644 index 0000000000..f44f337698 --- /dev/null +++ b/scene/3d/soft_body.h @@ -0,0 +1,197 @@ +/*************************************************************************/ +/* soft_physics_body.h */ +/* Author: AndreaCatania */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SOFT_PHYSICS_BODY_H +#define SOFT_PHYSICS_BODY_H + +#include "scene/3d/mesh_instance.h" + +class SoftBody; + +class SoftBodyVisualServerHandler { + + friend class SoftBody; + + RID mesh; + int surface; + PoolVector<uint8_t> buffer; + uint32_t stride; + uint32_t offset_vertices; + uint32_t offset_normal; + + PoolVector<uint8_t>::Write write_buffer; + +private: + SoftBodyVisualServerHandler(); + bool is_ready() { return mesh.is_valid(); } + void prepare(RID p_mesh_rid, int p_surface); + void clear(); + void open(); + void close(); + void commit_changes(); + +public: + void set_vertex(int p_vertex_id, const void *p_vector3); + void set_normal(int p_vertex_id, const void *p_vector3); + void set_aabb(const AABB &p_aabb); +}; + +class SoftBody : public MeshInstance { + GDCLASS(SoftBody, MeshInstance); + +public: + struct PinnedPoint { + int point_index; + NodePath spatial_attachment_path; + Spatial *spatial_attachment; // Cache + /// This is the offset from the soft body to point or attachment to point + /// Depend if the spatial_attachment_node is NULL or not + Transform vertex_offset_transform; // Cache + + PinnedPoint(); + PinnedPoint(const PinnedPoint &obj_tocopy); + }; + +private: + SoftBodyVisualServerHandler visual_server_handler; + + RID physics_rid; + + bool mesh_owner; + uint32_t collision_mask; + uint32_t collision_layer; + NodePath parent_collision_ignore; + PoolVector<PinnedPoint> pinned_points_indices; + bool simulation_started; + bool pinned_points_cache_dirty; + + Ref<ArrayMesh> debug_mesh_cache; + class MeshInstance *debug_mesh; + + bool capture_input_on_drag; + bool ray_pickable; + + void _update_pickable(); + +protected: + 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; + + bool _set_property_pinned_points_indices(const Array &p_indices); + bool _set_property_pinned_points_attachment(int p_item, const String &p_what, const Variant &p_value); + bool _get_property_pinned_points(int p_item, const String &p_what, Variant &r_ret) const; + + virtual void _changed_callback(Object *p_changed, const char *p_prop); + + void _notification(int p_what); + static void _bind_methods(); + + virtual String get_configuration_warning() const; + +protected: + void _draw_soft_mesh(); + +public: + void update_physics_server(); + void become_mesh_owner(); + + void set_collision_mask(uint32_t p_mask); + uint32_t get_collision_mask() const; + + void set_collision_layer(uint32_t p_layer); + uint32_t get_collision_layer() const; + + void set_collision_mask_bit(int p_bit, bool p_value); + bool get_collision_mask_bit(int p_bit) const; + + void set_collision_layer_bit(int p_bit, bool p_value); + bool get_collision_layer_bit(int p_bit) const; + + void set_parent_collision_ignore(const NodePath &p_parent_collision_ignore); + const NodePath &get_parent_collision_ignore() const; + + void set_pinned_points_indices(PoolVector<PinnedPoint> p_pinned_points_indices); + PoolVector<PinnedPoint> get_pinned_points_indices(); + + void set_simulation_precision(int p_simulation_precision); + int get_simulation_precision(); + + void set_total_mass(real_t p_total_mass); + real_t get_total_mass(); + + void set_linear_stiffness(real_t p_linear_stiffness); + real_t get_linear_stiffness(); + + void set_areaAngular_stiffness(real_t p_areaAngular_stiffness); + real_t get_areaAngular_stiffness(); + + void set_volume_stiffness(real_t p_volume_stiffness); + real_t get_volume_stiffness(); + + void set_pressure_coefficient(real_t p_pressure_coefficient); + real_t get_pressure_coefficient(); + + void set_pose_matching_coefficient(real_t p_pose_matching_coefficient); + real_t get_pose_matching_coefficient(); + + void set_damping_coefficient(real_t p_damping_coefficient); + real_t get_damping_coefficient(); + + void set_drag_coefficient(real_t p_drag_coefficient); + real_t get_drag_coefficient(); + + void add_collision_exception_with(Node *p_node); + void remove_collision_exception_with(Node *p_node); + + Vector3 get_point_transform(int p_point_index); + + void pin_point_toggle(int p_point_index); + void pin_point(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path = NodePath()); + bool is_point_pinned(int p_point_index) const; + + void set_ray_pickable(bool p_ray_pickable); + bool is_ray_pickable() const; + + SoftBody(); + ~SoftBody(); + +private: + void reset_softbody_pin(); + void _update_cache_pin_points_datas(); + void _pin_point_on_physics_server(int p_point_index, bool pin); + void _add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path); + void _remove_pinned_point(int p_point_index); + int _get_pinned_point(int p_point_index, PinnedPoint *&r_point) const; + int _has_pinned_point(int p_point_index) const; +}; + +#endif // SOFT_PHYSICS_BODY_H diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index 9b27faed6a..64cb9ec4ca 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -645,19 +645,15 @@ void Spatial::scale_object_local(const Vector3 &p_scale) { void Spatial::global_rotate(const Vector3 &p_axis, float p_angle) { - Basis rotation(p_axis, p_angle); Transform t = get_global_transform(); - t.basis = rotation * t.basis; + t.basis.rotate(p_axis, p_angle); set_global_transform(t); } void Spatial::global_scale(const Vector3 &p_scale) { - Basis s; - s.set_scale(p_scale); - Transform t = get_global_transform(); - t.basis = s * t.basis; + t.basis.scale(p_scale); set_global_transform(t); } diff --git a/scene/3d/spatial_velocity_tracker.cpp b/scene/3d/spatial_velocity_tracker.cpp index c547e76e30..d96b003a81 100644 --- a/scene/3d/spatial_velocity_tracker.cpp +++ b/scene/3d/spatial_velocity_tracker.cpp @@ -53,11 +53,11 @@ void SpatialVelocityTracker::update_position(const Vector3 &p_position) { if (position_history_len == 0 || position_history[0].frame != ph.frame) { //in same frame, use latest position_history_len = MIN(position_history.size(), position_history_len + 1); for (int i = position_history_len - 1; i > 0; i--) { - position_history[i] = position_history[i - 1]; + position_history.write[i] = position_history[i - 1]; } } - position_history[0] = ph; + position_history.write[0] = ph; } Vector3 SpatialVelocityTracker::get_tracked_linear_velocity() const { @@ -114,7 +114,7 @@ void SpatialVelocityTracker::reset(const Vector3 &p_new_pos) { ph.frame = Engine::get_singleton()->get_idle_frame_ticks(); } - position_history[0] = ph; + position_history.write[0] = ph; position_history_len = 1; } diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp index 385956dc16..26958930e4 100644 --- a/scene/3d/vehicle_body.cpp +++ b/scene/3d/vehicle_body.cpp @@ -524,7 +524,7 @@ void VehicleBody::_update_suspension(PhysicsDirectBodyState *s) { //bilateral constraint between two dynamic objects void VehicleBody::_resolve_single_bilateral(PhysicsDirectBodyState *s, const Vector3 &pos1, - PhysicsBody *body2, const Vector3 &pos2, const Vector3 &normal, real_t &impulse, real_t p_rollInfluence) { + PhysicsBody *body2, const Vector3 &pos2, const Vector3 &normal, real_t &impulse, const real_t p_rollInfluence) { real_t normalLenSqr = normal.length_squared(); //ERR_FAIL_COND( normalLenSqr < real_t(1.1)); @@ -677,8 +677,8 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) { //collapse all those loops into one! for (int i = 0; i < wheels.size(); i++) { - m_sideImpulse[i] = real_t(0.); - m_forwardImpulse[i] = real_t(0.); + m_sideImpulse.write[i] = real_t(0.); + m_forwardImpulse.write[i] = real_t(0.); } { @@ -693,22 +693,22 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) { Basis wheelBasis0 = wheelInfo.m_worldTransform.basis; //get_global_transform().basis; - m_axle[i] = wheelBasis0.get_axis(Vector3::AXIS_X); + m_axle.write[i] = wheelBasis0.get_axis(Vector3::AXIS_X); //m_axle[i] = wheelInfo.m_raycastInfo.m_wheelAxleWS; const Vector3 &surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS; real_t proj = m_axle[i].dot(surfNormalWS); - m_axle[i] -= surfNormalWS * proj; - m_axle[i] = m_axle[i].normalized(); + m_axle.write[i] -= surfNormalWS * proj; + m_axle.write[i] = m_axle[i].normalized(); - m_forwardWS[i] = surfNormalWS.cross(m_axle[i]); - m_forwardWS[i].normalize(); + m_forwardWS.write[i] = surfNormalWS.cross(m_axle[i]); + m_forwardWS.write[i].normalize(); _resolve_single_bilateral(s, wheelInfo.m_raycastInfo.m_contactPointWS, wheelInfo.m_raycastInfo.m_groundObject, wheelInfo.m_raycastInfo.m_contactPointWS, - m_axle[i], m_sideImpulse[i], wheelInfo.m_rollInfluence); + m_axle[i], m_sideImpulse.write[i], wheelInfo.m_rollInfluence); - m_sideImpulse[i] *= sideFrictionStiffness2; + m_sideImpulse.write[i] *= sideFrictionStiffness2; } } } @@ -739,7 +739,7 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) { //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break) - m_forwardImpulse[wheel] = real_t(0.); + m_forwardImpulse.write[wheel] = real_t(0.); wheelInfo.m_skidInfo = real_t(1.); if (wheelInfo.m_raycastInfo.m_isInContact) { @@ -750,7 +750,7 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) { real_t maximpSquared = maximp * maximpSide; - m_forwardImpulse[wheel] = rollingFriction; //wheelInfo.m_engineForce* timeStep; + m_forwardImpulse.write[wheel] = rollingFriction; //wheelInfo.m_engineForce* timeStep; real_t x = (m_forwardImpulse[wheel]) * fwdFactor; real_t y = (m_sideImpulse[wheel]) * sideFactor; @@ -772,8 +772,8 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) { for (int wheel = 0; wheel < wheels.size(); wheel++) { if (m_sideImpulse[wheel] != real_t(0.)) { if (wheels[wheel]->m_skidInfo < real_t(1.)) { - m_forwardImpulse[wheel] *= wheels[wheel]->m_skidInfo; - m_sideImpulse[wheel] *= wheels[wheel]->m_skidInfo; + m_forwardImpulse.write[wheel] *= wheels[wheel]->m_skidInfo; + m_sideImpulse.write[wheel] *= wheels[wheel]->m_skidInfo; } } } @@ -942,8 +942,6 @@ VehicleBody::VehicleBody() : engine_force = 0; brake = 0; - friction = 1; - state = NULL; ccd = false; diff --git a/scene/3d/vehicle_body.h b/scene/3d/vehicle_body.h index 1ac3693cc4..68fbf8d873 100644 --- a/scene/3d/vehicle_body.h +++ b/scene/3d/vehicle_body.h @@ -168,7 +168,7 @@ class VehicleBody : public RigidBody { btVehicleWheelContactPoint(PhysicsDirectBodyState *s, PhysicsBody *body1, const Vector3 &frictionPosWorld, const Vector3 &frictionDirectionWorld, real_t maxImpulse); }; - void _resolve_single_bilateral(PhysicsDirectBodyState *s, const Vector3 &pos1, PhysicsBody *body2, const Vector3 &pos2, const Vector3 &normal, real_t &impulse, real_t p_rollInfluence); + void _resolve_single_bilateral(PhysicsDirectBodyState *s, const Vector3 &pos1, PhysicsBody *body2, const Vector3 &pos2, const Vector3 &normal, real_t &impulse, const real_t p_rollInfluence); real_t _calc_rolling_friction(btVehicleWheelContactPoint &contactPoint); void _update_friction(PhysicsDirectBodyState *s); diff --git a/scene/3d/voxel_light_baker.cpp b/scene/3d/voxel_light_baker.cpp index ba2807d4e8..f3abdc6bbe 100644 --- a/scene/3d/voxel_light_baker.cpp +++ b/scene/3d/voxel_light_baker.cpp @@ -409,16 +409,16 @@ void VoxelLightBaker::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p } //put this temporarily here, corrected in a later step - bake_cells[p_idx].albedo[0] += albedo_accum.r; - bake_cells[p_idx].albedo[1] += albedo_accum.g; - bake_cells[p_idx].albedo[2] += albedo_accum.b; - bake_cells[p_idx].emission[0] += emission_accum.r; - bake_cells[p_idx].emission[1] += emission_accum.g; - bake_cells[p_idx].emission[2] += emission_accum.b; - bake_cells[p_idx].normal[0] += normal_accum.x; - bake_cells[p_idx].normal[1] += normal_accum.y; - bake_cells[p_idx].normal[2] += normal_accum.z; - bake_cells[p_idx].alpha += alpha; + bake_cells.write[p_idx].albedo[0] += albedo_accum.r; + bake_cells.write[p_idx].albedo[1] += albedo_accum.g; + bake_cells.write[p_idx].albedo[2] += albedo_accum.b; + bake_cells.write[p_idx].emission[0] += emission_accum.r; + bake_cells.write[p_idx].emission[1] += emission_accum.g; + bake_cells.write[p_idx].emission[2] += emission_accum.b; + bake_cells.write[p_idx].normal[0] += normal_accum.x; + bake_cells.write[p_idx].normal[1] += normal_accum.y; + bake_cells.write[p_idx].normal[2] += normal_accum.z; + bake_cells.write[p_idx].alpha += alpha; } else { //go down @@ -465,9 +465,9 @@ void VoxelLightBaker::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p //sub cell must be created uint32_t child_idx = bake_cells.size(); - bake_cells[p_idx].children[i] = child_idx; + bake_cells.write[p_idx].children[i] = child_idx; bake_cells.resize(bake_cells.size() + 1); - bake_cells[child_idx].level = p_level + 1; + bake_cells.write[child_idx].level = p_level + 1; } _plot_face(bake_cells[p_idx].children[i], p_level + 1, nx, ny, nz, p_vtx, p_normal, p_uv, p_material, aabb); @@ -483,7 +483,7 @@ Vector<Color> VoxelLightBaker::_get_bake_texture(Ref<Image> p_image, const Color ret.resize(bake_texture_size * bake_texture_size); for (int i = 0; i < bake_texture_size * bake_texture_size; i++) { - ret[i] = p_color_add; + ret.write[i] = p_color_add; } return ret; @@ -509,7 +509,7 @@ Vector<Color> VoxelLightBaker::_get_bake_texture(Ref<Image> p_image, const Color c.a = r[i * 4 + 3] / 255.0; - ret[i] = c; + ret.write[i] = c; } return ret; @@ -686,13 +686,13 @@ void VoxelLightBaker::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, con void VoxelLightBaker::_init_light_plot(int p_idx, int p_level, int p_x, int p_y, int p_z, uint32_t p_parent) { - bake_light[p_idx].x = p_x; - bake_light[p_idx].y = p_y; - bake_light[p_idx].z = p_z; + bake_light.write[p_idx].x = p_x; + bake_light.write[p_idx].y = p_y; + bake_light.write[p_idx].z = p_z; if (p_level == cell_subdiv - 1) { - bake_light[p_idx].next_leaf = first_leaf; + bake_light.write[p_idx].next_leaf = first_leaf; first_leaf = p_idx; } else { @@ -1197,33 +1197,33 @@ void VoxelLightBaker::_fixup_plot(int p_idx, int p_level) { leaf_voxel_count++; float alpha = bake_cells[p_idx].alpha; - bake_cells[p_idx].albedo[0] /= alpha; - bake_cells[p_idx].albedo[1] /= alpha; - bake_cells[p_idx].albedo[2] /= alpha; + bake_cells.write[p_idx].albedo[0] /= alpha; + bake_cells.write[p_idx].albedo[1] /= alpha; + bake_cells.write[p_idx].albedo[2] /= alpha; //transfer emission to light - bake_cells[p_idx].emission[0] /= alpha; - bake_cells[p_idx].emission[1] /= alpha; - bake_cells[p_idx].emission[2] /= alpha; + bake_cells.write[p_idx].emission[0] /= alpha; + bake_cells.write[p_idx].emission[1] /= alpha; + bake_cells.write[p_idx].emission[2] /= alpha; - bake_cells[p_idx].normal[0] /= alpha; - bake_cells[p_idx].normal[1] /= alpha; - bake_cells[p_idx].normal[2] /= alpha; + bake_cells.write[p_idx].normal[0] /= alpha; + bake_cells.write[p_idx].normal[1] /= alpha; + bake_cells.write[p_idx].normal[2] /= alpha; Vector3 n(bake_cells[p_idx].normal[0], bake_cells[p_idx].normal[1], bake_cells[p_idx].normal[2]); if (n.length() < 0.01) { //too much fight over normal, zero it - bake_cells[p_idx].normal[0] = 0; - bake_cells[p_idx].normal[1] = 0; - bake_cells[p_idx].normal[2] = 0; + bake_cells.write[p_idx].normal[0] = 0; + bake_cells.write[p_idx].normal[1] = 0; + bake_cells.write[p_idx].normal[2] = 0; } else { n.normalize(); - bake_cells[p_idx].normal[0] = n.x; - bake_cells[p_idx].normal[1] = n.y; - bake_cells[p_idx].normal[2] = n.z; + bake_cells.write[p_idx].normal[0] = n.x; + bake_cells.write[p_idx].normal[1] = n.y; + bake_cells.write[p_idx].normal[2] = n.z; } - bake_cells[p_idx].alpha = 1.0; + bake_cells.write[p_idx].alpha = 1.0; /*if (bake_light.size()) { for(int i=0;i<6;i++) { @@ -1235,20 +1235,20 @@ void VoxelLightBaker::_fixup_plot(int p_idx, int p_level) { //go down - bake_cells[p_idx].emission[0] = 0; - bake_cells[p_idx].emission[1] = 0; - bake_cells[p_idx].emission[2] = 0; - bake_cells[p_idx].normal[0] = 0; - bake_cells[p_idx].normal[1] = 0; - bake_cells[p_idx].normal[2] = 0; - bake_cells[p_idx].albedo[0] = 0; - bake_cells[p_idx].albedo[1] = 0; - bake_cells[p_idx].albedo[2] = 0; + bake_cells.write[p_idx].emission[0] = 0; + bake_cells.write[p_idx].emission[1] = 0; + bake_cells.write[p_idx].emission[2] = 0; + bake_cells.write[p_idx].normal[0] = 0; + bake_cells.write[p_idx].normal[1] = 0; + bake_cells.write[p_idx].normal[2] = 0; + bake_cells.write[p_idx].albedo[0] = 0; + bake_cells.write[p_idx].albedo[1] = 0; + bake_cells.write[p_idx].albedo[2] = 0; if (bake_light.size()) { for (int j = 0; j < 6; j++) { - bake_light[p_idx].accum[j][0] = 0; - bake_light[p_idx].accum[j][1] = 0; - bake_light[p_idx].accum[j][2] = 0; + bake_light.write[p_idx].accum[j][0] = 0; + bake_light.write[p_idx].accum[j][1] = 0; + bake_light.write[p_idx].accum[j][2] = 0; } } @@ -1267,29 +1267,29 @@ void VoxelLightBaker::_fixup_plot(int p_idx, int p_level) { if (bake_light.size() > 0) { for (int j = 0; j < 6; j++) { - bake_light[p_idx].accum[j][0] += bake_light[child].accum[j][0]; - bake_light[p_idx].accum[j][1] += bake_light[child].accum[j][1]; - bake_light[p_idx].accum[j][2] += bake_light[child].accum[j][2]; + bake_light.write[p_idx].accum[j][0] += bake_light[child].accum[j][0]; + bake_light.write[p_idx].accum[j][1] += bake_light[child].accum[j][1]; + bake_light.write[p_idx].accum[j][2] += bake_light[child].accum[j][2]; } - bake_cells[p_idx].emission[0] += bake_cells[child].emission[0]; - bake_cells[p_idx].emission[1] += bake_cells[child].emission[1]; - bake_cells[p_idx].emission[2] += bake_cells[child].emission[2]; + bake_cells.write[p_idx].emission[0] += bake_cells[child].emission[0]; + bake_cells.write[p_idx].emission[1] += bake_cells[child].emission[1]; + bake_cells.write[p_idx].emission[2] += bake_cells[child].emission[2]; } children_found++; } - bake_cells[p_idx].alpha = alpha_average / 8.0; + bake_cells.write[p_idx].alpha = alpha_average / 8.0; if (bake_light.size() && children_found) { float divisor = Math::lerp(8, children_found, propagation); for (int j = 0; j < 6; j++) { - bake_light[p_idx].accum[j][0] /= divisor; - bake_light[p_idx].accum[j][1] /= divisor; - bake_light[p_idx].accum[j][2] /= divisor; + bake_light.write[p_idx].accum[j][0] /= divisor; + bake_light.write[p_idx].accum[j][1] /= divisor; + bake_light.write[p_idx].accum[j][2] /= divisor; } - bake_cells[p_idx].emission[0] /= divisor; - bake_cells[p_idx].emission[1] /= divisor; - bake_cells[p_idx].emission[2] /= divisor; + bake_cells.write[p_idx].emission[0] /= divisor; + bake_cells.write[p_idx].emission[1] /= divisor; + bake_cells.write[p_idx].emission[2] /= divisor; } } } @@ -2403,25 +2403,25 @@ PoolVector<uint8_t> VoxelLightBaker::create_capture_octree(int p_subdiv) { new_size++; demap.push_back(i); } - remap[i] = c; + remap.write[i] = c; } Vector<VoxelLightBakerOctree> octree; octree.resize(new_size); for (int i = 0; i < new_size; i++) { - octree[i].alpha = bake_cells[demap[i]].alpha; + octree.write[i].alpha = bake_cells[demap[i]].alpha; for (int j = 0; j < 6; j++) { for (int k = 0; k < 3; k++) { float l = bake_light[demap[i]].accum[j][k]; //add anisotropic light l += bake_cells[demap[i]].emission[k]; //add emission - octree[i].light[j][k] = CLAMP(l * 1024, 0, 65535); //give two more bits to octree + octree.write[i].light[j][k] = CLAMP(l * 1024, 0, 65535); //give two more bits to octree } } for (int j = 0; j < 8; j++) { uint32_t child = bake_cells[demap[i]].children[j]; - octree[i].children[j] = child == CHILD_EMPTY ? CHILD_EMPTY : remap[child]; + octree.write[i].children[j] = child == CHILD_EMPTY ? CHILD_EMPTY : remap[child]; } } diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp index bba25d64d9..3c93a0c8ec 100644 --- a/scene/animation/animation_blend_space_2d.cpp +++ b/scene/animation/animation_blend_space_2d.cpp @@ -24,7 +24,7 @@ void AnimationNodeBlendSpace2D::add_blend_point(const Ref<AnimationRootNode> &p_ for (int i = 0; i < triangles.size(); i++) { for (int j = 0; j < 3; j++) { if (triangles[i].points[j] >= p_at_index) { - triangles[i].points[j]++; + triangles.write[i].points[j]++; } } } @@ -81,7 +81,7 @@ void AnimationNodeBlendSpace2D::remove_blend_point(int p_point) { erase = true; break; } else if (triangles[i].points[j] > p_point) { - triangles[i].points[j]--; + triangles.write[i].points[j]--; } } if (erase) { @@ -264,9 +264,9 @@ Vector<int> AnimationNodeBlendSpace2D::_get_triangles() const { t.resize(triangles.size() * 3); for (int i = 0; i < triangles.size(); i++) { - t[i * 3 + 0] = triangles[i].points[0]; - t[i * 3 + 1] = triangles[i].points[1]; - t[i * 3 + 2] = triangles[i].points[2]; + t.write[i * 3 + 0] = triangles[i].points[0]; + t.write[i * 3 + 1] = triangles[i].points[1]; + t.write[i * 3 + 2] = triangles[i].points[2]; } return t; } @@ -284,7 +284,7 @@ void AnimationNodeBlendSpace2D::_update_triangles() { Vector<Vector2> points; points.resize(blend_points_used); for (int i = 0; i < blend_points_used; i++) { - points[i] = blend_points[i].position; + points.write[i] = blend_points[i].position; } Vector<Delaunay2D::Triangle> triangles = Delaunay2D::triangulate(points); diff --git a/scene/animation/animation_cache.cpp b/scene/animation/animation_cache.cpp index 949a0be3bc..756907c41c 100644 --- a/scene/animation/animation_cache.cpp +++ b/scene/animation/animation_cache.cpp @@ -43,7 +43,7 @@ void AnimationCache::_node_exit_tree(Node *p_node) { if (path_cache[i].node != p_node) continue; - path_cache[i].valid = false; //invalidate path cache + path_cache.write[i].valid = false; //invalidate path cache } } @@ -196,7 +196,7 @@ void AnimationCache::set_track_transform(int p_idx, const Transform &p_transform ERR_FAIL_COND(!cache_valid); ERR_FAIL_INDEX(p_idx, path_cache.size()); - Path &p = path_cache[p_idx]; + Path &p = path_cache.write[p_idx]; if (!p.valid) return; @@ -217,7 +217,7 @@ void AnimationCache::set_track_value(int p_idx, const Variant &p_value) { ERR_FAIL_COND(!cache_valid); ERR_FAIL_INDEX(p_idx, path_cache.size()); - Path &p = path_cache[p_idx]; + Path &p = path_cache.write[p_idx]; if (!p.valid) return; @@ -232,7 +232,7 @@ void AnimationCache::call_track(int p_idx, const StringName &p_method, const Var ERR_FAIL_COND(!cache_valid); ERR_FAIL_INDEX(p_idx, path_cache.size()); - Path &p = path_cache[p_idx]; + Path &p = path_cache.write[p_idx]; if (!p.valid) return; @@ -297,11 +297,11 @@ void AnimationCache::set_all(float p_time, float p_delta) { call_track(i, name, NULL, 0, err); } else { - Vector<Variant *> argptrs; + Vector<const Variant *> argptrs; argptrs.resize(args.size()); for (int j = 0; j < args.size(); j++) { - argptrs[j] = &args[j]; + argptrs.write[j] = &args.write[j]; } call_track(i, name, (const Variant **)&argptrs[0], args.size(), err); diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index 36587a1e91..f478112a36 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -169,11 +169,11 @@ void AnimationNodeStateMachine::rename_node(const StringName &p_name, const Stri for (int i = 0; i < transitions.size(); i++) { if (transitions[i].from == p_name) { - transitions[i].from = p_new_name; + transitions.write[i].from = p_new_name; } if (transitions[i].to == p_name) { - transitions[i].to = p_new_name; + transitions.write[i].to = p_new_name; } } diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 111620dac1..2782354432 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -233,7 +233,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) { for (int i = 0; i < a->get_track_count(); i++) { - p_anim->node_cache[i] = NULL; + p_anim->node_cache.write[i] = NULL; RES resource; Vector<StringName> leftover_path; Node *child = parent->get_node_and_resource(a->track_get_path(i), resource, leftover_path); @@ -265,12 +265,12 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) { if (node_cache_map.has(key)) { - p_anim->node_cache[i] = &node_cache_map[key]; + p_anim->node_cache.write[i] = &node_cache_map[key]; } else { node_cache_map[key] = TrackNodeCache(); - p_anim->node_cache[i] = &node_cache_map[key]; + p_anim->node_cache.write[i] = &node_cache_map[key]; p_anim->node_cache[i]->path = a->track_get_path(i); p_anim->node_cache[i]->node = child; p_anim->node_cache[i]->resource = resource; @@ -331,11 +331,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) { if (!p_anim->node_cache[i]->bezier_anim.has(a->track_get_path(i).get_concatenated_subnames())) { TrackNodeCache::BezierAnim ba; - String path = leftover_path[leftover_path.size() - 1]; - Vector<String> index = path.split("."); - for (int j = 0; j < index.size(); j++) { - ba.bezier_property.push_back(index[j]); - } + ba.bezier_property = leftover_path; ba.object = resource.is_valid() ? (Object *)resource.ptr() : (Object *)child; ba.owner = p_anim->node_cache[i]; diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 4fa66e8ede..de9f82dadc 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -78,9 +78,9 @@ float AnimationNode::blend_input(int p_input, float p_time, bool p_seek, float p return 0; } - inputs[p_input].last_pass = state->last_pass; + inputs.write[p_input].last_pass = state->last_pass; - return _blend_node(node, p_time, p_seek, p_blend, p_filter, p_optimize, &inputs[p_input].activity); + return _blend_node(node, p_time, p_seek, p_blend, p_filter, p_optimize, &inputs.write[p_input].activity); } float AnimationNode::blend_node(Ref<AnimationNode> p_node, float p_time, bool p_seek, float p_blend, FilterAction p_filter, bool p_optimize) { @@ -221,7 +221,7 @@ StringName AnimationNode::get_input_connection(int p_input) { void AnimationNode::set_input_connection(int p_input, const StringName &p_connection) { ERR_FAIL_INDEX(p_input, inputs.size()); - inputs[p_input].connected_to = p_connection; + inputs.write[p_input].connected_to = p_connection; } String AnimationNode::get_caption() const { @@ -248,7 +248,7 @@ void AnimationNode::add_input(const String &p_name) { void AnimationNode::set_input_name(int p_input, const String &p_name) { ERR_FAIL_INDEX(p_input, inputs.size()); ERR_FAIL_COND(p_name.find(".") != -1 || p_name.find("/") != -1); - inputs[p_input].name = p_name; + inputs.write[p_input].name = p_name; emit_changed(); } diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp index 026215508b..179f5d9698 100644 --- a/scene/animation/animation_tree_player.cpp +++ b/scene/animation/animation_tree_player.cpp @@ -1152,7 +1152,7 @@ void AnimationTreePlayer::transition_node_set_input_auto_advance(const StringNam GET_NODE(NODE_TRANSITION, TransitionNode); ERR_FAIL_INDEX(p_input, n->input_data.size()); - n->input_data[p_input].auto_advance = p_auto_advance; + n->input_data.write[p_input].auto_advance = p_auto_advance; } void AnimationTreePlayer::transition_node_set_xfade_time(const StringName &p_node, float p_time) { @@ -1365,7 +1365,7 @@ void AnimationTreePlayer::remove_node(const StringName &p_node) { for (int i = 0; i < nb->inputs.size(); i++) { if (nb->inputs[i].node == p_node) - nb->inputs[i].node = StringName(); + nb->inputs.write[i].node = StringName(); } } @@ -1426,11 +1426,11 @@ Error AnimationTreePlayer::connect_nodes(const StringName &p_src_node, const Str for (int i = 0; i < nb->inputs.size(); i++) { if (nb->inputs[i].node == p_src_node) - nb->inputs[i].node = StringName(); + nb->inputs.write[i].node = StringName(); } } - dst->inputs[p_dst_input].node = p_src_node; + dst->inputs.write[p_dst_input].node = p_src_node; _clear_cycle_test(); @@ -1463,7 +1463,7 @@ void AnimationTreePlayer::disconnect_nodes(const StringName &p_node, int p_input NodeBase *dst = node_map[p_node]; ERR_FAIL_INDEX(p_input, dst->inputs.size()); - dst->inputs[p_input].node = StringName(); + dst->inputs.write[p_input].node = StringName(); last_error = CONNECT_INCOMPLETE; dirty_caches = true; } @@ -1703,7 +1703,7 @@ Error AnimationTreePlayer::node_rename(const StringName &p_node, const StringNam for (int i = 0; i < nb->inputs.size(); i++) { if (nb->inputs[i].node == p_node) { - nb->inputs[i].node = p_new_name; + nb->inputs.write[i].node = p_new_name; } } } diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index 9f7503577b..81fdc32788 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -150,7 +150,7 @@ void Tween::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { - if (!processing) { + if (!is_active()) { //make sure that a previous process state was not saved //only process if "processing" is set set_physics_process_internal(false); @@ -164,7 +164,7 @@ void Tween::_notification(int p_what) { if (tween_process_mode == TWEEN_PROCESS_PHYSICS) break; - if (processing) + if (is_active()) _tween_process(get_process_delta_time()); } break; case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { @@ -172,7 +172,7 @@ void Tween::_notification(int p_what) { if (tween_process_mode == TWEEN_PROCESS_IDLE) break; - if (processing) + if (is_active()) _tween_process(get_physics_process_delta_time()); } break; case NOTIFICATION_EXIT_TREE: { @@ -201,7 +201,6 @@ void Tween::_bind_methods() { ClassDB::bind_method(D_METHOD("reset_all"), &Tween::reset_all); ClassDB::bind_method(D_METHOD("stop", "object", "key"), &Tween::stop, DEFVAL("")); ClassDB::bind_method(D_METHOD("stop_all"), &Tween::stop_all); - ClassDB::bind_method(D_METHOD("is_stopped"), &Tween::is_stopped); ClassDB::bind_method(D_METHOD("resume", "object", "key"), &Tween::resume, DEFVAL("")); ClassDB::bind_method(D_METHOD("resume_all"), &Tween::resume_all); ClassDB::bind_method(D_METHOD("remove", "object", "key"), &Tween::remove, DEFVAL("")); @@ -522,8 +521,8 @@ void Tween::_tween_process(float p_delta) { pending_update++; // if repeat and all interpolates was finished then reset all interpolates + bool all_finished = true; if (repeat) { - bool all_finished = true; for (List<InterpolateData>::Element *E = interpolates.front(); E; E = E->next()) { @@ -539,9 +538,12 @@ void Tween::_tween_process(float p_delta) { reset_all(); } + all_finished = true; for (List<InterpolateData>::Element *E = interpolates.front(); E; E = E->next()) { InterpolateData &data = E->get(); + all_finished = all_finished && data.finish; + if (!data.active || data.finish) continue; @@ -555,8 +557,8 @@ void Tween::_tween_process(float p_delta) { continue; else if (prev_delaying) { - emit_signal("tween_started", object, NodePath(Vector<StringName>(), data.key, false)); _apply_tween_value(data, data.initial_val); + emit_signal("tween_started", object, NodePath(Vector<StringName>(), data.key, false)); } if (data.elapsed > (data.delay + data.duration)) { @@ -603,32 +605,29 @@ void Tween::_tween_process(float p_delta) { } } else { Variant result = _run_equation(data); - emit_signal("tween_step", object, NodePath(Vector<StringName>(), data.key, false), data.elapsed, result); _apply_tween_value(data, result); + emit_signal("tween_step", object, NodePath(Vector<StringName>(), data.key, false), data.elapsed, result); } if (data.finish) { _apply_tween_value(data, data.final_val); + data.elapsed = 0; emit_signal("tween_completed", object, NodePath(Vector<StringName>(), data.key, false)); // not repeat mode, remove completed action if (!repeat) call_deferred("_remove", object, NodePath(Vector<StringName>(), data.key, false), true); - } + } else if (!repeat) + all_finished = all_finished && data.finish; } pending_update--; + + if (all_finished) + set_active(false); } void Tween::set_tween_process_mode(TweenProcessMode p_mode) { - if (tween_process_mode == p_mode) - return; - - bool pr = processing; - if (pr) - _set_process(false); tween_process_mode = p_mode; - if (pr) - _set_process(true); } Tween::TweenProcessMode Tween::get_tween_process_mode() const { @@ -636,32 +635,21 @@ Tween::TweenProcessMode Tween::get_tween_process_mode() const { return tween_process_mode; } -void Tween::_set_process(bool p_process, bool p_force) { - - if (processing == p_process && !p_force) - return; - - switch (tween_process_mode) { - - case TWEEN_PROCESS_PHYSICS: set_physics_process_internal(p_process && active); break; - case TWEEN_PROCESS_IDLE: set_process_internal(p_process && active); break; - } - - processing = p_process; -} - bool Tween::is_active() const { - return active; + return is_processing_internal() || is_physics_processing_internal(); } void Tween::set_active(bool p_active) { - if (active == p_active) + if (is_active() == p_active) return; - active = p_active; - _set_process(processing, true); + switch (tween_process_mode) { + + case TWEEN_PROCESS_IDLE: set_process_internal(p_active); break; + case TWEEN_PROCESS_PHYSICS: set_physics_process_internal(p_active); break; + } } bool Tween::is_repeat() const { @@ -687,7 +675,6 @@ float Tween::get_speed_scale() const { bool Tween::start() { set_active(true); - _set_process(true); return true; } @@ -744,14 +731,9 @@ bool Tween::stop(Object *p_object, StringName p_key) { return true; } -bool Tween::is_stopped() const { - return tell() >= get_runtime(); -} - bool Tween::stop_all() { set_active(false); - _set_process(false); pending_update++; for (List<InterpolateData>::Element *E = interpolates.front(); E; E = E->next()) { @@ -766,7 +748,6 @@ bool Tween::stop_all() { bool Tween::resume(Object *p_object, StringName p_key) { set_active(true); - _set_process(true); pending_update++; for (List<InterpolateData>::Element *E = interpolates.front(); E; E = E->next()) { @@ -785,7 +766,6 @@ bool Tween::resume(Object *p_object, StringName p_key) { bool Tween::resume_all() { set_active(true); - _set_process(true); pending_update++; for (List<InterpolateData>::Element *E = interpolates.front(); E; E = E->next()) { @@ -834,7 +814,6 @@ bool Tween::remove_all() { return true; } set_active(false); - _set_process(false); interpolates.clear(); return true; } @@ -1425,8 +1404,6 @@ Tween::Tween() { //String autoplay; tween_process_mode = TWEEN_PROCESS_IDLE; - processing = false; - active = false; repeat = false; speed_scale = 1; pending_update = 0; diff --git a/scene/animation/tween.h b/scene/animation/tween.h index 36094bf294..9997349c64 100644 --- a/scene/animation/tween.h +++ b/scene/animation/tween.h @@ -104,8 +104,6 @@ private: String autoplay; TweenProcessMode tween_process_mode; - bool processing; - bool active; bool repeat; float speed_scale; mutable int pending_update; @@ -133,7 +131,6 @@ private: bool _apply_tween_value(InterpolateData &p_data, Variant &value); void _tween_process(float p_delta); - void _set_process(bool p_process, bool p_force = false); void _remove(Object *p_object, StringName p_key, bool first_only); protected: @@ -162,7 +159,6 @@ public: bool reset_all(); bool stop(Object *p_object, StringName p_key); bool stop_all(); - bool is_stopped() const; bool resume(Object *p_object, StringName p_key); bool resume_all(); bool remove(Object *p_object, StringName p_key); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 17c349858f..12aeed1520 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2972,7 +2972,6 @@ Control::Control() { data.SI = NULL; data.MI = NULL; data.RI = NULL; - data.modal = false; data.theme_owner = NULL; data.modal_exclusive = false; data.default_cursor = CURSOR_ARROW; diff --git a/scene/gui/control.h b/scene/gui/control.h index 94231867d7..6bea04345b 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -182,7 +182,6 @@ private: Control *parent; ObjectID drag_owner; - bool modal; bool modal_exclusive; uint64_t modal_frame; //frame used to put something as modal Ref<Theme> theme; diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp index b5622604e2..749efe8364 100644 --- a/scene/gui/gradient_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -256,7 +256,7 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) { if (!valid) return; - points[grabbed].offset = newofs; + points.write[grabbed].offset = newofs; points.sort(); for (int i = 0; i < points.size(); i++) { @@ -407,7 +407,7 @@ void GradientEdit::_color_changed(const Color &p_color) { if (grabbed == -1) return; - points[grabbed].color = p_color; + points.write[grabbed].color = p_color; update(); emit_signal("ramp_changed"); } diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index e2c730a56e..d95ec9e495 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -268,6 +268,10 @@ void GraphEdit::remove_child_notify(Node *p_child) { void GraphEdit::_notification(int p_what) { + if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { + port_grab_distance_horizontal = get_constant("port_grab_distance_horizontal"); + port_grab_distance_vertical = get_constant("port_grab_distance_vertical"); + } if (p_what == NOTIFICATION_READY) { Size2 hmin = h_scroll->get_combined_minimum_size(); Size2 vmin = v_scroll->get_combined_minimum_size(); @@ -343,8 +347,6 @@ bool GraphEdit::_filter_input(const Point2 &p_point) { Ref<Texture> port = get_icon("port", "GraphNode"); - float grab_r_extend = 2.0; - float grab_r = port->get_width() * 0.5 * grab_r_extend; for (int i = get_child_count() - 1; i >= 0; i--) { GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); @@ -354,14 +356,14 @@ bool GraphEdit::_filter_input(const Point2 &p_point) { for (int j = 0; j < gn->get_connection_output_count(); j++) { Vector2 pos = gn->get_connection_output_position(j) + gn->get_position(); - if (pos.distance_to(p_point) < grab_r) + if (create_hot_zone(pos).has_point(p_point)) return true; } for (int j = 0; j < gn->get_connection_input_count(); j++) { Vector2 pos = gn->get_connection_input_position(j) + gn->get_position(); - if (pos.distance_to(p_point) < grab_r) { + if (create_hot_zone(pos).has_point(p_point)) { return true; } } @@ -372,13 +374,11 @@ bool GraphEdit::_filter_input(const Point2 &p_point) { void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { - float grab_r_extend = 2.0; Ref<InputEventMouseButton> mb = p_ev; if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) { Ref<Texture> port = get_icon("port", "GraphNode"); Vector2 mpos(mb->get_position().x, mb->get_position().y); - float grab_r = port->get_width() * 0.5 * grab_r_extend; for (int i = get_child_count() - 1; i >= 0; i--) { GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); @@ -388,7 +388,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { for (int j = 0; j < gn->get_connection_output_count(); j++) { Vector2 pos = gn->get_connection_output_position(j) + gn->get_position(); - if (pos.distance_to(mpos) < grab_r) { + if (create_hot_zone(pos).has_point(mpos)) { if (valid_left_disconnect_types.has(gn->get_connection_output_type(j))) { //check disconnect @@ -435,8 +435,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { for (int j = 0; j < gn->get_connection_input_count(); j++) { Vector2 pos = gn->get_connection_input_position(j) + gn->get_position(); - - if (pos.distance_to(mpos) < grab_r) { + if (create_hot_zone(pos).has_point(mpos)) { if (right_disconnects || valid_right_disconnect_types.has(gn->get_connection_input_type(j))) { //check disconnect @@ -492,7 +491,6 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { Ref<Texture> port = get_icon("port", "GraphNode"); Vector2 mpos = mm->get_position(); - float grab_r = port->get_width() * 0.5 * grab_r_extend; for (int i = get_child_count() - 1; i >= 0; i--) { GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); @@ -504,7 +502,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { Vector2 pos = gn->get_connection_output_position(j) + gn->get_position(); int type = gn->get_connection_output_type(j); - if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && pos.distance_to(mpos) < grab_r) { + if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && create_hot_zone(pos).has_point(mpos)) { connecting_target = true; connecting_to = pos; @@ -519,7 +517,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { Vector2 pos = gn->get_connection_input_position(j) + gn->get_position(); int type = gn->get_connection_input_type(j); - if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && pos.distance_to(mpos) < grab_r) { + if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && create_hot_zone(pos).has_point(mpos)) { connecting_target = true; connecting_to = pos; connecting_target_to = gn->get_name(); @@ -559,6 +557,10 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { } } +Rect2 GraphEdit::create_hot_zone(const Vector2 &pos) { + return Rect2(pos.x - port_grab_distance_horizontal, pos.y - port_grab_distance_vertical, port_grab_distance_horizontal * 2, port_grab_distance_vertical * 2); +} + template <class Vector2> static _FORCE_INLINE_ Vector2 _bezier_interp(real_t t, Vector2 start, Vector2 control_1, Vector2 control_2, Vector2 end) { /* Formula from Wikipedia article on Bezier curves. */ diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index 14789001e4..64ba18681e 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -81,6 +81,9 @@ private: HScrollBar *h_scroll; VScrollBar *v_scroll; + float port_grab_distance_horizontal; + float port_grab_distance_vertical; + bool connecting; String connecting_from; bool connecting_out; @@ -127,6 +130,9 @@ private: Control *connections_layer; GraphEditFilter *top_layer; void _top_layer_input(const Ref<InputEvent> &p_ev); + + Rect2 create_hot_zone(const Vector2 &pos); + void _top_layer_draw(); void _connections_layer_draw(); void _update_scroll_offset(); diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index aa52739b0a..5c79741682 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -72,7 +72,7 @@ void ItemList::set_item_text(int p_idx, const String &p_text) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].text = p_text; + items.write[p_idx].text = p_text; update(); shape_changed = true; } @@ -85,7 +85,7 @@ String ItemList::get_item_text(int p_idx) const { void ItemList::set_item_tooltip_enabled(int p_idx, const bool p_enabled) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].tooltip_enabled = p_enabled; + items.write[p_idx].tooltip_enabled = p_enabled; } bool ItemList::is_item_tooltip_enabled(int p_idx) const { @@ -97,7 +97,7 @@ void ItemList::set_item_tooltip(int p_idx, const String &p_tooltip) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].tooltip = p_tooltip; + items.write[p_idx].tooltip = p_tooltip; update(); shape_changed = true; } @@ -112,7 +112,7 @@ void ItemList::set_item_icon(int p_idx, const Ref<Texture> &p_icon) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].icon = p_icon; + items.write[p_idx].icon = p_icon; update(); shape_changed = true; } @@ -128,7 +128,7 @@ void ItemList::set_item_icon_region(int p_idx, const Rect2 &p_region) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].icon_region = p_region; + items.write[p_idx].icon_region = p_region; update(); shape_changed = true; } @@ -144,7 +144,7 @@ void ItemList::set_item_icon_modulate(int p_idx, const Color &p_modulate) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].icon_modulate = p_modulate; + items.write[p_idx].icon_modulate = p_modulate; update(); } @@ -159,7 +159,7 @@ void ItemList::set_item_custom_bg_color(int p_idx, const Color &p_custom_bg_colo ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].custom_bg = p_custom_bg_color; + items.write[p_idx].custom_bg = p_custom_bg_color; } Color ItemList::get_item_custom_bg_color(int p_idx) const { @@ -173,7 +173,7 @@ void ItemList::set_item_custom_fg_color(int p_idx, const Color &p_custom_fg_colo ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].custom_fg = p_custom_fg_color; + items.write[p_idx].custom_fg = p_custom_fg_color; } Color ItemList::get_item_custom_fg_color(int p_idx) const { @@ -187,7 +187,7 @@ void ItemList::set_item_tag_icon(int p_idx, const Ref<Texture> &p_tag_icon) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].tag_icon = p_tag_icon; + items.write[p_idx].tag_icon = p_tag_icon; update(); shape_changed = true; } @@ -202,7 +202,7 @@ void ItemList::set_item_selectable(int p_idx, bool p_selectable) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].selectable = p_selectable; + items.write[p_idx].selectable = p_selectable; } bool ItemList::is_item_selectable(int p_idx) const { @@ -215,7 +215,7 @@ void ItemList::set_item_disabled(int p_idx, bool p_disabled) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].disabled = p_disabled; + items.write[p_idx].disabled = p_disabled; update(); } @@ -229,7 +229,7 @@ void ItemList::set_item_metadata(int p_idx, const Variant &p_metadata) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].metadata = p_metadata; + items.write[p_idx].metadata = p_metadata; update(); shape_changed = true; } @@ -250,7 +250,7 @@ void ItemList::select(int p_idx, bool p_single) { } for (int i = 0; i < items.size(); i++) { - items[i].selected = p_idx == i; + items.write[i].selected = p_idx == i; } current = p_idx; @@ -258,7 +258,7 @@ void ItemList::select(int p_idx, bool p_single) { } else { if (items[p_idx].selectable && !items[p_idx].disabled) { - items[p_idx].selected = true; + items.write[p_idx].selected = true; } } update(); @@ -268,10 +268,10 @@ void ItemList::unselect(int p_idx) { ERR_FAIL_INDEX(p_idx, items.size()); if (select_mode != SELECT_MULTI) { - items[p_idx].selected = false; + items.write[p_idx].selected = false; current = -1; } else { - items[p_idx].selected = false; + items.write[p_idx].selected = false; } update(); } @@ -283,7 +283,7 @@ void ItemList::unselect_all() { for (int i = 0; i < items.size(); i++) { - items[i].selected = false; + items.write[i].selected = false; } current = -1; update(); @@ -869,8 +869,8 @@ void ItemList::_notification(int p_what) { // elements need to adapt to the selected size minsize.y += vseparation; minsize.x += hseparation; - items[i].rect_cache.size = minsize; - items[i].min_rect_cache.size = minsize; + items.write[i].rect_cache.size = minsize; + items.write[i].min_rect_cache.size = minsize; } int fit_size = size.x - bg->get_minimum_size().width - mw; @@ -897,8 +897,8 @@ void ItemList::_notification(int p_what) { } if (same_column_width) - items[i].rect_cache.size.x = max_column_width; - items[i].rect_cache.position = ofs; + items.write[i].rect_cache.size.x = max_column_width; + items.write[i].rect_cache.position = ofs; max_h = MAX(max_h, items[i].rect_cache.size.y); ofs.x += items[i].rect_cache.size.x + hseparation; col++; @@ -908,7 +908,7 @@ void ItemList::_notification(int p_what) { separators.push_back(ofs.y + max_h + vseparation / 2); for (int j = i; j >= 0 && col > 0; j--, col--) { - items[j].rect_cache.size.y = max_h; + items.write[j].rect_cache.size.y = max_h; } ofs.x = 0; @@ -919,7 +919,7 @@ void ItemList::_notification(int p_what) { } for (int j = items.size() - 1; j >= 0 && col > 0; j--, col--) { - items[j].rect_cache.size.y = max_h; + items.write[j].rect_cache.size.y = max_h; } if (all_fit) { @@ -1103,8 +1103,8 @@ void ItemList::_notification(int p_what) { int cs = j < ss ? font->get_char_size(items[i].text[j], items[i].text[j + 1]).x : 0; if (ofs + cs > max_len || j == ss) { - line_limit_cache[line] = j; - line_size_cache[line] = ofs; + line_limit_cache.write[line] = j; + line_size_cache.write[line] = ofs; line++; ofs = 0; if (line >= max_text_lines) diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h index 2356444ecb..0636accfee 100644 --- a/scene/gui/menu_button.h +++ b/scene/gui/menu_button.h @@ -43,7 +43,6 @@ class MenuButton : public Button { bool clicked; bool disable_shortcuts; PopupMenu *popup; - virtual void pressed(); void _unhandled_key_input(Ref<InputEvent> p_event); Array _get_items() const; @@ -55,6 +54,8 @@ protected: static void _bind_methods(); public: + virtual void pressed(); + PopupMenu *get_popup() const; void set_disable_shortcuts(bool p_disabled); diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index ebec61ee6d..cd4ece0950 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -410,7 +410,7 @@ void PopupMenu::_notification(int p_what) { case NOTIFICATION_TRANSLATION_CHANGED: { for (int i = 0; i < items.size(); i++) { - items[i].xl_text = tr(items[i].text); + items.write[i].xl_text = tr(items[i].text); } minimum_size_changed(); @@ -524,7 +524,7 @@ void PopupMenu::_notification(int p_what) { font->draw(ci, item_ofs + Point2(0, Math::floor((h - font_h) / 2.0)), text, i == mouse_over ? font_color_hover : font_color_accel); } - items[i]._ofs_cache = ofs.y; + items.write[i]._ofs_cache = ofs.y; ofs.y += h; } @@ -622,7 +622,7 @@ void PopupMenu::add_check_item(const String &p_label, int p_ID, uint32_t p_accel void PopupMenu::add_radio_check_item(const String &p_label, int p_ID, uint32_t p_accel) { add_check_item(p_label, p_ID, p_accel); - items[items.size() - 1].checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; + items.write[items.size() - 1].checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; update(); minimum_size_changed(); } @@ -630,7 +630,7 @@ void PopupMenu::add_radio_check_item(const String &p_label, int p_ID, uint32_t p void PopupMenu::add_icon_radio_check_item(const Ref<Texture> &p_icon, const String &p_label, int p_ID, uint32_t p_accel) { add_icon_check_item(p_icon, p_label, p_ID, p_accel); - items[items.size() - 1].checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; + items.write[items.size() - 1].checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; update(); minimum_size_changed(); } @@ -702,7 +702,7 @@ void PopupMenu::add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_ID, bo void PopupMenu::add_radio_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_ID, bool p_global) { add_check_shortcut(p_shortcut, p_ID, p_global); - items[items.size() - 1].checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; + items.write[items.size() - 1].checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; update(); minimum_size_changed(); } @@ -724,8 +724,8 @@ void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int void PopupMenu::set_item_text(int p_idx, const String &p_text) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].text = p_text; - items[p_idx].xl_text = tr(p_text); + items.write[p_idx].text = p_text; + items.write[p_idx].xl_text = tr(p_text); update(); minimum_size_changed(); @@ -733,7 +733,7 @@ void PopupMenu::set_item_text(int p_idx, const String &p_text) { void PopupMenu::set_item_icon(int p_idx, const Ref<Texture> &p_icon) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].icon = p_icon; + items.write[p_idx].icon = p_icon; update(); minimum_size_changed(); @@ -742,7 +742,7 @@ void PopupMenu::set_item_checked(int p_idx, bool p_checked) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].checked = p_checked; + items.write[p_idx].checked = p_checked; update(); minimum_size_changed(); @@ -750,7 +750,7 @@ void PopupMenu::set_item_checked(int p_idx, bool p_checked) { void PopupMenu::set_item_id(int p_idx, int p_ID) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].ID = p_ID; + items.write[p_idx].ID = p_ID; update(); minimum_size_changed(); @@ -759,7 +759,7 @@ void PopupMenu::set_item_id(int p_idx, int p_ID) { void PopupMenu::set_item_accelerator(int p_idx, uint32_t p_accel) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].accel = p_accel; + items.write[p_idx].accel = p_accel; update(); minimum_size_changed(); @@ -768,7 +768,7 @@ void PopupMenu::set_item_accelerator(int p_idx, uint32_t p_accel) { void PopupMenu::set_item_metadata(int p_idx, const Variant &p_meta) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].metadata = p_meta; + items.write[p_idx].metadata = p_meta; update(); minimum_size_changed(); } @@ -776,7 +776,7 @@ void PopupMenu::set_item_metadata(int p_idx, const Variant &p_meta) { void PopupMenu::set_item_disabled(int p_idx, bool p_disabled) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].disabled = p_disabled; + items.write[p_idx].disabled = p_disabled; update(); minimum_size_changed(); } @@ -784,7 +784,7 @@ void PopupMenu::set_item_disabled(int p_idx, bool p_disabled) { void PopupMenu::set_item_submenu(int p_idx, const String &p_submenu) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].submenu = p_submenu; + items.write[p_idx].submenu = p_submenu; update(); minimum_size_changed(); } @@ -792,7 +792,7 @@ void PopupMenu::set_item_submenu(int p_idx, const String &p_submenu) { void PopupMenu::toggle_item_checked(int p_idx) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].checked = !items[p_idx].checked; + items.write[p_idx].checked = !items[p_idx].checked; update(); minimum_size_changed(); } @@ -886,7 +886,7 @@ int PopupMenu::get_item_state(int p_idx) const { void PopupMenu::set_item_as_separator(int p_idx, bool p_separator) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].separator = p_separator; + items.write[p_idx].separator = p_separator; update(); } @@ -898,21 +898,21 @@ bool PopupMenu::is_item_separator(int p_idx) const { void PopupMenu::set_item_as_checkable(int p_idx, bool p_checkable) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].checkable_type = p_checkable ? Item::CHECKABLE_TYPE_CHECK_BOX : Item::CHECKABLE_TYPE_NONE; + items.write[p_idx].checkable_type = p_checkable ? Item::CHECKABLE_TYPE_CHECK_BOX : Item::CHECKABLE_TYPE_NONE; update(); } void PopupMenu::set_item_as_radio_checkable(int p_idx, bool p_radio_checkable) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].checkable_type = p_radio_checkable ? Item::CHECKABLE_TYPE_RADIO_BUTTON : Item::CHECKABLE_TYPE_NONE; + items.write[p_idx].checkable_type = p_radio_checkable ? Item::CHECKABLE_TYPE_RADIO_BUTTON : Item::CHECKABLE_TYPE_NONE; update(); } void PopupMenu::set_item_tooltip(int p_idx, const String &p_tooltip) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].tooltip = p_tooltip; + items.write[p_idx].tooltip = p_tooltip; update(); } @@ -921,8 +921,8 @@ void PopupMenu::set_item_shortcut(int p_idx, const Ref<ShortCut> &p_shortcut, bo if (items[p_idx].shortcut.is_valid()) { _unref_shortcut(items[p_idx].shortcut); } - items[p_idx].shortcut = p_shortcut; - items[p_idx].shortcut_is_global = p_global; + items.write[p_idx].shortcut = p_shortcut; + items.write[p_idx].shortcut_is_global = p_global; if (items[p_idx].shortcut.is_valid()) { _ref_shortcut(items[p_idx].shortcut); @@ -934,7 +934,7 @@ void PopupMenu::set_item_shortcut(int p_idx, const Ref<ShortCut> &p_shortcut, bo void PopupMenu::set_item_h_offset(int p_idx, int p_offset) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].h_ofs = p_offset; + items.write[p_idx].h_ofs = p_offset; update(); minimum_size_changed(); } @@ -942,14 +942,14 @@ void PopupMenu::set_item_h_offset(int p_idx, int p_offset) { void PopupMenu::set_item_multistate(int p_idx, int p_state) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].state = p_state; + items.write[p_idx].state = p_state; update(); } void PopupMenu::set_item_shortcut_disabled(int p_idx, bool p_disabled) { ERR_FAIL_INDEX(p_idx, items.size()); - items[p_idx].shortcut_is_disabled = p_disabled; + items.write[p_idx].shortcut_is_disabled = p_disabled; update(); } @@ -960,9 +960,9 @@ void PopupMenu::toggle_item_multistate(int p_idx) { return; } - ++items[p_idx].state; - if (items[p_idx].max_states <= items[p_idx].state) - items[p_idx].state = 0; + ++items.write[p_idx].state; + if (items.write[p_idx].max_states <= items[p_idx].state) + items.write[p_idx].state = 0; update(); } diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 857ae8ff4c..a3748bf14c 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -149,7 +149,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & if (r_click_item) *r_click_item = NULL; } - Line &l = p_frame->lines[p_line]; + Line &l = p_frame->lines.write[p_line]; Item *it = l.from; int line_ofs = 0; @@ -535,9 +535,9 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & int idx = 0; //set minimums to zero for (int i = 0; i < table->columns.size(); i++) { - table->columns[i].min_width = 0; - table->columns[i].max_width = 0; - table->columns[i].width = 0; + table->columns.write[i].min_width = 0; + table->columns.write[i].max_width = 0; + table->columns.write[i].width = 0; } //compute minimum width for each cell const int available_width = p_width - hseparation * (table->columns.size() - 1) - wofs; @@ -553,8 +553,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & for (int i = 0; i < frame->lines.size(); i++) { _process_line(frame, Point2(), ly, available_width, i, PROCESS_CACHE, cfont, Color(), font_color_shadow, use_outline, shadow_ofs); - table->columns[column].min_width = MAX(table->columns[column].min_width, frame->lines[i].minimum_width); - table->columns[column].max_width = MAX(table->columns[column].max_width, frame->lines[i].maximum_width); + table->columns.write[column].min_width = MAX(table->columns[column].min_width, frame->lines[i].minimum_width); + table->columns.write[column].max_width = MAX(table->columns[column].max_width, frame->lines[i].maximum_width); } idx++; } @@ -568,16 +568,16 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & for (int i = 0; i < table->columns.size(); i++) { remaining_width -= table->columns[i].min_width; if (table->columns[i].max_width > table->columns[i].min_width) - table->columns[i].expand = true; + table->columns.write[i].expand = true; if (table->columns[i].expand) total_ratio += table->columns[i].expand_ratio; } //assign actual widths for (int i = 0; i < table->columns.size(); i++) { - table->columns[i].width = table->columns[i].min_width; + table->columns.write[i].width = table->columns[i].min_width; if (table->columns[i].expand) - table->columns[i].width += table->columns[i].expand_ratio * remaining_width / total_ratio; + table->columns.write[i].width += table->columns[i].expand_ratio * remaining_width / total_ratio; table->total_width += table->columns[i].width + hseparation; } @@ -592,7 +592,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & int dif = table->columns[i].width - table->columns[i].max_width; if (dif > 0) { table_need_fit = true; - table->columns[i].width = table->columns[i].max_width; + table->columns.write[i].width = table->columns[i].max_width; table->total_width -= dif; total_ratio -= table->columns[i].expand_ratio; } @@ -606,7 +606,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & if (dif > 0) { int slice = table->columns[i].expand_ratio * remaining_width / total_ratio; int incr = MIN(dif, slice); - table->columns[i].width += incr; + table->columns.write[i].width += incr; table->total_width += incr; } } @@ -626,8 +626,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & int ly = 0; _process_line(frame, Point2(), ly, table->columns[column].width, i, PROCESS_CACHE, cfont, Color(), font_color_shadow, use_outline, shadow_ofs); - frame->lines[i].height_cache = ly; //actual height - frame->lines[i].height_accum_cache = ly; //actual height + frame->lines.write[i].height_cache = ly; //actual height + frame->lines.write[i].height_accum_cache = ly; //actual height } idx++; } @@ -669,7 +669,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & yofs += frame->lines[i].height_cache; if (p_mode == PROCESS_CACHE) { - frame->lines[i].height_accum_cache = offset.y + draw_ofs.y + frame->lines[i].height_cache; + frame->lines.write[i].height_accum_cache = offset.y + draw_ofs.y + frame->lines[i].height_cache; } } @@ -1267,11 +1267,11 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) { int y = 0; _process_line(p_frame, text_rect.get_position(), y, text_rect.get_size().width - scroll_w, i, PROCESS_CACHE, base_font, Color(), font_color_shadow, use_outline, shadow_ofs); - p_frame->lines[i].height_cache = y; - p_frame->lines[i].height_accum_cache = y; + p_frame->lines.write[i].height_cache = y; + p_frame->lines.write[i].height_accum_cache = y; if (i > 0) - p_frame->lines[i].height_accum_cache += p_frame->lines[i - 1].height_accum_cache; + p_frame->lines.write[i].height_accum_cache += p_frame->lines[i - 1].height_accum_cache; } int total_height = 0; @@ -1346,7 +1346,7 @@ void RichTextLabel::add_text(const String &p_text) { _add_item(item, false); current_frame->lines.resize(current_frame->lines.size() + 1); if (item->type != ITEM_NEWLINE) - current_frame->lines[current_frame->lines.size() - 1].from = item; + current_frame->lines.write[current_frame->lines.size() - 1].from = item; _invalidate_current_line(current_frame); } @@ -1369,7 +1369,7 @@ void RichTextLabel::_add_item(Item *p_item, bool p_enter, bool p_ensure_newline) } if (current_frame->lines[current_frame->lines.size() - 1].from == NULL) { - current_frame->lines[current_frame->lines.size() - 1].from = p_item; + current_frame->lines.write[current_frame->lines.size() - 1].from = p_item; } p_item->line = current_frame->lines.size() - 1; @@ -1431,7 +1431,7 @@ bool RichTextLabel::remove_line(const int p_line) { _remove_item(current->subitems[lines], current->subitems[lines]->line, lines); if (p_line == 0) { - main->lines[0].from = main; + main->lines.write[0].from = main; } main->first_invalid_line = 0; @@ -1510,8 +1510,8 @@ void RichTextLabel::push_table(int p_columns) { item->columns.resize(p_columns); item->total_width = 0; for (int i = 0; i < item->columns.size(); i++) { - item->columns[i].expand = false; - item->columns[i].expand_ratio = 1; + item->columns.write[i].expand = false; + item->columns.write[i].expand_ratio = 1; } _add_item(item, true, true); } @@ -1521,8 +1521,8 @@ void RichTextLabel::set_table_column_expand(int p_column, bool p_expand, int p_r ERR_FAIL_COND(current->type != ITEM_TABLE); ItemTable *table = static_cast<ItemTable *>(current); ERR_FAIL_INDEX(p_column, table->columns.size()); - table->columns[p_column].expand = p_expand; - table->columns[p_column].expand_ratio = p_ratio; + table->columns.write[p_column].expand = p_expand; + table->columns.write[p_column].expand_ratio = p_ratio; } void RichTextLabel::push_cell() { @@ -1536,7 +1536,7 @@ void RichTextLabel::push_cell() { item->cell = true; item->parent_line = item->parent_frame->lines.size() - 1; item->lines.resize(1); - item->lines[0].from = NULL; + item->lines.write[0].from = NULL; item->first_invalid_line = 0; } @@ -2269,7 +2269,7 @@ RichTextLabel::RichTextLabel() { main->index = 0; current = main; main->lines.resize(1); - main->lines[0].from = main; + main->lines.write[0].from = main; main->first_invalid_line = 0; current_frame = main; tab_size = 4; diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp index b114264de1..50bd1d867c 100644 --- a/scene/gui/tabs.cpp +++ b/scene/gui/tabs.cpp @@ -286,7 +286,7 @@ void Tabs::_notification(int p_what) { for (int i = 0; i < tabs.size(); i++) { - tabs[i].ofs_cache = mw; + tabs.write[i].ofs_cache = mw; mw += get_tab_width(i); } @@ -314,7 +314,7 @@ void Tabs::_notification(int p_what) { if (i < offset) continue; - tabs[i].ofs_cache = w; + tabs.write[i].ofs_cache = w; int lsize = tabs[i].size_cache; @@ -379,7 +379,7 @@ void Tabs::_notification(int p_what) { rb->draw(ci, Point2i(w + style->get_margin(MARGIN_LEFT), rb_rect.position.y + style->get_margin(MARGIN_TOP))); w += rb->get_width(); - tabs[i].rb_rect = rb_rect; + tabs.write[i].rb_rect = rb_rect; } if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current)) { @@ -403,7 +403,7 @@ void Tabs::_notification(int p_what) { cb->draw(ci, Point2i(w + style->get_margin(MARGIN_LEFT), cb_rect.position.y + style->get_margin(MARGIN_TOP))); w += cb->get_width(); - tabs[i].cb_rect = cb_rect; + tabs.write[i].cb_rect = cb_rect; } w += sb->get_margin(MARGIN_RIGHT); @@ -471,7 +471,7 @@ bool Tabs::get_offset_buttons_visible() const { void Tabs::set_tab_title(int p_tab, const String &p_title) { ERR_FAIL_INDEX(p_tab, tabs.size()); - tabs[p_tab].text = p_title; + tabs.write[p_tab].text = p_title; update(); minimum_size_changed(); } @@ -485,7 +485,7 @@ String Tabs::get_tab_title(int p_tab) const { void Tabs::set_tab_icon(int p_tab, const Ref<Texture> &p_icon) { ERR_FAIL_INDEX(p_tab, tabs.size()); - tabs[p_tab].icon = p_icon; + tabs.write[p_tab].icon = p_icon; update(); minimum_size_changed(); } @@ -499,7 +499,7 @@ Ref<Texture> Tabs::get_tab_icon(int p_tab) const { void Tabs::set_tab_disabled(int p_tab, bool p_disabled) { ERR_FAIL_INDEX(p_tab, tabs.size()); - tabs[p_tab].disabled = p_disabled; + tabs.write[p_tab].disabled = p_disabled; update(); } bool Tabs::get_tab_disabled(int p_tab) const { @@ -511,7 +511,7 @@ bool Tabs::get_tab_disabled(int p_tab) const { void Tabs::set_tab_right_button(int p_tab, const Ref<Texture> &p_right_button) { ERR_FAIL_INDEX(p_tab, tabs.size()); - tabs[p_tab].right_button = p_right_button; + tabs.write[p_tab].right_button = p_right_button; _update_cache(); update(); minimum_size_changed(); @@ -536,9 +536,9 @@ void Tabs::_update_cache() { int size_fixed = 0; int count_resize = 0; for (int i = 0; i < tabs.size(); i++) { - tabs[i].ofs_cache = mw; - tabs[i].size_cache = get_tab_width(i); - tabs[i].size_text = font->get_string_size(tabs[i].text).width; + tabs.write[i].ofs_cache = mw; + tabs.write[i].size_cache = get_tab_width(i); + tabs.write[i].size_text = font->get_string_size(tabs[i].text).width; mw += tabs[i].size_cache; if (tabs[i].size_cache <= min_width || i == current) { size_fixed += tabs[i].size_cache; @@ -579,9 +579,9 @@ void Tabs::_update_cache() { lsize = m_width; } } - tabs[i].ofs_cache = w; - tabs[i].size_cache = lsize; - tabs[i].size_text = slen; + tabs.write[i].ofs_cache = w; + tabs.write[i].size_cache = lsize; + tabs.write[i].size_text = slen; w += lsize; } } diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 218b5060a1..8926c1ec00 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -127,13 +127,13 @@ void TextEdit::Text::_update_line_cache(int p_line) const { w += get_char_width(str[i], str[i + 1], w); } - text[p_line].width_cache = w; + text.write[p_line].width_cache = w; - text[p_line].wrap_amount_cache = -1; + text.write[p_line].wrap_amount_cache = -1; //update regions - text[p_line].region_info.clear(); + text.write[p_line].region_info.clear(); for (int i = 0; i < len; i++) { @@ -172,7 +172,7 @@ void TextEdit::Text::_update_line_cache(int p_line) const { ColorRegionInfo cri; cri.end = false; cri.region = j; - text[p_line].region_info[i] = cri; + text.write[p_line].region_info[i] = cri; i += lr - 1; break; @@ -200,7 +200,7 @@ void TextEdit::Text::_update_line_cache(int p_line) const { ColorRegionInfo cri; cri.end = true; cri.region = j; - text[p_line].region_info[i] = cri; + text.write[p_line].region_info[i] = cri; i += lr - 1; break; @@ -236,7 +236,7 @@ void TextEdit::Text::set_line_wrap_amount(int p_line, int p_wrap_amount) const { ERR_FAIL_INDEX(p_line, text.size()); - text[p_line].wrap_amount_cache = p_wrap_amount; + text.write[p_line].wrap_amount_cache = p_wrap_amount; } int TextEdit::Text::get_line_wrap_amount(int p_line) const { @@ -249,14 +249,14 @@ int TextEdit::Text::get_line_wrap_amount(int p_line) const { void TextEdit::Text::clear_width_cache() { for (int i = 0; i < text.size(); i++) { - text[i].width_cache = -1; + text.write[i].width_cache = -1; } } void TextEdit::Text::clear_wrap_cache() { for (int i = 0; i < text.size(); i++) { - text[i].wrap_amount_cache = -1; + text.write[i].wrap_amount_cache = -1; } } @@ -281,15 +281,16 @@ void TextEdit::Text::set(int p_line, const String &p_text) { ERR_FAIL_INDEX(p_line, text.size()); - text[p_line].width_cache = -1; - text[p_line].wrap_amount_cache = -1; - text[p_line].data = p_text; + text.write[p_line].width_cache = -1; + text.write[p_line].wrap_amount_cache = -1; + text.write[p_line].data = p_text; } void TextEdit::Text::insert(int p_at, const String &p_text) { Line line; line.marked = false; + line.safe = false; line.breakpoint = false; line.hidden = false; line.width_cache = -1; @@ -336,10 +337,6 @@ void TextEdit::_update_scrollbars() { int hscroll_rows = ((hmin.height - 1) / get_row_height()) + 1; int visible_rows = get_visible_rows(); - int first_vis_line = get_first_visible_line(); - int wi; - int num_rows = MAX(visible_rows, num_lines_from_rows(first_vis_line, cursor.wrap_ofs, visible_rows, wi)); - int total_rows = get_total_visible_rows(); if (scroll_past_end_of_file_enabled) { total_rows += visible_rows - 1; @@ -972,7 +969,7 @@ void TextEdit::_notification(int p_what) { fc = line_num_padding + fc; } - cache.font->draw(ci, Point2(cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width + ofs_x, yofs + cache.font->get_ascent()), fc, cache.line_number_color); + cache.font->draw(ci, Point2(cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width + ofs_x, yofs + cache.font->get_ascent()), fc, text.is_safe(line) ? cache.safe_line_number_color : cache.line_number_color); } } @@ -1672,7 +1669,6 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co rows /= get_row_height(); rows += get_v_scroll_offset(); int first_vis_line = get_first_visible_line(); - int last_vis_line = get_last_visible_line(); int row = first_vis_line + Math::floor(rows); int wrap_index = 0; @@ -3799,7 +3795,6 @@ Vector<String> TextEdit::get_wrap_rows_text(int p_line) const { } // line ends before hit wrap_at; add this word to the substring wrap_substring += word_str; - px += word_px; lines.push_back(wrap_substring); return lines; } @@ -4314,6 +4309,7 @@ void TextEdit::_update_caches() { cache.caret_color = get_color("caret_color"); cache.caret_background_color = get_color("caret_background_color"); cache.line_number_color = get_color("line_number_color"); + cache.safe_line_number_color = get_color("safe_line_number_color"); cache.font_color = get_color("font_color"); cache.font_selected_color = get_color("font_selected_color"); cache.keyword_color = get_color("keyword_color"); @@ -4885,6 +4881,17 @@ void TextEdit::set_line_as_marked(int p_line, bool p_marked) { update(); } +void TextEdit::set_line_as_safe(int p_line, bool p_safe) { + ERR_FAIL_INDEX(p_line, text.size()); + text.set_safe(p_line, p_safe); + update(); +} + +bool TextEdit::is_line_set_as_safe(int p_line) const { + ERR_FAIL_INDEX_V(p_line, text.size(), false); + return text.is_safe(p_line); +} + bool TextEdit::is_line_set_as_breakpoint(int p_line) const { ERR_FAIL_INDEX_V(p_line, text.size(), false); @@ -5506,9 +5513,8 @@ int TextEdit::get_last_visible_line() const { int TextEdit::get_last_visible_line_wrap_index() const { int first_vis_line = get_first_visible_line(); - int last_vis_line = 0; int wi; - last_vis_line = first_vis_line + num_lines_from_rows(first_vis_line, cursor.wrap_ofs, get_visible_rows() + 1, wi) - 1; + num_lines_from_rows(first_vis_line, cursor.wrap_ofs, get_visible_rows() + 1, wi); return wi; } @@ -5723,7 +5729,7 @@ void TextEdit::_update_completion_candidates() { for (int i = 0; i < completion_strings.size(); i++) { if (single_quote && completion_strings[i].is_quoted()) { - completion_strings[i] = completion_strings[i].unquote().quote("'"); + completion_strings.write[i] = completion_strings[i].unquote().quote("'"); } if (s == completion_strings[i]) { diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 586f4c8e93..19b5d574c6 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -76,6 +76,7 @@ public: bool marked : 1; bool breakpoint : 1; bool hidden : 1; + bool safe : 1; int wrap_amount_cache : 24; Map<int, ColorRegionInfo> region_info; String data; @@ -100,12 +101,14 @@ public: int get_line_wrap_amount(int p_line) const; const Map<int, ColorRegionInfo> &get_color_region_info(int p_line) const; void set(int p_line, const String &p_text); - void set_marked(int p_line, bool p_marked) { text[p_line].marked = p_marked; } + void set_marked(int p_line, bool p_marked) { text.write[p_line].marked = p_marked; } bool is_marked(int p_line) const { return text[p_line].marked; } - void set_breakpoint(int p_line, bool p_breakpoint) { text[p_line].breakpoint = p_breakpoint; } + void set_breakpoint(int p_line, bool p_breakpoint) { text.write[p_line].breakpoint = p_breakpoint; } bool is_breakpoint(int p_line) const { return text[p_line].breakpoint; } - void set_hidden(int p_line, bool p_hidden) { text[p_line].hidden = p_hidden; } + void set_hidden(int p_line, bool p_hidden) { text.write[p_line].hidden = p_hidden; } bool is_hidden(int p_line) const { return text[p_line].hidden; } + void set_safe(int p_line, bool p_safe) { text.write[p_line].safe = p_safe; } + bool is_safe(int p_line) const { return text[p_line].safe; } void insert(int p_at, const String &p_text); void remove(int p_at); int size() const { return text.size(); } @@ -165,6 +168,7 @@ private: Color caret_color; Color caret_background_color; Color line_number_color; + Color safe_line_number_color; Color font_color; Color font_selected_color; Color keyword_color; @@ -472,6 +476,8 @@ public: void set_line_as_marked(int p_line, bool p_marked); void set_line_as_breakpoint(int p_line, bool p_breakpoint); bool is_line_set_as_breakpoint(int p_line) const; + void set_line_as_safe(int p_line, bool p_safe); + bool is_line_set_as_safe(int p_line) const; void get_breakpoints(List<int> *p_breakpoints) const; Array get_breakpoints_array() const; void remove_breakpoints(); diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp index 82d983184b..6e4fe88dbf 100644 --- a/scene/gui/texture_progress.cpp +++ b/scene/gui/texture_progress.cpp @@ -309,15 +309,23 @@ void TextureProgress::_notification(int p_what) { draw_texture_rect_region(progress, region, region, tint_progress); } break; case FILL_CLOCKWISE: - case FILL_COUNTER_CLOCKWISE: { + case FILL_COUNTER_CLOCKWISE: + case FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE: { float val = get_as_ratio() * rad_max_degrees / 360; if (val == 1) { Rect2 region = Rect2(Point2(), s); draw_texture_rect_region(progress, region, region, tint_progress); } else if (val != 0) { Array pts; - float direction = mode == FILL_CLOCKWISE ? 1 : -1; - float start = rad_init_angle / 360; + float direction = mode == FILL_COUNTER_CLOCKWISE ? -1 : 1; + float start; + + if (mode == FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE) { + start = rad_init_angle / 360 - val / 2; + } else { + start = rad_init_angle / 360; + } + float end = start + direction * val; pts.append(start); pts.append(end); @@ -351,6 +359,14 @@ void TextureProgress::_notification(int p_what) { draw_line(p - Point2(0, 8), p + Point2(0, 8), Color(0.9, 0.5, 0.5), 2); } } break; + case FILL_BILINEAR_LEFT_AND_RIGHT: { + Rect2 region = Rect2(Point2(s.x / 2 - s.x * get_as_ratio() / 2, 0), Size2(s.x * get_as_ratio(), s.y)); + draw_texture_rect_region(progress, region, region, tint_progress); + } break; + case FILL_BILINEAR_TOP_AND_BOTTOM: { + Rect2 region = Rect2(Point2(0, s.y / 2 - s.y * get_as_ratio() / 2), Size2(s.x, s.y * get_as_ratio())); + draw_texture_rect_region(progress, region, region, tint_progress); + } break; default: draw_texture_rect_region(progress, Rect2(Point2(), Size2(s.x * get_as_ratio(), s.y)), Rect2(Point2(), Size2(s.x * get_as_ratio(), s.y)), tint_progress); } @@ -364,7 +380,7 @@ void TextureProgress::_notification(int p_what) { } void TextureProgress::set_fill_mode(int p_fill) { - ERR_FAIL_INDEX(p_fill, 6); + ERR_FAIL_INDEX(p_fill, 9); mode = (FillMode)p_fill; update(); } @@ -446,7 +462,7 @@ void TextureProgress::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_under", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_under_texture", "get_under_texture"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_over", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_over_texture", "get_over_texture"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_progress", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_progress_texture", "get_progress_texture"); - ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "fill_mode", PROPERTY_HINT_ENUM, "Left to Right,Right to Left,Top to Bottom,Bottom to Top,Clockwise,Counter Clockwise"), "set_fill_mode", "get_fill_mode"); + ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "fill_mode", PROPERTY_HINT_ENUM, "Left to Right,Right to Left,Top to Bottom,Bottom to Top,Clockwise,Counter Clockwise,Bilinear (Left and Right),Bilinear (Top and Bottom), Clockwise and Counter Clockwise"), "set_fill_mode", "get_fill_mode"); ADD_GROUP("Tint", "tint_"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "tint_under", PROPERTY_HINT_COLOR_NO_ALPHA), "set_tint_under", "get_tint_under"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "tint_over", PROPERTY_HINT_COLOR_NO_ALPHA), "set_tint_over", "get_tint_over"); @@ -468,6 +484,9 @@ void TextureProgress::_bind_methods() { BIND_ENUM_CONSTANT(FILL_BOTTOM_TO_TOP); BIND_ENUM_CONSTANT(FILL_CLOCKWISE); BIND_ENUM_CONSTANT(FILL_COUNTER_CLOCKWISE); + BIND_ENUM_CONSTANT(FILL_BILINEAR_LEFT_AND_RIGHT); + BIND_ENUM_CONSTANT(FILL_BILINEAR_TOP_AND_BOTTOM); + BIND_ENUM_CONSTANT(FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE); } TextureProgress::TextureProgress() { diff --git a/scene/gui/texture_progress.h b/scene/gui/texture_progress.h index 34158b5db5..a11e55234a 100644 --- a/scene/gui/texture_progress.h +++ b/scene/gui/texture_progress.h @@ -52,7 +52,10 @@ public: FILL_TOP_TO_BOTTOM, FILL_BOTTOM_TO_TOP, FILL_CLOCKWISE, - FILL_COUNTER_CLOCKWISE + FILL_COUNTER_CLOCKWISE, + FILL_BILINEAR_LEFT_AND_RIGHT, + FILL_BILINEAR_TOP_AND_BOTTOM, + FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE }; void set_fill_mode(int p_fill); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 1d27612766..6f09488b64 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -121,7 +121,7 @@ void TreeItem::_cell_deselected(int p_cell) { void TreeItem::set_cell_mode(int p_column, TreeCellMode p_mode) { ERR_FAIL_INDEX(p_column, cells.size()); - Cell &c = cells[p_column]; + Cell &c = cells.write[p_column]; c.mode = p_mode; c.min = 0; c.max = 100; @@ -144,7 +144,7 @@ TreeItem::TreeCellMode TreeItem::get_cell_mode(int p_column) const { void TreeItem::set_checked(int p_column, bool p_checked) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].checked = p_checked; + cells.write[p_column].checked = p_checked; _changed_notify(p_column); } @@ -157,22 +157,22 @@ bool TreeItem::is_checked(int p_column) const { void TreeItem::set_text(int p_column, String p_text) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].text = p_text; + cells.write[p_column].text = p_text; if (cells[p_column].mode == TreeItem::CELL_MODE_RANGE || cells[p_column].mode == TreeItem::CELL_MODE_RANGE_EXPRESSION) { Vector<String> strings = p_text.split(","); - cells[p_column].min = INT_MAX; - cells[p_column].max = INT_MIN; + cells.write[p_column].min = INT_MAX; + cells.write[p_column].max = INT_MIN; for (int i = 0; i < strings.size(); i++) { int value = i; if (!strings[i].get_slicec(':', 1).empty()) { value = strings[i].get_slicec(':', 1).to_int(); } - cells[p_column].min = MIN(cells[p_column].min, value); - cells[p_column].max = MAX(cells[p_column].max, value); + cells.write[p_column].min = MIN(cells[p_column].min, value); + cells.write[p_column].max = MAX(cells[p_column].max, value); } - cells[p_column].step = 0; + cells.write[p_column].step = 0; } _changed_notify(p_column); } @@ -186,7 +186,7 @@ String TreeItem::get_text(int p_column) const { void TreeItem::set_suffix(int p_column, String p_suffix) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].suffix = p_suffix; + cells.write[p_column].suffix = p_suffix; _changed_notify(p_column); } @@ -200,7 +200,7 @@ String TreeItem::get_suffix(int p_column) const { void TreeItem::set_icon(int p_column, const Ref<Texture> &p_icon) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].icon = p_icon; + cells.write[p_column].icon = p_icon; _changed_notify(p_column); } @@ -213,7 +213,7 @@ Ref<Texture> TreeItem::get_icon(int p_column) const { void TreeItem::set_icon_region(int p_column, const Rect2 &p_icon_region) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].icon_region = p_icon_region; + cells.write[p_column].icon_region = p_icon_region; _changed_notify(p_column); } @@ -226,7 +226,7 @@ Rect2 TreeItem::get_icon_region(int p_column) const { void TreeItem::set_icon_color(int p_column, const Color &p_icon_color) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].icon_color = p_icon_color; + cells.write[p_column].icon_color = p_icon_color; _changed_notify(p_column); } @@ -239,7 +239,7 @@ Color TreeItem::get_icon_color(int p_column) const { void TreeItem::set_icon_max_width(int p_column, int p_max) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].icon_max_w = p_max; + cells.write[p_column].icon_max_w = p_max; _changed_notify(p_column); } @@ -260,7 +260,7 @@ void TreeItem::set_range(int p_column, double p_value) { if (p_value > cells[p_column].max) p_value = cells[p_column].max; - cells[p_column].val = p_value; + cells.write[p_column].val = p_value; _changed_notify(p_column); } @@ -278,10 +278,10 @@ bool TreeItem::is_range_exponential(int p_column) const { void TreeItem::set_range_config(int p_column, double p_min, double p_max, double p_step, bool p_exp) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].min = p_min; - cells[p_column].max = p_max; - cells[p_column].step = p_step; - cells[p_column].expr = p_exp; + cells.write[p_column].min = p_min; + cells.write[p_column].max = p_max; + cells.write[p_column].step = p_step; + cells.write[p_column].expr = p_exp; _changed_notify(p_column); } @@ -296,7 +296,7 @@ void TreeItem::get_range_config(int p_column, double &r_min, double &r_max, doub void TreeItem::set_metadata(int p_column, const Variant &p_meta) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].meta = p_meta; + cells.write[p_column].meta = p_meta; } Variant TreeItem::get_metadata(int p_column) const { @@ -311,8 +311,8 @@ void TreeItem::set_custom_draw(int p_column, Object *p_object, const StringName ERR_FAIL_INDEX(p_column, cells.size()); ERR_FAIL_NULL(p_object); - cells[p_column].custom_draw_obj = p_object->get_instance_id(); - cells[p_column].custom_draw_callback = p_callback; + cells.write[p_column].custom_draw_obj = p_object->get_instance_id(); + cells.write[p_column].custom_draw_callback = p_callback; } void TreeItem::set_collapsed(bool p_collapsed) { @@ -467,7 +467,7 @@ void TreeItem::remove_child(TreeItem *p_item) { void TreeItem::set_selectable(int p_column, bool p_selectable) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].selectable = p_selectable; + cells.write[p_column].selectable = p_selectable; } bool TreeItem::is_selectable(int p_column) const { @@ -517,7 +517,7 @@ void TreeItem::add_button(int p_column, const Ref<Texture> &p_button, int p_id, button.id = p_id; button.disabled = p_disabled; button.tooltip = p_tooltip; - cells[p_column].buttons.push_back(button); + cells.write[p_column].buttons.push_back(button); _changed_notify(p_column); } @@ -540,7 +540,7 @@ void TreeItem::erase_button(int p_column, int p_idx) { ERR_FAIL_INDEX(p_column, cells.size()); ERR_FAIL_INDEX(p_idx, cells[p_column].buttons.size()); - cells[p_column].buttons.remove(p_idx); + cells.write[p_column].buttons.remove(p_idx); _changed_notify(p_column); } @@ -568,7 +568,7 @@ void TreeItem::set_button(int p_column, int p_idx, const Ref<Texture> &p_button) ERR_FAIL_COND(p_button.is_null()); ERR_FAIL_INDEX(p_column, cells.size()); ERR_FAIL_INDEX(p_idx, cells[p_column].buttons.size()); - cells[p_column].buttons[p_idx].texture = p_button; + cells.write[p_column].buttons.write[p_idx].texture = p_button; _changed_notify(p_column); } @@ -576,14 +576,14 @@ void TreeItem::set_button_color(int p_column, int p_idx, const Color &p_color) { ERR_FAIL_INDEX(p_column, cells.size()); ERR_FAIL_INDEX(p_idx, cells[p_column].buttons.size()); - cells[p_column].buttons[p_idx].color = p_color; + cells.write[p_column].buttons.write[p_idx].color = p_color; _changed_notify(p_column); } void TreeItem::set_editable(int p_column, bool p_editable) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].editable = p_editable; + cells.write[p_column].editable = p_editable; _changed_notify(p_column); } @@ -596,8 +596,8 @@ bool TreeItem::is_editable(int p_column) { void TreeItem::set_custom_color(int p_column, const Color &p_color) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].custom_color = true; - cells[p_column].color = p_color; + cells.write[p_column].custom_color = true; + cells.write[p_column].color = p_color; _changed_notify(p_column); } Color TreeItem::get_custom_color(int p_column) const { @@ -610,15 +610,15 @@ Color TreeItem::get_custom_color(int p_column) const { void TreeItem::clear_custom_color(int p_column) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].custom_color = false; - cells[p_column].color = Color(); + cells.write[p_column].custom_color = false; + cells.write[p_column].color = Color(); _changed_notify(p_column); } void TreeItem::set_tooltip(int p_column, const String &p_tooltip) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].tooltip = p_tooltip; + cells.write[p_column].tooltip = p_tooltip; } String TreeItem::get_tooltip(int p_column) const { @@ -630,17 +630,17 @@ String TreeItem::get_tooltip(int p_column) const { void TreeItem::set_custom_bg_color(int p_column, const Color &p_color, bool p_bg_outline) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].custom_bg_color = true; - cells[p_column].custom_bg_outline = p_bg_outline; - cells[p_column].bg_color = p_color; + cells.write[p_column].custom_bg_color = true; + cells.write[p_column].custom_bg_outline = p_bg_outline; + cells.write[p_column].bg_color = p_color; _changed_notify(p_column); } void TreeItem::clear_custom_bg_color(int p_column) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].custom_bg_color = false; - cells[p_column].bg_color = Color(); + cells.write[p_column].custom_bg_color = false; + cells.write[p_column].bg_color = Color(); _changed_notify(p_column); } @@ -655,7 +655,7 @@ Color TreeItem::get_custom_bg_color(int p_column) const { void TreeItem::set_custom_as_button(int p_column, bool p_button) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].custom_button = p_button; + cells.write[p_column].custom_button = p_button; } bool TreeItem::is_custom_set_as_button(int p_column) const { @@ -666,7 +666,7 @@ bool TreeItem::is_custom_set_as_button(int p_column) const { void TreeItem::set_text_align(int p_column, TextAlign p_align) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].text_align = p_align; + cells.write[p_column].text_align = p_align; _changed_notify(p_column); } @@ -678,7 +678,7 @@ TreeItem::TextAlign TreeItem::get_text_align(int p_column) const { void TreeItem::set_expand_right(int p_column, bool p_enable) { ERR_FAIL_INDEX(p_column, cells.size()); - cells[p_column].expand_right = p_enable; + cells.write[p_column].expand_right = p_enable; _changed_notify(p_column); } @@ -1486,7 +1486,7 @@ int Tree::_count_selected_items(TreeItem *p_from) const { } void Tree::select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev, bool *r_in_range, bool p_force_deselect) { - TreeItem::Cell &selected_cell = p_selected->cells[p_col]; + TreeItem::Cell &selected_cell = p_selected->cells.write[p_col]; bool switched = false; if (r_in_range && !*r_in_range && (p_current == p_selected || p_current == p_prev)) { @@ -1498,7 +1498,7 @@ void Tree::select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_c for (int i = 0; i < columns.size(); i++) { - TreeItem::Cell &c = p_current->cells[i]; + TreeItem::Cell &c = p_current->cells.write[i]; if (!c.selectable) continue; @@ -1689,7 +1689,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool return -1; //collapse/uncollapse because nothing can be done with item } - TreeItem::Cell &c = p_item->cells[col]; + const TreeItem::Cell &c = p_item->cells[col]; bool already_selected = c.selected; bool already_cursor = (p_item == selected_item) && col == selected_col; @@ -1990,7 +1990,7 @@ void Tree::text_editor_enter(String p_text) { if (popup_edited_item_col < 0 || popup_edited_item_col > columns.size()) return; - TreeItem::Cell &c = popup_edited_item->cells[popup_edited_item_col]; + TreeItem::Cell &c = popup_edited_item->cells.write[popup_edited_item_col]; switch (c.mode) { case TreeItem::CELL_MODE_STRING: { @@ -2041,7 +2041,7 @@ void Tree::value_editor_changed(double p_value) { return; } - TreeItem::Cell &c = popup_edited_item->cells[popup_edited_item_col]; + TreeItem::Cell &c = popup_edited_item->cells.write[popup_edited_item_col]; c.val = p_value; item_edited(popup_edited_item_col, popup_edited_item); update(); @@ -2055,7 +2055,7 @@ void Tree::popup_select(int p_option) { if (popup_edited_item_col < 0 || popup_edited_item_col > columns.size()) return; - popup_edited_item->cells[popup_edited_item_col].val = p_option; + popup_edited_item->cells.write[popup_edited_item_col].val = p_option; //popup_edited_item->edited_signal.call( popup_edited_item_col ); update(); item_edited(popup_edited_item_col, popup_edited_item); @@ -2426,14 +2426,23 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { int col, h, section; TreeItem *it = _find_item_at_pos(root, mpos, col, h, section); - if ((drop_mode_flags && it != drop_mode_over) || section != drop_mode_section) { - drop_mode_over = it; - drop_mode_section = section; - update(); + if (drop_mode_flags) { + if (it != drop_mode_over) { + drop_mode_over = it; + update(); + } + if (it && section != drop_mode_section) { + drop_mode_section = section; + update(); + } } - if (it != cache.hover_item || col != cache.hover_cell) { + if (it != cache.hover_item) { cache.hover_item = it; + update(); + } + + if (it && col != cache.hover_cell) { cache.hover_cell = col; update(); } @@ -2458,7 +2467,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { } } else { - TreeItem::Cell &c = popup_edited_item->cells[popup_edited_item_col]; + const TreeItem::Cell &c = popup_edited_item->cells[popup_edited_item_col]; float diff_y = -mm->get_relative().y; diff_y = Math::pow(ABS(diff_y), 1.8f) * SGN(diff_y); diff_y *= 0.1; @@ -2672,7 +2681,7 @@ bool Tree::edit_selected() { popup_edited_item = s; popup_edited_item_col = col; - TreeItem::Cell &c = s->cells[col]; + const TreeItem::Cell &c = s->cells[col]; if (c.mode == TreeItem::CELL_MODE_CHECK) { @@ -3063,7 +3072,7 @@ void Tree::item_selected(int p_column, TreeItem *p_item) { if (!p_item->cells[p_column].selectable) return; - p_item->cells[p_column].selected = true; + p_item->cells.write[p_column].selected = true; //emit_signal("multi_selected",p_item,p_column,true); - NO this is for TreeItem::select selected_col = p_column; @@ -3077,7 +3086,7 @@ void Tree::item_selected(int p_column, TreeItem *p_item) { void Tree::item_deselected(int p_column, TreeItem *p_item) { if (select_mode == SELECT_MULTI || select_mode == SELECT_SINGLE) { - p_item->cells[p_column].selected = false; + p_item->cells.write[p_column].selected = false; } update(); } @@ -3158,14 +3167,14 @@ void Tree::set_column_min_width(int p_column, int p_min_width) { if (p_min_width < 1) return; - columns[p_column].min_width = p_min_width; + columns.write[p_column].min_width = p_min_width; update(); } void Tree::set_column_expand(int p_column, bool p_expand) { ERR_FAIL_INDEX(p_column, columns.size()); - columns[p_column].expand = p_expand; + columns.write[p_column].expand = p_expand; update(); } @@ -3413,7 +3422,7 @@ bool Tree::are_column_titles_visible() const { void Tree::set_column_title(int p_column, const String &p_title) { ERR_FAIL_INDEX(p_column, columns.size()); - columns[p_column].title = p_title; + columns.write[p_column].title = p_title; update(); } @@ -3659,7 +3668,7 @@ String Tree::get_tooltip(const Point2 &p_pos) const { if (it) { - TreeItem::Cell &c = it->cells[col]; + const TreeItem::Cell &c = it->cells[col]; int col_width = get_column_width(col); for (int j = c.buttons.size() - 1; j >= 0; j--) { Ref<Texture> b = c.buttons[j].texture; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index e1333bcae2..b7b26d1c55 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -809,6 +809,22 @@ bool Node::is_processing_internal() const { return data.idle_process_internal; } +void Node::set_process_priority(int p_priority) { + data.process_priority = p_priority; + + if (is_processing()) + data.tree->make_group_changed("idle_process"); + + if (is_processing_internal()) + data.tree->make_group_changed("idle_process_internal"); + + if (is_physics_processing()) + data.tree->make_group_changed("physics_process"); + + if (is_physics_processing_internal()) + data.tree->make_group_changed("physics_process_internal"); +} + void Node::set_process_input(bool p_enable) { if (p_enable == data.input) @@ -1388,6 +1404,11 @@ bool Node::is_greater_than(const Node *p_node) const { return res; } +bool Node::has_priority_higher_than(const Node *p_node) const { + ERR_FAIL_NULL_V(p_node, false); + return data.process_priority > p_node->data.process_priority; +} + void Node::get_owned_by(Node *p_by, List<Node *> *p_owned) { if (data.owner == p_by) @@ -2608,6 +2629,7 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("is_physics_processing"), &Node::is_physics_processing); ClassDB::bind_method(D_METHOD("get_process_delta_time"), &Node::get_process_delta_time); ClassDB::bind_method(D_METHOD("set_process", "enable"), &Node::set_process); + ClassDB::bind_method(D_METHOD("set_process_priority", "priority"), &Node::set_process_priority); ClassDB::bind_method(D_METHOD("is_processing"), &Node::is_processing); ClassDB::bind_method(D_METHOD("set_process_input", "enable"), &Node::set_process_input); ClassDB::bind_method(D_METHOD("is_processing_input"), &Node::is_processing_input); @@ -2759,6 +2781,7 @@ Node::Node() { data.tree = NULL; data.physics_process = false; data.idle_process = false; + data.process_priority = 0; data.physics_process_internal = false; data.idle_process_internal = false; data.inside_tree = false; diff --git a/scene/main/node.h b/scene/main/node.h index 341349de79..4b8f584ba7 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -70,6 +70,11 @@ public: bool operator()(const Node *p_a, const Node *p_b) const { return p_b->is_greater_than(p_a); } }; + struct ComparatorWithPriority { + + bool operator()(const Node *p_a, const Node *p_b) const { return p_b->has_priority_higher_than(p_a) || p_b->is_greater_than(p_a); } + }; + private: struct GroupData { @@ -118,6 +123,7 @@ private: //should move all the stuff below to bits bool physics_process; bool idle_process; + int process_priority; bool physics_process_internal; bool idle_process_internal; @@ -259,6 +265,7 @@ public: bool is_a_parent_of(const Node *p_node) const; bool is_greater_than(const Node *p_node) const; + bool has_priority_higher_than(const Node *p_node) const; NodePath get_path() const; NodePath get_path_to(const Node *p_node) const; @@ -319,6 +326,8 @@ public: void set_process_internal(bool p_idle_process_internal); bool is_processing_internal() const; + void set_process_priority(int p_priority); + void set_process_input(bool p_enable); bool is_processing_input() const; diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 6438616cf2..1b2e87dd99 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -132,6 +132,12 @@ void SceneTree::remove_from_group(const StringName &p_group, Node *p_node) { group_map.erase(E); } +void SceneTree::make_group_changed(const StringName &p_group) { + Map<StringName, Group>::Element *E = group_map.find(p_group); + if (E) + E->get().changed = true; +} + void SceneTree::flush_transform_notifications() { SelfList<Node> *n = xform_change_list.first(); @@ -165,18 +171,23 @@ void SceneTree::_flush_ugc() { ugc_locked = false; } -void SceneTree::_update_group_order(Group &g) { +void SceneTree::_update_group_order(Group &g, bool p_use_priority) { if (!g.changed) return; if (g.nodes.empty()) return; - Node **nodes = &g.nodes[0]; + Node **nodes = g.nodes.ptrw(); int node_count = g.nodes.size(); - SortArray<Node *, Node::Comparator> node_sort; - node_sort.sort(nodes, node_count); + if (p_use_priority) { + SortArray<Node *, Node::ComparatorWithPriority> node_sort; + node_sort.sort(nodes, node_count); + } else { + SortArray<Node *, Node::Comparator> node_sort; + node_sort.sort(nodes, node_count); + } g.changed = false; } @@ -216,7 +227,7 @@ void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_grou _update_group_order(g); Vector<Node *> nodes_copy = g.nodes; - Node **nodes = &nodes_copy[0]; + Node **nodes = nodes_copy.ptrw(); int node_count = nodes_copy.size(); call_lock++; @@ -271,7 +282,7 @@ void SceneTree::notify_group_flags(uint32_t p_call_flags, const StringName &p_gr _update_group_order(g); Vector<Node *> nodes_copy = g.nodes; - Node **nodes = &nodes_copy[0]; + Node **nodes = nodes_copy.ptrw(); int node_count = nodes_copy.size(); call_lock++; @@ -320,7 +331,7 @@ void SceneTree::set_group_flags(uint32_t p_call_flags, const StringName &p_group _update_group_order(g); Vector<Node *> nodes_copy = g.nodes; - Node **nodes = &nodes_copy[0]; + Node **nodes = nodes_copy.ptrw(); int node_count = nodes_copy.size(); call_lock++; @@ -884,7 +895,7 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p Vector<Node *> nodes_copy = g.nodes; int node_count = nodes_copy.size(); - Node **nodes = &nodes_copy[0]; + Node **nodes = nodes_copy.ptrw(); Variant arg = p_input; const Variant *v[1] = { &arg }; @@ -921,14 +932,14 @@ void SceneTree::_notify_group_pause(const StringName &p_group, int p_notificatio if (g.nodes.empty()) return; - _update_group_order(g); + _update_group_order(g, p_notification == Node::NOTIFICATION_PROCESS || p_notification == Node::NOTIFICATION_INTERNAL_PROCESS || p_notification == Node::NOTIFICATION_PHYSICS_PROCESS || p_notification == Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS); //copy, so copy on write happens in case something is removed from process while being called //performance is not lost because only if something is added/removed the vector is copied. Vector<Node *> nodes_copy = g.nodes; int node_count = nodes_copy.size(); - Node **nodes = &nodes_copy[0]; + Node **nodes = nodes_copy.ptrw(); call_lock++; diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index aa8d78b1e1..11201097d4 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -161,7 +161,7 @@ private: bool ugc_locked; void _flush_ugc(); - _FORCE_INLINE_ void _update_group_order(Group &g); + _FORCE_INLINE_ void _update_group_order(Group &g, bool p_use_priority = false); void _update_listener(); Array _get_nodes_in_group(const StringName &p_group); @@ -204,6 +204,7 @@ private: Group *add_to_group(const StringName &p_group, Node *p_node); void remove_from_group(const StringName &p_group, Node *p_node); + void make_group_changed(const StringName &p_group); void _notify_group_pause(const StringName &p_group, int p_notification); void _call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 9013d276c7..573c401290 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -41,7 +41,10 @@ #include "scene/3d/spatial.h" #include "scene/gui/control.h" #include "scene/gui/label.h" +#include "scene/gui/menu_button.h" +#include "scene/gui/panel.h" #include "scene/gui/panel_container.h" +#include "scene/gui/popup_menu.h" #include "scene/main/timer.h" #include "scene/resources/mesh.h" #include "scene/scene_string_names.h" @@ -1853,8 +1856,32 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (gui.drag_data.get_type() == Variant::NIL && over && !gui.modal_stack.empty()) { Control *top = gui.modal_stack.back()->get(); + if (over != top && !top->is_a_parent_of(over)) { - over = NULL; //nothing can be found outside the modal stack + + PopupMenu *popup_menu = Object::cast_to<PopupMenu>(top); + MenuButton *popup_menu_parent; + MenuButton *menu_button = Object::cast_to<MenuButton>(over); + + if (popup_menu) + popup_menu_parent = Object::cast_to<MenuButton>(popup_menu->get_parent()); + + // If the mouse is over a menu button, this menu will open automatically + // if there is already a pop-up menu open at the same hierarchical level. + if (popup_menu_parent && menu_button && + popup_menu_parent->get_icon().is_null() && + menu_button->get_icon().is_null() && + (popup_menu->get_parent()->get_parent()->is_a_parent_of(menu_button) || + menu_button->get_parent()->is_a_parent_of(popup_menu))) { + + popup_menu->notification(Control::NOTIFICATION_MODAL_CLOSE); + popup_menu->_modal_stack_remove(); + popup_menu->hide(); + + menu_button->pressed(); + } else { + over = NULL; //nothing can be found outside the modal stack + } } } diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 8f78e137b4..a4fd35304a 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -156,6 +156,7 @@ #include "scene/resources/sky_box.h" #include "scene/resources/sphere_shape.h" #include "scene/resources/surface_tool.h" +#include "scene/resources/text_file.h" #include "scene/resources/texture.h" #include "scene/resources/tile_set.h" #include "scene/resources/video_stream.h" @@ -199,10 +200,12 @@ #include "scene/3d/remote_transform.h" #include "scene/3d/room_instance.h" #include "scene/3d/skeleton.h" +#include "scene/3d/soft_body.h" #include "scene/3d/sprite_3d.h" #include "scene/3d/vehicle_body.h" #include "scene/3d/visibility_notifier.h" #include "scene/resources/environment.h" +#include "scene/resources/physics_material.h" #endif static ResourceFormatLoaderTheme *resource_loader_theme = NULL; @@ -312,21 +315,19 @@ void register_scene_types() { ClassDB::register_class<CenterContainer>(); ClassDB::register_class<ScrollContainer>(); ClassDB::register_class<PanelContainer>(); - ClassDB::register_virtual_class<SplitContainer>(); - ClassDB::register_class<HSplitContainer>(); - ClassDB::register_class<VSplitContainer>(); - ClassDB::register_class<GraphNode>(); - ClassDB::register_class<GraphEdit>(); OS::get_singleton()->yield(); //may take time to init ClassDB::register_class<TextureProgress>(); ClassDB::register_class<ItemList>(); + ClassDB::register_class<LineEdit>(); + ClassDB::register_class<VideoPlayer>(); + #ifndef ADVANCED_GUI_DISABLED ClassDB::register_class<FileDialog>(); - ClassDB::register_class<LineEdit>(); + ClassDB::register_class<PopupMenu>(); ClassDB::register_class<Tree>(); @@ -343,9 +344,13 @@ void register_scene_types() { ClassDB::register_class<WindowDialog>(); ClassDB::register_class<AcceptDialog>(); ClassDB::register_class<ConfirmationDialog>(); - ClassDB::register_class<VideoPlayer>(); ClassDB::register_class<MarginContainer>(); ClassDB::register_class<ViewportContainer>(); + ClassDB::register_virtual_class<SplitContainer>(); + ClassDB::register_class<HSplitContainer>(); + ClassDB::register_class<VSplitContainer>(); + ClassDB::register_class<GraphNode>(); + ClassDB::register_class<GraphEdit>(); OS::get_singleton()->yield(); //may take time to init @@ -425,6 +430,7 @@ void register_scene_types() { ClassDB::register_class<KinematicCollision>(); ClassDB::register_class<KinematicBody>(); ClassDB::register_class<PhysicalBone>(); + ClassDB::register_class<SoftBody>(); ClassDB::register_class<VehicleBody>(); ClassDB::register_class<VehicleWheel>(); @@ -588,6 +594,8 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init ClassDB::register_class<SpatialVelocityTracker>(); + + ClassDB::register_class<PhysicsMaterial>(); #endif ClassDB::register_class<World>(); ClassDB::register_class<Environment>(); @@ -610,6 +618,8 @@ void register_scene_types() { ClassDB::register_class<BitmapFont>(); ClassDB::register_class<Curve>(); + ClassDB::register_class<TextFile>(); + ClassDB::register_class<DynamicFontData>(); ClassDB::register_class<DynamicFont>(); diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 8acfdc482a..7041b62487 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -100,7 +100,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { for (int i = 0; i < (vcount / 12); i++) { - TKey<TransformKey> &tk = tt->transforms[i]; + TKey<TransformKey> &tk = tt->transforms.write[i]; const float *ofs = &r[i * 12]; tk.time = ofs[0]; tk.transition = ofs[1]; @@ -154,8 +154,8 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { for (int i = 0; i < valcount; i++) { - vt->values[i].time = rt[i]; - vt->values[i].value = values[i]; + vt->values.write[i].time = rt[i]; + vt->values.write[i].value = values[i]; } if (d.has("transitions")) { @@ -167,7 +167,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { for (int i = 0; i < valcount; i++) { - vt->values[i].transition = rtr[i]; + vt->values.write[i].transition = rtr[i]; } } } @@ -235,13 +235,13 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { for (int i = 0; i < valcount; i++) { - bt->values[i].time = rt[i]; - bt->values[i].transition = 0; //unused in bezier - bt->values[i].value.value = rv[i * 5 + 0]; - bt->values[i].value.in_handle.x = rv[i * 5 + 1]; - bt->values[i].value.in_handle.y = rv[i * 5 + 2]; - bt->values[i].value.out_handle.x = rv[i * 5 + 3]; - bt->values[i].value.out_handle.y = rv[i * 5 + 4]; + bt->values.write[i].time = rt[i]; + bt->values.write[i].transition = 0; //unused in bezier + bt->values.write[i].value.value = rv[i * 5 + 0]; + bt->values.write[i].value.in_handle.x = rv[i * 5 + 1]; + bt->values.write[i].value.in_handle.y = rv[i * 5 + 2]; + bt->values.write[i].value.out_handle.x = rv[i * 5 + 3]; + bt->values.write[i].value.out_handle.y = rv[i * 5 + 4]; } } @@ -313,7 +313,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { TKey<StringName> ak; ak.time = rt[i]; ak.value = rc[i]; - an->values[i] = ak; + an->values.write[i] = ak; } } @@ -822,7 +822,7 @@ int Animation::_insert(float p_time, T &p_keys, const V &p_value) { } else if (p_keys[idx - 1].time == p_time) { // condition for replacing. - p_keys[idx - 1] = p_value; + p_keys.write[idx - 1] = p_value; return idx - 1; } @@ -1349,18 +1349,18 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p ERR_FAIL_INDEX(p_key_idx, tt->transforms.size()); Dictionary d = p_value; if (d.has("location")) - tt->transforms[p_key_idx].value.loc = d["location"]; + tt->transforms.write[p_key_idx].value.loc = d["location"]; if (d.has("rotation")) - tt->transforms[p_key_idx].value.rot = d["rotation"]; + tt->transforms.write[p_key_idx].value.rot = d["rotation"]; if (d.has("scale")) - tt->transforms[p_key_idx].value.scale = d["scale"]; + tt->transforms.write[p_key_idx].value.scale = d["scale"]; } break; case TYPE_VALUE: { ValueTrack *vt = static_cast<ValueTrack *>(t); ERR_FAIL_INDEX(p_key_idx, vt->values.size()); - vt->values[p_key_idx].value = p_value; + vt->values.write[p_key_idx].value = p_value; } break; case TYPE_METHOD: { @@ -1369,9 +1369,9 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p ERR_FAIL_INDEX(p_key_idx, mt->methods.size()); Dictionary d = p_value; if (d.has("method")) - mt->methods[p_key_idx].method = d["method"]; + mt->methods.write[p_key_idx].method = d["method"]; if (d.has("args")) - mt->methods[p_key_idx].params = d["args"]; + mt->methods.write[p_key_idx].params = d["args"]; } break; case TYPE_BEZIER: { @@ -1381,11 +1381,11 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p Array arr = p_value; ERR_FAIL_COND(arr.size() != 5); - bt->values[p_key_idx].value.value = arr[0]; - bt->values[p_key_idx].value.in_handle.x = arr[1]; - bt->values[p_key_idx].value.in_handle.y = arr[2]; - bt->values[p_key_idx].value.out_handle.x = arr[3]; - bt->values[p_key_idx].value.out_handle.y = arr[4]; + bt->values.write[p_key_idx].value.value = arr[0]; + bt->values.write[p_key_idx].value.in_handle.x = arr[1]; + bt->values.write[p_key_idx].value.in_handle.y = arr[2]; + bt->values.write[p_key_idx].value.out_handle.x = arr[3]; + bt->values.write[p_key_idx].value.out_handle.y = arr[4]; } break; case TYPE_AUDIO: { @@ -1397,16 +1397,16 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p ERR_FAIL_COND(!k.has("end_offset")); ERR_FAIL_COND(!k.has("stream")); - at->values[p_key_idx].value.start_offset = k["start_offset"]; - at->values[p_key_idx].value.end_offset = k["end_offset"]; - at->values[p_key_idx].value.stream = k["stream"]; + at->values.write[p_key_idx].value.start_offset = k["start_offset"]; + at->values.write[p_key_idx].value.end_offset = k["end_offset"]; + at->values.write[p_key_idx].value.stream = k["stream"]; } break; case TYPE_ANIMATION: { AnimationTrack *at = static_cast<AnimationTrack *>(t); - at->values[p_key_idx].value = p_value; + at->values.write[p_key_idx].value = p_value; } break; } @@ -1423,20 +1423,20 @@ void Animation::track_set_key_transition(int p_track, int p_key_idx, float p_tra TransformTrack *tt = static_cast<TransformTrack *>(t); ERR_FAIL_INDEX(p_key_idx, tt->transforms.size()); - tt->transforms[p_key_idx].transition = p_transition; + tt->transforms.write[p_key_idx].transition = p_transition; } break; case TYPE_VALUE: { ValueTrack *vt = static_cast<ValueTrack *>(t); ERR_FAIL_INDEX(p_key_idx, vt->values.size()); - vt->values[p_key_idx].transition = p_transition; + vt->values.write[p_key_idx].transition = p_transition; } break; case TYPE_METHOD: { MethodTrack *mt = static_cast<MethodTrack *>(t); ERR_FAIL_INDEX(p_key_idx, mt->methods.size()); - mt->methods[p_key_idx].transition = p_transition; + mt->methods.write[p_key_idx].transition = p_transition; } break; case TYPE_BEZIER: @@ -2210,7 +2210,7 @@ void Animation::bezier_track_set_key_value(int p_track, int p_index, float p_val ERR_FAIL_INDEX(p_index, bt->values.size()); - bt->values[p_index].value.value = p_value; + bt->values.write[p_index].value.value = p_value; emit_changed(); } @@ -2224,9 +2224,9 @@ void Animation::bezier_track_set_key_in_handle(int p_track, int p_index, const V ERR_FAIL_INDEX(p_index, bt->values.size()); - bt->values[p_index].value.in_handle = p_handle; + bt->values.write[p_index].value.in_handle = p_handle; if (bt->values[p_index].value.in_handle.x > 0) { - bt->values[p_index].value.in_handle.x = 0; + bt->values.write[p_index].value.in_handle.x = 0; } emit_changed(); } @@ -2240,9 +2240,9 @@ void Animation::bezier_track_set_key_out_handle(int p_track, int p_index, const ERR_FAIL_INDEX(p_index, bt->values.size()); - bt->values[p_index].value.out_handle = p_handle; + bt->values.write[p_index].value.out_handle = p_handle; if (bt->values[p_index].value.out_handle.x < 0) { - bt->values[p_index].value.out_handle.x = 0; + bt->values.write[p_index].value.out_handle.x = 0; } emit_changed(); } @@ -2396,7 +2396,7 @@ void Animation::audio_track_set_key_stream(int p_track, int p_key, const RES &p_ ERR_FAIL_INDEX(p_key, at->values.size()); - at->values[p_key].value.stream = p_stream; + at->values.write[p_key].value.stream = p_stream; emit_changed(); } @@ -2414,7 +2414,7 @@ void Animation::audio_track_set_key_start_offset(int p_track, int p_key, float p if (p_offset < 0) p_offset = 0; - at->values[p_key].value.start_offset = p_offset; + at->values.write[p_key].value.start_offset = p_offset; emit_changed(); } @@ -2432,7 +2432,7 @@ void Animation::audio_track_set_key_end_offset(int p_track, int p_key, float p_o if (p_offset < 0) p_offset = 0; - at->values[p_key].value.end_offset = p_offset; + at->values.write[p_key].value.end_offset = p_offset; emit_changed(); } @@ -2505,7 +2505,7 @@ void Animation::animation_track_set_key_animation(int p_track, int p_key, const ERR_FAIL_INDEX(p_key, at->values.size()); - at->values[p_key].value = p_animation; + at->values.write[p_key].value = p_animation; emit_changed(); } @@ -2550,7 +2550,7 @@ void Animation::track_move_up(int p_track) { if (p_track >= 0 && p_track < (tracks.size() - 1)) { - SWAP(tracks[p_track], tracks[p_track + 1]); + SWAP(tracks.write[p_track], tracks.write[p_track + 1]); } emit_changed(); @@ -2585,7 +2585,7 @@ void Animation::track_move_down(int p_track) { if (p_track > 0 && p_track < tracks.size()) { - SWAP(tracks[p_track], tracks[p_track - 1]); + SWAP(tracks.write[p_track], tracks.write[p_track - 1]); } emit_changed(); } @@ -2596,7 +2596,7 @@ void Animation::track_swap(int p_track, int p_with_track) { ERR_FAIL_INDEX(p_with_track, tracks.size()); if (p_track == p_with_track) return; - SWAP(tracks[p_track], tracks[p_with_track]); + SWAP(tracks.write[p_track], tracks.write[p_with_track]); emit_changed(); } @@ -2927,9 +2927,9 @@ void Animation::_transform_track_optimize(int p_idx, float p_allowed_linear_err, for (int i = 1; i < tt->transforms.size() - 1; i++) { - TKey<TransformKey> &t0 = tt->transforms[i - 1]; - TKey<TransformKey> &t1 = tt->transforms[i]; - TKey<TransformKey> &t2 = tt->transforms[i + 1]; + TKey<TransformKey> &t0 = tt->transforms.write[i - 1]; + TKey<TransformKey> &t1 = tt->transforms.write[i]; + TKey<TransformKey> &t2 = tt->transforms.write[i + 1]; bool erase = _transform_track_optimize_key(t0, t1, t2, p_allowed_linear_err, p_allowed_angular_err, p_max_optimizable_angle, norm); if (erase && !prev_erased) { diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp index 02a9e4d69b..e6a4b01deb 100644 --- a/scene/resources/audio_stream_sample.cpp +++ b/scene/resources/audio_stream_sample.cpp @@ -29,6 +29,8 @@ /*************************************************************************/ #include "audio_stream_sample.h" +#include "io/marshalls.h" +#include "os/file_access.h" void AudioStreamPlaybackSample::start(float p_from_pos) { @@ -509,6 +511,76 @@ PoolVector<uint8_t> AudioStreamSample::get_data() const { return pv; } +void AudioStreamSample::save_to_wav(String p_path) { + if (format == AudioStreamSample::FORMAT_IMA_ADPCM) { + WARN_PRINTS("Saving IMA_ADPC samples are not supported yet"); + return; + } + + int sub_chunk_2_size = data_bytes; //Subchunk2Size = Size of data in bytes + + // Format code + // 1:PCM format (for 8 or 16 bit) + // 3:IEEE float format + int format_code = (format == FORMAT_IMA_ADPCM) ? 3 : 1; + + int n_channels = stereo ? 2 : 1; + + long sample_rate = mix_rate; + + int byte_pr_sample = 0; + switch (format) { + case AudioStreamSample::FORMAT_8_BITS: byte_pr_sample = 1; break; + case AudioStreamSample::FORMAT_16_BITS: byte_pr_sample = 2; break; + case AudioStreamSample::FORMAT_IMA_ADPCM: byte_pr_sample = 4; break; + } + + String file_path = p_path; + if (!(file_path.substr(file_path.length() - 4, 4) == ".wav")) { + file_path += ".wav"; + } + + Error err; + FileAccess *file = FileAccess::open(file_path, FileAccess::WRITE, &err); //Overrides existing file if present + + // Create WAV Header + file->store_string("RIFF"); //ChunkID + file->store_32(sub_chunk_2_size + 36); //ChunkSize = 36 + SubChunk2Size (size of entire file minus the 8 bits for this and previous header) + file->store_string("WAVE"); //Format + file->store_string("fmt "); //Subchunk1ID + file->store_32(16); //Subchunk1Size = 16 + file->store_16(format_code); //AudioFormat + file->store_16(n_channels); //Number of Channels + file->store_32(sample_rate); //SampleRate + file->store_32(sample_rate * n_channels * byte_pr_sample); //ByteRate + file->store_16(n_channels * byte_pr_sample); //BlockAlign = NumChannels * BytePrSample + file->store_16(byte_pr_sample * 8); //BitsPerSample + file->store_string("data"); //Subchunk2ID + file->store_32(sub_chunk_2_size); //Subchunk2Size + + // Add data + PoolVector<uint8_t>::Read read_data = get_data().read(); + switch (format) { + case AudioStreamSample::FORMAT_8_BITS: + for (int i = 0; i < data_bytes; i++) { + uint8_t data_point = (read_data[i] + 128); + file->store_8(data_point); + } + break; + case AudioStreamSample::FORMAT_16_BITS: + for (int i = 0; i < data_bytes / 2; i++) { + uint16_t data_point = decode_uint16(&read_data[i * 2]); + file->store_16(data_point); + } + break; + case AudioStreamSample::FORMAT_IMA_ADPCM: + //Unimplemented + break; + } + + file->close(); +} + Ref<AudioStreamPlayback> AudioStreamSample::instance_playback() { Ref<AudioStreamPlaybackSample> sample; @@ -545,6 +617,8 @@ void AudioStreamSample::_bind_methods() { ClassDB::bind_method(D_METHOD("set_stereo", "stereo"), &AudioStreamSample::set_stereo); ClassDB::bind_method(D_METHOD("is_stereo"), &AudioStreamSample::is_stereo); + ClassDB::bind_method(D_METHOD("save_to_wav", "path"), &AudioStreamSample::save_to_wav); + ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_data", "get_data"); ADD_PROPERTY(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_ENUM, "8-Bit,16-Bit,IMA-ADPCM"), "set_format", "get_format"); ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode", PROPERTY_HINT_ENUM, "Disabled,Forward,Ping-Pong"), "set_loop_mode", "get_loop_mode"); diff --git a/scene/resources/audio_stream_sample.h b/scene/resources/audio_stream_sample.h index 5fe65c194e..a27acc92b7 100644 --- a/scene/resources/audio_stream_sample.h +++ b/scene/resources/audio_stream_sample.h @@ -140,6 +140,8 @@ public: void set_data(const PoolVector<uint8_t> &p_data); PoolVector<uint8_t> get_data() const; + void save_to_wav(String p_path); + virtual Ref<AudioStreamPlayback> instance_playback(); virtual String get_stream_name() const; diff --git a/scene/resources/bit_mask.cpp b/scene/resources/bit_mask.cpp index 29ffefd9d6..85e36abf4e 100644 --- a/scene/resources/bit_mask.cpp +++ b/scene/resources/bit_mask.cpp @@ -130,7 +130,7 @@ void BitMap::set_bit(const Point2 &p_pos, bool p_value) { else b &= ~(1 << bbit); - bitmask[bbyte] = b; + bitmask.write[bbyte] = b; } bool BitMap::get_bit(const Point2 &p_pos) const { @@ -322,8 +322,8 @@ Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start) curx += stepx; cury += stepy; if (stepx == prevx && stepy == prevy) { - _points[_points.size() - 1].x = (float)(curx - rect.position.x); - _points[_points.size() - 1].y = (float)(cury + rect.position.y); + _points.write[_points.size() - 1].x = (float)(curx - rect.position.x); + _points.write[_points.size() - 1].y = (float)(cury + rect.position.y); } else { _points.push_back(Vector2((float)(curx - rect.position.x), (float)(cury + rect.position.y))); } @@ -373,11 +373,11 @@ static Vector<Vector2> rdp(const Vector<Vector2> &v, float optimization) { Vector<Vector2> left, right; left.resize(index); for (int i = 0; i < index; i++) { - left[i] = v[i]; + left.write[i] = v[i]; } right.resize(v.size() - index); for (int i = 0; i < right.size(); i++) { - right[i] = v[index + i]; + right.write[i] = v[index + i]; } Vector<Vector2> r1 = rdp(left, optimization); Vector<Vector2> r2 = rdp(right, optimization); @@ -385,7 +385,7 @@ static Vector<Vector2> rdp(const Vector<Vector2> &v, float optimization) { int middle = r1.size(); r1.resize(r1.size() + r2.size()); for (int i = 0; i < r2.size(); i++) { - r1[middle + i] = r2[i]; + r1.write[middle + i] = r2[i]; } return r1; } else { @@ -412,7 +412,7 @@ static Vector<Vector2> reduce(const Vector<Vector2> &points, const Rect2i &rect, Vector2 last = result[result.size() - 1]; if (last.y > result[0].y && last.distance_to(result[0]) < ep * 0.5f) { - result[0].y = last.y; + result.write[0].y = last.y; result.resize(result.size() - 1); } return result; diff --git a/scene/resources/color_ramp.cpp b/scene/resources/color_ramp.cpp index b2f586d02d..4a43303d84 100644 --- a/scene/resources/color_ramp.cpp +++ b/scene/resources/color_ramp.cpp @@ -40,10 +40,10 @@ Gradient::Gradient() { //Set initial color ramp transition from black to white points.resize(2); - points[0].color = Color(0, 0, 0, 1); - points[0].offset = 0; - points[1].color = Color(1, 1, 1, 1); - points[1].offset = 1; + points.write[0].color = Color(0, 0, 0, 1); + points.write[0].offset = 0; + points.write[1].color = Color(1, 1, 1, 1); + points.write[1].offset = 1; is_sorted = true; } @@ -79,7 +79,7 @@ Vector<float> Gradient::get_offsets() const { Vector<float> offsets; offsets.resize(points.size()); for (int i = 0; i < points.size(); i++) { - offsets[i] = points[i].offset; + offsets.write[i] = points[i].offset; } return offsets; } @@ -88,7 +88,7 @@ Vector<Color> Gradient::get_colors() const { Vector<Color> colors; colors.resize(points.size()); for (int i = 0; i < points.size(); i++) { - colors[i] = points[i].color; + colors.write[i] = points[i].color; } return colors; } @@ -96,7 +96,7 @@ Vector<Color> Gradient::get_colors() const { void Gradient::set_offsets(const Vector<float> &p_offsets) { points.resize(p_offsets.size()); for (int i = 0; i < points.size(); i++) { - points[i].offset = p_offsets[i]; + points.write[i].offset = p_offsets[i]; } is_sorted = false; emit_signal(CoreStringNames::get_singleton()->changed); @@ -107,7 +107,7 @@ void Gradient::set_colors(const Vector<Color> &p_colors) { is_sorted = false; points.resize(p_colors.size()); for (int i = 0; i < points.size(); i++) { - points[i].color = p_colors[i]; + points.write[i].color = p_colors[i]; } emit_signal(CoreStringNames::get_singleton()->changed); } @@ -144,7 +144,7 @@ void Gradient::set_points(Vector<Gradient::Point> &p_points) { void Gradient::set_offset(int pos, const float offset) { if (points.size() <= pos) points.resize(pos + 1); - points[pos].offset = offset; + points.write[pos].offset = offset; is_sorted = false; emit_signal(CoreStringNames::get_singleton()->changed); } @@ -160,7 +160,7 @@ void Gradient::set_color(int pos, const Color &color) { points.resize(pos + 1); is_sorted = false; } - points[pos].color = color; + points.write[pos].color = color; emit_signal(CoreStringNames::get_singleton()->changed); } diff --git a/scene/resources/color_ramp.h b/scene/resources/color_ramp.h index c042a0d3d0..070ad7f0d3 100644 --- a/scene/resources/color_ramp.h +++ b/scene/resources/color_ramp.h @@ -98,7 +98,7 @@ public: while (low <= high) { middle = (low + high) / 2; - Point &point = points[middle]; + const Point &point = points[middle]; if (point.offset > p_offset) { high = middle - 1; //search low end of array } else if (point.offset < p_offset) { @@ -118,8 +118,8 @@ public: return points[points.size() - 1].color; if (first < 0) return points[0].color; - Point &pointFirst = points[first]; - Point &pointSecond = points[second]; + const Point &pointFirst = points[first]; + const Point &pointSecond = points[second]; return pointFirst.color.linear_interpolate(pointSecond.color, (p_offset - pointFirst.offset) / (pointSecond.offset - pointFirst.offset)); } diff --git a/scene/resources/concave_polygon_shape.cpp b/scene/resources/concave_polygon_shape.cpp index 935f041837..bc9e2848b3 100644 --- a/scene/resources/concave_polygon_shape.cpp +++ b/scene/resources/concave_polygon_shape.cpp @@ -56,8 +56,8 @@ Vector<Vector3> ConcavePolygonShape::_gen_debug_mesh_lines() { int idx = 0; for (Set<DrawEdge>::Element *E = edges.front(); E; E = E->next()) { - points[idx + 0] = E->get().a; - points[idx + 1] = E->get().b; + points.write[idx + 0] = E->get().a; + points.write[idx + 1] = E->get().b; idx += 2; } diff --git a/scene/resources/convex_polygon_shape.cpp b/scene/resources/convex_polygon_shape.cpp index a2e0996996..fa9369d3bc 100644 --- a/scene/resources/convex_polygon_shape.cpp +++ b/scene/resources/convex_polygon_shape.cpp @@ -46,8 +46,8 @@ Vector<Vector3> ConvexPolygonShape::_gen_debug_mesh_lines() { Vector<Vector3> lines; lines.resize(md.edges.size() * 2); for (int i = 0; i < md.edges.size(); i++) { - lines[i * 2 + 0] = md.vertices[md.edges[i].a]; - lines[i * 2 + 1] = md.vertices[md.edges[i].b]; + lines.write[i * 2 + 0] = md.vertices[md.edges[i].a]; + lines.write[i * 2 + 1] = md.vertices[md.edges[i].b]; } return lines; } diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index f2fd919f20..d8989bf062 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -153,25 +153,25 @@ void Curve::clean_dupes() { void Curve::set_point_left_tangent(int i, real_t tangent) { ERR_FAIL_INDEX(i, _points.size()); - _points[i].left_tangent = tangent; - _points[i].left_mode = TANGENT_FREE; + _points.write[i].left_tangent = tangent; + _points.write[i].left_mode = TANGENT_FREE; mark_dirty(); } void Curve::set_point_right_tangent(int i, real_t tangent) { ERR_FAIL_INDEX(i, _points.size()); - _points[i].right_tangent = tangent; - _points[i].right_mode = TANGENT_FREE; + _points.write[i].right_tangent = tangent; + _points.write[i].right_mode = TANGENT_FREE; mark_dirty(); } void Curve::set_point_left_mode(int i, TangentMode p_mode) { ERR_FAIL_INDEX(i, _points.size()); - _points[i].left_mode = p_mode; + _points.write[i].left_mode = p_mode; if (i > 0) { if (p_mode == TANGENT_LINEAR) { Vector2 v = (_points[i - 1].pos - _points[i].pos).normalized(); - _points[i].left_tangent = v.y / v.x; + _points.write[i].left_tangent = v.y / v.x; } } mark_dirty(); @@ -179,11 +179,11 @@ void Curve::set_point_left_mode(int i, TangentMode p_mode) { void Curve::set_point_right_mode(int i, TangentMode p_mode) { ERR_FAIL_INDEX(i, _points.size()); - _points[i].right_mode = p_mode; + _points.write[i].right_mode = p_mode; if (i + 1 < _points.size()) { if (p_mode == TANGENT_LINEAR) { Vector2 v = (_points[i + 1].pos - _points[i].pos).normalized(); - _points[i].right_tangent = v.y / v.x; + _points.write[i].right_tangent = v.y / v.x; } } mark_dirty(); @@ -222,7 +222,7 @@ void Curve::clear_points() { void Curve::set_point_value(int p_index, real_t pos) { ERR_FAIL_INDEX(p_index, _points.size()); - _points[p_index].pos.y = pos; + _points.write[p_index].pos.y = pos; update_auto_tangents(p_index); mark_dirty(); } @@ -232,10 +232,10 @@ int Curve::set_point_offset(int p_index, float offset) { Point p = _points[p_index]; remove_point(p_index); int i = add_point(Vector2(offset, p.pos.y)); - _points[i].left_tangent = p.left_tangent; - _points[i].right_tangent = p.right_tangent; - _points[i].left_mode = p.left_mode; - _points[i].right_mode = p.right_mode; + _points.write[i].left_tangent = p.left_tangent; + _points.write[i].right_tangent = p.right_tangent; + _points.write[i].left_mode = p.left_mode; + _points.write[i].right_mode = p.right_mode; if (p_index != i) update_auto_tangents(p_index); update_auto_tangents(i); @@ -254,7 +254,7 @@ Curve::Point Curve::get_point(int p_index) const { void Curve::update_auto_tangents(int i) { - Point &p = _points[i]; + Point &p = _points.write[i]; if (i > 0) { if (p.left_mode == TANGENT_LINEAR) { @@ -263,7 +263,7 @@ void Curve::update_auto_tangents(int i) { } if (_points[i - 1].right_mode == TANGENT_LINEAR) { Vector2 v = (_points[i - 1].pos - p.pos).normalized(); - _points[i - 1].right_tangent = v.y / v.x; + _points.write[i - 1].right_tangent = v.y / v.x; } } @@ -274,7 +274,7 @@ void Curve::update_auto_tangents(int i) { } if (_points[i + 1].left_mode == TANGENT_LINEAR) { Vector2 v = (_points[i + 1].pos - p.pos).normalized(); - _points[i + 1].left_tangent = v.y / v.x; + _points.write[i + 1].left_tangent = v.y / v.x; } } } @@ -402,7 +402,7 @@ void Curve::set_data(Array input) { for (int j = 0; j < _points.size(); ++j) { - Point &p = _points[j]; + Point &p = _points.write[j]; int i = j * ELEMS; p.pos = input[i]; @@ -426,12 +426,12 @@ void Curve::bake() { for (int i = 1; i < _bake_resolution - 1; ++i) { real_t x = i / static_cast<real_t>(_bake_resolution); real_t y = interpolate(x); - _baked_cache[i] = y; + _baked_cache.write[i] = y; } if (_points.size() != 0) { - _baked_cache[0] = _points[0].pos.y; - _baked_cache[_baked_cache.size() - 1] = _points[_points.size() - 1].pos.y; + _baked_cache.write[0] = _points[0].pos.y; + _baked_cache.write[_baked_cache.size() - 1] = _points[_points.size() - 1].pos.y; } _baked_cache_dirty = false; @@ -553,7 +553,7 @@ void Curve2D::set_point_position(int p_index, const Vector2 &p_pos) { ERR_FAIL_INDEX(p_index, points.size()); - points[p_index].pos = p_pos; + points.write[p_index].pos = p_pos; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } @@ -567,7 +567,7 @@ void Curve2D::set_point_in(int p_index, const Vector2 &p_in) { ERR_FAIL_INDEX(p_index, points.size()); - points[p_index].in = p_in; + points.write[p_index].in = p_in; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } @@ -581,7 +581,7 @@ void Curve2D::set_point_out(int p_index, const Vector2 &p_out) { ERR_FAIL_INDEX(p_index, points.size()); - points[p_index].out = p_out; + points.write[p_index].out = p_out; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } @@ -930,9 +930,9 @@ void Curve2D::_set_data(const Dictionary &p_data) { for (int i = 0; i < points.size(); i++) { - points[i].in = r[i * 3 + 0]; - points[i].out = r[i * 3 + 1]; - points[i].pos = r[i * 3 + 2]; + points.write[i].in = r[i * 3 + 0]; + points.write[i].out = r[i * 3 + 1]; + points.write[i].pos = r[i * 3 + 2]; } baked_cache_dirty = true; @@ -952,7 +952,7 @@ PoolVector2Array Curve2D::tessellate(int p_max_stages, float p_tolerance) const int pc = 1; for (int i = 0; i < points.size() - 1; i++) { - _bake_segment2d(midpoints[i], 0, 1, points[i].pos, points[i].out, points[i + 1].pos, points[i + 1].in, 0, p_max_stages, p_tolerance); + _bake_segment2d(midpoints.write[i], 0, 1, points[i].pos, points[i].out, points[i + 1].pos, points[i + 1].in, 0, p_max_stages, p_tolerance); pc++; pc += midpoints[i].size(); } @@ -1049,7 +1049,7 @@ void Curve3D::set_point_position(int p_index, const Vector3 &p_pos) { ERR_FAIL_INDEX(p_index, points.size()); - points[p_index].pos = p_pos; + points.write[p_index].pos = p_pos; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } @@ -1063,7 +1063,7 @@ void Curve3D::set_point_tilt(int p_index, float p_tilt) { ERR_FAIL_INDEX(p_index, points.size()); - points[p_index].tilt = p_tilt; + points.write[p_index].tilt = p_tilt; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } @@ -1077,7 +1077,7 @@ void Curve3D::set_point_in(int p_index, const Vector3 &p_in) { ERR_FAIL_INDEX(p_index, points.size()); - points[p_index].in = p_in; + points.write[p_index].in = p_in; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } @@ -1091,7 +1091,7 @@ void Curve3D::set_point_out(int p_index, const Vector3 &p_out) { ERR_FAIL_INDEX(p_index, points.size()); - points[p_index].out = p_out; + points.write[p_index].out = p_out; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } @@ -1621,10 +1621,10 @@ void Curve3D::_set_data(const Dictionary &p_data) { for (int i = 0; i < points.size(); i++) { - points[i].in = r[i * 3 + 0]; - points[i].out = r[i * 3 + 1]; - points[i].pos = r[i * 3 + 2]; - points[i].tilt = rt[i]; + points.write[i].in = r[i * 3 + 0]; + points.write[i].out = r[i * 3 + 1]; + points.write[i].pos = r[i * 3 + 2]; + points.write[i].tilt = rt[i]; } baked_cache_dirty = true; @@ -1644,7 +1644,7 @@ PoolVector3Array Curve3D::tessellate(int p_max_stages, float p_tolerance) const int pc = 1; for (int i = 0; i < points.size() - 1; i++) { - _bake_segment3d(midpoints[i], 0, 1, points[i].pos, points[i].out, points[i + 1].pos, points[i + 1].in, 0, p_max_stages, p_tolerance); + _bake_segment3d(midpoints.write[i], 0, 1, points[i].pos, points[i].out, points[i + 1].pos, points[i + 1].in, 0, p_max_stages, p_tolerance); pc++; pc += midpoints[i].size(); } diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index d4432b969f..601f6fb558 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -476,6 +476,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_color("symbol_color", "TextEdit", control_font_color_hover); theme->set_color("brace_mismatch_color", "TextEdit", Color(1, 0.2, 0.2)); theme->set_color("line_number_color", "TextEdit", Color::html("66aaaaaa")); + theme->set_color("safe_line_number_color", "TextEdit", Color::html("99aac8aa")); theme->set_color("function_color", "TextEdit", Color::html("66a2ce")); theme->set_color("member_variable_color", "TextEdit", Color::html("e64e59")); theme->set_color("number_color", "TextEdit", Color::html("EB9532")); @@ -882,6 +883,10 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_icon("logo", "Icons", make_icon(logo_png)); + // Visual Node Ports + theme->set_constant("port_grab_distance_horizontal", "GraphEdit", 48 * scale); + theme->set_constant("port_grab_distance_vertical", "GraphEdit", 6 * scale); + // Theme default_icon = make_icon(error_icon_png); diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index e5d463d391..2f2abd4e08 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -211,9 +211,9 @@ Error DynamicFontAtSize::_load() { scale_color_font = float(id.size) / face->available_sizes[i].width; } } - error = FT_Select_Size(face, best_match); + FT_Select_Size(face, best_match); } else { - error = FT_Set_Pixel_Sizes(face, 0, id.size * oversampling); + FT_Set_Pixel_Sizes(face, 0, id.size * oversampling); } ascent = (face->size->metrics.ascender / 64.0) / oversampling * scale_color_font; @@ -314,7 +314,7 @@ void DynamicFontAtSize::set_texture_flags(uint32_t p_flags) { texture_flags = p_flags; for (int i = 0; i < textures.size(); i++) { - Ref<ImageTexture> &tex = textures[i].texture; + Ref<ImageTexture> &tex = textures.write[i].texture; if (!tex.is_null()) tex->set_flags(p_flags); } @@ -400,7 +400,7 @@ DynamicFontAtSize::TexturePosition DynamicFontAtSize::_find_texture_pos_for_glyp for (int i = 0; i < textures.size(); i++) { - CharTexture &ct = textures[i]; + const CharTexture &ct = textures[i]; if (ct.texture->get_format() != p_image_format) continue; @@ -466,7 +466,7 @@ DynamicFontAtSize::TexturePosition DynamicFontAtSize::_find_texture_pos_for_glyp } tex.offsets.resize(texsize); for (int i = 0; i < texsize; i++) //zero offsets - tex.offsets[i] = 0; + tex.offsets.write[i] = 0; textures.push_back(tex); ret.index = textures.size() - 1; @@ -493,7 +493,7 @@ DynamicFontAtSize::Character DynamicFontAtSize::_bitmap_to_character(FT_Bitmap b //fit character in char texture - CharTexture &tex = textures[tex_pos.index]; + CharTexture &tex = textures.write[tex_pos.index]; { PoolVector<uint8_t>::Write wr = tex.imgdata.write(); @@ -547,7 +547,7 @@ DynamicFontAtSize::Character DynamicFontAtSize::_bitmap_to_character(FT_Bitmap b // update height array for (int k = tex_pos.x; k < tex_pos.x + mw; k++) { - tex.offsets[k] = tex_pos.y + mh; + tex.offsets.write[k] = tex_pos.y + mh; } Character chr; @@ -698,9 +698,9 @@ void DynamicFont::_reload_cache() { } for (int i = 0; i < fallbacks.size(); i++) { - fallback_data_at_size[i] = fallbacks[i]->_get_dynamic_font_at_size(cache_id); + fallback_data_at_size.write[i] = fallbacks.write[i]->_get_dynamic_font_at_size(cache_id); if (outline_cache_id.outline_size > 0) - fallback_outline_data_at_size[i] = fallbacks[i]->_get_dynamic_font_at_size(outline_cache_id); + fallback_outline_data_at_size.write[i] = fallbacks.write[i]->_get_dynamic_font_at_size(outline_cache_id); } emit_changed(); @@ -895,17 +895,17 @@ void DynamicFont::set_fallback(int p_idx, const Ref<DynamicFontData> &p_data) { ERR_FAIL_COND(p_data.is_null()); ERR_FAIL_INDEX(p_idx, fallbacks.size()); - fallbacks[p_idx] = p_data; - fallback_data_at_size[p_idx] = fallbacks[p_idx]->_get_dynamic_font_at_size(cache_id); + fallbacks.write[p_idx] = p_data; + fallback_data_at_size.write[p_idx] = fallbacks.write[p_idx]->_get_dynamic_font_at_size(cache_id); } void DynamicFont::add_fallback(const Ref<DynamicFontData> &p_data) { ERR_FAIL_COND(p_data.is_null()); fallbacks.push_back(p_data); - fallback_data_at_size.push_back(fallbacks[fallbacks.size() - 1]->_get_dynamic_font_at_size(cache_id)); //const.. + fallback_data_at_size.push_back(fallbacks.write[fallbacks.size() - 1]->_get_dynamic_font_at_size(cache_id)); //const.. if (outline_cache_id.outline_size > 0) - fallback_outline_data_at_size.push_back(fallbacks[fallbacks.size() - 1]->_get_dynamic_font_at_size(outline_cache_id)); + fallback_outline_data_at_size.push_back(fallbacks.write[fallbacks.size() - 1]->_get_dynamic_font_at_size(outline_cache_id)); _change_notify(); emit_changed(); @@ -1092,7 +1092,7 @@ void DynamicFont::update_oversampling() { dynamic_font_mutex->unlock(); for (int i = 0; i < changed.size(); i++) { - changed[i]->emit_changed(); + changed.write[i]->emit_changed(); } } diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 0bae9d9b2d..3dfde01320 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -386,7 +386,7 @@ Vector<CharType> BitmapFont::get_char_keys() const { int count = 0; while ((ct = char_map.next(ct))) { - chars[count++] = *ct; + chars.write[count++] = *ct; }; return chars; @@ -438,7 +438,7 @@ Vector<BitmapFont::KerningPairKey> BitmapFont::get_kerning_pair_keys() const { int i = 0; for (Map<KerningPairKey, int>::Element *E = kerning_map.front(); E; E = E->next()) { - ret[i++] = E->key(); + ret.write[i++] = E->key(); } return ret; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 56b3ee70bb..df5bbe9e6c 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -554,9 +554,20 @@ void SpatialMaterial::_update_shader() { case BILLBOARD_ENABLED: { code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],CAMERA_MATRIX[1],CAMERA_MATRIX[2],WORLD_MATRIX[3]);\n"; + + if (flags[FLAG_BILLBOARD_KEEP_SCALE]) { + code += "\tMODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(WORLD_MATRIX[0].xyz),0,0,0),vec4(0,length(WORLD_MATRIX[1].xyz),0,0),vec4(0,0,length(WORLD_MATRIX[2].xyz),0),vec4(0,0,0,1));\n"; + } } break; case BILLBOARD_FIXED_Y: { + code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],WORLD_MATRIX[1],vec4(normalize(cross(CAMERA_MATRIX[0].xyz,WORLD_MATRIX[1].xyz)),0.0),WORLD_MATRIX[3]);\n"; + + if (flags[FLAG_BILLBOARD_KEEP_SCALE]) { + code += "\tMODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(WORLD_MATRIX[0].xyz),0,0,0),vec4(0,1,0,0),vec4(0,0,length(WORLD_MATRIX[2].xyz),0),vec4(0,0,0,1));\n"; + } else { + code += "\tMODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(1,0,0,0),vec4(0,1.0/length(WORLD_MATRIX[1].xyz),0,0),vec4(0,0,1,0),vec4(0,0,0,1));\n"; + } } break; case BILLBOARD_PARTICLES: { @@ -573,8 +584,6 @@ void SpatialMaterial::_update_shader() { code += "\tif (particles_anim_loop) particle_frame=clamp(particle_frame,0,particle_total_frames-1); else particle_frame=abs(particle_frame)%particle_total_frames;\n"; code += "\tUV /= vec2(float(particles_anim_h_frames),float(particles_anim_v_frames));\n"; code += "\tUV += vec2(float(particle_frame % particles_anim_h_frames) / float(particles_anim_h_frames),float(particle_frame / particles_anim_h_frames) / float(particles_anim_v_frames));\n"; - //handle rotation - // code += "\tmat4 rotation = mat4(" } break; } @@ -1883,7 +1892,8 @@ void SpatialMaterial::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "params_depth_draw_mode", PROPERTY_HINT_ENUM, "Opaque Only,Always,Never,Opaque Pre-Pass"), "set_depth_draw_mode", "get_depth_draw_mode"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_line_width", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_line_width", "get_line_width"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_point_size", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_point_size", "get_point_size"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "params_billboard_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard,Particle Billboard"), "set_billboard_mode", "get_billboard_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "params_billboard_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard,Particle Billboard1"), "set_billboard_mode", "get_billboard_mode"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "params_billboard_keep_scale"), "set_flag", "get_flag", FLAG_BILLBOARD_KEEP_SCALE); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "params_grow"), "set_grow_enabled", "is_grow_enabled"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_grow_amount", PROPERTY_HINT_RANGE, "-16,10,0.01"), "set_grow", "get_grow"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "params_use_alpha_scissor"), "set_flag", "get_flag", FLAG_USE_ALPHA_SCISSOR); @@ -2053,6 +2063,7 @@ void SpatialMaterial::_bind_methods() { BIND_ENUM_CONSTANT(FLAG_SRGB_VERTEX_COLOR); BIND_ENUM_CONSTANT(FLAG_USE_POINT_SIZE); BIND_ENUM_CONSTANT(FLAG_FIXED_SIZE); + BIND_ENUM_CONSTANT(FLAG_BILLBOARD_KEEP_SCALE); BIND_ENUM_CONSTANT(FLAG_UV1_USE_TRIPLANAR); BIND_ENUM_CONSTANT(FLAG_UV2_USE_TRIPLANAR); BIND_ENUM_CONSTANT(FLAG_AO_ON_UV2); diff --git a/scene/resources/material.h b/scene/resources/material.h index 84f1005b03..7a1a4acfbf 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -183,6 +183,7 @@ public: FLAG_SRGB_VERTEX_COLOR, FLAG_USE_POINT_SIZE, FLAG_FIXED_SIZE, + FLAG_BILLBOARD_KEEP_SCALE, FLAG_UV1_USE_TRIPLANAR, FLAG_UV2_USE_TRIPLANAR, FLAG_TRIPLANAR_USE_WORLD, @@ -241,7 +242,7 @@ private: uint64_t blend_mode : 2; uint64_t depth_draw_mode : 2; uint64_t cull_mode : 2; - uint64_t flags : 17; + uint64_t flags : 18; uint64_t detail_blend_mode : 2; uint64_t diffuse_mode : 3; uint64_t specular_mode : 2; diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index b0620d3363..e74ad2e55b 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -40,7 +40,6 @@ void Mesh::_clear_triangle_mesh() const { triangle_mesh.unref(); - ; } Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { @@ -110,6 +109,54 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { return triangle_mesh; } +void Mesh::generate_debug_mesh_lines(Vector<Vector3> &r_lines) { + + Ref<TriangleMesh> tm = generate_triangle_mesh(); + if (tm.is_null()) + return; + + PoolVector<int> triangle_indices; + tm->get_indices(&triangle_indices); + const int triangles_num = tm->get_triangles().size(); + PoolVector<Vector3> vertices = tm->get_vertices(); + + r_lines.resize(tm->get_triangles().size() * 6); // 3 lines x 2 points each line + + PoolVector<int>::Read ind_r = triangle_indices.read(); + PoolVector<Vector3>::Read ver_r = vertices.read(); + for (int j = 0, x = 0, i = 0; i < triangles_num; j += 6, x += 3, ++i) { + // Triangle line 1 + r_lines.write[j + 0] = ver_r[ind_r[x + 0]]; + r_lines.write[j + 1] = ver_r[ind_r[x + 1]]; + + // Triangle line 2 + r_lines.write[j + 2] = ver_r[ind_r[x + 1]]; + r_lines.write[j + 3] = ver_r[ind_r[x + 2]]; + + // Triangle line 3 + r_lines.write[j + 4] = ver_r[ind_r[x + 2]]; + r_lines.write[j + 5] = ver_r[ind_r[x + 0]]; + } +} +void Mesh::generate_debug_mesh_indices(Vector<Vector3> &r_points) { + Ref<TriangleMesh> tm = generate_triangle_mesh(); + if (tm.is_null()) + return; + + PoolVector<Vector3> vertices = tm->get_vertices(); + + int vertices_size = vertices.size(); + r_points.resize(vertices_size); + for (int i = 0; i < vertices_size; ++i) { + r_points.write[i] = vertices[i]; + } +} + +bool Mesh::surface_is_softbody_friendly(int p_idx) const { + const uint32_t surface_format = surface_get_format(p_idx); + return (surface_format & Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE && (!(surface_format & Mesh::ARRAY_COMPRESS_VERTEX)) && (!(surface_format & Mesh::ARRAY_COMPRESS_NORMAL))); +} + PoolVector<Face3> Mesh::get_faces() const { Ref<TriangleMesh> tm = generate_triangle_mesh(); @@ -484,6 +531,10 @@ void Mesh::_bind_methods() { BIND_ENUM_CONSTANT(ARRAY_MAX); } +void Mesh::clear_cache() { + _clear_triangle_mesh(); +} + Mesh::Mesh() { } @@ -616,7 +667,7 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { bone_aabb.resize(baabb.size()); for (int i = 0; i < baabb.size(); i++) { - bone_aabb[i] = baabb[i]; + bone_aabb.write[i] = baabb[i]; } } @@ -788,8 +839,8 @@ void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array & aabb.expand_to(vtx[i]); } - surfaces[surfaces.size() - 1].aabb = aabb; - surfaces[surfaces.size() - 1].is_2d = arr.get_type() == Variant::POOL_VECTOR2_ARRAY; + surfaces.write[surfaces.size() - 1].aabb = aabb; + surfaces.write[surfaces.size() - 1].is_2d = arr.get_type() == Variant::POOL_VECTOR2_ARRAY; _recompute_aabb(); } @@ -908,7 +959,7 @@ void ArrayMesh::surface_set_material(int p_idx, const Ref<Material> &p_material) ERR_FAIL_INDEX(p_idx, surfaces.size()); if (surfaces[p_idx].material == p_material) return; - surfaces[p_idx].material = p_material; + surfaces.write[p_idx].material = p_material; VisualServer::get_singleton()->mesh_surface_set_material(mesh, p_idx, p_material.is_null() ? RID() : p_material->get_rid()); _change_notify("material"); @@ -919,7 +970,7 @@ void ArrayMesh::surface_set_name(int p_idx, const String &p_name) { ERR_FAIL_INDEX(p_idx, surfaces.size()); - surfaces[p_idx].name = p_name; + surfaces.write[p_idx].name = p_name; emit_changed(); } @@ -939,7 +990,7 @@ void ArrayMesh::surface_update_region(int p_surface, int p_offset, const PoolVec void ArrayMesh::surface_set_custom_aabb(int p_idx, const AABB &p_aabb) { ERR_FAIL_INDEX(p_idx, surfaces.size()); - surfaces[p_idx].aabb = p_aabb; + surfaces.write[p_idx].aabb = p_aabb; // set custom aabb too? emit_changed(); } @@ -1042,8 +1093,8 @@ void ArrayMesh::regen_normalmaps() { for (int i = 0; i < surfs.size(); i++) { - surfs[i]->generate_tangents(); - surfs[i]->commit(Ref<ArrayMesh>(this)); + surfs.write[i]->generate_tangents(); + surfs.write[i]->commit(Ref<ArrayMesh>(this)); } } @@ -1108,13 +1159,13 @@ Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texe Vector3 v = p_base_transform.xform(r[j]); Vector3 n = p_base_transform.basis.xform(rn[j]).normalized(); - vertices[(j + vertex_ofs) * 3 + 0] = v.x; - vertices[(j + vertex_ofs) * 3 + 1] = v.y; - vertices[(j + vertex_ofs) * 3 + 2] = v.z; - normals[(j + vertex_ofs) * 3 + 0] = n.x; - normals[(j + vertex_ofs) * 3 + 1] = n.y; - normals[(j + vertex_ofs) * 3 + 2] = n.z; - uv_index[j + vertex_ofs] = Pair<int, int>(i, j); + vertices.write[(j + vertex_ofs) * 3 + 0] = v.x; + vertices.write[(j + vertex_ofs) * 3 + 1] = v.y; + vertices.write[(j + vertex_ofs) * 3 + 2] = v.z; + normals.write[(j + vertex_ofs) * 3 + 0] = n.x; + normals.write[(j + vertex_ofs) * 3 + 1] = n.y; + normals.write[(j + vertex_ofs) * 3 + 2] = n.z; + uv_index.write[j + vertex_ofs] = Pair<int, int>(i, j); } PoolVector<int> rindices = arrays[Mesh::ARRAY_INDEX]; @@ -1197,31 +1248,31 @@ Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texe SurfaceTool::Vertex v = surfaces[surface].vertices[uv_index[gen_vertices[gen_indices[i + j]]].second]; if (surfaces[surface].format & ARRAY_FORMAT_COLOR) { - surfaces_tools[surface]->add_color(v.color); + surfaces_tools.write[surface]->add_color(v.color); } if (surfaces[surface].format & ARRAY_FORMAT_TEX_UV) { - surfaces_tools[surface]->add_uv(v.uv); + surfaces_tools.write[surface]->add_uv(v.uv); } if (surfaces[surface].format & ARRAY_FORMAT_NORMAL) { - surfaces_tools[surface]->add_normal(v.normal); + surfaces_tools.write[surface]->add_normal(v.normal); } if (surfaces[surface].format & ARRAY_FORMAT_TANGENT) { Plane t; t.normal = v.tangent; t.d = v.binormal.dot(v.normal.cross(v.tangent)) < 0 ? -1 : 1; - surfaces_tools[surface]->add_tangent(t); + surfaces_tools.write[surface]->add_tangent(t); } if (surfaces[surface].format & ARRAY_FORMAT_BONES) { - surfaces_tools[surface]->add_bones(v.bones); + surfaces_tools.write[surface]->add_bones(v.bones); } if (surfaces[surface].format & ARRAY_FORMAT_WEIGHTS) { - surfaces_tools[surface]->add_weights(v.weights); + surfaces_tools.write[surface]->add_weights(v.weights); } Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]); - surfaces_tools[surface]->add_uv2(uv2); + surfaces_tools.write[surface]->add_uv2(uv2); - surfaces_tools[surface]->add_vertex(v.vertex); + surfaces_tools.write[surface]->add_vertex(v.vertex); } } @@ -1233,8 +1284,8 @@ Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texe //generate surfaces for (int i = 0; i < surfaces_tools.size(); i++) { - surfaces_tools[i]->index(); - surfaces_tools[i]->commit(Ref<ArrayMesh>((ArrayMesh *)this), surfaces[i].format); + surfaces_tools.write[i]->index(); + surfaces_tools.write[i]->commit(Ref<ArrayMesh>((ArrayMesh *)this), surfaces[i].format); } set_lightmap_size_hint(Size2(size_x, size_y)); diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index a3fb068569..2127eaae4c 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -123,6 +123,7 @@ public: virtual int get_surface_count() const = 0; virtual int surface_get_array_len(int p_idx) const = 0; virtual int surface_get_array_index_len(int p_idx) const = 0; + virtual bool surface_is_softbody_friendly(int p_idx) const; virtual Array surface_get_arrays(int p_surface) const = 0; virtual Array surface_get_blend_shape_arrays(int p_surface) const = 0; virtual uint32_t surface_get_format(int p_idx) const = 0; @@ -133,6 +134,8 @@ public: PoolVector<Face3> get_faces() const; Ref<TriangleMesh> generate_triangle_mesh() const; + void generate_debug_mesh_lines(Vector<Vector3> &r_lines); + void generate_debug_mesh_indices(Vector<Vector3> &r_points); Ref<Shape> create_trimesh_shape() const; Ref<Shape> create_convex_shape() const; @@ -143,6 +146,7 @@ public: void set_lightmap_size_hint(const Vector2 &p_size); Size2 get_lightmap_size_hint() const; + void clear_cache(); Mesh(); }; diff --git a/scene/resources/mesh_data_tool.cpp b/scene/resources/mesh_data_tool.cpp index 8639b325c3..6732303925 100644 --- a/scene/resources/mesh_data_tool.cpp +++ b/scene/resources/mesh_data_tool.cpp @@ -120,7 +120,7 @@ Error MeshDataTool::create_from_surface(const Ref<ArrayMesh> &p_mesh, int p_surf v.bones.push_back(bo[i * 4 + 3]); } - vertices[i] = v; + vertices.write[i] = v; } PoolVector<int> indices; @@ -143,7 +143,7 @@ Error MeshDataTool::create_from_surface(const Ref<ArrayMesh> &p_mesh, int p_surf for (int i = 0; i < icount; i += 3) { - Vertex *v[3] = { &vertices[r[i + 0]], &vertices[r[i + 1]], &vertices[r[i + 2]] }; + Vertex *v[3] = { &vertices.write[r[i + 0]], &vertices.write[r[i + 1]], &vertices.write[r[i + 2]] }; int fidx = faces.size(); Face face; @@ -169,7 +169,7 @@ Error MeshDataTool::create_from_surface(const Ref<ArrayMesh> &p_mesh, int p_surf edges.push_back(e); } - edges[face.edges[j]].faces.push_back(fidx); + edges.write[face.edges[j]].faces.push_back(fidx); v[j]->faces.push_back(fidx); v[j]->edges.push_back(face.edges[j]); } @@ -247,7 +247,7 @@ Error MeshDataTool::commit_to_surface(const Ref<ArrayMesh> &p_mesh) { for (int i = 0; i < vcount; i++) { - Vertex &vtx = vertices[i]; + const Vertex &vtx = vertices[i]; vr[i] = vtx.vertex; if (nr.ptr()) @@ -344,7 +344,7 @@ Vector3 MeshDataTool::get_vertex(int p_idx) const { void MeshDataTool::set_vertex(int p_idx, const Vector3 &p_vertex) { ERR_FAIL_INDEX(p_idx, vertices.size()); - vertices[p_idx].vertex = p_vertex; + vertices.write[p_idx].vertex = p_vertex; } Vector3 MeshDataTool::get_vertex_normal(int p_idx) const { @@ -355,7 +355,7 @@ Vector3 MeshDataTool::get_vertex_normal(int p_idx) const { void MeshDataTool::set_vertex_normal(int p_idx, const Vector3 &p_normal) { ERR_FAIL_INDEX(p_idx, vertices.size()); - vertices[p_idx].normal = p_normal; + vertices.write[p_idx].normal = p_normal; format |= Mesh::ARRAY_FORMAT_NORMAL; } @@ -367,7 +367,7 @@ Plane MeshDataTool::get_vertex_tangent(int p_idx) const { void MeshDataTool::set_vertex_tangent(int p_idx, const Plane &p_tangent) { ERR_FAIL_INDEX(p_idx, vertices.size()); - vertices[p_idx].tangent = p_tangent; + vertices.write[p_idx].tangent = p_tangent; format |= Mesh::ARRAY_FORMAT_TANGENT; } @@ -379,7 +379,7 @@ Vector2 MeshDataTool::get_vertex_uv(int p_idx) const { void MeshDataTool::set_vertex_uv(int p_idx, const Vector2 &p_uv) { ERR_FAIL_INDEX(p_idx, vertices.size()); - vertices[p_idx].uv = p_uv; + vertices.write[p_idx].uv = p_uv; format |= Mesh::ARRAY_FORMAT_TEX_UV; } @@ -391,7 +391,7 @@ Vector2 MeshDataTool::get_vertex_uv2(int p_idx) const { void MeshDataTool::set_vertex_uv2(int p_idx, const Vector2 &p_uv2) { ERR_FAIL_INDEX(p_idx, vertices.size()); - vertices[p_idx].uv2 = p_uv2; + vertices.write[p_idx].uv2 = p_uv2; format |= Mesh::ARRAY_FORMAT_TEX_UV2; } @@ -403,7 +403,7 @@ Color MeshDataTool::get_vertex_color(int p_idx) const { void MeshDataTool::set_vertex_color(int p_idx, const Color &p_color) { ERR_FAIL_INDEX(p_idx, vertices.size()); - vertices[p_idx].color = p_color; + vertices.write[p_idx].color = p_color; format |= Mesh::ARRAY_FORMAT_COLOR; } @@ -415,7 +415,7 @@ Vector<int> MeshDataTool::get_vertex_bones(int p_idx) const { void MeshDataTool::set_vertex_bones(int p_idx, const Vector<int> &p_bones) { ERR_FAIL_INDEX(p_idx, vertices.size()); - vertices[p_idx].bones = p_bones; + vertices.write[p_idx].bones = p_bones; format |= Mesh::ARRAY_FORMAT_BONES; } @@ -426,7 +426,7 @@ Vector<float> MeshDataTool::get_vertex_weights(int p_idx) const { } void MeshDataTool::set_vertex_weights(int p_idx, const Vector<float> &p_weights) { ERR_FAIL_INDEX(p_idx, vertices.size()); - vertices[p_idx].weights = p_weights; + vertices.write[p_idx].weights = p_weights; format |= Mesh::ARRAY_FORMAT_WEIGHTS; } @@ -439,7 +439,7 @@ Variant MeshDataTool::get_vertex_meta(int p_idx) const { void MeshDataTool::set_vertex_meta(int p_idx, const Variant &p_meta) { ERR_FAIL_INDEX(p_idx, vertices.size()); - vertices[p_idx].meta = p_meta; + vertices.write[p_idx].meta = p_meta; } Vector<int> MeshDataTool::get_vertex_edges(int p_idx) const { @@ -472,7 +472,7 @@ Variant MeshDataTool::get_edge_meta(int p_idx) const { void MeshDataTool::set_edge_meta(int p_idx, const Variant &p_meta) { ERR_FAIL_INDEX(p_idx, edges.size()); - edges[p_idx].meta = p_meta; + edges.write[p_idx].meta = p_meta; } int MeshDataTool::get_face_vertex(int p_face, int p_vertex) const { @@ -495,7 +495,7 @@ Variant MeshDataTool::get_face_meta(int p_face) const { void MeshDataTool::set_face_meta(int p_face, const Variant &p_meta) { ERR_FAIL_INDEX(p_face, faces.size()); - faces[p_face].meta = p_meta; + faces.write[p_face].meta = p_meta; } Vector3 MeshDataTool::get_face_normal(int p_face) const { diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp index e1d3540fd1..a1d3e0ba1e 100644 --- a/scene/resources/mesh_library.cpp +++ b/scene/resources/mesh_library.cpp @@ -209,7 +209,7 @@ Vector<int> MeshLibrary::get_item_list() const { int idx = 0; for (Map<int, Item>::Element *E = item_map.front(); E; E = E->next()) { - ret[idx++] = E->key(); + ret.write[idx++] = E->key(); } return ret; diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 846f6e356e..b95e0495d9 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -325,7 +325,7 @@ Node *SceneState::instance(GenEditState p_edit_state) const { if (c.binds.size()) { binds.resize(c.binds.size()); for (int j = 0; j < c.binds.size(); j++) - binds[j] = props[c.binds[j]]; + binds.write[j] = props[c.binds[j]]; } cfrom->connect(snames[c.signal], cto, snames[c.method], binds, CONNECT_PERSIST | c.flags); @@ -875,7 +875,7 @@ Error SceneState::pack(Node *p_scene) { for (Map<StringName, int>::Element *E = name_map.front(); E; E = E->next()) { - names[E->get()] = E->key(); + names.write[E->get()] = E->key(); } variants.resize(variant_map.size()); @@ -883,13 +883,13 @@ Error SceneState::pack(Node *p_scene) { while ((K = variant_map.next(K))) { int idx = variant_map[*K]; - variants[idx] = *K; + variants.write[idx] = *K; } node_paths.resize(nodepath_map.size()); for (Map<Node *, int>::Element *E = nodepath_map.front(); E; E = E->next()) { - node_paths[E->get()] = scene->get_path_to(E->key()); + node_paths.write[E->get()] = scene->get_path_to(E->key()); } return OK; @@ -1090,7 +1090,7 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { names.resize(namecount); PoolVector<String>::Read r = snames.read(); for (int i = 0; i < names.size(); i++) - names[i] = r[i]; + names.write[i] = r[i]; } Array svariants = p_dictionary["variants"]; @@ -1100,7 +1100,7 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { variants.resize(varcount); for (int i = 0; i < varcount; i++) { - variants[i] = svariants[i]; + variants.write[i] = svariants[i]; } } else { @@ -1114,7 +1114,7 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { PoolVector<int>::Read r = snodes.read(); int idx = 0; for (int i = 0; i < nc; i++) { - NodeData &nd = nodes[i]; + NodeData &nd = nodes.write[i]; nd.parent = r[idx++]; nd.owner = r[idx++]; nd.type = r[idx++]; @@ -1126,13 +1126,13 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { nd.properties.resize(r[idx++]); for (int j = 0; j < nd.properties.size(); j++) { - nd.properties[j].name = r[idx++]; - nd.properties[j].value = r[idx++]; + nd.properties.write[j].name = r[idx++]; + nd.properties.write[j].value = r[idx++]; } nd.groups.resize(r[idx++]); for (int j = 0; j < nd.groups.size(); j++) { - nd.groups[j] = r[idx++]; + nd.groups.write[j] = r[idx++]; } } } @@ -1146,7 +1146,7 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { PoolVector<int>::Read r = sconns.read(); int idx = 0; for (int i = 0; i < cc; i++) { - ConnectionData &cd = connections[i]; + ConnectionData &cd = connections.write[i]; cd.from = r[idx++]; cd.to = r[idx++]; cd.signal = r[idx++]; @@ -1156,7 +1156,7 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { for (int j = 0; j < cd.binds.size(); j++) { - cd.binds[j] = r[idx++]; + cd.binds.write[j] = r[idx++]; } } } @@ -1167,7 +1167,7 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { } node_paths.resize(np.size()); for (int i = 0; i < np.size(); i++) { - node_paths[i] = np[i]; + node_paths.write[i] = np[i]; } Array ei; @@ -1181,7 +1181,7 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { editable_instances.resize(ei.size()); for (int i = 0; i < editable_instances.size(); i++) { - editable_instances[i] = ei[i]; + editable_instances.write[i] = ei[i]; } //path=p_dictionary["path"]; @@ -1563,13 +1563,13 @@ void SceneState::add_node_property(int p_node, int p_name, int p_value) { NodeData::Property prop; prop.name = p_name; prop.value = p_value; - nodes[p_node].properties.push_back(prop); + nodes.write[p_node].properties.push_back(prop); } void SceneState::add_node_group(int p_node, int p_group) { ERR_FAIL_INDEX(p_node, nodes.size()); ERR_FAIL_INDEX(p_group, names.size()); - nodes[p_node].groups.push_back(p_group); + nodes.write[p_node].groups.push_back(p_group); } void SceneState::set_base_scene(int p_idx) { diff --git a/scene/resources/physics_material.cpp b/scene/resources/physics_material.cpp new file mode 100644 index 0000000000..de3cfd1371 --- /dev/null +++ b/scene/resources/physics_material.cpp @@ -0,0 +1,94 @@ +/*************************************************************************/ +/* physics_material.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "physics_material.h" + +bool PhysicsMaterial::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "bounce") { + set_bounce(p_value); + } else if (p_name == "bounce_combine_mode") { + set_bounce_combine_mode(static_cast<PhysicsServer::CombineMode>(int(p_value))); + } else if (p_name == "friction") { + set_friction(p_value); + } else if (p_name == "friction_combine_mode") { + set_friction_combine_mode(static_cast<PhysicsServer::CombineMode>(int(p_value))); + } else { + return false; + } + + emit_changed(); + return true; +} + +bool PhysicsMaterial::_get(const StringName &p_name, Variant &r_ret) const { + if (p_name == "bounce") { + r_ret = bounce; + } else if (p_name == "bounce_combine_mode") { + r_ret = int(bounce_combine_mode); + } else if (p_name == "friction") { + r_ret = friction; + } else if (p_name == "friction_combine_mode") { + r_ret = int(friction_combine_mode); + } else { + return false; + } + + return true; +} + +void PhysicsMaterial::_get_property_list(List<PropertyInfo> *p_list) const { + p_list->push_back(PropertyInfo(Variant::REAL, "bounce")); + p_list->push_back(PropertyInfo(Variant::INT, "bounce_combine_mode", PROPERTY_HINT_ENUM, "Max,Min,Multiply,Average")); + p_list->push_back(PropertyInfo(Variant::REAL, "friction")); + p_list->push_back(PropertyInfo(Variant::INT, "friction_combine_mode", PROPERTY_HINT_ENUM, "Max,Min,Multiply,Average")); +} + +void PhysicsMaterial::_bind_methods() {} + +void PhysicsMaterial::set_bounce(real_t p_val) { + bounce = p_val; +} + +void PhysicsMaterial::set_bounce_combine_mode(PhysicsServer::CombineMode p_val) { + bounce_combine_mode = p_val; +} + +void PhysicsMaterial::set_friction(real_t p_val) { + friction = p_val; +} + +void PhysicsMaterial::set_friction_combine_mode(PhysicsServer::CombineMode p_val) { + friction_combine_mode = p_val; +} + +PhysicsMaterial::PhysicsMaterial() : + bounce(0), + bounce_combine_mode(PhysicsServer::COMBINE_MODE_MAX), + friction(0), + friction_combine_mode(PhysicsServer::COMBINE_MODE_MULTIPLY) {} diff --git a/scene/resources/physics_material.h b/scene/resources/physics_material.h new file mode 100644 index 0000000000..a6cb8c288e --- /dev/null +++ b/scene/resources/physics_material.h @@ -0,0 +1,70 @@ +/*************************************************************************/ +/* physics_material.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef physics_material_override_H +#define physics_material_override_H + +#include "resource.h" +#include "servers/physics_server.h" + +class PhysicsMaterial : public Resource { + + GDCLASS(PhysicsMaterial, Resource); + OBJ_SAVE_TYPE(PhysicsMaterial); + RES_BASE_EXTENSION("PhyMat"); + + real_t bounce; + PhysicsServer::CombineMode bounce_combine_mode; + real_t friction; + PhysicsServer::CombineMode friction_combine_mode; + +protected: + 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; + + static void _bind_methods(); + +public: + void set_bounce(real_t p_val); + _FORCE_INLINE_ real_t get_bounce() const { return bounce; } + + void set_bounce_combine_mode(PhysicsServer::CombineMode p_val); + _FORCE_INLINE_ PhysicsServer::CombineMode get_bounce_combine_mode() const { return bounce_combine_mode; } + + void set_friction(real_t p_val); + _FORCE_INLINE_ real_t get_friction() const { return friction; } + + void set_friction_combine_mode(PhysicsServer::CombineMode p_val); + _FORCE_INLINE_ PhysicsServer::CombineMode get_friction_combine_mode() const { return friction_combine_mode; } + + PhysicsMaterial(); +}; + +#endif // physics_material_override_H diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp index 6fea2e1a8e..44f9ebaf33 100644 --- a/scene/resources/polygon_path_finder.cpp +++ b/scene/resources/polygon_path_finder.cpp @@ -65,8 +65,8 @@ void PolygonPathFinder::setup(const Vector<Vector2> &p_points, const Vector<int> for (int i = 0; i < p_points.size(); i++) { - points[i].pos = p_points[i]; - points[i].penalty = 0; + points.write[i].pos = p_points[i]; + points.write[i].penalty = 0; outside_point.x = i == 0 ? p_points[0].x : (MAX(p_points[i].x, outside_point.x)); outside_point.y = i == 0 ? p_points[0].y : (MAX(p_points[i].y, outside_point.y)); @@ -88,8 +88,8 @@ void PolygonPathFinder::setup(const Vector<Vector2> &p_points, const Vector<int> Edge e(p_connections[i], p_connections[i + 1]); ERR_FAIL_INDEX(e.points[0], point_count); ERR_FAIL_INDEX(e.points[1], point_count); - points[p_connections[i]].connections.insert(p_connections[i + 1]); - points[p_connections[i + 1]].connections.insert(p_connections[i]); + points.write[p_connections[i]].connections.insert(p_connections[i + 1]); + points.write[p_connections[i + 1]].connections.insert(p_connections[i]); edges.insert(e); } @@ -126,8 +126,8 @@ void PolygonPathFinder::setup(const Vector<Vector2> &p_points, const Vector<int> } if (valid) { - points[i].connections.insert(j); - points[j].connections.insert(i); + points.write[i].connections.insert(j); + points.write[j].connections.insert(i); } } } @@ -227,21 +227,21 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector int aidx = points.size() - 2; int bidx = points.size() - 1; - points[aidx].pos = from; - points[bidx].pos = to; - points[aidx].distance = 0; - points[bidx].distance = 0; - points[aidx].prev = -1; - points[bidx].prev = -1; - points[aidx].penalty = 0; - points[bidx].penalty = 0; + points.write[aidx].pos = from; + points.write[bidx].pos = to; + points.write[aidx].distance = 0; + points.write[bidx].distance = 0; + points.write[aidx].prev = -1; + points.write[bidx].prev = -1; + points.write[aidx].penalty = 0; + points.write[bidx].penalty = 0; for (int i = 0; i < points.size() - 2; i++) { bool valid_a = true; bool valid_b = true; - points[i].prev = -1; - points[i].distance = 0; + points.write[i].prev = -1; + points.write[i].distance = 0; if (!_is_point_inside(from * 0.5 + points[i].pos * 0.5)) { valid_a = false; @@ -292,26 +292,26 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector } if (valid_a) { - points[i].connections.insert(aidx); - points[aidx].connections.insert(i); + points.write[i].connections.insert(aidx); + points.write[aidx].connections.insert(i); } if (valid_b) { - points[i].connections.insert(bidx); - points[bidx].connections.insert(i); + points.write[i].connections.insert(bidx); + points.write[bidx].connections.insert(i); } } //solve graph Set<int> open_list; - points[aidx].distance = 0; - points[aidx].prev = aidx; + points.write[aidx].distance = 0; + points.write[aidx].prev = aidx; for (Set<int>::Element *E = points[aidx].connections.front(); E; E = E->next()) { open_list.insert(E->get()); - points[E->get()].distance = from.distance_to(points[E->get()].pos); - points[E->get()].prev = aidx; + points.write[E->get()].distance = from.distance_to(points[E->get()].pos); + points.write[E->get()].prev = aidx; } bool found_route = false; @@ -342,12 +342,12 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector } } - Point &np = points[least_cost_point]; + const Point &np = points[least_cost_point]; //open the neighbours for search for (Set<int>::Element *E = np.connections.front(); E; E = E->next()) { - Point &p = points[E->get()]; + Point &p = points.write[E->get()]; float distance = np.pos.distance_to(p.pos) + np.distance; if (p.prev != -1) { @@ -392,18 +392,18 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector for (int i = 0; i < points.size() - 2; i++) { - points[i].connections.erase(aidx); - points[i].connections.erase(bidx); - points[i].prev = -1; - points[i].distance = 0; + points.write[i].connections.erase(aidx); + points.write[i].connections.erase(bidx); + points.write[i].prev = -1; + points.write[i].distance = 0; } - points[aidx].connections.clear(); - points[aidx].prev = -1; - points[aidx].distance = 0; - points[bidx].connections.clear(); - points[bidx].prev = -1; - points[bidx].distance = 0; + points.write[aidx].connections.clear(); + points.write[aidx].prev = -1; + points.write[aidx].distance = 0; + points.write[bidx].connections.clear(); + points.write[bidx].prev = -1; + points.write[bidx].distance = 0; return path; } @@ -427,13 +427,13 @@ void PolygonPathFinder::_set_data(const Dictionary &p_data) { PoolVector<Vector2>::Read pr = p.read(); for (int i = 0; i < pc; i++) { - points[i].pos = pr[i]; + points.write[i].pos = pr[i]; PoolVector<int> con = c[i]; PoolVector<int>::Read cr = con.read(); int cc = con.size(); for (int j = 0; j < cc; j++) { - points[i].connections.insert(cr[j]); + points.write[i].connections.insert(cr[j]); } } @@ -443,7 +443,7 @@ void PolygonPathFinder::_set_data(const Dictionary &p_data) { if (penalties.size() == pc) { PoolVector<float>::Read pr = penalties.read(); for (int i = 0; i < pc; i++) { - points[i].penalty = pr[i]; + points.write[i].penalty = pr[i]; } } } @@ -566,7 +566,7 @@ Rect2 PolygonPathFinder::get_bounds() const { void PolygonPathFinder::set_point_penalty(int p_point, float p_penalty) { ERR_FAIL_INDEX(p_point, points.size() - 2); - points[p_point].penalty = p_penalty; + points.write[p_point].penalty = p_penalty; } float PolygonPathFinder::get_point_penalty(int p_point) const { diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp index 9df117d09c..fd9989fe72 100644 --- a/scene/resources/scene_format_text.cpp +++ b/scene/resources/scene_format_text.cpp @@ -1523,7 +1523,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r for (Map<RES, int>::Element *E = external_resources.front(); E; E = E->next()) { - sorted_er[E->get()] = E->key(); + sorted_er.write[E->get()] = E->key(); } for (int i = 0; i < sorted_er.size(); i++) { diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 5a42873d79..ec489e5c5b 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -421,6 +421,7 @@ Ref<ArrayMesh> SurfaceTool::commit(const Ref<ArrayMesh> &p_existing, uint32_t p_ Array a = commit_to_arrays(); mesh->add_surface_from_arrays(primitive, a, Array(), p_flags); + if (material.is_valid()) mesh->surface_set_material(surface, material); @@ -465,7 +466,7 @@ void SurfaceTool::deindex() { int idx = 0; for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next()) { - varr[idx++] = E->get(); + varr.write[idx++] = E->get(); } vertex_array.clear(); for (List<int>::Element *E = index_array.front(); E; E = E->next()) { @@ -569,19 +570,19 @@ Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_array if (lformat & VS::ARRAY_FORMAT_BONES) { Vector<int> b; b.resize(4); - b[0] = barr[i * 4 + 0]; - b[1] = barr[i * 4 + 1]; - b[2] = barr[i * 4 + 2]; - b[3] = barr[i * 4 + 3]; + b.write[0] = barr[i * 4 + 0]; + b.write[1] = barr[i * 4 + 1]; + b.write[2] = barr[i * 4 + 2]; + b.write[3] = barr[i * 4 + 3]; v.bones = b; } if (lformat & VS::ARRAY_FORMAT_WEIGHTS) { Vector<float> w; w.resize(4); - w[0] = warr[i * 4 + 0]; - w[1] = warr[i * 4 + 1]; - w[2] = warr[i * 4 + 2]; - w[3] = warr[i * 4 + 3]; + w.write[0] = warr[i * 4 + 0]; + w.write[1] = warr[i * 4 + 1]; + w.write[2] = warr[i * 4 + 2]; + w.write[3] = warr[i * 4 + 3]; v.weights = w; } @@ -674,19 +675,19 @@ void SurfaceTool::_create_list_from_arrays(Array arr, List<Vertex> *r_vertex, Li if (lformat & VS::ARRAY_FORMAT_BONES) { Vector<int> b; b.resize(4); - b[0] = barr[i * 4 + 0]; - b[1] = barr[i * 4 + 1]; - b[2] = barr[i * 4 + 2]; - b[3] = barr[i * 4 + 3]; + b.write[0] = barr[i * 4 + 0]; + b.write[1] = barr[i * 4 + 1]; + b.write[2] = barr[i * 4 + 2]; + b.write[3] = barr[i * 4 + 3]; v.bones = b; } if (lformat & VS::ARRAY_FORMAT_WEIGHTS) { Vector<float> w; w.resize(4); - w[0] = warr[i * 4 + 0]; - w[1] = warr[i * 4 + 1]; - w[2] = warr[i * 4 + 2]; - w[3] = warr[i * 4 + 3]; + w.write[0] = warr[i * 4 + 0]; + w.write[1] = warr[i * 4 + 1]; + w.write[2] = warr[i * 4 + 2]; + w.write[3] = warr[i * 4 + 3]; v.weights = w; } @@ -845,7 +846,7 @@ void SurfaceTool::generate_tangents() { vtx.resize(vertex_array.size()); int idx = 0; for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next()) { - vtx[idx++] = E; + vtx.write[idx++] = E; E->get().binormal = Vector3(); E->get().tangent = Vector3(); } diff --git a/scene/resources/text_file.cpp b/scene/resources/text_file.cpp new file mode 100644 index 0000000000..e2fe0adfc5 --- /dev/null +++ b/scene/resources/text_file.cpp @@ -0,0 +1,77 @@ +/*************************************************************************/ +/* text_file.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "text_file.h" + +#include "os/file_access.h" + +bool TextFile::has_text() const { + return text != ""; +} + +String TextFile::get_text() const { + return text; +} + +void TextFile::set_text(const String &p_code) { + text = p_code; +} + +void TextFile::reload_from_file() { + load_text(path); +} + +Error TextFile::load_text(const String &p_path) { + + PoolVector<uint8_t> sourcef; + Error err; + FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); + if (err) { + ERR_FAIL_COND_V(err, err); + } + + int len = f->get_len(); + sourcef.resize(len + 1); + PoolVector<uint8_t>::Write w = sourcef.write(); + int r = f->get_buffer(w.ptr(), len); + f->close(); + memdelete(f); + ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN); + w[len] = 0; + + String s; + if (s.parse_utf8((const char *)w.ptr())) { + ERR_EXPLAIN("Script '" + p_path + "' contains invalid unicode (utf-8), so it was not loaded. Please ensure that scripts are saved in valid utf-8 unicode."); + ERR_FAIL_V(ERR_INVALID_DATA); + } + text = s; + path = p_path; + return OK; +} diff --git a/scene/resources/text_file.h b/scene/resources/text_file.h new file mode 100644 index 0000000000..40b648eebb --- /dev/null +++ b/scene/resources/text_file.h @@ -0,0 +1,55 @@ +/*************************************************************************/ +/* text_file.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TEXTFILE_H +#define TEXTFILE_H + +#include "io/resource_loader.h" +#include "io/resource_saver.h" + +class TextFile : public Resource { + + GDCLASS(TextFile, Resource) + +private: + String text; + String path; + +public: + virtual bool has_text() const; + virtual String get_text() const; + virtual void set_text(const String &p_code); + virtual void reload_from_file(); + + void set_file_path(const String &p_path) { path = p_path; } + Error load_text(const String &p_path); +}; + +#endif // TEXTFILE_H diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 2baad555c0..c8d12b88fc 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -235,6 +235,8 @@ Error ImageTexture::load(const String &p_path) { void ImageTexture::set_data(const Ref<Image> &p_image) { + ERR_FAIL_COND(p_image.is_null()); + VisualServer::get_singleton()->texture_set_data(texture, p_image); _change_notify(); @@ -1037,7 +1039,7 @@ bool LargeTexture::has_alpha() const { void LargeTexture::set_flags(uint32_t p_flags) { for (int i = 0; i < pieces.size(); i++) { - pieces[i].texture->set_flags(p_flags); + pieces.write[i].texture->set_flags(p_flags); } } @@ -1063,13 +1065,13 @@ int LargeTexture::add_piece(const Point2 &p_offset, const Ref<Texture> &p_textur void LargeTexture::set_piece_offset(int p_idx, const Point2 &p_offset) { ERR_FAIL_INDEX(p_idx, pieces.size()); - pieces[p_idx].offset = p_offset; + pieces.write[p_idx].offset = p_offset; }; void LargeTexture::set_piece_texture(int p_idx, const Ref<Texture> &p_texture) { ERR_FAIL_INDEX(p_idx, pieces.size()); - pieces[p_idx].texture = p_texture; + pieces.write[p_idx].texture = p_texture; }; void LargeTexture::set_size(const Size2 &p_size) { diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 58057cda0c..dd50671fa0 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -576,7 +576,7 @@ void TileSet::tile_set_shape(int p_id, int p_shape_id, const Ref<Shape2D> &p_sha ERR_FAIL_COND(!tile_map.has(p_id)); if (tile_map[p_id].shapes_data.size() <= p_shape_id) tile_map[p_id].shapes_data.resize(p_shape_id + 1); - tile_map[p_id].shapes_data[p_shape_id].shape = p_shape; + tile_map[p_id].shapes_data.write[p_shape_id].shape = p_shape; emit_changed(); } @@ -594,7 +594,7 @@ void TileSet::tile_set_shape_transform(int p_id, int p_shape_id, const Transform ERR_FAIL_COND(!tile_map.has(p_id)); if (tile_map[p_id].shapes_data.size() <= p_shape_id) tile_map[p_id].shapes_data.resize(p_shape_id + 1); - tile_map[p_id].shapes_data[p_shape_id].shape_transform = p_offset; + tile_map[p_id].shapes_data.write[p_shape_id].shape_transform = p_offset; emit_changed(); } @@ -622,7 +622,7 @@ void TileSet::tile_set_shape_one_way(int p_id, int p_shape_id, const bool p_one_ ERR_FAIL_COND(!tile_map.has(p_id)); if (tile_map[p_id].shapes_data.size() <= p_shape_id) tile_map[p_id].shapes_data.resize(p_shape_id + 1); - tile_map[p_id].shapes_data[p_shape_id].one_way_collision = p_one_way; + tile_map[p_id].shapes_data.write[p_shape_id].one_way_collision = p_one_way; emit_changed(); } @@ -923,6 +923,8 @@ void TileSet::_bind_methods() { ClassDB::bind_method(D_METHOD("tile_get_normal_map", "id"), &TileSet::tile_get_normal_map); ClassDB::bind_method(D_METHOD("tile_set_material", "id", "material"), &TileSet::tile_set_material); ClassDB::bind_method(D_METHOD("tile_get_material", "id"), &TileSet::tile_get_material); + ClassDB::bind_method(D_METHOD("tile_set_modulate", "id", "color"), &TileSet::tile_set_modulate); + ClassDB::bind_method(D_METHOD("tile_get_modulate", "id"), &TileSet::tile_get_modulate); ClassDB::bind_method(D_METHOD("tile_set_texture_offset", "id", "texture_offset"), &TileSet::tile_set_texture_offset); ClassDB::bind_method(D_METHOD("tile_get_texture_offset", "id"), &TileSet::tile_get_texture_offset); ClassDB::bind_method(D_METHOD("tile_set_region", "id", "region"), &TileSet::tile_set_region); diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index b7b7802d1b..d8fc3677fb 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -949,8 +949,8 @@ void VisualShader::_bind_methods() { ClassDB::bind_method(D_METHOD("add_node", "type", "node", "position", "id"), &VisualShader::add_node); ClassDB::bind_method(D_METHOD("set_node_position", "type", "id", "position"), &VisualShader::set_node_position); + ClassDB::bind_method(D_METHOD("get_node", "type", "id"), &VisualShader::get_node); ClassDB::bind_method(D_METHOD("get_node_position", "type", "id"), &VisualShader::get_node_position); - ClassDB::bind_method(D_METHOD("get_node", "type"), &VisualShader::get_node); ClassDB::bind_method(D_METHOD("get_node_list", "type"), &VisualShader::get_node_list); ClassDB::bind_method(D_METHOD("get_valid_node_id", "type"), &VisualShader::get_valid_node_id); |