diff --git a/Cargo.lock b/Cargo.lock index 52c84f0..18287d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -166,6 +166,12 @@ dependencies = [ "libc", ] +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + [[package]] name = "approx" version = "0.5.1" @@ -466,6 +472,19 @@ dependencies = [ "wgpu-types", ] +[[package]] +name = "bevy_common_assets" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3521990269672c442f2bf0fbed0fce9db719e3dd136dd4012a97809464a4389d" +dependencies = [ + "anyhow", + "bevy", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "bevy_core" version = "0.15.3" @@ -2635,7 +2654,9 @@ name = "logisim" version = "0.1.0" dependencies = [ "bevy", + "bevy_common_assets", "iyes_perf_ui", + "serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index fabe759..be1e73f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,8 @@ edition = "2024" [dependencies] bevy = { version = "0.15.0", features = ["bevy_dev_tools"] } iyes_perf_ui = "0.4.0" - +serde = { version = "1.0.219", features = ["derive"] } +bevy_common_assets = { version = "0.12.0", features = ["json"] } # Enable more optimization in the release profile at the cost of compile time. diff --git a/assets/logisim/blocks/sample1.blockdef.json b/assets/logisim/blocks/sample1.blockdef.json new file mode 100644 index 0000000..ad0322f --- /dev/null +++ b/assets/logisim/blocks/sample1.blockdef.json @@ -0,0 +1,117 @@ +{ + "id": 1, + "pos": [ + 0.0, + 0.0 + ], + "size": [ + 50, + 80 + ], + "name": "AND", + "color": { + "Srgba": { + "red": 1.0, + "green": 0.0, + "blue": 0.0, + "alpha": 1.0 + } + }, + "wires": [ + { + "connections": [ + { + "parent_block": 1, + "id": 1 + }, + { + "parent_block": 1, + "id": 2 + }, + { + "parent_block": 1, + "id": 3 + }, + { + "parent_block": 1, + "id": 4 + }, + { + "parent_block": 1, + "id": 6 + } + ] + } + ], + "inputs": [ + { + "id": 1, + "value": { + "HalfByte": [ + false, + false, + true, + true + ] + } + }, + { + "id": 2, + "value": { + "HalfByte": [ + true, + false, + false, + true + ] + } + } + ], + "outputs": [ + { + "id": 3, + "value": { + "HalfByte": [ + false, + false, + false, + true + ] + } + }, + { + "id": 4, + "value": { + "HalfByte": [ + false, + true, + false, + true + ] + } + }, + { + "id": 5, + "value": { + "HalfByte": [ + false, + true, + false, + false + ] + } + }, + { + "id": 6, + "value": { + "HalfByte": [ + true, + false, + true, + true + ] + } + } + ], + "inner_blocks": [] +} diff --git a/assets/logisim/blocks/sample1.json b/assets/logisim/blocks/sample1.json deleted file mode 100644 index 2c63c08..0000000 --- a/assets/logisim/blocks/sample1.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/src/logic_sim/mod.rs b/src/logic_sim/mod.rs index 2319dbb..9ee49eb 100644 --- a/src/logic_sim/mod.rs +++ b/src/logic_sim/mod.rs @@ -2,11 +2,22 @@ use crate::camera::Canvas; use bevy::color::palettes::basic::{GREEN, RED, WHITE}; use bevy::prelude::*; use bevy::text::TextBounds; +use bevy_common_assets::json::JsonAssetPlugin; +use serde::Deserialize; use std::ops::BitOr; const LABEL_SCALING_FACTOR: f32 = 0.2; -#[derive(Resource, Debug, Clone)] +#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)] +enum AppState { + #[default] + Loading, + Running, +} + +#[derive(Resource)] +struct BlockDefinitionHandle(Handle); +#[derive(Deserialize, Asset, TypePath, Debug, Clone)] pub struct BlockDefinition { id: usize, pos: Vec2, @@ -18,22 +29,23 @@ pub struct BlockDefinition { inputs: Vec, outputs: Vec, } -#[derive(Resource, Debug, Clone)] +#[derive(Deserialize, Asset, TypePath, Debug, Clone)] pub struct WireDefinition { connections: Vec, } -#[derive(Resource, Debug, Clone, Copy)] +#[derive(Deserialize, Asset, TypePath, Debug, Clone, Copy)] pub struct ConnectionDefinition { id: usize, value: ConnectionValues, } -#[derive(Resource, Debug, Clone, Copy)] +#[derive(Deserialize, Asset, TypePath, Debug, Clone, Copy)] pub struct ConnectionDefinitionRef { parent_block: usize, id: usize, } #[derive(Bundle, Debug)] pub struct BlockBundle { + id: BlockId, block: Block, transform: Transform, global_transform: GlobalTransform, @@ -72,6 +84,10 @@ pub struct BlockVisuals { #[derive(Component, Debug, Copy, Clone)] pub struct ConnectionReference(Entity); #[derive(Component, Debug)] +pub struct BlockId { + id: usize, +} +#[derive(Component, Debug)] pub struct Block { inputs: Vec, outputs: Vec, @@ -91,7 +107,7 @@ pub struct OutputConnection; pub struct Connection { values: ConnectionValues, } -#[derive(Debug, Clone, Copy)] +#[derive(Deserialize, Debug, Clone, Copy)] pub enum ConnectionValues { Single(bool), HalfByte(bool, bool, bool, bool), @@ -353,8 +369,14 @@ impl Plugin for LogicSimPlugin { app //hi // .insert_resource(get_sample_block()) + .add_plugins(JsonAssetPlugin::::new(&["blockdef.json"])) .add_systems(Startup, setup) - .add_systems(Update, spawn_block_resources) + .init_asset::() + .init_state::() + .add_systems( + Update, + spawn_block_definition_from_asset.run_if(in_state(AppState::Loading)), + ) .add_systems( Update, ( @@ -429,11 +451,34 @@ fn get_sample_block() -> BlockDefinition { ], } } -fn setup(commands: Commands, asset_server: Res) { - let block = get_sample_block(); - spawn_block_definition(commands, asset_server, block); +fn setup(mut commands: Commands, asset_server: Res) { + let block_def = + BlockDefinitionHandle(asset_server.load("logisim/blocks/sample1.blockdef.json")); + commands.insert_resource(block_def); + + // let block = get_sample_block(); + // spawn_block_definition(commands, asset_server, block); } +fn spawn_block_definition_from_asset( + mut commands: Commands, + asset_server: Res, + block: Res, + mut blocks: ResMut>, + mut state: ResMut>, + spawned_blocks: Query<(Entity, &BlockId)>, +) { + if let Some(block) = blocks.remove(block.0.id()) { + let spawned_block = spawned_blocks + .iter() + .find_map(|(e, b)| if b.id == block.id { Some(e) } else { None }); + if let Some(e) = spawned_block { + commands.entity(e).despawn_recursive(); + } + spawn_block_definition(commands, asset_server, block); + state.set(AppState::Running) + } +} fn spawn_block_definition( mut commands: Commands, asset_server: Res, @@ -502,6 +547,7 @@ fn spawn_block_definition( commands .spawn(BlockBundle { + id: BlockId { id: block.id }, block_visuals: BlockVisuals { size: block.size, color: block.color, @@ -516,9 +562,6 @@ fn spawn_block_definition( .with_child(BlockLabelBundle::new(block.name, block.size, text_font)); } -fn spawn_block_resources(// mut ev_asset -) { -} fn render_blocks( blocks: Query<(&BlockVisuals, &Transform)>, canvas: Res,