pub fn stippled_line(
        &mut self,
        mut a: Vec2<f32>, mut b: Vec2<f32>, 
        width: f32, stipple_length: f32, stipple_spacing: f32, 
        color: Color
    ) { 
        // If we try to draw a very long stippled line this will take up a lot of memory, as each
        // small segment is a separate line. I often accidentally draw a very long line, where the
        // vast majority of it lies offscreen. This is fixed by clipping the line so we only render
        // the minimum required segments to be visible on screen.
        // This might change the apperance of the line slightly because it will shift its segments...
        if let Some(region) = self.working_clip_stack.last() {
            let hit = |pos: Vec2<f32>, dir: Vec2<f32>| -> Option<f32> {
                if region.contains(pos) {
                    return Some(0.0); 
                }

                if pos.x <= region.min.x && dir.x > 0.0 {
                    let t = (region.min.x - pos.x) / dir.x;
                    let y = pos.y + dir.y*t;
                    if t >= 0.0 && t <= 1.0 && y >= region.min.y && y <= region.max.y {
                        return Some(t);
                    }
                }
                if pos.x >= region.max.x && dir.x < 0.0 {
                    let t = (region.max.x - pos.x) / dir.x;
                    let y = pos.y + dir.y*t;
                    if t >= 0.0 && t <= 1.0 && y >= region.min.y && y <= region.max.y {
                        return Some(t);
                    }
                }

                if pos.y <= region.min.y && dir.y > 0.0 {
                    let t = (region.min.y - pos.y) / dir.y;
                    let x = pos.y + dir.y*t;
                    if t >= 0.0 && t <= 1.0 && x >= region.min.x && x <= region.max.x {
                        return Some(t);
                    }
                }
                if pos.y >= region.max.y && dir.y < 0.0 {
                    let t = (region.max.y - pos.y) / dir.y;
                    let x = pos.x + dir.x*t;
                    if t >= 0.0 && t <= 1.0 && x >= region.min.x && x <= region.max.x {
                        return Some(t);
                    }
                }

                return None;
            };

            if let Some(t) = hit(a, b - a) {
                a = Vec2::lerp(a, b, t);
            } else {
                return;
            }

            if let Some(t) = hit(b, a - b) {
                b = Vec2::lerp(b, a, t);
            } else {
                return;
            }
        }

        self.push_state_cmd(StateCmd::TextureChange(SamplerId::Solid)); 

        let len = (b - a).len(); // The length of the line
        let dir = (b - a) / len; // Unit vector from a to b

        // Just draw a single, slightly extended, segment
        if stipple_length + stipple_spacing > len {
            self.line(a, b, width, color);
        // Create a bunch of line segments, starting at the middle
        } else {
            let mut start = 0.0;
            while start < len/2.0 {
                let end = if start == 0.0 {
                    stipple_length/2.0
                } else {
                    (start + stipple_length).min(len/2.0)
                };

                self.line(a + dir*(len/2.0 + start), a + dir*(len/2.0 + end), width, color);
                self.line(a + dir*(len/2.0 - start), a + dir*(len/2.0 - end), width, color);

                start = end + stipple_spacing;
            }
        } 
    }
/// Generate the vertices for a stippled line
Generate the vertices for a stippled line
Generate the vertices for a stippled line
pub fn stippled_line(
        &mut self,
        mut a: Vec2<f32>, mut b: Vec2<f32>, 
        width: f32, stipple_length: f32, stipple_spacing: f32, 
        color: Color
    ) { 
        // If we try to draw a very long stippled line this will take up a lot of memory, as each
        // small segment is a separate line. I often accidentally draw a very long line, where the
        // vast majority of it lies offscreen. This is fixed by clipping the line so we only render
        // the minimum required segments to be visible on screen.
        // This might change the apperance of the line slightly because it will shift its segments...
        if let Some(region) = self.working_clip_stack.last() {
            let hit = |pos: Vec2<f32>, dir: Vec2<f32>| -> Option<f32> {
                if region.contains(pos) {
                    return Some(0.0); 
                }
                if pos.x <= region.min.x && dir.x > 0.0 {
                    let t = (region.min.x - pos.x) / dir.x;
                    let y = pos.y + dir.y*t;
                    if t >= 0.0 && t <= 1.0 && y >= region.min.y && y <= region.max.y {
                        return Some(t);
                    }
                }
                if pos.x >= region.max.x && dir.x < 0.0 {
                    let t = (region.max.x - pos.x) / dir.x;
                    let y = pos.y + dir.y*t;
                    if t >= 0.0 && t <= 1.0 && y >= region.min.y && y <= region.max.y {
                        return Some(t);
                    }
                }
                if pos.y <= region.min.y && dir.y > 0.0 {
                    let t = (region.min.y - pos.y) / dir.y;
                    let x = pos.y + dir.y*t;
                    if t >= 0.0 && t <= 1.0 && x >= region.min.x && x <= region.max.x {
                        return Some(t);
                    }
                }
                if pos.y >= region.max.y && dir.y < 0.0 {
                    let t = (region.max.y - pos.y) / dir.y;
                    let x = pos.x + dir.x*t;
                    if t >= 0.0 && t <= 1.0 && x >= region.min.x && x <= region.max.x {
                        return Some(t);
                    }
                }
                return None;
            };
            if let Some(t) = hit(a, b - a) {
                a = Vec2::lerp(a, b, t);
            } else {
                return;
            }
            if let Some(t) = hit(b, a - b) {
                b = Vec2::lerp(b, a, t);
            } else {
                return;
            }
        }
        self.push_state_cmd(StateCmd::TextureChange(SamplerId::Solid)); 
        let len = (b - a).len(); // The length of the line
        let dir = (b - a) / len; // Unit vector from a to b
        // Just draw a single, slightly extended, segment
        if stipple_length + stipple_spacing > len {
            self.line(a, b, width, color);
        // Create a bunch of line segments, starting at the middle
        } else {
            let mut start = 0.0;
            while start < len/2.0 {
                let end = if start == 0.0 {
                    stipple_length/2.0
                } else {
                    (start + stipple_length).min(len/2.0)
                };
                self.line(a + dir*(len/2.0 + start), a + dir*(len/2.0 + end), width, color);
                self.line(a + dir*(len/2.0 - start), a + dir*(len/2.0 - end), width, color);
                start = end + stipple_spacing;
            }
        } 
    }
pub fn stippled_line ( & mut self , mut a : Vec2 < f32 > , mut b : Vec2 < f32 > , width : f32 , stipple_length : f32 , stipple_spacing : f32 , color : Color ) { // If we try to draw a very long stippled line this will take up a lot of memory, as each // small segment is a separate line. I often accidentally draw a very long line, where the // vast majority of it lies offscreen. This is fixed by clipping the line so we only render // the minimum required segments to be visible on screen. // This might change the apperance of the line slightly because it will shift its segments... if let Some ( region ) = self . working_clip_stack . last ( ) { let hit = | pos : Vec2 < f32 > , dir : Vec2 < f32 > | -> Option < f32 > { if region . contains ( pos ) { return Some ( 0.0 ) ; } if pos . x <= region . min . x && dir . x > 0.0 { let t = ( region . min . x - pos . x ) / dir . x ; let y = pos . y + dir . y * t ; if t >= 0.0 && t <= 1.0 && y >= region . min . y && y <= region . max . y { return Some ( t ) ; } } if pos . x >= region . max . x && dir . x < 0.0 { let t = ( region . max . x - pos . x ) / dir . x ; let y = pos . y + dir . y * t ; if t >= 0.0 && t <= 1.0 && y >= region . min . y && y <= region . max . y { return Some ( t ) ; } } if pos . y <= region . min . y && dir . y > 0.0 { let t = ( region . min . y - pos . y ) / dir . y ; let x = pos . y + dir . y * t ; if t >= 0.0 && t <= 1.0 && x >= region . min . x && x <= region . max . x { return Some ( t ) ; } } if pos . y >= region . max . y && dir . y < 0.0 { let t = ( region . max . y - pos . y ) / dir . y ; let x = pos . x + dir . x * t ; if t >= 0.0 && t <= 1.0 && x >= region . min . x && x <= region . max . x { return Some ( t ) ; } } return None ; } ; if let Some ( t ) = hit ( a , b - a ) { a = Vec2 :: lerp ( a , b , t ) ; } else { return ; } if let Some ( t ) = hit ( b , a - b ) { b = Vec2 :: lerp ( b , a , t ) ; } else { return ; } } self . push_state_cmd ( StateCmd :: TextureChange ( SamplerId :: Solid ) ) ; let len = ( b - a ) . len ( ) ; // The length of the line let dir = ( b - a ) / len ; // Unit vector from a to b // Just draw a single, slightly extended, segment if stipple_length + stipple_spacing > len { self . line ( a , b , width , color ) ; // Create a bunch of line segments, starting at the middle } else { let mut start = 0.0 ; while start < len / 2.0 { let end = if start == 0.0 { stipple_length / 2.0 } else { ( start + stipple_length ) . min ( len / 2.0 ) } ; self . line ( a + dir * ( len / 2.0 + start ) , a + dir * ( len / 2.0 + end ) , width , color ) ; self . line ( a + dir * ( len / 2.0 - start ) , a + dir * ( len / 2.0 - end ) , width , color ) ; start = end + stipple_spacing ; } } }
Generate the vertices for a stippled line
Generate the vertices for a stippled line
&mut self
a
Vec2<f32>
b
Vec2<f32>
width
f32
stipple_length
f32
stipple_spacing
f32
color
Color
&mut self
a
Vec2<f32>
b
Vec2<f32>
width
f32
stipple_length
f32
stipple_spacing
f32
color
Color