use std::fs; use std::num::NonZeroU32; use crate::gsa::Gsa; use crate::gsa_render_to_screen::render_to_screen; use crate::gsa_render_to_screen::render_to_window; use crate::sprite::Sprite; use crate::tileset::*; use crate::*; use clap::crate_version; use glam::IVec2; use winit::{ dpi::LogicalSize, event::{Event, KeyboardInput, VirtualKeyCode, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::WindowBuilder, }; const SPR_CURSOR: usize = 0x01; const TILE_CURSOR: u16 = 0x7308; const TILE_MARKER: u16 = 0x7309; pub(crate) fn run_mapedit() { println!("running map edit"); let tileset_path = "examples/basic/gfx.gif"; let (tileset, palette) = load_tileset(&fs::read(tileset_path).unwrap()); let mut gsa = Gsa { sprites: [Sprite::default(); MAX_SPRITES], palette, bgs: Default::default(), font: FONT_BOLD, pressed: 0, released: 0, down: 0, }; gsa.reset_bgs(); gsa.reset_sprites(); for i in 0..3 { gsa.bgs[i].scroll = IVec2 { x: -16, y: 0 }; } 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; gsa2.bgs[2].active = true; for y in 0..BACKGROUND_MAX_SIZE { gsa2.bgs[2].tiles[0][y] = 0x7408; } gsa2.bgs[2].tiles[0][0] = 0x7409; gsa2.bgs[2].tiles[0][2] = 0x740a; let event_loop = EventLoop::new(); let size = LogicalSize::new(1280, 720); let window = WindowBuilder::new() .with_title(format!( "Game Skunk Advance Map Editor v{}", crate_version!() )) .with_inner_size(size) .build(&event_loop) .unwrap(); let context = unsafe { softbuffer::Context::new(&window) }.unwrap(); let mut surface = unsafe { softbuffer::Surface::new(&context, &window) }.unwrap(); 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, .. } => { match ( input.state, input.virtual_keycode.unwrap_or(VirtualKeyCode::F24), ) { (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) => { *left_down = true; } (winit::event::ElementState::Released, winit::event::MouseButton::Left) => { *left_down = false; } (winit::event::ElementState::Pressed, winit::event::MouseButton::Middle) => { *middle_down = true; } (winit::event::ElementState::Released, winit::event::MouseButton::Middle) => { *middle_down = false; } (winit::event::ElementState::Pressed, winit::event::MouseButton::Right) => { *right_down = true; } (winit::event::ElementState::Released, winit::event::MouseButton::Right) => { *right_down = false; } _ => {} }, WindowEvent::CursorMoved { position, .. } => { let new_pos = IVec2 { x: position.x as i32 / 2, y: position.y as i32 / 2, }; let delta = new_pos - *mouse_pos; if *middle_down { 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 = 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 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 { // 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; } } } // render let size = window.inner_size(); surface .resize( NonZeroU32::new(size.width).unwrap(), NonZeroU32::new(size.height).unwrap(), ) .unwrap(); let mut screen_buffer = vec![TRANSPARENT; size.width as usize * size.height as usize / 4]; let mut window_buffer = surface.buffer_mut().unwrap(); render_to_screen( &mut screen_buffer, &gsa, &tileset, IVec2 { x: size.width as i32 / 2, y: size.height as i32 / 2, }, ); render_to_screen( &mut screen_buffer, &gsa2, &tileset, IVec2 { x: size.width as i32 / 2, y: size.height as i32 / 2, }, ); render_to_window( &mut window_buffer, &mut screen_buffer, &palette, IVec2 { x: size.width as i32, y: size.height as i32, }, IVec2 { x: size.width as i32 / 2, y: size.height as i32 / 2, }, 2, 0, 0, ); window_buffer.present().unwrap(); } _ => {} } }); }