Fleshed out samplers, segments, and the rail graph.
This commit is contained in:
parent
98e8cc418b
commit
600fd0c276
12 changed files with 1783 additions and 0 deletions
136
src/rail_segment.rs
Normal file
136
src/rail_segment.rs
Normal file
|
@ -0,0 +1,136 @@
|
|||
use crate::prelude::*;
|
||||
use crate::rail_connector::RailConnector;
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::iter::Iterator;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
IndexError,
|
||||
EndpointError,
|
||||
OffsetError,
|
||||
NeighborError,
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::IndexError => write!(f, "Nonexistent internal curve index"),
|
||||
Self::EndpointError => write!(f, "Nonexistent endpoint index"),
|
||||
Self::OffsetError => write!(f, "Invalid offset"),
|
||||
Self::NeighborError => write!(f, "Invalid Neighbor"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {}
|
||||
|
||||
pub struct ConnectionIter<'a> {
|
||||
segment: &'a dyn RailSegment,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<'a> ConnectionIter<'a> {
|
||||
pub fn new(segment: &'a impl RailSegment) -> Self {
|
||||
Self {
|
||||
segment,
|
||||
index: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for ConnectionIter<'a> {
|
||||
type Item = &'a RailConnector;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
while self.index < self.segment.num_endpoints() {
|
||||
if let Ok(connection) = self.segment.borrow_connection(self.index) {
|
||||
self.index += 1;
|
||||
return Some(connection);
|
||||
} else {
|
||||
self.index += 1;
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
/** A RailSegment represents a section of track.
|
||||
* They contain at least one internal curve which is addressibe via an integer
|
||||
* index. Valid indecies start at 0, though a negative index may be used to
|
||||
* indicate that a point does not exist on any internal curve. Offsets are in
|
||||
* Godot units (which shall be interpreted as meters).
|
||||
*/
|
||||
pub trait RailSegment {
|
||||
|
||||
/** Get the overall length of the internal curve represented by the given
|
||||
* `index`.
|
||||
*/
|
||||
fn get_length(&self, index: usize) -> Result<f32, Error>;
|
||||
|
||||
/** Get the location defined by the given `offset` on the internal curve
|
||||
* represented by the given `index`.
|
||||
*/
|
||||
fn sample(&self, index: usize, offset: f32) -> Result<Vector3, Error>;
|
||||
|
||||
/** Get the location defined by the given `offset` on the internal curve
|
||||
* represented by the given `index`, but with additional rotation data.
|
||||
*/
|
||||
fn sample_with_rotation(&self, index: usize, offset: f32) -> Result<Transform3D, Error>;
|
||||
|
||||
/** Similar to sample_with_rotation, but the rotation is facing the opposite direction.
|
||||
*/
|
||||
fn sample_with_rotation_reverse(&self, index: usize, offset: f32) -> Result<Transform3D, Error>;
|
||||
|
||||
/** Get the direction that constitutes "up" for the given `offset` on the
|
||||
* internal curve represented by the given `index`.
|
||||
*/
|
||||
fn sample_up_vector(&self, index: usize, offset: f32) -> Result<Vector3, Error>;
|
||||
|
||||
// endpoint functions
|
||||
|
||||
/** Get the segment index associated with an endpoint. */
|
||||
fn segment_from_endpoint(&self, endpoint: usize) -> Result<usize, Error>;
|
||||
|
||||
/** Get the location of an endpoint. */
|
||||
fn get_endpoint_transform(&self, endpoint: usize) -> Result<Transform3D, Error>;
|
||||
|
||||
/** Get whether an endpoint represents the upper or lower end of a segment. */
|
||||
fn is_endpoint_upper(&self, endpoint: usize) -> Result<bool, Error>;
|
||||
|
||||
/** Get the number of endpoins this segment has. */
|
||||
fn num_endpoints(&self) -> usize;
|
||||
|
||||
// connection functions
|
||||
|
||||
/** Borrow the connector associated with the given endpoint. */
|
||||
fn borrow_connection(&self, endpoint: usize) -> Result<&RailConnector, Error>;
|
||||
|
||||
/** Check if a connection is established on the given endpoint. */
|
||||
fn check_connection(&self, endpoint: usize) -> Result<bool, Error>;
|
||||
|
||||
/** Get an iterator of the connections on this segment.
|
||||
* If an endpoint is not connected, then it will not be represented by this iterator.
|
||||
* This iterator keeps an immutable reference to the segment from which it was created.
|
||||
*/
|
||||
fn connection_iter(&self) -> ConnectionIter;
|
||||
|
||||
/** Add a connection to the given endpoint.
|
||||
* Any previous connection on it is overwritten.
|
||||
*/
|
||||
fn add_connection(&mut self, endpoint: usize, connector: RailConnector) -> Result<bool, Error>;
|
||||
|
||||
/** Remove the given endpoint's connection if it has one. */
|
||||
fn remove_connection(&mut self, endpoint: usize) -> Result<bool, Error>;
|
||||
|
||||
/** Remove all connections from the segment. */
|
||||
fn remove_all_connections(&mut self);
|
||||
|
||||
// internal variable state functions
|
||||
|
||||
/** Get the internal state float value. */
|
||||
fn get_state(&self) -> f32;
|
||||
|
||||
/** Set the internal state float value. */
|
||||
fn set_state(&mut self, value: f32);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue