Parcourir la source

Add mid height property to CapsuleShape2D/3D

Aaron Franke il y a 1 an
Parent
commit
9f38cfe3ca

+ 4 - 1
doc/classes/CapsuleShape2D.xml

@@ -11,7 +11,10 @@
 	</tutorials>
 	<members>
 		<member name="height" type="float" setter="set_height" getter="get_height" default="30.0">
-			The capsule's height.
+			The capsule's full height, including the semicircles.
+		</member>
+		<member name="mid_height" type="float" setter="set_mid_height" getter="get_mid_height">
+			The capsule's height, excluding the semicircles. This is the height of the central rectangular part in the middle of the capsule, and is the distance between the centers of the two semicircles. This is a wrapper for [member height].
 		</member>
 		<member name="radius" type="float" setter="set_radius" getter="get_radius" default="10.0">
 			The capsule's radius.

+ 4 - 1
doc/classes/CapsuleShape3D.xml

@@ -12,7 +12,10 @@
 	</tutorials>
 	<members>
 		<member name="height" type="float" setter="set_height" getter="get_height" default="2.0">
-			The capsule's height.
+			The capsule's full height, including the hemispheres.
+		</member>
+		<member name="mid_height" type="float" setter="set_mid_height" getter="get_mid_height">
+			The capsule's height, excluding the hemispheres. This is the height of the central cylindrical part in the middle of the capsule, and is the distance between the centers of the two hemispheres. This is a wrapper for [member height].
 		</member>
 		<member name="radius" type="float" setter="set_radius" getter="get_radius" default="0.5">
 			The capsule's radius.

+ 4 - 1
doc/classes/SpringBoneCollisionCapsule3D.xml

@@ -10,11 +10,14 @@
 	</tutorials>
 	<members>
 		<member name="height" type="float" setter="set_height" getter="get_height" default="0.5">
-			The capsule's height.
+			The capsule's full height, including the hemispheres.
 		</member>
 		<member name="inside" type="bool" setter="set_inside" getter="is_inside" default="false">
 			If [code]true[/code], the collision acts to trap the joint within the collision.
 		</member>
+		<member name="mid_height" type="float" setter="set_mid_height" getter="get_mid_height">
+			The capsule's height, excluding the hemispheres. This is the height of the central cylindrical part in the middle of the capsule, and is the distance between the centers of the two hemispheres. This is a wrapper for [member height].
+		</member>
 		<member name="radius" type="float" setter="set_radius" getter="get_radius" default="0.1">
 			The capsule's radius.
 		</member>

+ 15 - 0
scene/3d/spring_bone_collision_capsule_3d.cpp

@@ -60,6 +60,18 @@ float SpringBoneCollisionCapsule3D::get_height() const {
 	return height;
 }
 
+void SpringBoneCollisionCapsule3D::set_mid_height(real_t p_mid_height) {
+	ERR_FAIL_COND_MSG(p_mid_height < 0.0f, "SpringBoneCollisionCapsule3D mid-height cannot be negative.");
+	height = p_mid_height + radius * 2.0f;
+#ifdef TOOLS_ENABLED
+	update_gizmos();
+#endif // TOOLS_ENABLED
+}
+
+real_t SpringBoneCollisionCapsule3D::get_mid_height() const {
+	return height - radius * 2.0f;
+}
+
 void SpringBoneCollisionCapsule3D::set_inside(bool p_enabled) {
 	inside = p_enabled;
 #ifdef TOOLS_ENABLED
@@ -83,11 +95,14 @@ void SpringBoneCollisionCapsule3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_radius"), &SpringBoneCollisionCapsule3D::get_radius);
 	ClassDB::bind_method(D_METHOD("set_height", "height"), &SpringBoneCollisionCapsule3D::set_height);
 	ClassDB::bind_method(D_METHOD("get_height"), &SpringBoneCollisionCapsule3D::get_height);
+	ClassDB::bind_method(D_METHOD("set_mid_height", "mid_height"), &SpringBoneCollisionCapsule3D::set_mid_height);
+	ClassDB::bind_method(D_METHOD("get_mid_height"), &SpringBoneCollisionCapsule3D::get_mid_height);
 	ClassDB::bind_method(D_METHOD("set_inside", "enabled"), &SpringBoneCollisionCapsule3D::set_inside);
 	ClassDB::bind_method(D_METHOD("is_inside"), &SpringBoneCollisionCapsule3D::is_inside);
 
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0,1,0.001,or_greater,suffix:m"), "set_radius", "get_radius");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0,1,0.001,or_greater,suffix:m"), "set_height", "get_height");
+	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mid_height", PROPERTY_HINT_RANGE, "0,1,0.001,or_greater,suffix:m", PROPERTY_USAGE_NONE), "set_mid_height", "get_mid_height");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "inside"), "set_inside", "is_inside");
 }
 

+ 2 - 0
scene/3d/spring_bone_collision_capsule_3d.h

@@ -49,6 +49,8 @@ public:
 	float get_radius() const;
 	void set_height(float p_height);
 	float get_height() const;
+	void set_mid_height(real_t p_mid_height);
+	real_t get_mid_height() const;
 	void set_inside(bool p_enabled);
 	bool is_inside() const;
 

+ 25 - 11
scene/resources/2d/capsule_shape_2d.cpp

@@ -38,7 +38,7 @@ Vector<Vector2> CapsuleShape2D::_get_points() const {
 	Vector<Vector2> points;
 	const real_t turn_step = Math::TAU / 24.0;
 	for (int i = 0; i < 24; i++) {
-		Vector2 ofs = Vector2(0, (i > 6 && i <= 18) ? -height * 0.5 + radius : height * 0.5 - radius);
+		Vector2 ofs = Vector2(0, (i > 6 && i <= 18) ? -height * 0.5f + radius : height * 0.5f - radius);
 
 		points.push_back(Vector2(Math::sin(i * turn_step), Math::cos(i * turn_step)) * radius + ofs);
 		if (i == 6 || i == 18) {
@@ -59,13 +59,13 @@ void CapsuleShape2D::_update_shape() {
 }
 
 void CapsuleShape2D::set_radius(real_t p_radius) {
-	ERR_FAIL_COND_MSG(p_radius < 0, "CapsuleShape2D radius cannot be negative.");
+	ERR_FAIL_COND_MSG(p_radius < 0.0f, "CapsuleShape2D radius cannot be negative.");
 	if (radius == p_radius) {
 		return;
 	}
 	radius = p_radius;
-	if (radius > height * 0.5) {
-		height = radius * 2.0;
+	if (height < radius * 2.0f) {
+		height = radius * 2.0f;
 	}
 	_update_shape();
 }
@@ -75,13 +75,13 @@ real_t CapsuleShape2D::get_radius() const {
 }
 
 void CapsuleShape2D::set_height(real_t p_height) {
-	ERR_FAIL_COND_MSG(p_height < 0, "CapsuleShape2D height cannot be negative.");
+	ERR_FAIL_COND_MSG(p_height < 0.0f, "CapsuleShape2D height cannot be negative.");
 	if (height == p_height) {
 		return;
 	}
 	height = p_height;
-	if (radius > height * 0.5) {
-		radius = height * 0.5;
+	if (radius > height * 0.5f) {
+		radius = height * 0.5f;
 	}
 	_update_shape();
 }
@@ -90,6 +90,16 @@ real_t CapsuleShape2D::get_height() const {
 	return height;
 }
 
+void CapsuleShape2D::set_mid_height(real_t p_mid_height) {
+	ERR_FAIL_COND_MSG(p_mid_height < 0.0f, "CapsuleShape2D mid-height cannot be negative.");
+	height = p_mid_height + radius * 2.0f;
+	_update_shape();
+}
+
+real_t CapsuleShape2D::get_mid_height() const {
+	return height - radius * 2.0f;
+}
+
 void CapsuleShape2D::draw(const RID &p_to_rid, const Color &p_color) {
 	Vector<Vector2> points = _get_points();
 	Vector<Color> col = { p_color };
@@ -97,18 +107,18 @@ void CapsuleShape2D::draw(const RID &p_to_rid, const Color &p_color) {
 
 	if (is_collision_outline_enabled()) {
 		points.push_back(points[0]);
-		col = { Color(p_color, 1.0) };
+		col = { Color(p_color, 1.0f) };
 		RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col);
 	}
 }
 
 Rect2 CapsuleShape2D::get_rect() const {
-	const Vector2 half_size = Vector2(radius, height * 0.5);
-	return Rect2(-half_size, half_size * 2.0);
+	const Vector2 half_size = Vector2(radius, height * 0.5f);
+	return Rect2(-half_size, half_size * 2.0f);
 }
 
 real_t CapsuleShape2D::get_enclosing_radius() const {
-	return height * 0.5;
+	return height * 0.5f;
 }
 
 void CapsuleShape2D::_bind_methods() {
@@ -118,8 +128,12 @@ void CapsuleShape2D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_height", "height"), &CapsuleShape2D::set_height);
 	ClassDB::bind_method(D_METHOD("get_height"), &CapsuleShape2D::get_height);
 
+	ClassDB::bind_method(D_METHOD("set_mid_height", "mid_height"), &CapsuleShape2D::set_mid_height);
+	ClassDB::bind_method(D_METHOD("get_mid_height"), &CapsuleShape2D::get_mid_height);
+
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:px"), "set_radius", "get_radius");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:px"), "set_height", "get_height");
+	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mid_height", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:px", PROPERTY_USAGE_NONE), "set_mid_height", "get_mid_height");
 	ADD_LINKED_PROPERTY("radius", "height");
 	ADD_LINKED_PROPERTY("height", "radius");
 }

+ 3 - 0
scene/resources/2d/capsule_shape_2d.h

@@ -53,6 +53,9 @@ public:
 	void set_radius(real_t p_radius);
 	real_t get_radius() const;
 
+	void set_mid_height(real_t p_mid_height);
+	real_t get_mid_height() const;
+
 	virtual void draw(const RID &p_to_rid, const Color &p_color) override;
 	virtual Rect2 get_rect() const override;
 	virtual real_t get_enclosing_radius() const override;

+ 22 - 8
scene/resources/3d/capsule_shape_3d.cpp

@@ -39,7 +39,7 @@ Vector<Vector3> CapsuleShape3D::get_debug_mesh_lines() const {
 
 	Vector<Vector3> points;
 
-	Vector3 d(0, c_height * 0.5 - c_radius, 0);
+	Vector3 d(0, c_height * 0.5f - c_radius, 0);
 	for (int i = 0; i < 360; i++) {
 		float ra = Math::deg_to_rad((float)i);
 		float rb = Math::deg_to_rad((float)i + 1);
@@ -87,7 +87,7 @@ Ref<ArrayMesh> CapsuleShape3D::get_debug_arraymesh_faces(const Color &p_modulate
 }
 
 real_t CapsuleShape3D::get_enclosing_radius() const {
-	return height * 0.5;
+	return height * 0.5f;
 }
 
 void CapsuleShape3D::_update_shape() {
@@ -99,10 +99,10 @@ void CapsuleShape3D::_update_shape() {
 }
 
 void CapsuleShape3D::set_radius(float p_radius) {
-	ERR_FAIL_COND_MSG(p_radius < 0, "CapsuleShape3D radius cannot be negative.");
+	ERR_FAIL_COND_MSG(p_radius < 0.0f, "CapsuleShape3D radius cannot be negative.");
 	radius = p_radius;
-	if (radius > height * 0.5) {
-		height = radius * 2.0;
+	if (height < radius * 2.0f) {
+		height = radius * 2.0f;
 	}
 	_update_shape();
 	emit_changed();
@@ -113,10 +113,10 @@ float CapsuleShape3D::get_radius() const {
 }
 
 void CapsuleShape3D::set_height(float p_height) {
-	ERR_FAIL_COND_MSG(p_height < 0, "CapsuleShape3D height cannot be negative.");
+	ERR_FAIL_COND_MSG(p_height < 0.0f, "CapsuleShape3D height cannot be negative.");
 	height = p_height;
-	if (radius > height * 0.5) {
-		radius = height * 0.5;
+	if (radius > height * 0.5f) {
+		radius = height * 0.5f;
 	}
 	_update_shape();
 	emit_changed();
@@ -126,14 +126,28 @@ float CapsuleShape3D::get_height() const {
 	return height;
 }
 
+void CapsuleShape3D::set_mid_height(real_t p_mid_height) {
+	ERR_FAIL_COND_MSG(p_mid_height < 0.0f, "CapsuleShape3D mid-height cannot be negative.");
+	height = p_mid_height + radius * 2.0f;
+	_update_shape();
+	emit_changed();
+}
+
+real_t CapsuleShape3D::get_mid_height() const {
+	return height - radius * 2.0f;
+}
+
 void CapsuleShape3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CapsuleShape3D::set_radius);
 	ClassDB::bind_method(D_METHOD("get_radius"), &CapsuleShape3D::get_radius);
 	ClassDB::bind_method(D_METHOD("set_height", "height"), &CapsuleShape3D::set_height);
 	ClassDB::bind_method(D_METHOD("get_height"), &CapsuleShape3D::get_height);
+	ClassDB::bind_method(D_METHOD("set_mid_height", "mid_height"), &CapsuleShape3D::set_mid_height);
+	ClassDB::bind_method(D_METHOD("get_mid_height"), &CapsuleShape3D::get_mid_height);
 
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,100,0.001,or_greater,suffix:m"), "set_radius", "get_radius");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.001,100,0.001,or_greater,suffix:m"), "set_height", "get_height");
+	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mid_height", PROPERTY_HINT_RANGE, "0.001,100,0.001,or_greater,suffix:m", PROPERTY_USAGE_NONE), "set_mid_height", "get_mid_height");
 	ADD_LINKED_PROPERTY("radius", "height");
 	ADD_LINKED_PROPERTY("height", "radius");
 }

+ 2 - 0
scene/resources/3d/capsule_shape_3d.h

@@ -49,6 +49,8 @@ public:
 	float get_radius() const;
 	void set_height(float p_height);
 	float get_height() const;
+	void set_mid_height(real_t p_mid_height);
+	real_t get_mid_height() const;
 
 	virtual Vector<Vector3> get_debug_mesh_lines() const override;
 	virtual Ref<ArrayMesh> get_debug_arraymesh_faces(const Color &p_modulate) const override;