Skip to content
Snippets Groups Projects
extract.rs 7.42 KiB
Newer Older
Louis's avatar
Louis committed
use crate::{
    render::unified::pipeline::{ExtractedQuad, UIQuadType},
    styles::{Corner, Edge},
};
use bevy::{
    math::Vec2,
    prelude::*,
    render::{color::Color, texture::Image},
};

pub fn extract_nine_patch(
    camera_entity: Entity,
    layout: crate::layout::Rect,
    handle: Handle<Image>,
    border: Edge<f32>,
    scale: f32,
    opacity_layer: u32,
    images: &Assets<Image>,
    dpi: f32,
) -> Vec<ExtractedQuad> {
    let mut extracted_quads = Vec::new();

    let image = images.get(&handle);

    if image.is_none() {
        return vec![];
    }

    let image_size = image
        .map(|i| {
            Vec2::new(
                i.texture_descriptor.size.width as f32 * scale,
                i.texture_descriptor.size.height as f32 * scale,
            )
        })
        .unwrap()
        * dpi;

    let extracted_quad_template = ExtractedQuad {
        camera_entity,
        rect: Rect {
            min: Vec2::ZERO,
            max: Vec2::ZERO,
        },
        color: Color::WHITE,
        char_id: 0,
        font_handle: None,
        quad_type: UIQuadType::Image,
        type_index: 0,
        border_radius: Corner::default(),
        image: Some(handle.clone_weak()),
        uv_max: None,
        uv_min: None,
        opacity_layer,
        ..Default::default()
    };

    let top_uv_min_y = (image_size.y - border.top) / image_size.y;
    let top_uv_max_y = 1.0;
    let bottom_uv_min_y = 0.0;
    let bottom_uv_max_y = border.bottom / image_size.y;
    let middle_uv_min_y = border.bottom / image_size.y;
    let middle_uv_max_y = (image_size.y - border.top) / image_size.y;

    // TOP
    let top_left_quad = ExtractedQuad {
        rect: Rect {
            min: Vec2::new(layout.posx, layout.posy),
            max: Vec2::new(layout.posx + border.left, layout.posy + border.top),
        },
        uv_min: Some(Vec2::new(0.0, top_uv_min_y)),
        uv_max: Some(Vec2::new(border.left / image_size.x, top_uv_max_y)),
        ..extracted_quad_template.clone()
    };
    extracted_quads.push(top_left_quad);

    let top_right_pos_x = (layout.posx + layout.width) - border.left;
    let top_right_quad = ExtractedQuad {
        rect: Rect {
            min: Vec2::new(top_right_pos_x, layout.posy),
            max: Vec2::new(top_right_pos_x + border.left, layout.posy + border.top),
        },
        uv_min: Some(Vec2::new(
            (image_size.x - border.left) / image_size.x,
            top_uv_min_y,
        )),
        uv_max: Some(Vec2::new(1.0, top_uv_max_y)),
        ..extracted_quad_template.clone()
    };
    extracted_quads.push(top_right_quad);

    let top_middle_pos_x = layout.posx + border.left;
    let top_middle_size_x = layout.width - (border.left + border.right);
    let top_middle_quad = ExtractedQuad {
        rect: Rect {
            min: Vec2::new(top_middle_pos_x, layout.posy),
            max: Vec2::new(
                top_middle_pos_x + top_middle_size_x,
                layout.posy + border.top,
            ),
        },
        uv_min: Some(Vec2::new(border.left / image_size.x, top_uv_min_y)),
        uv_max: Some(Vec2::new(
            (image_size.x - border.left) / image_size.x,
            top_uv_max_y,
        )),
        ..extracted_quad_template.clone()
    };
    extracted_quads.push(top_middle_quad);

    // Bottom
    let bottom_y_pos = layout.posy + (layout.height - border.bottom);
    let bottom_left_quad = ExtractedQuad {
        rect: Rect {
            min: Vec2::new(layout.posx, bottom_y_pos),
            max: Vec2::new(layout.posx + border.left, bottom_y_pos + border.bottom),
        },
        uv_min: Some(Vec2::new(0.0, bottom_uv_min_y)),
        uv_max: Some(Vec2::new(border.left / image_size.x, bottom_uv_max_y)),
        ..extracted_quad_template.clone()
    };
    extracted_quads.push(bottom_left_quad);

    let bottom_right_pos_x = (layout.posx + layout.width) - border.left;
    let bottom_right_quad = ExtractedQuad {
        rect: Rect {
            min: Vec2::new(bottom_right_pos_x, bottom_y_pos),
            max: Vec2::new(bottom_right_pos_x + border.left, bottom_y_pos + border.top),
        },
        uv_min: Some(Vec2::new(
            (image_size.x - border.left) / image_size.x,
            bottom_uv_min_y,
        )),
        uv_max: Some(Vec2::new(1.0, bottom_uv_max_y)),
        ..extracted_quad_template.clone()
    };
    extracted_quads.push(bottom_right_quad);

    let bottom_middle_pos_x = layout.posx + border.left;
    let bottom_middle_size_x = layout.width - (border.left + border.right);
    let bottom_middle_quad = ExtractedQuad {
        rect: Rect {
            min: Vec2::new(bottom_middle_pos_x, bottom_y_pos),
            max: Vec2::new(
                bottom_middle_pos_x + bottom_middle_size_x,
                bottom_y_pos + border.top,
            ),
        },
        uv_min: Some(Vec2::new(border.left / image_size.x, bottom_uv_min_y)),
        uv_max: Some(Vec2::new(
            (image_size.x - border.left) / image_size.x,
            bottom_uv_max_y,
        )),
        ..extracted_quad_template.clone()
    };
    extracted_quads.push(bottom_middle_quad);

    // Left + Right center
    let left_middle_pos_y = layout.posy + border.top;
    let left_middle_size_y = layout.height - (border.top + border.bottom);
    let left_middle_quad = ExtractedQuad {
        rect: Rect {
            min: Vec2::new(layout.posx, left_middle_pos_y),
            max: Vec2::new(
                layout.posx + border.left,
                left_middle_pos_y + left_middle_size_y,
            ),
        },
        uv_min: Some(Vec2::new(0.0, middle_uv_min_y)),
        uv_max: Some(Vec2::new(border.left / image_size.x, middle_uv_max_y)),
        ..extracted_quad_template.clone()
    };
    extracted_quads.push(left_middle_quad);

    let right_middle_pos_x = layout.posx + (layout.width - border.right);
    let right_middle_pos_y = layout.posy + border.top;
    let right_middle_size_y = layout.height - (border.top + border.bottom);
    let right_middle_quad = ExtractedQuad {
        rect: Rect {
            min: Vec2::new(right_middle_pos_x, right_middle_pos_y),
            max: Vec2::new(
                right_middle_pos_x + border.left,
                right_middle_pos_y + right_middle_size_y,
            ),
        },
        uv_min: Some(Vec2::new(
            (image_size.x - border.left) / image_size.x,
            middle_uv_min_y,
        )),
        uv_max: Some(Vec2::new(1.0, middle_uv_max_y)),
        ..extracted_quad_template.clone()
    };
    extracted_quads.push(right_middle_quad);

    // Last quad in middle.
    let middle_pos_x = layout.posx + border.left;
    let middle_pos_y = layout.posy + border.top;
    let middle_size_x = layout.width - (border.left + border.right);
    let middle_size_y = layout.height - (border.top + border.bottom);
    let middle_quad = ExtractedQuad {
        rect: Rect {
            min: Vec2::new(middle_pos_x, middle_pos_y),
            max: Vec2::new(middle_pos_x + middle_size_x, middle_pos_y + middle_size_y),
        },
        uv_min: Some(Vec2::new(border.left / image_size.x, middle_uv_min_y)),
        uv_max: Some(Vec2::new(
            (image_size.x - border.right) / image_size.x,
            middle_uv_max_y,
        )),
        ..extracted_quad_template
    };
    extracted_quads.push(middle_quad);

    extracted_quads
}