-
Notifications
You must be signed in to change notification settings - Fork 76
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adds PhysicsDirectSpaceState3D.IntersectRayResult and tests (#321)
* adds PhysicsDirectSpaceState3D.IntersectRayResult and tests * Update Sources/SwiftGodot/Extensions/PhysicsDirectSpaceState3D+IntersectRayResult.swift * Update Sources/SwiftGodot/Extensions/PhysicsDirectSpaceState3D+IntersectRayResult.swift * Update Sources/SwiftGodot/Extensions/PhysicsDirectSpaceState3D+IntersectRayResult.swift * Update Sources/SwiftGodot/Extensions/PhysicsDirectSpaceState3D+IntersectRayResult.swift * Update PhysicsDirectSpaceState3D+IntersectRayResult.swift Documented fields. --------- Co-authored-by: Miguel de Icaza <[email protected]>
- Loading branch information
1 parent
372692c
commit 96b2f63
Showing
2 changed files
with
131 additions
and
0 deletions.
There are no files selected for viewing
73 changes: 73 additions & 0 deletions
73
Sources/SwiftGodot/Extensions/PhysicsDirectSpaceState3D+IntersectRayResult.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// | ||
// PhysicsDirectSpaceState3D+IntersectRayResult | ||
// | ||
// | ||
// Created by Estevan Hernandez on 12/24/23. | ||
// | ||
|
||
private extension GDictionary { | ||
func makeOrUnwrap<T: VariantStorable>(key: String) -> T? { | ||
guard let variant = self[key] else { | ||
GD.pushWarning("There was no Variant for key: \(key)") | ||
return nil | ||
} | ||
guard let result = T.makeOrUnwrap(variant) else { | ||
GD.pushWarning("\(T.self).makeOrUnwrap(\(variant)) was nil") | ||
return nil | ||
} | ||
|
||
return result | ||
} | ||
} | ||
|
||
extension PhysicsDirectSpaceState3D { | ||
/// Result from intersecting a ray | ||
public struct IntersectRayResult<T: Object> { | ||
/// The intersection point | ||
public let position: Vector3 | ||
/// The object's surface normal at the intersection point, or `Vector3(x: 0, y: 0, z: 0)` if the ray starts inside the shape and `PhysicsRayQueryParameters3D.hitFromInside` is true. | ||
public let normal: Vector3 | ||
/// The colliding object | ||
public let collider: T | ||
/// The colliding object's ID. | ||
public let colliderId: Int | ||
/// The The intersecting object's ``RID``. | ||
public let rid: RID | ||
/// The shape index of the colliding shape. | ||
public let shape: Int | ||
/// The metadata value from the dictionary. | ||
public let metadata: Variant? | ||
/// The face index at the intersection point. | ||
public let faceIndex: Int | ||
|
||
init?(_ dictionary: GDictionary) { | ||
guard dictionary.isEmpty() == false, | ||
let position: Vector3 = dictionary.makeOrUnwrap(key: "position"), | ||
let normal: Vector3 = dictionary.makeOrUnwrap(key: "normal"), | ||
let colliderVariant = dictionary["collider"], | ||
let collider = T.makeOrUnwrap(colliderVariant), | ||
let colliderId: Int = dictionary.makeOrUnwrap(key: "collider_id"), | ||
let rid: RID = dictionary.makeOrUnwrap(key: "rid"), | ||
let shape: Int = dictionary.makeOrUnwrap(key: "shape"), | ||
let faceIndex: Int = dictionary.makeOrUnwrap(key: "face_index") else { | ||
return nil | ||
} | ||
self.position = position | ||
self.normal = normal | ||
self.collider = collider | ||
self.colliderId = colliderId | ||
self.rid = rid | ||
self.shape = shape | ||
self.faceIndex = faceIndex | ||
self.metadata = dictionary["metadata"] | ||
} | ||
} | ||
} | ||
|
||
extension PhysicsDirectSpaceState3D { | ||
/// Intersects a ray in a given space. Ray position and other parameters are defined through `PhysicsRayQueryParameters3D` The return value is an `IntersectRayResult<T>?` where `T` is any Godot `Object`, however if the ray did not intersect anything, or the intersecting collider was not of type `T` then a nil object is returned instead. Usually `T` is a physics object such as `StaticBody` for example but it could also be a `GridMap` if the `mesh_library` has collisions. | ||
public func intersectRay<T: Object>(_ type: T.Type = T.self, parameters: PhysicsRayQueryParameters3D) -> IntersectRayResult<T>? { | ||
let dictionary: GDictionary = intersectRay(parameters: parameters) | ||
return IntersectRayResult<T>(dictionary) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// | ||
// IntersectRayResultTests.swift | ||
// SwiftGodotTests | ||
// | ||
// Created by Estevan Hernandez on 12/24/23. | ||
// | ||
|
||
import XCTest | ||
import SwiftGodotTestability | ||
@testable import SwiftGodot | ||
|
||
final class IntersectRayResultTests: GodotTestCase { | ||
func testIntersectRayResultPropertiesMatchDictionary_whenAllPropertiesPresent() throws { | ||
let collider: Object = GridMap() | ||
|
||
let dictionary: GDictionary = { | ||
let dictionary = GDictionary() | ||
dictionary["position"] = Variant(Vector3(x: 1, y: 2, z: 3)) | ||
dictionary["normal"] = Variant(Vector3(x: 4, y: 5, z: 6)) | ||
dictionary["collider"] = Variant(collider) | ||
dictionary["collider_id"] = Variant(collider.id) | ||
dictionary["rid"] = Variant(RID()) | ||
dictionary["shape"] = Variant(22) | ||
dictionary["face_index"] = Variant(44) | ||
return dictionary | ||
}() | ||
|
||
let result = try XCTUnwrap(PhysicsDirectSpaceState3D.IntersectRayResult<GridMap>(dictionary)) | ||
|
||
XCTAssertEqual(result.position, Vector3(x: 1, y: 2, z: 3)) | ||
XCTAssertEqual(result.normal, Vector3(x: 4, y: 5, z: 6)) | ||
XCTAssertEqual(result.collider, collider) | ||
XCTAssertEqual(result.colliderId, collider.id) | ||
XCTAssertEqual(result.rid, RID()) | ||
XCTAssertEqual(result.shape, 22) | ||
XCTAssertEqual(result.faceIndex, 44) | ||
} | ||
|
||
func testIntersectRayResultIsNil_whenColliderPropertyIsMissing() { | ||
let collider: Object = GridMap() | ||
|
||
let dictionary: GDictionary = { | ||
let dictionary = GDictionary() | ||
dictionary["position"] = Variant(Vector3(x: 1, y: 2, z: 3)) | ||
dictionary["normal"] = Variant(Vector3(x: 4, y: 5, z: 6)) | ||
// dictionary["collider"] = Variant(collider) | ||
dictionary["collider_id"] = Variant(collider.id) | ||
dictionary["rid"] = Variant(RID()) | ||
dictionary["shape"] = Variant(22) | ||
dictionary["face_index"] = Variant(44) | ||
return dictionary | ||
}() | ||
|
||
let result = PhysicsDirectSpaceState3D.IntersectRayResult<GridMap>(dictionary) | ||
|
||
XCTAssertNil(result) | ||
} | ||
} |