diff options
Diffstat (limited to 'modules')
25 files changed, 335 insertions, 94 deletions
diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp index 402a276f95..441fa7c8af 100644 --- a/modules/bullet/collision_object_bullet.cpp +++ b/modules/bullet/collision_object_bullet.cpp @@ -304,7 +304,11 @@ bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) { } void RigidCollisionObjectBullet::shape_changed(int p_shape_index) { - bulletdelete(shapes.write[p_shape_index].bt_shape); + ShapeWrapper &shp = shapes.write[p_shape_index]; + if (shp.bt_shape == mainShape) { + mainShape = NULL; + } + bulletdelete(shp.bt_shape); reload_shapes(); } @@ -366,5 +370,8 @@ void RigidCollisionObjectBullet::body_scale_changed() { void RigidCollisionObjectBullet::internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody) { ShapeWrapper &shp = shapes.write[p_index]; shp.shape->remove_owner(this, p_permanentlyFromThisBody); + if (shp.bt_shape == mainShape) { + mainShape = NULL; + } bulletdelete(shp.bt_shape); } diff --git a/modules/bullet/generic_6dof_joint_bullet.cpp b/modules/bullet/generic_6dof_joint_bullet.cpp index a36f1123bc..a94b88d566 100644 --- a/modules/bullet/generic_6dof_joint_bullet.cpp +++ b/modules/bullet/generic_6dof_joint_bullet.cpp @@ -135,6 +135,15 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: sixDOFConstraint->getTranslationalLimitMotor()->m_maxMotorForce.m_floats[p_axis] = p_value; break; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: + sixDOFConstraint->getTranslationalLimitMotor()->m_springDamping.m_floats[p_axis] = p_value; + break; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: + sixDOFConstraint->getTranslationalLimitMotor()->m_springStiffness.m_floats[p_axis] = p_value; + break; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: + sixDOFConstraint->getTranslationalLimitMotor()->m_equilibriumPoint.m_floats[p_axis] = p_value; + break; case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: limits_lower[1][p_axis] = p_value; set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter @@ -143,6 +152,9 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO limits_upper[1][p_axis] = p_value; set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter break; + case PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION: + sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_bounce = p_value; + break; case PhysicsServer::G6DOF_JOINT_ANGULAR_ERP: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_stopERP = p_value; break; @@ -152,6 +164,15 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce = p_value; break; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: + sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springStiffness = p_value; + break; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: + sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springDamping = p_value; + break; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: + sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_equilibriumPoint = p_value; + break; default: ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated"); WARN_DEPRECATED @@ -170,6 +191,12 @@ real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer::G6 return sixDOFConstraint->getTranslationalLimitMotor()->m_targetVelocity.m_floats[p_axis]; case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: return sixDOFConstraint->getTranslationalLimitMotor()->m_maxMotorForce.m_floats[p_axis]; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: + return sixDOFConstraint->getTranslationalLimitMotor()->m_springDamping.m_floats[p_axis]; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: + return sixDOFConstraint->getTranslationalLimitMotor()->m_springStiffness.m_floats[p_axis]; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: + return sixDOFConstraint->getTranslationalLimitMotor()->m_equilibriumPoint.m_floats[p_axis]; case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: return limits_lower[1][p_axis]; case PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: @@ -182,6 +209,12 @@ real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer::G6 return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_targetVelocity; case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: + return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springStiffness; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: + return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springDamping; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: + return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_equilibriumPoint; default: ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated"); WARN_DEPRECATED; @@ -215,6 +248,12 @@ void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOF case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: sixDOFConstraint->getTranslationalLimitMotor()->m_enableMotor[p_axis] = flags[p_axis][p_flag]; break; + case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: + sixDOFConstraint->getTranslationalLimitMotor()->m_enableSpring[p_axis] = p_value; + break; + case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: + sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_enableSpring = p_value; + break; default: ERR_EXPLAIN("This flag " + itos(p_flag) + " is deprecated"); WARN_DEPRECATED @@ -224,6 +263,5 @@ void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOF bool Generic6DOFJointBullet::get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag) const { ERR_FAIL_INDEX_V(p_axis, 3, false); - return flags[p_axis][p_flag]; } diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index 37e7718969..85659e1523 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -797,7 +797,10 @@ void RigidBodyBullet::reload_shapes() { const btScalar mass = invMass == 0 ? 0 : 1 / invMass; if (mainShape) { - btVector3 inertia; + // inertia initialised zero here because some of bullet's collision + // shapes incorrectly do not set the vector in calculateLocalIntertia. + // Arbitrary zero is preferable to undefined behaviour. + btVector3 inertia(0, 0, 0); mainShape->calculateLocalInertia(mass, inertia); btBody->setMassProps(mass, inertia); } diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 4eb798de11..a4c34e7583 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -159,6 +159,72 @@ CSGBrush *CSGShape::_get_brush() { return brush; } +int CSGShape::mikktGetNumFaces(const SMikkTSpaceContext *pContext) { + ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); + + return surface.vertices.size() / 3; +} + +int CSGShape::mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace) { + // always 3 + return 3; +} + +void CSGShape::mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert) { + ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); + + Vector3 v = surface.verticesw[iFace * 3 + iVert]; + fvPosOut[0] = v.x; + fvPosOut[1] = v.y; + fvPosOut[2] = v.z; +} + +void CSGShape::mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert) { + ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); + + Vector3 n = surface.normalsw[iFace * 3 + iVert]; + fvNormOut[0] = n.x; + fvNormOut[1] = n.y; + fvNormOut[2] = n.z; +} + +void CSGShape::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert) { + ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); + + Vector2 t = surface.uvsw[iFace * 3 + iVert]; + fvTexcOut[0] = t.x; + fvTexcOut[1] = t.y; +} + +void CSGShape::mikktSetTSpaceBasic(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert) { + ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); + + int i = (iFace * 3 + iVert) * 4; + + surface.tansw[i++] = fvTangent[0]; + surface.tansw[i++] = fvTangent[1]; + surface.tansw[i++] = fvTangent[2]; + surface.tansw[i++] = fSign; +} + +void CSGShape::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT, + const tbool bIsOrientationPreserving, const int iFace, const int iVert) { + + ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); + + int i = iFace * 3 + iVert; + Vector3 normal = surface.normalsw[i]; + Vector3 tangent = Vector3(fvTangent[0], fvTangent[1], fvTangent[2]); + Vector3 bitangent = Vector3(fvBiTangent[0], fvBiTangent[1], fvBiTangent[2]); + float d = bitangent.dot(normal.cross(tangent)); + + i *= 4; + surface.tansw[i++] = tangent.x; + surface.tansw[i++] = tangent.y; + surface.tansw[i++] = tangent.z; + surface.tansw[i++] = d < 0 ? -1 : 1; +} + void CSGShape::_update_shape() { if (parent) @@ -211,6 +277,9 @@ void CSGShape::_update_shape() { surfaces.write[i].vertices.resize(face_count[i] * 3); surfaces.write[i].normals.resize(face_count[i] * 3); surfaces.write[i].uvs.resize(face_count[i] * 3); + if (calculate_tangents) { + surfaces.write[i].tans.resize(face_count[i] * 3 * 4); + } surfaces.write[i].last_added = 0; if (i != surfaces.size() - 1) { @@ -220,6 +289,9 @@ void CSGShape::_update_shape() { surfaces.write[i].verticesw = surfaces.write[i].vertices.write(); surfaces.write[i].normalsw = surfaces.write[i].normals.write(); surfaces.write[i].uvsw = surfaces.write[i].uvs.write(); + if (calculate_tangents) { + surfaces.write[i].tansw = surfaces.write[i].tans.write(); + } } //fill arrays @@ -274,9 +346,19 @@ void CSGShape::_update_shape() { normal = -normal; } - surfaces[idx].verticesw[last + order[j]] = v; - surfaces[idx].uvsw[last + order[j]] = n->faces[i].uvs[j]; - surfaces[idx].normalsw[last + order[j]] = normal; + int k = last + order[j]; + surfaces[idx].verticesw[k] = v; + surfaces[idx].uvsw[k] = n->faces[i].uvs[j]; + surfaces[idx].normalsw[k] = normal; + + if (calculate_tangents) { + // zero out our tangents for now + k *= 4; + surfaces[idx].tansw[k++] = 0.0; + surfaces[idx].tansw[k++] = 0.0; + surfaces[idx].tansw[k++] = 0.0; + surfaces[idx].tansw[k++] = 0.0; + } } surfaces.write[idx].last_added += 3; @@ -287,20 +369,43 @@ void CSGShape::_update_shape() { //create surfaces for (int i = 0; i < surfaces.size(); i++) { + // calculate tangents for this surface + bool have_tangents = calculate_tangents; + if (have_tangents) { + SMikkTSpaceInterface mkif; + mkif.m_getNormal = mikktGetNormal; + mkif.m_getNumFaces = mikktGetNumFaces; + mkif.m_getNumVerticesOfFace = mikktGetNumVerticesOfFace; + mkif.m_getPosition = mikktGetPosition; + mkif.m_getTexCoord = mikktGetTexCoord; + mkif.m_setTSpace = mikktSetTSpaceDefault; + mkif.m_setTSpaceBasic = NULL; + + SMikkTSpaceContext msc; + msc.m_pInterface = &mkif; + msc.m_pUserData = &surfaces.write[i]; + have_tangents = genTangSpaceDefault(&msc); + } + // unset write access surfaces.write[i].verticesw = PoolVector<Vector3>::Write(); surfaces.write[i].normalsw = PoolVector<Vector3>::Write(); surfaces.write[i].uvsw = PoolVector<Vector2>::Write(); + surfaces.write[i].tansw = PoolVector<float>::Write(); if (surfaces[i].last_added == 0) continue; + // and convert to surface array Array array; array.resize(Mesh::ARRAY_MAX); array[Mesh::ARRAY_VERTEX] = surfaces[i].vertices; array[Mesh::ARRAY_NORMAL] = surfaces[i].normals; array[Mesh::ARRAY_TEX_UV] = surfaces[i].uvs; + if (have_tangents) { + array[Mesh::ARRAY_TANGENT] = surfaces[i].tans; + } int idx = root_mesh->get_surface_count(); root_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, array); @@ -400,6 +505,15 @@ CSGShape::Operation CSGShape::get_operation() const { return operation; } +void CSGShape::set_calculate_tangents(bool p_calculate_tangents) { + calculate_tangents = p_calculate_tangents; + _make_dirty(); +} + +bool CSGShape::is_calculating_tangents() const { + return calculate_tangents; +} + void CSGShape::_validate_property(PropertyInfo &property) const { if (is_inside_tree() && property.name.begins_with("use_collision") && !is_root_shape()) { //hide collision if not root @@ -421,9 +535,13 @@ void CSGShape::_bind_methods() { ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CSGShape::set_snap); ClassDB::bind_method(D_METHOD("get_snap"), &CSGShape::get_snap); + ClassDB::bind_method(D_METHOD("set_calculate_tangents", "enabled"), &CSGShape::set_calculate_tangents); + ClassDB::bind_method(D_METHOD("is_calculating_tangents"), &CSGShape::is_calculating_tangents); + ADD_PROPERTY(PropertyInfo(Variant::INT, "operation", PROPERTY_HINT_ENUM, "Union,Intersection,Subtraction"), "set_operation", "get_operation"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_collision"), "set_use_collision", "is_using_collision"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "snap", PROPERTY_HINT_RANGE, "0.0001,1,0.001"), "set_snap", "get_snap"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "calculate_tangents"), "set_calculate_tangents", "is_calculating_tangents"); BIND_ENUM_CONSTANT(OPERATION_UNION); BIND_ENUM_CONSTANT(OPERATION_INTERSECTION); @@ -438,6 +556,7 @@ CSGShape::CSGShape() { use_collision = false; operation = OPERATION_UNION; snap = 0.001; + calculate_tangents = true; } CSGShape::~CSGShape() { @@ -1545,6 +1664,24 @@ CSGBrush *CSGPolygon::_build_brush() { Path *path = NULL; Ref<Curve3D> curve; + // get bounds for our polygon + Vector2 final_polygon_min; + Vector2 final_polygon_max; + for (int i = 0; i < final_polygon.size(); i++) { + Vector2 p = final_polygon[i]; + if (i == 0) { + final_polygon_min = p; + final_polygon_max = final_polygon_min; + } else { + if (p.x < final_polygon_min.x) final_polygon_min.x = p.x; + if (p.y < final_polygon_min.y) final_polygon_min.y = p.y; + + if (p.x > final_polygon_max.x) final_polygon_max.x = p.x; + if (p.y > final_polygon_max.y) final_polygon_max.y = p.y; + } + } + Vector2 final_polygon_size = final_polygon_max - final_polygon_min; + if (mode == MODE_PATH) { if (!has_node(path_node)) return NULL; @@ -1636,6 +1773,10 @@ CSGBrush *CSGPolygon::_build_brush() { v.z -= depth; } facesw[face * 3 + k] = v; + uvsw[face * 3 + k] = (p - final_polygon_min) / final_polygon_size; + if (i == 0) { + uvsw[face * 3 + k].x = 1.0 - uvsw[face * 3 + k].x; /* flip x */ + } } smoothw[face] = false; @@ -1767,6 +1908,7 @@ CSGBrush *CSGPolygon::_build_brush() { Vector2 p = final_polygon[triangles[j + src[k]]]; Vector3 v = Vector3(p.x, p.y, 0); facesw[face * 3 + k] = v; + uvsw[face * 3 + k] = (p - final_polygon_min) / final_polygon_size; } smoothw[face] = false; @@ -1784,6 +1926,8 @@ CSGBrush *CSGPolygon::_build_brush() { Vector2 p = final_polygon[triangles[j + src[k]]]; Vector3 v = Vector3(normali_n.x * p.x, p.y, normali_n.z * p.x); facesw[face * 3 + k] = v; + uvsw[face * 3 + k] = (p - final_polygon_min) / final_polygon_size; + uvsw[face * 3 + k].x = 1.0 - uvsw[face * 3 + k].x; /* flip x */ } smoothw[face] = false; @@ -1869,10 +2013,10 @@ CSGBrush *CSGPolygon::_build_brush() { }; Vector2 u[4] = { - Vector2(u1, 0), Vector2(u1, 1), - Vector2(u2, 1), - Vector2(u2, 0) + Vector2(u1, 0), + Vector2(u2, 0), + Vector2(u2, 1) }; // face 1 @@ -1915,6 +2059,7 @@ CSGBrush *CSGPolygon::_build_brush() { Vector2 p = final_polygon[triangles[j + src[k]]]; Vector3 v = Vector3(p.x, p.y, 0); facesw[face * 3 + k] = xf.xform(v); + uvsw[face * 3 + k] = (p - final_polygon_min) / final_polygon_size; } smoothw[face] = false; @@ -1932,6 +2077,8 @@ CSGBrush *CSGPolygon::_build_brush() { Vector2 p = final_polygon[triangles[j + src[k]]]; Vector3 v = Vector3(p.x, p.y, 0); facesw[face * 3 + k] = xf.xform(v); + uvsw[face * 3 + k] = (p - final_polygon_min) / final_polygon_size; + uvsw[face * 3 + k].x = 1.0 - uvsw[face * 3 + k].x; /* flip x */ } smoothw[face] = false; @@ -1956,6 +2103,9 @@ CSGBrush *CSGPolygon::_build_brush() { } else { aabb.expand_to(facesw[i]); } + + // invert UVs on the Y-axis OpenGL = upside down + uvsw[i].y = 1.0 - uvsw[i].y; } } diff --git a/modules/csg/csg_shape.h b/modules/csg/csg_shape.h index 6898cdaf64..0a4bb5f665 100644 --- a/modules/csg/csg_shape.h +++ b/modules/csg/csg_shape.h @@ -36,6 +36,7 @@ #include "csg.h" #include "scene/3d/visual_instance.h" #include "scene/resources/concave_polygon_shape.h" +#include "thirdparty/misc/mikktspace.h" class CSGShape : public VisualInstance { GDCLASS(CSGShape, VisualInstance); @@ -63,6 +64,8 @@ private: Ref<ConcavePolygonShape> root_collision_shape; RID root_collision_instance; + bool calculate_tangents; + Ref<ArrayMesh> root_mesh; struct Vector3Hasher { @@ -78,14 +81,26 @@ private: PoolVector<Vector3> vertices; PoolVector<Vector3> normals; PoolVector<Vector2> uvs; + PoolVector<float> tans; Ref<Material> material; int last_added; PoolVector<Vector3>::Write verticesw; PoolVector<Vector3>::Write normalsw; PoolVector<Vector2>::Write uvsw; + PoolVector<float>::Write tansw; }; + //mikktspace callbacks + static int mikktGetNumFaces(const SMikkTSpaceContext *pContext); + static int mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace); + static void mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert); + static void mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert); + static void mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert); + static void mikktSetTSpaceBasic(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert); + static void mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT, + const tbool bIsOrientationPreserving, const int iFace, const int iVert); + void _update_shape(); protected: @@ -115,6 +130,9 @@ public: void set_snap(float p_snap); float get_snap() const; + void set_calculate_tangents(bool p_calculate_tangents); + bool is_calculating_tangents() const; + bool is_root_shape() const; CSGShape(); ~CSGShape(); diff --git a/modules/csg/doc_classes/CSGShape.xml b/modules/csg/doc_classes/CSGShape.xml index 90621b94f4..ac3c2342fc 100644 --- a/modules/csg/doc_classes/CSGShape.xml +++ b/modules/csg/doc_classes/CSGShape.xml @@ -20,6 +20,9 @@ </method> </methods> <members> + <member name="calculate_tangents" type="bool" setter="set_calculate_tangents" getter="is_calculating_tangents"> + Calculate tangents for the CSG shape which allows the use of normal maps. This is only applied on the root shape, this setting is ignored on any child. + </member> <member name="operation" type="int" setter="set_operation" getter="get_operation" enum="CSGShape.Operation"> The operation that is performed on this shape. This is ignored for the first CSG child node as the operation is between this node and the previous child of this nodes parent. </member> diff --git a/modules/gdnative/gdnative_builders.py b/modules/gdnative/gdnative_builders.py index f9d1ed9dc5..ff18a3ae69 100644 --- a/modules/gdnative/gdnative_builders.py +++ b/modules/gdnative/gdnative_builders.py @@ -87,20 +87,20 @@ def _build_gdnative_api_struct_header(api): ret_val = [] if core['next']: ret_val += generate_core_extension_struct(core['next']) - + ret_val += [ 'typedef struct godot_gdnative_core_' + ('{0}_{1}'.format(core['version']['major'], core['version']['minor'])) + '_api_struct {', '\tunsigned int type;', '\tgodot_gdnative_api_version version;', '\tconst godot_gdnative_api_struct *next;', ] - + for funcdef in core['api']: args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']]) ret_val.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args)) - + ret_val += ['} godot_gdnative_core_' + '{0}_{1}'.format(core['version']['major'], core['version']['minor']) + '_api_struct;', ''] - + return ret_val @@ -171,26 +171,26 @@ def _build_gdnative_api_struct_source(api): ret_val += ['};\n'] return ret_val - - + + def get_core_struct_definition(core): ret_val = [] - + if core['next']: ret_val += get_core_struct_definition(core['next']) - + ret_val += [ 'extern const godot_gdnative_core_' + ('{0}_{1}_api_struct api_{0}_{1}'.format(core['version']['major'], core['version']['minor'])) + ' = {', '\tGDNATIVE_' + core['type'] + ',', '\t{' + str(core['version']['major']) + ', ' + str(core['version']['minor']) + '},', '\t' + ('NULL' if not core['next'] else ('(const godot_gdnative_api_struct *)& api_{0}_{1}'.format(core['version']['major'], core['version']['minor']))) + ',' ] - + for funcdef in core['api']: ret_val.append('\t%s,' % funcdef['name']) - + ret_val += ['};\n'] - + return ret_val for ext in api['extensions']: @@ -204,7 +204,7 @@ def _build_gdnative_api_struct_source(api): out += ['\t(godot_gdnative_api_struct *)&api_extension_' + name + '_struct,'] out += ['};\n'] - + if api['core']['next']: out += get_core_struct_definition(api['core']['next']) diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index 31115a4bd9..c67cf124c0 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -477,56 +477,53 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a GET_VARIANT_PTR(dst, 3); #ifdef DEBUG_ENABLED - if (a->get_type() != Variant::OBJECT || a->operator Object *() == NULL) { - - err_text = "Left operand of 'is' is not an instance of anything."; - OPCODE_BREAK; - } if (b->get_type() != Variant::OBJECT || b->operator Object *() == NULL) { err_text = "Right operand of 'is' is not a class."; OPCODE_BREAK; } #endif - Object *obj_A = *a; - Object *obj_B = *b; - - GDScript *scr_B = Object::cast_to<GDScript>(obj_B); bool extends_ok = false; + if (a->get_type() == Variant::OBJECT && a->operator Object *() != NULL) { + Object *obj_A = *a; + Object *obj_B = *b; - if (scr_B) { - //if B is a script, the only valid condition is that A has an instance which inherits from the script - //in other situation, this shoul return false. + GDScript *scr_B = Object::cast_to<GDScript>(obj_B); - if (obj_A->get_script_instance() && obj_A->get_script_instance()->get_language() == GDScriptLanguage::get_singleton()) { + if (scr_B) { + //if B is a script, the only valid condition is that A has an instance which inherits from the script + //in other situation, this shoul return false. - GDScript *cmp = static_cast<GDScript *>(obj_A->get_script_instance()->get_script().ptr()); - //bool found=false; - while (cmp) { + if (obj_A->get_script_instance() && obj_A->get_script_instance()->get_language() == GDScriptLanguage::get_singleton()) { - if (cmp == scr_B) { - //inherits from script, all ok - extends_ok = true; - break; - } + GDScript *cmp = static_cast<GDScript *>(obj_A->get_script_instance()->get_script().ptr()); + //bool found=false; + while (cmp) { - cmp = cmp->_base; + if (cmp == scr_B) { + //inherits from script, all ok + extends_ok = true; + break; + } + + cmp = cmp->_base; + } } - } - } else { + } else { - GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(obj_B); + GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(obj_B); #ifdef DEBUG_ENABLED - if (!nc) { + if (!nc) { - err_text = "Right operand of 'is' is not a class (type: '" + obj_B->get_class() + "')."; - OPCODE_BREAK; - } + err_text = "Right operand of 'is' is not a class (type: '" + obj_B->get_class() + "')."; + OPCODE_BREAK; + } #endif - extends_ok = ClassDB::is_parent_class(obj_A->get_class_name(), nc->get_name()); + extends_ok = ClassDB::is_parent_class(obj_A->get_class_name(), nc->get_name()); + } } *dst = extends_ok; diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 09b3a5631f..a4bda42b16 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -6432,6 +6432,10 @@ bool GDScriptParser::_get_function_signature(DataType &p_base_type, const String StringName native; if (p_base_type.kind == DataType::GDSCRIPT) { base_gdscript = p_base_type.script_type; + if (base_gdscript.is_null() || !base_gdscript->is_valid()) { + // GDScript wasn't properly compíled, don't bother trying + return false; + } } else if (p_base_type.kind == DataType::SCRIPT) { base_script = p_base_type.script_type; } else if (p_base_type.kind == DataType::NATIVE) { @@ -6472,6 +6476,12 @@ bool GDScriptParser::_get_function_signature(DataType &p_base_type, const String base_script = base_script->get_base_script(); } + if (native == StringName()) { + // Empty native class, might happen in some Script implementations + // Just ignore it + return false; + } + #ifdef DEBUG_METHODS_ENABLED // Only native remains @@ -6914,6 +6924,10 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN Ref<GDScript> gds; if (base_type.kind == DataType::GDSCRIPT) { gds = base_type.script_type; + if (gds.is_null() || !gds->is_valid()) { + // GDScript wasn't properly compíled, don't bother trying + return false; + } } Ref<Script> scr; @@ -6976,6 +6990,12 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN scr = scr->get_base_script(); } + if (native == StringName()) { + // Empty native class, might happen in some Script implementations + // Just ignore it + return false; + } + // Check ClassDB if (!ClassDB::class_exists(native)) { native = "_" + native.operator String(); diff --git a/modules/mono/glue/Managed/Files/AABB.cs b/modules/mono/glue/Managed/Files/AABB.cs index 66490b5e25..33b2b46712 100644 --- a/modules/mono/glue/Managed/Files/AABB.cs +++ b/modules/mono/glue/Managed/Files/AABB.cs @@ -407,8 +407,8 @@ namespace Godot return new AABB(min, max - min); } - - // Constructors + + // Constructors public AABB(Vector3 position, Vector3 size) { _position = position; diff --git a/modules/mono/glue/Managed/Files/Basis.cs b/modules/mono/glue/Managed/Files/Basis.cs index a5618cb28d..54d2813abf 100644 --- a/modules/mono/glue/Managed/Files/Basis.cs +++ b/modules/mono/glue/Managed/Files/Basis.cs @@ -410,10 +410,12 @@ namespace Godot ); } - public Quat Quat() { + public Quat Quat() + { real_t trace = _x[0] + _y[1] + _z[2]; - if (trace > 0.0f) { + if (trace > 0.0f) + { real_t s = Mathf.Sqrt(trace + 1.0f) * 2f; real_t inv_s = 1f / s; return new Quat( @@ -424,7 +426,8 @@ namespace Godot ); } - if (_x[0] > _y[1] && _x[0] > _z[2]) { + if (_x[0] > _y[1] && _x[0] > _z[2]) + { real_t s = Mathf.Sqrt(_x[0] - _y[1] - _z[2] + 1.0f) * 2f; real_t inv_s = 1f / s; return new Quat( @@ -435,7 +438,8 @@ namespace Godot ); } - if (_y[1] > _z[2]) { + if (_y[1] > _z[2]) + { real_t s = Mathf.Sqrt(-_x[0] + _y[1] - _z[2] + 1.0f) * 2f; real_t inv_s = 1f / s; return new Quat( @@ -444,7 +448,9 @@ namespace Godot (_y[2] + _z[1]) * inv_s, (_x[2] - _z[0]) * inv_s ); - } else { + } + else + { real_t s = Mathf.Sqrt(-_x[0] - _y[1] + _z[2] + 1.0f) * 2f; real_t inv_s = 1f / s; return new Quat( @@ -502,8 +508,8 @@ namespace Godot { var axis_sq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z); - real_t cosine = Mathf.Cos( phi); - real_t sine = Mathf.Sin( phi); + real_t cosine = Mathf.Cos(phi); + real_t sine = Mathf.Sin(phi); _x = new Vector3 ( @@ -529,9 +535,9 @@ namespace Godot public Basis(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis) { - _x = xAxis; - _y = yAxis; - _z = zAxis; + x = xAxis; + y = yAxis; + z = zAxis; } public Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) diff --git a/modules/mono/glue/Managed/Files/Color.cs b/modules/mono/glue/Managed/Files/Color.cs index 88cb8524b8..fc5bb010a9 100644 --- a/modules/mono/glue/Managed/Files/Color.cs +++ b/modules/mono/glue/Managed/Files/Color.cs @@ -379,8 +379,8 @@ namespace Godot return txt; } - - // Constructors + + // Constructors public Color(float r, float g, float b, float a = 1.0f) { this.r = r; diff --git a/modules/mono/glue/Managed/Files/Mathf.cs b/modules/mono/glue/Managed/Files/Mathf.cs index a89dfe5f27..dcab3c1ffc 100644 --- a/modules/mono/glue/Managed/Files/Mathf.cs +++ b/modules/mono/glue/Managed/Files/Mathf.cs @@ -206,7 +206,7 @@ namespace Godot public static real_t PosMod(real_t a, real_t b) { real_t c = a % b; - if ((c < 0 && b > 0) || (c > 0 && b < 0)) + if ((c < 0 && b > 0) || (c > 0 && b < 0)) { c += b; } @@ -219,7 +219,7 @@ namespace Godot public static int PosMod(int a, int b) { int c = a % b; - if ((c < 0 && b > 0) || (c > 0 && b < 0)) + if ((c < 0 && b > 0) || (c > 0 && b < 0)) { c += b; } diff --git a/modules/mono/glue/Managed/Files/MathfEx.cs b/modules/mono/glue/Managed/Files/MathfEx.cs index 739b7fb568..2ef02cc288 100644 --- a/modules/mono/glue/Managed/Files/MathfEx.cs +++ b/modules/mono/glue/Managed/Files/MathfEx.cs @@ -29,7 +29,7 @@ namespace Godot public static int FloorToInt(real_t s) { return (int)Math.Floor(s); - } + } public static int RoundToInt(real_t s) { diff --git a/modules/mono/glue/Managed/Files/Plane.cs b/modules/mono/glue/Managed/Files/Plane.cs index 9611dce11e..f11cd490a9 100644 --- a/modules/mono/glue/Managed/Files/Plane.cs +++ b/modules/mono/glue/Managed/Files/Plane.cs @@ -144,7 +144,7 @@ namespace Godot { return point - _normal * DistanceTo(point); } - + // Constants private static readonly Plane _planeYZ = new Plane(1, 0, 0, 0); private static readonly Plane _planeXZ = new Plane(0, 1, 0, 0); @@ -153,8 +153,8 @@ namespace Godot public static Plane PlaneYZ { get { return _planeYZ; } } public static Plane PlaneXZ { get { return _planeXZ; } } public static Plane PlaneXY { get { return _planeXY; } } - - // Constructors + + // Constructors public Plane(real_t a, real_t b, real_t c, real_t d) { _normal = new Vector3(a, b, c); diff --git a/modules/mono/glue/Managed/Files/Quat.cs b/modules/mono/glue/Managed/Files/Quat.cs index eaa027eb69..fd1ac01083 100644 --- a/modules/mono/glue/Managed/Files/Quat.cs +++ b/modules/mono/glue/Managed/Files/Quat.cs @@ -202,7 +202,7 @@ namespace Godot // Static Readonly Properties public static Quat Identity { get; } = new Quat(0f, 0f, 0f, 1f); - // Constructors + // Constructors public Quat(real_t x, real_t y, real_t z, real_t w) { this.x = x; diff --git a/modules/mono/glue/Managed/Files/Rect2.cs b/modules/mono/glue/Managed/Files/Rect2.cs index cb25c267bc..888f300347 100644 --- a/modules/mono/glue/Managed/Files/Rect2.cs +++ b/modules/mono/glue/Managed/Files/Rect2.cs @@ -182,8 +182,8 @@ namespace Godot return newRect; } - - // Constructors + + // Constructors public Rect2(Vector2 position, Vector2 size) { _position = position; diff --git a/modules/mono/glue/Managed/Files/StringExtensions.cs b/modules/mono/glue/Managed/Files/StringExtensions.cs index 21c9be98c1..c194facd0b 100644 --- a/modules/mono/glue/Managed/Files/StringExtensions.cs +++ b/modules/mono/glue/Managed/Files/StringExtensions.cs @@ -185,7 +185,7 @@ namespace Godot int instanceIndex = 0; int toIndex = 0; - + if (caseSensitive) // Outside while loop to avoid checking multiple times, despite some code duplication. { while (true) @@ -480,9 +480,9 @@ namespace Godot return false; // Don't start with number plz } - bool validChar = instance[i] >= '0' && - instance[i] <= '9' || instance[i] >= 'a' && - instance[i] <= 'z' || instance[i] >= 'A' && + bool validChar = instance[i] >= '0' && + instance[i] <= '9' || instance[i] >= 'a' && + instance[i] <= 'z' || instance[i] >= 'A' && instance[i] <= 'Z' || instance[i] == '_'; if (!validChar) diff --git a/modules/mono/glue/Managed/Files/Transform.cs b/modules/mono/glue/Managed/Files/Transform.cs index 068007d7f0..687ed8f011 100644 --- a/modules/mono/glue/Managed/Files/Transform.cs +++ b/modules/mono/glue/Managed/Files/Transform.cs @@ -133,7 +133,7 @@ namespace Godot public static Transform FlipY { get { return _flipY; } } public static Transform FlipZ { get { return _flipZ; } } - // Constructors + // Constructors public Transform(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis, Vector3 origin) { basis = Basis.CreateFromAxes(xAxis, yAxis, zAxis); diff --git a/modules/mono/glue/Managed/Files/Transform2D.cs b/modules/mono/glue/Managed/Files/Transform2D.cs index 8d30833066..c9e5b560b2 100644 --- a/modules/mono/glue/Managed/Files/Transform2D.cs +++ b/modules/mono/glue/Managed/Files/Transform2D.cs @@ -261,15 +261,15 @@ namespace Godot public static Transform2D Identity { get { return _identity; } } public static Transform2D FlipX { get { return _flipX; } } public static Transform2D FlipY { get { return _flipY; } } - - // Constructors + + // Constructors public Transform2D(Vector2 xAxis, Vector2 yAxis, Vector2 origin) { x = xAxis; y = yAxis; o = origin; } - + public Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) { x = new Vector2(xx, xy); diff --git a/modules/mono/glue/Managed/Files/Vector2.cs b/modules/mono/glue/Managed/Files/Vector2.cs index 080b8802ba..ce41886bfc 100644 --- a/modules/mono/glue/Managed/Files/Vector2.cs +++ b/modules/mono/glue/Managed/Files/Vector2.cs @@ -215,7 +215,7 @@ namespace Godot x = v.x; y = v.y; } - + public Vector2 Slerp(Vector2 b, real_t t) { real_t theta = AngleTo(b); @@ -242,7 +242,7 @@ namespace Godot private static readonly Vector2 _one = new Vector2(1, 1); private static readonly Vector2 _negOne = new Vector2(-1, -1); private static readonly Vector2 _inf = new Vector2(Mathf.Inf, Mathf.Inf); - + private static readonly Vector2 _up = new Vector2(0, -1); private static readonly Vector2 _down = new Vector2(0, 1); private static readonly Vector2 _right = new Vector2(1, 0); diff --git a/modules/mono/glue/Managed/Files/Vector3.cs b/modules/mono/glue/Managed/Files/Vector3.cs index 6fffe5e4d6..8e62ec778d 100644 --- a/modules/mono/glue/Managed/Files/Vector3.cs +++ b/modules/mono/glue/Managed/Files/Vector3.cs @@ -276,13 +276,13 @@ namespace Godot 0f, 0f, z ); } - + // Constants private static readonly Vector3 _zero = new Vector3(0, 0, 0); private static readonly Vector3 _one = new Vector3(1, 1, 1); private static readonly Vector3 _negOne = new Vector3(-1, -1, -1); private static readonly Vector3 _inf = new Vector3(Mathf.Inf, Mathf.Inf, Mathf.Inf); - + private static readonly Vector3 _up = new Vector3(0, 1, 0); private static readonly Vector3 _down = new Vector3(0, -1, 0); private static readonly Vector3 _right = new Vector3(1, 0, 0); @@ -294,7 +294,7 @@ namespace Godot public static Vector3 One { get { return _one; } } public static Vector3 NegOne { get { return _negOne; } } public static Vector3 Inf { get { return _inf; } } - + public static Vector3 Up { get { return _up; } } public static Vector3 Down { get { return _down; } } public static Vector3 Right { get { return _right; } } diff --git a/modules/mono/glue/Managed/Properties/AssemblyInfo.cs b/modules/mono/glue/Managed/Properties/AssemblyInfo.cs index 7ed68acad7..77b3774e81 100644 --- a/modules/mono/glue/Managed/Properties/AssemblyInfo.cs +++ b/modules/mono/glue/Managed/Properties/AssemblyInfo.cs @@ -1,7 +1,7 @@ using System.Reflection; using System.Runtime.CompilerServices; -// Information about this assembly is defined by the following attributes. +// Information about this assembly is defined by the following attributes. // Change them to the values specific to your project. [assembly: AssemblyTitle("Managed")] @@ -19,7 +19,7 @@ using System.Runtime.CompilerServices; [assembly: AssemblyVersion("1.0.*")] -// The following attributes are used to specify the signing key for the assembly, +// The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. //[assembly: AssemblyDelaySign(false)] diff --git a/modules/squish/image_compress_squish.cpp b/modules/squish/image_compress_squish.cpp index 26cb76011c..a08ac7bd28 100644 --- a/modules/squish/image_compress_squish.cpp +++ b/modules/squish/image_compress_squish.cpp @@ -64,12 +64,13 @@ void image_decompress_squish(Image *p_image) { return; } - int dst_ofs = 0; - for (int i = 0; i <= mm_count; i++) { int src_ofs = 0, mipmap_size = 0, mipmap_w = 0, mipmap_h = 0; p_image->get_mipmap_offset_size_and_dimensions(i, src_ofs, mipmap_size, mipmap_w, mipmap_h); - squish::DecompressImage(&wb[dst_ofs], mipmap_w, mipmap_h, &rb[src_ofs], squish_flags); + int dst_ofs = Image::get_image_mipmap_offset(p_image->get_width(), p_image->get_height(), target_format, i); + squish::DecompressImage(&wb[dst_ofs], w, h, &rb[src_ofs], squish_flags); + w >>= 1; + h >>= 1; } p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data); diff --git a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml index b8e77a1b0f..ff3ed66e81 100644 --- a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml +++ b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml @@ -125,12 +125,10 @@ </argument> <description> Execute the custom node's logic, returning the index of the output sequence port to use or a [String] when there is an error. - The [code]inputs[/code] array contains the values of the input ports. [code]outputs[/code] is an array whose indices should be set to the respective outputs. The [code]start_mode[/code] is usually [code]START_MODE_BEGIN_SEQUENCE[/code], unless you have used the STEP_* constants. [code]working_mem[/code] is an array which can be used to persist information between runs of the custom node. - When returning, you can mask the returned value with one of the STEP_* constants. </description> </method> |