mirror of
https://github.com/OMGeeky/logisim.git
synced 2025-12-26 16:57:23 +01:00
use canvas zoom & a bunch of other changes
This commit is contained in:
BIN
assets/fonts/arcane_nine.otf
Normal file
BIN
assets/fonts/arcane_nine.otf
Normal file
Binary file not shown.
@@ -1,17 +1,42 @@
|
||||
use bevy::color::palettes::basic::RED;
|
||||
// pub struct Block
|
||||
use crate::camera::Canvas;
|
||||
use bevy::color::palettes::basic::{GREEN, RED, WHITE};
|
||||
use bevy::prelude::*;
|
||||
use bevy::text::TextBounds;
|
||||
|
||||
const LABEL_SCALING_FACTOR: f32 = 0.2;
|
||||
|
||||
#[derive(Bundle, Debug)]
|
||||
pub struct BlockBundle {
|
||||
// name: Text2d,
|
||||
block: Block,
|
||||
transform: Transform,
|
||||
global_transform: GlobalTransform,
|
||||
block_visuals: BlockVisuals,
|
||||
}
|
||||
#[derive(Bundle, Debug)]
|
||||
pub struct BlockLabelBundle {
|
||||
text: Text2d,
|
||||
font: TextFont,
|
||||
text_layout: TextLayout,
|
||||
text_bounds: TextBounds,
|
||||
transform: Transform,
|
||||
marker: CanvasText,
|
||||
}
|
||||
|
||||
impl BlockLabelBundle {
|
||||
fn new(name: impl Into<String>, size: IVec2, font: TextFont) -> Self {
|
||||
Self {
|
||||
text: Text2d(name.into()),
|
||||
font,
|
||||
text_layout: TextLayout::new(JustifyText::Justified, LineBreak::WordOrCharacter),
|
||||
text_bounds: TextBounds::from(size.as_vec2() * (1.0 / LABEL_SCALING_FACTOR)),
|
||||
transform: Transform::from_translation(Vec3::Z),
|
||||
marker: CanvasText,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct CanvasText;
|
||||
#[derive(Component, Debug)]
|
||||
pub struct BlockVisuals {
|
||||
size: IVec2,
|
||||
@@ -32,11 +57,18 @@ pub struct LogicSimPlugin;
|
||||
impl Plugin for LogicSimPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_systems(Startup, setup)
|
||||
.add_systems(Update, render_blocks);
|
||||
.add_systems(Update, (render_blocks, scale_labels));
|
||||
}
|
||||
}
|
||||
fn setup(mut commands: Commands) {
|
||||
let size = IVec2::new(50, 40);
|
||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
let font = asset_server.load("fonts/arcane_nine.otf");
|
||||
let text_font = TextFont {
|
||||
font,
|
||||
font_size: 100.0,
|
||||
..default()
|
||||
};
|
||||
|
||||
let size = IVec2::new(50, 80);
|
||||
commands
|
||||
.spawn(BlockBundle {
|
||||
// name: Text2d("AND".into()),
|
||||
@@ -45,37 +77,122 @@ fn setup(mut commands: Commands) {
|
||||
color: Color::from(RED),
|
||||
},
|
||||
block: Block {
|
||||
inputs: vec![Connection {
|
||||
size: 2,
|
||||
values: vec![false, true],
|
||||
}],
|
||||
inputs: vec![
|
||||
Connection {
|
||||
size: 10,
|
||||
values: vec![
|
||||
false, true, false, true, false, true, false, true, false, true,
|
||||
],
|
||||
},
|
||||
Connection {
|
||||
size: 9,
|
||||
values: vec![false, true, false, true, false, true, false, true, false],
|
||||
},
|
||||
],
|
||||
outputs: vec![
|
||||
Connection {
|
||||
size: 1,
|
||||
values: vec![false],
|
||||
},
|
||||
Connection {
|
||||
size: 1,
|
||||
values: vec![true],
|
||||
size: 2,
|
||||
values: vec![true, false],
|
||||
},
|
||||
Connection {
|
||||
size: 3,
|
||||
values: vec![true, false, true],
|
||||
},
|
||||
Connection {
|
||||
size: 4,
|
||||
values: vec![true, false, true, false],
|
||||
},
|
||||
],
|
||||
},
|
||||
global_transform: GlobalTransform::default(),
|
||||
transform: Transform::default(),
|
||||
})
|
||||
.with_child((
|
||||
Text2d("AND".into()),
|
||||
TextLayout::new(JustifyText::Center, LineBreak::WordBoundary),
|
||||
TextBounds::from(size.as_vec2()),
|
||||
Transform::from_translation(Vec3::Z),
|
||||
));
|
||||
.with_child(BlockLabelBundle::new("AND", size, text_font));
|
||||
}
|
||||
fn render_blocks(blocks: Query<(&BlockVisuals, &GlobalTransform)>, mut gizmos: Gizmos) {
|
||||
for (block_visual, transform) in blocks.iter() {
|
||||
gizmos.rect_2d(
|
||||
transform.translation().xy(),
|
||||
block_visual.size.as_vec2(),
|
||||
block_visual.color,
|
||||
);
|
||||
fn render_blocks(
|
||||
blocks: Query<(&BlockVisuals, &Block, &GlobalTransform)>,
|
||||
canvas: Res<Canvas>,
|
||||
mut gizmos: Gizmos,
|
||||
) {
|
||||
for (block_visual, block, transform) in blocks.iter() {
|
||||
let size = block_visual.size.as_vec2() * canvas.zoom;
|
||||
let center = transform.translation().xy();
|
||||
let half_size = size / 2.0;
|
||||
let top = center.y + half_size.y;
|
||||
// let bottom = center.y - half_size.y;
|
||||
let left = center.x - half_size.x;
|
||||
let right = center.x + half_size.x;
|
||||
gizmos.rect_2d(center, size, block_visual.color);
|
||||
draw_connections(left, top, size.y, &block.inputs, &mut gizmos, &canvas);
|
||||
draw_connections(right, top, size.y, &block.outputs, &mut gizmos, &canvas);
|
||||
}
|
||||
}
|
||||
fn draw_connections(
|
||||
x: f32,
|
||||
y: f32,
|
||||
available_height: f32,
|
||||
connections: &[Connection],
|
||||
gizmos: &mut Gizmos,
|
||||
canvas: &Canvas,
|
||||
) {
|
||||
let input_count = connections.len();
|
||||
let input_spacing = available_height / (input_count + 1) as f32;
|
||||
// println!("{} -> {}", input_count, input_spacing);
|
||||
for (i, connection) in connections.iter().enumerate() {
|
||||
draw_connection(x, y, gizmos, input_spacing, i, connection, canvas);
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_connection(
|
||||
x: f32,
|
||||
y: f32,
|
||||
gizmos: &mut Gizmos,
|
||||
input_spacing: f32,
|
||||
i: usize,
|
||||
|
||||
connection: &Connection,
|
||||
canvas: &Canvas,
|
||||
) {
|
||||
const CONNECTION_BIT_SIZE: f32 = 10.0;
|
||||
let connection_bit_size = CONNECTION_BIT_SIZE * canvas.zoom;
|
||||
let connection_bit_half_size = connection_bit_size * 0.5;
|
||||
let connection_pos = Vec2::new(x, y - input_spacing * (i + 1) as f32);
|
||||
|
||||
let rows = if connection.size > 8 { 2 } else { 1 };
|
||||
let columns = (connection.size as f32 / rows as f32).ceil() as u32;
|
||||
|
||||
let half_offset = Vec2::new(columns as f32, rows as f32) * (connection_bit_size / 2.0);
|
||||
let one_size = Vec2::new(connection_bit_size, connection_bit_size);
|
||||
let half_one_size = one_size / 2.0;
|
||||
|
||||
'rows: for y in 0..rows {
|
||||
for x in 0..columns {
|
||||
let index = y * columns + x;
|
||||
if index >= connection.size {
|
||||
break 'rows;
|
||||
}
|
||||
let pos = connection_pos
|
||||
+ Vec2::new(x as f32, (rows - y - 1) as f32) * connection_bit_size
|
||||
- half_offset
|
||||
+ half_one_size;
|
||||
let value = connection.values[index as usize];
|
||||
let color = if value { RED } else { GREEN };
|
||||
gizmos.circle_2d(pos, connection_bit_half_size, color);
|
||||
}
|
||||
}
|
||||
gizmos.rect_2d(
|
||||
connection_pos,
|
||||
Vec2::new(columns as f32, rows as f32) * connection_bit_size,
|
||||
WHITE,
|
||||
);
|
||||
}
|
||||
|
||||
fn scale_labels(mut labels: Query<(&mut Transform), With<CanvasText>>, canvas: Res<Canvas>) {
|
||||
for (mut transform) in labels.iter_mut() {
|
||||
transform.scale = Vec3::splat(canvas.zoom) * LABEL_SCALING_FACTOR;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user