use egui::{epaint::PathShape, vec2, Color32, Painter, Pos2, Rect, Shape, Stroke, Vec2};
use crate::{InPinId, OutPinId};
use super::WireStyle;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum AnyPin {
Out(OutPinId),
In(InPinId),
}
#[derive(Debug)]
pub enum AnyPins<'a> {
Out(&'a [OutPinId]),
In(&'a [InPinId]),
}
tiny_fn::tiny_fn! {
pub struct CustomPinShape = Fn(painter: &Painter, rect: Rect, fill: Color32, stroke: Stroke);
}
pub enum PinShape {
Circle,
Triangle,
Square,
Star,
Custom(CustomPinShape<'static>),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "egui-probe", derive(egui_probe::EguiProbe))]
pub enum BasicPinShape {
Circle,
Triangle,
Square,
Star,
}
impl Default for BasicPinShape {
#[inline(always)]
fn default() -> Self {
BasicPinShape::Circle
}
}
impl From<BasicPinShape> for PinShape {
#[inline(always)]
fn from(shape: BasicPinShape) -> Self {
match shape {
BasicPinShape::Circle => PinShape::Circle,
BasicPinShape::Triangle => PinShape::Triangle,
BasicPinShape::Square => PinShape::Square,
BasicPinShape::Star => PinShape::Star,
}
}
}
#[derive(Default)]
pub struct PinInfo {
pub shape: Option<PinShape>,
pub size: Option<f32>,
pub fill: Option<Color32>,
pub stroke: Option<Stroke>,
pub wire_style: Option<WireStyle>,
}
impl PinInfo {
pub fn with_shape(mut self, shape: PinShape) -> Self {
self.shape = Some(shape);
self
}
pub fn with_size(mut self, size: f32) -> Self {
self.size = Some(size);
self
}
pub fn with_fill(mut self, fill: Color32) -> Self {
self.fill = Some(fill);
self
}
pub fn with_stroke(mut self, stroke: Stroke) -> Self {
self.stroke = Some(stroke);
self
}
pub fn with_wire_style(mut self, wire_style: WireStyle) -> Self {
self.wire_style = Some(wire_style);
self
}
pub fn circle() -> Self {
PinInfo {
shape: Some(PinShape::Circle),
..Default::default()
}
}
pub fn triangle() -> Self {
PinInfo {
shape: Some(PinShape::Triangle),
..Default::default()
}
}
pub fn square() -> Self {
PinInfo {
shape: Some(PinShape::Square),
..Default::default()
}
}
pub fn star() -> Self {
PinInfo {
shape: Some(PinShape::Star),
..Default::default()
}
}
pub fn custom<F>(f: F) -> Self
where
F: Fn(&Painter, Rect, Color32, Stroke) + 'static,
{
PinInfo {
shape: Some(PinShape::Custom(CustomPinShape::new(f))),
..Default::default()
}
}
}
pub fn draw_pin(
painter: &Painter,
shape: &PinShape,
fill: Color32,
stroke: Stroke,
pos: Pos2,
size: f32,
) {
match shape {
PinShape::Circle => {
painter.circle(pos, size * 2.0 / std::f32::consts::PI, fill, stroke);
}
PinShape::Triangle => {
const A: Vec2 = vec2(-0.649_519, 0.4875);
const B: Vec2 = vec2(0.649_519, 0.4875);
const C: Vec2 = vec2(0.0, -0.6375);
let points = vec![pos + A * size, pos + B * size, pos + C * size];
painter.add(Shape::Path(PathShape {
points,
closed: true,
fill,
stroke: stroke.into(),
}));
}
PinShape::Square => {
let points = vec![
pos + vec2(-0.5, -0.5) * size,
pos + vec2(0.5, -0.5) * size,
pos + vec2(0.5, 0.5) * size,
pos + vec2(-0.5, 0.5) * size,
];
painter.add(Shape::Path(PathShape {
points,
closed: true,
fill,
stroke: stroke.into(),
}));
}
PinShape::Star => {
let points = vec![
pos + size * 0.700000 * vec2(0.0, -1.0),
pos + size * 0.267376 * vec2(-0.587785, -0.809017),
pos + size * 0.700000 * vec2(-0.951057, -0.309017),
pos + size * 0.267376 * vec2(-0.951057, 0.309017),
pos + size * 0.700000 * vec2(-0.587785, 0.809017),
pos + size * 0.267376 * vec2(0.0, 1.0),
pos + size * 0.700000 * vec2(0.587785, 0.809017),
pos + size * 0.267376 * vec2(0.951057, 0.309017),
pos + size * 0.700000 * vec2(0.951057, -0.309017),
pos + size * 0.267376 * vec2(0.587785, -0.809017),
];
painter.add(Shape::Path(PathShape {
points,
closed: true,
fill,
stroke: stroke.into(),
}));
}
PinShape::Custom(f) => f.call(
painter,
Rect::from_center_size(pos, vec2(size, size)),
fill,
stroke,
),
}
}