diff options
Diffstat (limited to 'scene/3d')
-rw-r--r-- | scene/3d/camera.cpp | 10 | ||||
-rw-r--r-- | scene/3d/physics_body.cpp | 40 | ||||
-rw-r--r-- | scene/3d/physics_body.h | 1 | ||||
-rw-r--r-- | scene/3d/skeleton.cpp | 103 | ||||
-rw-r--r-- | scene/3d/skeleton.h | 10 | ||||
-rw-r--r-- | scene/3d/soft_body.cpp | 85 | ||||
-rw-r--r-- | scene/3d/soft_body.h | 6 | ||||
-rw-r--r-- | scene/3d/spatial.cpp | 5 | ||||
-rw-r--r-- | scene/3d/spatial.h | 1 |
9 files changed, 190 insertions, 71 deletions
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index 0fe427d5fc..2176b45faf 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -74,10 +74,7 @@ void Camera::_update_camera() { if (!is_inside_tree()) return; - Transform tr = get_camera_transform(); - tr.origin += tr.basis.get_axis(1) * v_offset; - tr.origin += tr.basis.get_axis(0) * h_offset; - VisualServer::get_singleton()->camera_set_transform(camera, tr); + VisualServer::get_singleton()->camera_set_transform(camera, get_camera_transform()); // here goes listener stuff /* @@ -143,7 +140,10 @@ void Camera::_notification(int p_what) { Transform Camera::get_camera_transform() const { - return get_global_transform().orthonormalized(); + Transform tr = get_global_transform().orthonormalized(); + tr.origin += tr.basis.get_axis(1) * v_offset; + tr.origin += tr.basis.get_axis(0) * h_offset; + return tr; } void Camera::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) { diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 4b3a4add4a..e53ccb4cf4 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -189,9 +189,10 @@ void StaticBody::set_friction(real_t p_friction) { if (physics_material_override.is_null()) { physics_material_override.instance(); + set_physics_material_override(physics_material_override); } + physics_material_override->set_friction(p_friction); - _reload_physics_characteristics(); } real_t StaticBody::get_friction() const { @@ -215,9 +216,9 @@ void StaticBody::set_bounce(real_t p_bounce) { if (physics_material_override.is_null()) { physics_material_override.instance(); + set_physics_material_override(physics_material_override); } physics_material_override->set_bounce(p_bounce); - _reload_physics_characteristics(); } real_t StaticBody::get_bounce() const { @@ -235,7 +236,8 @@ real_t StaticBody::get_bounce() const { 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"); + if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics")) + physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics"); } physics_material_override = p_physics_material_override; @@ -313,13 +315,9 @@ 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()); + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce()); + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->computed_friction()); } } @@ -626,9 +624,9 @@ void RigidBody::set_friction(real_t p_friction) { if (physics_material_override.is_null()) { physics_material_override.instance(); + set_physics_material_override(physics_material_override); } physics_material_override->set_friction(p_friction); - _reload_physics_characteristics(); } real_t RigidBody::get_friction() const { @@ -648,9 +646,9 @@ void RigidBody::set_bounce(real_t p_bounce) { if (physics_material_override.is_null()) { physics_material_override.instance(); + set_physics_material_override(physics_material_override); } 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") @@ -665,7 +663,8 @@ real_t RigidBody::get_bounce() const { 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"); + if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics")) + physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics"); } physics_material_override = p_physics_material_override; @@ -1070,13 +1069,9 @@ 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()); + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce()); + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->computed_friction()); } } @@ -1130,6 +1125,9 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_in return colliding; } +//so, if you pass 45 as limit, avoid numerical precision erros when angle is 45. +#define FLOOR_ANGLE_THRESHOLD 0.01 + Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { Vector3 lv = p_linear_velocity; @@ -1162,7 +1160,7 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve //all is a wall on_wall = true; } else { - if (collision.normal.dot(p_floor_direction) >= Math::cos(p_floor_max_angle)) { //floor + if (collision.normal.dot(p_floor_direction) >= Math::cos(p_floor_max_angle + FLOOR_ANGLE_THRESHOLD)) { //floor on_floor = true; floor_velocity = collision.collider_vel; @@ -1176,7 +1174,7 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve set_global_transform(gt); return floor_velocity - p_floor_direction * p_floor_direction.dot(floor_velocity); } - } else if (collision.normal.dot(-p_floor_direction) >= Math::cos(p_floor_max_angle)) { //ceiling + } else if (collision.normal.dot(-p_floor_direction) >= Math::cos(p_floor_max_angle + FLOOR_ANGLE_THRESHOLD)) { //ceiling on_ceiling = true; } else { on_wall = true; @@ -2044,6 +2042,8 @@ void PhysicalBone::_bind_methods() { ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBone::is_simulating_physics); + ClassDB::bind_method(D_METHOD("get_bone_id"), &PhysicalBone::get_bone_id); + ClassDB::bind_method(D_METHOD("set_mass", "mass"), &PhysicalBone::set_mass); ClassDB::bind_method(D_METHOD("get_mass"), &PhysicalBone::get_mass); diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index 4143989671..80bf422c98 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -557,6 +557,7 @@ protected: private: static Skeleton *find_skeleton_parent(Node *p_parent); + void _fix_joint_offset(); void _reload_joint(); diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index 4b6b59b2d3..c796e47f25 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -131,7 +131,7 @@ void Skeleton::_get_property_list(List<PropertyInfo> *p_list) const { String prep = "bones/" + itos(i) + "/"; p_list->push_back(PropertyInfo(Variant::STRING, prep + "name")); - p_list->push_back(PropertyInfo(Variant::INT, prep + "parent", PROPERTY_HINT_RANGE, "-1," + itos(i - 1) + ",1")); + p_list->push_back(PropertyInfo(Variant::INT, prep + "parent", PROPERTY_HINT_RANGE, "-1," + itos(bones.size() - 1) + ",1")); p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "rest")); p_list->push_back(PropertyInfo(Variant::BOOL, prep + "enabled")); p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "pose", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); @@ -139,6 +139,59 @@ void Skeleton::_get_property_list(List<PropertyInfo> *p_list) const { } } +void Skeleton::_update_process_order() { + + if (!process_order_dirty) + return; + + Bone *bonesptr = bones.ptrw(); + int len = bones.size(); + + process_order.resize(len); + int *order = process_order.ptrw(); + for (int i = 0; i < len; i++) { + + if (bonesptr[i].parent >= len) { + //validate this just in case + ERR_PRINTS("Bone " + itos(i) + " has invalid parent: " + itos(bonesptr[i].parent)); + bonesptr[i].parent = -1; + } + order[i] = i; + bonesptr[i].sort_index = i; + } + //now check process order + int pass_count = 0; + while (pass_count < len * len) { + //using bubblesort because of simplicity, it wont run every frame though. + //bublesort worst case is O(n^2), and this may be an infinite loop if cyclic + bool swapped = false; + for (int i = 0; i < len; i++) { + int parent_idx = bonesptr[order[i]].parent; + if (parent_idx < 0) + continue; //do nothing because it has no parent + //swap indices + int parent_order = bonesptr[parent_idx].sort_index; + if (parent_order > i) { + bonesptr[order[i]].sort_index = parent_order; + bonesptr[parent_idx].sort_index = i; + //swap order + SWAP(order[i], order[parent_order]); + swapped = true; + } + } + + if (!swapped) + break; + pass_count++; + } + + if (pass_count == len * len) { + ERR_PRINT("Skeleton parenthood graph is cyclic"); + } + + process_order_dirty = false; +} + void Skeleton::_notification(int p_what) { switch (p_what) { @@ -181,19 +234,23 @@ void Skeleton::_notification(int p_what) { vs->skeleton_allocate(skeleton, len); // if same size, nothin really happens + _update_process_order(); + + const int *order = process_order.ptr(); + // pose changed, rebuild cache of inverses if (rest_global_inverse_dirty) { // calculate global rests and invert them for (int i = 0; i < len; i++) { - Bone &b = bonesptr[i]; + Bone &b = bonesptr[order[i]]; if (b.parent >= 0) b.rest_global_inverse = bonesptr[b.parent].rest_global_inverse * b.rest; else b.rest_global_inverse = b.rest; } for (int i = 0; i < len; i++) { - Bone &b = bonesptr[i]; + Bone &b = bonesptr[order[i]]; b.rest_global_inverse.affine_invert(); } @@ -205,7 +262,7 @@ void Skeleton::_notification(int p_what) { for (int i = 0; i < len; i++) { - Bone &b = bonesptr[i]; + Bone &b = bonesptr[order[i]]; if (b.disable_rest) { if (b.enabled) { @@ -319,12 +376,13 @@ void Skeleton::add_bone(const String &p_name) { for (int i = 0; i < bones.size(); i++) { - ERR_FAIL_COND(bones[i].name == "p_name"); + ERR_FAIL_COND(bones[i].name == p_name); } Bone b; b.name = p_name; bones.push_back(b); + process_order_dirty = true; rest_global_inverse_dirty = true; _make_dirty(); @@ -368,10 +426,11 @@ int Skeleton::get_bone_count() const { 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)); + ERR_FAIL_COND(p_parent != -1 && (p_parent < 0)); bones.write[p_bone].parent = p_parent; rest_global_inverse_dirty = true; + process_order_dirty = true; _make_dirty(); } @@ -379,6 +438,8 @@ void Skeleton::unparent_bone_and_rest(int p_bone) { ERR_FAIL_INDEX(p_bone, bones.size()); + _update_process_order(); + int parent = bones[p_bone].parent; while (parent >= 0) { bones.write[p_bone].rest = bones[parent].rest * bones[p_bone].rest; @@ -387,6 +448,7 @@ void Skeleton::unparent_bone_and_rest(int p_bone) { bones.write[p_bone].parent = -1; bones.write[p_bone].rest_global_inverse = bones[p_bone].rest.affine_inverse(); //same thing + process_order_dirty = true; _make_dirty(); } @@ -489,6 +551,8 @@ void Skeleton::clear_bones() { bones.clear(); rest_global_inverse_dirty = true; + process_order_dirty = true; + _make_dirty(); } @@ -538,12 +602,21 @@ void Skeleton::_make_dirty() { dirty = true; } +int Skeleton::get_process_order(int p_idx) { + ERR_FAIL_INDEX_V(p_idx, bones.size(), -1); + _update_process_order(); + return process_order[p_idx]; +} + void Skeleton::localize_rests() { - for (int i = bones.size() - 1; i >= 0; i--) { + _update_process_order(); - if (bones[i].parent >= 0) - set_bone_rest(i, bones[bones[i].parent].rest.affine_inverse() * bones[i].rest); + for (int i = bones.size() - 1; i >= 0; i--) { + int idx = process_order[i]; + if (bones[idx].parent >= 0) { + set_bone_rest(idx, bones[bones[idx].parent].rest.affine_inverse() * bones[idx].rest); + } } } @@ -600,9 +673,12 @@ 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.write[i].cache_parent_physical_bone = _get_physical_bone_parent(i); - if (bones[i].physical_bone) - bones[i].physical_bone->_on_bone_parent_changed(); + PhysicalBone *parent_pb = _get_physical_bone_parent(i); + if (parent_pb != bones[i].physical_bone) { + bones.write[i].cache_parent_physical_bone = parent_pb; + if (bones[i].physical_bone) + bones[i].physical_bone->_on_bone_parent_changed(); + } } } @@ -740,6 +816,8 @@ void Skeleton::_bind_methods() { #endif // _3D_DISABLED + ClassDB::bind_method(D_METHOD("set_bone_ignore_animation", "bone", "ignore"), &Skeleton::set_bone_ignore_animation); + BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON); } @@ -747,6 +825,7 @@ Skeleton::Skeleton() { rest_global_inverse_dirty = true; dirty = false; + process_order_dirty = true; skeleton = VisualServer::get_singleton()->skeleton_create(); set_notify_transform(true); } diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h index 9672acb57a..e044e08437 100644 --- a/scene/3d/skeleton.h +++ b/scene/3d/skeleton.h @@ -39,6 +39,8 @@ */ #ifndef _3D_DISABLED +typedef int BoneId; + class PhysicalBone; #endif // _3D_DISABLED @@ -52,6 +54,7 @@ class Skeleton : public Spatial { bool enabled; int parent; + int sort_index; //used for re-sorting process order bool ignore_animation; @@ -90,13 +93,15 @@ class Skeleton : public Spatial { bool rest_global_inverse_dirty; Vector<Bone> bones; + Vector<int> process_order; + bool process_order_dirty; RID skeleton; void _make_dirty(); bool dirty; - //bind helpers + // bind helpers Array _get_bound_child_nodes_to_bone(int p_bone) const { Array bound; @@ -110,6 +115,8 @@ class Skeleton : public Spatial { return bound; } + void _update_process_order(); + protected: bool _get(const StringName &p_path, Variant &r_ret) const; bool _set(const StringName &p_path, const Variant &p_value); @@ -170,6 +177,7 @@ public: Transform get_bone_custom_pose(int p_bone) const; void localize_rests(); // used for loaders and tools + int get_process_order(int p_idx); #ifndef _3D_DISABLED // Physical bone API diff --git a/scene/3d/soft_body.cpp b/scene/3d/soft_body.cpp index 4ab7013707..980c348c9b 100644 --- a/scene/3d/soft_body.cpp +++ b/scene/3d/soft_body.cpp @@ -133,8 +133,8 @@ bool SoftBody::_get(const StringName &p_name, Variant &r_ret) const { 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(); + const int pinned_points_indices_size = pinned_points.size(); + PoolVector<PinnedPoint>::Read r = pinned_points.read(); arr_ret.resize(pinned_points_indices_size); for (int i = 0; i < pinned_points_indices_size; ++i) { @@ -157,7 +157,7 @@ bool SoftBody::_get(const StringName &p_name, Variant &r_ret) const { void SoftBody::_get_property_list(List<PropertyInfo> *p_list) const { - const int pinned_points_indices_size = pinned_points_indices.size(); + const int pinned_points_indices_size = pinned_points.size(); p_list->push_back(PropertyInfo(Variant::POOL_INT_ARRAY, "pinned_points")); @@ -173,17 +173,17 @@ 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) { + PoolVector<PinnedPoint>::Read r = pinned_points.read(); + if (p_indices_size < pinned_points.size()) { + for (int i = pinned_points.size() - 1; i >= p_indices_size; --i) { pin_point(r[i].point_index, false); } } } - pinned_points_indices.resize(p_indices_size); + pinned_points.resize(p_indices_size); - PoolVector<PinnedPoint>::Write w = pinned_points_indices.write(); + PoolVector<PinnedPoint>::Write w = pinned_points.write(); int point_index; for (int i = 0; i < p_indices_size; ++i) { point_index = p_indices.get(i); @@ -198,16 +198,16 @@ bool SoftBody::_set_property_pinned_points_indices(const Array &p_indices) { } 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) { + if (pinned_points.size() <= p_item) { return false; } if ("spatial_attachment_path" == p_what) { - PoolVector<PinnedPoint>::Write w = pinned_points_indices.write(); + PoolVector<PinnedPoint>::Write w = pinned_points.write(); pin_point(w[p_item].point_index, true, p_value); _make_cache_dirty(); } else if ("offset" == p_what) { - PoolVector<PinnedPoint>::Write w = pinned_points_indices.write(); + PoolVector<PinnedPoint>::Write w = pinned_points.write(); w[p_item].offset = p_value; } else { return false; @@ -217,10 +217,10 @@ bool SoftBody::_set_property_pinned_points_attachment(int p_item, const String & } bool SoftBody::_get_property_pinned_points(int p_item, const String &p_what, Variant &r_ret) const { - if (pinned_points_indices.size() <= p_item) { + if (pinned_points.size() <= p_item) { return false; } - PoolVector<PinnedPoint>::Read r = pinned_points_indices.read(); + PoolVector<PinnedPoint>::Read r = pinned_points.read(); if ("point_index" == p_what) { r_ret = r[p_item].point_index; @@ -236,6 +236,8 @@ bool SoftBody::_get_property_pinned_points(int p_item, const String &p_what, Var } void SoftBody::_changed_callback(Object *p_changed, const char *p_prop) { + update_physics_server(); + _reset_points_offsets(); #ifdef TOOLS_ENABLED if (p_changed == this) { update_configuration_warning(); @@ -247,8 +249,10 @@ void SoftBody::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_WORLD: { - if (Engine::get_singleton()->is_editor_hint()) + 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); @@ -261,8 +265,10 @@ void SoftBody::_notification(int p_what) { } break; case NOTIFICATION_TRANSFORM_CHANGED: { - if (Engine::get_singleton()->is_editor_hint()) + if (Engine::get_singleton()->is_editor_hint()) { + _reset_points_offsets(); return; + } PhysicsServer::get_singleton()->soft_body_set_transform(physics_rid, get_global_transform()); @@ -280,8 +286,8 @@ void SoftBody::_notification(int p_what) { _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(); + const int pinned_points_indices_size = pinned_points.size(); + PoolVector<PinnedPoint>::Read r = pinned_points.read(); for (int i = 0; i < pinned_points_indices_size; ++i) { if (r[i].spatial_attachment) { PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, r[i].spatial_attachment->get_global_transform().xform(r[i].offset)); @@ -531,15 +537,15 @@ const NodePath &SoftBody::get_parent_collision_ignore() const { } 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) { + pinned_points = p_pinned_points_indices; + PoolVector<PinnedPoint>::Read w = pinned_points.read(); + for (int i = pinned_points.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; + return pinned_points; } void SoftBody::add_collision_exception_with(Node *p_node) { @@ -685,8 +691,8 @@ 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) { + PoolVector<PinnedPoint>::Read pps = pinned_points.read(); + for (int i = pinned_points.size() - 1; 0 < i; --i) { PhysicsServer::get_singleton()->soft_body_pin_point(physics_rid, pps[i].point_index, true); } } @@ -701,8 +707,8 @@ void SoftBody::_update_cache_pin_points_datas() { pinned_points_cache_dirty = false; - PoolVector<PinnedPoint>::Write w = pinned_points_indices.write(); - for (int i = pinned_points_indices.size() - 1; 0 <= i; --i) { + PoolVector<PinnedPoint>::Write w = pinned_points.write(); + for (int i = pinned_points.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)); @@ -731,7 +737,7 @@ void SoftBody::_add_pinned_point(int p_point_index, const NodePath &p_spatial_at pp.offset = (pp.spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, pp.point_index)); } - pinned_points_indices.push_back(pp); + pinned_points.push_back(pp); } else { @@ -745,10 +751,29 @@ void SoftBody::_add_pinned_point(int p_point_index, const NodePath &p_spatial_at } } +void SoftBody::_reset_points_offsets() { + + if (!Engine::get_singleton()->is_editor_hint()) + return; + + PoolVector<PinnedPoint>::Read r = pinned_points.read(); + PoolVector<PinnedPoint>::Write w = pinned_points.write(); + for (int i = pinned_points.size() - 1; 0 <= i; --i) { + + if (!r[i].spatial_attachment) + w[i].spatial_attachment = Object::cast_to<Spatial>(get_node(r[i].spatial_attachment_path)); + + if (!r[i].spatial_attachment) + continue; + + w[i].offset = (r[i].spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, r[i].point_index)); + } +} + 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); + pinned_points.remove(id); } } @@ -758,14 +783,14 @@ int SoftBody::_get_pinned_point(int p_point_index, SoftBody::PinnedPoint *&r_poi r_point = NULL; return -1; } else { - r_point = const_cast<SoftBody::PinnedPoint *>(&pinned_points_indices.read()[id]); + r_point = const_cast<SoftBody::PinnedPoint *>(&pinned_points.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) { + PoolVector<PinnedPoint>::Read r = pinned_points.read(); + for (int i = pinned_points.size() - 1; 0 <= i; --i) { if (p_point_index == r[i].point_index) { return i; } diff --git a/scene/3d/soft_body.h b/scene/3d/soft_body.h index 6cf19ef8c4..cee32b9651 100644 --- a/scene/3d/soft_body.h +++ b/scene/3d/soft_body.h @@ -87,7 +87,7 @@ private: uint32_t collision_mask; uint32_t collision_layer; NodePath parent_collision_ignore; - PoolVector<PinnedPoint> pinned_points_indices; + PoolVector<PinnedPoint> pinned_points; bool simulation_started; bool pinned_points_cache_dirty; @@ -184,10 +184,14 @@ public: private: void reset_softbody_pin(); + void _make_cache_dirty(); 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 _reset_points_offsets(); + 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; diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index 64cb9ec4ca..3f494264e7 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -202,6 +202,7 @@ void Spatial::_notification(int p_what) { #ifdef TOOLS_ENABLED if (data.gizmo.is_valid()) { data.gizmo->free(); + data.gizmo.unref(); } #endif @@ -793,13 +794,13 @@ void Spatial::_bind_methods() { //ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM,"transform/global",PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR ), "set_global_transform", "get_global_transform") ; ADD_GROUP("Transform", ""); - ADD_PROPERTYNZ(PropertyInfo(Variant::TRANSFORM, "transform", PROPERTY_HINT_NONE, ""), "set_transform", "get_transform"); ADD_PROPERTYNZ(PropertyInfo(Variant::TRANSFORM, "global_transform", PROPERTY_HINT_NONE, "", 0), "set_global_transform", "get_global_transform"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "translation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_translation", "get_translation"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_NONE, "", 0), "set_rotation", "get_rotation"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_scale", "get_scale"); - + ADD_GROUP("Matrix", ""); + ADD_PROPERTYNZ(PropertyInfo(Variant::TRANSFORM, "transform", PROPERTY_HINT_NONE, ""), "set_transform", "get_transform"); ADD_GROUP("Visibility", ""); ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "SpatialGizmo", 0), "set_gizmo", "get_gizmo"); diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h index 653714dc98..bc054a8763 100644 --- a/scene/3d/spatial.h +++ b/scene/3d/spatial.h @@ -51,6 +51,7 @@ public: virtual bool can_draw() const = 0; SpatialGizmo(); + virtual ~SpatialGizmo() {} }; class Spatial : public Node { |