gsa/src/mapedit.rs

281 lines
11 KiB
Rust

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();
}
_ => {}
}
});
}