diff --git a/examples/basic/gfx.gif b/examples/basic/gfx.gif index 50e4131..d58cb06 100644 Binary files a/examples/basic/gfx.gif and b/examples/basic/gfx.gif differ diff --git a/src/background.rs b/src/background.rs index 2696f35..2987eeb 100644 --- a/src/background.rs +++ b/src/background.rs @@ -9,6 +9,8 @@ pub struct Background { pub scroll: IVec2, /// Are tiles indices half-tile indices? pub half_tile: bool, + /// Is this background being displayed? + pub active: bool, } impl Default for Background { @@ -19,6 +21,7 @@ impl Default for Background { tiles, scroll: IVec2::ZERO, half_tile: false, + active: true, } } } diff --git a/src/gsa_render_to_screen.rs b/src/gsa_render_to_screen.rs index ec36170..e0d4ecc 100644 --- a/src/gsa_render_to_screen.rs +++ b/src/gsa_render_to_screen.rs @@ -69,7 +69,9 @@ fn render_map(target: &mut [u8], map: &Background, tileset: &[u8], screen_size: pub(crate) fn render_to_screen(target: &mut [u8], gsa: &Gsa, tileset: &[u8], screen_size: IVec2) { for i in 0..MAX_BACKGROUNDS { - render_map(target, &gsa.bgs[i], tileset, screen_size); + if gsa.bgs[i].active { + render_map(target, &gsa.bgs[i], tileset, screen_size); + } for sprite in &gsa.sprites { if sprite.tile != EMPTY_TILE && sprite.priority == i as u8 { draw_tile(target, sprite.pos, sprite.tile, tileset, false, screen_size); diff --git a/src/mapedit.rs b/src/mapedit.rs index 7c96be0..3ef4b48 100644 --- a/src/mapedit.rs +++ b/src/mapedit.rs @@ -17,6 +17,8 @@ use winit::{ }; const SPR_CURSOR: usize = 0x01; +const TILE_CURSOR: u16 = 0x7308; +const TILE_MARKER: u16 = 0x7309; pub(crate) fn run_mapedit() { println!("running map edit"); @@ -36,7 +38,27 @@ pub(crate) fn run_mapedit() { gsa.reset_bgs(); gsa.reset_sprites(); - gsa.sprites[SPR_CURSOR].tile = 0x7308; + + gsa.sprites[SPR_CURSOR].tile = TILE_CURSOR; + let mut gsa2 = Gsa { + sprites: [Sprite::default(); MAX_SPRITES], + palette, + bgs: Default::default(), + font: FONT_BOLD, + pressed: 0, + released: 0, + down: 0, + }; + gsa2.reset_bgs(); + gsa2.reset_sprites(); + + for y in 0..TILESET_SIZE { + for x in 0..TILESET_SIZE { + gsa2.bgs[0].tiles[x][y] = (x + (y << 8)) as u16; + } + } + gsa2.bgs[0].active = false; + gsa2.bgs[1].active = false; let event_loop = EventLoop::new(); let size = LogicalSize::new(1280, 720); @@ -54,26 +76,48 @@ pub(crate) fn run_mapedit() { window.request_redraw(); let mut mouse_pos = IVec2::ZERO; let mut tile_pos = IVec2::ZERO; + let mut tile_pos2 = IVec2::ZERO; let mut left_down = false; let mut middle_down = false; let mut right_down = false; + let mut selected_tile = IVec2::ZERO; + gsa2.bgs[1].tiles[0][0] = TILE_MARKER; event_loop.run(move |event, _, control_flow| { let mouse_pos = &mut mouse_pos; let tile_pos = &mut tile_pos; + let tile_pos2 = &mut tile_pos2; let left_down = &mut left_down; let middle_down = &mut middle_down; let right_down = &mut right_down; + let selected_tile = &mut selected_tile; + match event { Event::WindowEvent { event, .. } => match event { - WindowEvent::KeyboardInput { - input: - KeyboardInput { - virtual_keycode: Some(VirtualKeyCode::Escape, ..), - .. - }, - .. - } => { - *control_flow = ControlFlow::Exit; + WindowEvent::KeyboardInput { input, .. } => { + match (input.state, input.virtual_keycode.unwrap()) { + (winit::event::ElementState::Pressed, VirtualKeyCode::Escape) => { + *control_flow = ControlFlow::Exit; + } + (winit::event::ElementState::Pressed, VirtualKeyCode::LShift) => { + gsa.bgs[0].active = false; + gsa.bgs[1].active = false; + gsa.bgs[2].active = false; + gsa2.bgs[0].active = true; + gsa2.bgs[1].active = true; + gsa.sprites[SPR_CURSOR].tile = EMPTY_TILE; + gsa2.sprites[SPR_CURSOR].tile = TILE_CURSOR; + } + (winit::event::ElementState::Released, VirtualKeyCode::LShift) => { + gsa.bgs[0].active = true; + gsa.bgs[1].active = true; + gsa.bgs[2].active = true; + gsa2.bgs[0].active = false; + gsa2.bgs[1].active = false; + gsa.sprites[SPR_CURSOR].tile = TILE_CURSOR; + gsa2.sprites[SPR_CURSOR].tile = EMPTY_TILE; + } + _ => {} + } } WindowEvent::MouseInput { state, button, .. } => match (state, button) { (winit::event::ElementState::Pressed, winit::event::MouseButton::Left) => { @@ -103,34 +147,70 @@ pub(crate) fn run_mapedit() { }; let delta = new_pos - *mouse_pos; if *middle_down { - gsa.bgs[0].scroll -= delta; - gsa.bgs[1].scroll -= delta; - gsa.bgs[2].scroll -= delta; + if gsa.bgs[0].active { + // normal mode + gsa.bgs[0].scroll -= delta; + gsa.bgs[1].scroll -= delta; + gsa.bgs[2].scroll -= delta; + } else { + // tile select mode + gsa2.bgs[0].scroll -= delta; + gsa2.bgs[1].scroll -= delta; + gsa2.bgs[2].scroll -= delta; + } } *mouse_pos = new_pos; - *tile_pos = (new_pos + gsa.bgs[0].scroll) / TILE_SIZE as i32; + *tile_pos = IVec2 { + x: (new_pos.x + gsa.bgs[0].scroll.x).div_euclid(TILE_SIZE as i32), + y: (new_pos.y + gsa.bgs[0].scroll.y).div_euclid(TILE_SIZE as i32), + }; + *tile_pos2 = IVec2 { + x: (new_pos.x + gsa2.bgs[0].scroll.x).div_euclid(TILE_SIZE as i32), + y: (new_pos.y + gsa2.bgs[0].scroll.y).div_euclid(TILE_SIZE as i32), + }; let cursor_pos = *tile_pos * TILE_SIZE as i32 - gsa.bgs[0].scroll; + let cursor_pos2 = *tile_pos2 * TILE_SIZE as i32 - gsa2.bgs[0].scroll; gsa.sprites[SPR_CURSOR].pos = cursor_pos; + gsa2.sprites[SPR_CURSOR].pos = cursor_pos2; } _ => {} }, Event::MainEventsCleared => { - if *left_down { - if tile_pos.x >= 0 - && tile_pos.y >= 0 - && tile_pos.x < BACKGROUND_MAX_SIZE as i32 - && tile_pos.y < BACKGROUND_MAX_SIZE as i32 - { - gsa.bgs[0].tiles[tile_pos.x as usize][tile_pos.y as usize] = 0; + if gsa.bgs[0].active { + // normal mode + if *left_down { + if tile_pos.x >= 0 + && tile_pos.y >= 0 + && tile_pos.x < BACKGROUND_MAX_SIZE as i32 + && tile_pos.y < BACKGROUND_MAX_SIZE as i32 + { + let tile = (selected_tile.x + (selected_tile.y << 8)) as u16; + gsa.bgs[0].tiles[tile_pos.x as usize][tile_pos.y as usize] = tile; + } + } else if *right_down { + if tile_pos.x >= 0 + && tile_pos.y >= 0 + && tile_pos.x < BACKGROUND_MAX_SIZE as i32 + && tile_pos.y < BACKGROUND_MAX_SIZE as i32 + { + gsa.bgs[0].tiles[tile_pos.x as usize][tile_pos.y as usize] = EMPTY_TILE; + } } - } else if *right_down { - if tile_pos.x >= 0 - && tile_pos.y >= 0 - && tile_pos.x < BACKGROUND_MAX_SIZE as i32 - && tile_pos.y < BACKGROUND_MAX_SIZE as i32 - { - gsa.bgs[0].tiles[tile_pos.x as usize][tile_pos.y as usize] = EMPTY_TILE; + } else { + // tile select mode + if *left_down { + if tile_pos2.x >= 0 + && tile_pos2.y >= 0 + && tile_pos2.x < BACKGROUND_MAX_SIZE as i32 + && tile_pos2.y < BACKGROUND_MAX_SIZE as i32 + { + gsa2.bgs[1].tiles[selected_tile.x as usize][selected_tile.y as usize] = + EMPTY_TILE; + *selected_tile = *tile_pos2; + gsa2.bgs[1].tiles[selected_tile.x as usize][selected_tile.y as usize] = + TILE_MARKER; + } } } @@ -154,6 +234,15 @@ pub(crate) fn run_mapedit() { y: size.height as i32, }, ); + render_to_screen( + &mut screen_buffer, + &gsa2, + &tileset, + IVec2 { + x: size.width as i32, + y: size.height as i32, + }, + ); render_to_window( &mut window_buffer, &mut screen_buffer,