Commit 146141d9 authored by Jeremy Soller's avatar Jeremy Soller

Move orbital stuff into liborbital

parents
use super::Color;
use redox::String;
use redox::Vec;
// TODO: Follow naming convention
/// A bitmap
pub struct BmpFile {
/// The bitmap width
w: usize,
/// The bitmap height
h: usize,
/// The data of the bitmap
//data: Vec<[u8; 4]>,
data: Vec<Color>,
}
impl BmpFile {
/// Create a new bitmap
pub fn new(width: usize, height: usize) -> Self {
BmpFile {
w: width,
h: height,
data: Vec::new(),
}
}
/// Create a new empty bitmap
pub fn default() -> Self {
Self::new(0, 0)
}
/// Create a bitmap from some data
pub fn from_data(file_data: &[u8]) -> Self {
let get = |i: usize| -> u8 {
match file_data.get(i) {
Some(byte) => *byte,
None => 0,
}
};
let getw = |i: usize| -> u16 { (get(i) as u16) + ((get(i + 1) as u16) << 8) };
let getd = |i: usize| -> u32 {
(get(i) as u32) + ((get(i + 1) as u32) << 8) + ((get(i + 2) as u32) << 16) +
((get(i + 3) as u32) << 24)
};
let gets = |start: usize, len: usize| -> String {
(start..start + len).map(|i| get(i) as char).collect::<String>()
};
let mut ret: BmpFile;
if gets(0, 2) == "BM" {
//let file_size = getd(2);
let offset = getd(0xA);
//let header_size = getd(0xE);
let width = getd(0x12);
let height = getd(0x16);
let depth = getw(0x1C) as u32;
let bytes = (depth + 7) / 8;
let row_bytes = (depth * width + 31) / 32 * 4;
let mut blue_mask = 0xFF;
let mut green_mask = 0xFF00;
let mut red_mask = 0xFF0000;
let mut alpha_mask = 0xFF000000;
if getd(0x1E) == 3 {
red_mask = getd(0x36);
green_mask = getd(0x3A);
blue_mask = getd(0x3E);
alpha_mask = getd(0x42);
}
let mut blue_shift = 0;
while blue_mask > 0 && blue_shift < 32 && (blue_mask >> blue_shift) & 1 == 0 {
blue_shift += 1;
}
let mut green_shift = 0;
while green_mask > 0 && green_shift < 32 && (green_mask >> green_shift) & 1 == 0 {
green_shift += 1;
}
let mut red_shift = 0;
while red_mask > 0 && red_shift < 32 && (red_mask >> red_shift) & 1 == 0 {
red_shift += 1;
}
let mut alpha_shift = 0;
while alpha_mask > 0 && alpha_shift < 32 && (alpha_mask >> alpha_shift) & 1 == 0 {
alpha_shift += 1;
}
ret = Self::new(width as usize, height as usize);
for y in 0..height {
for x in 0..width {
let pixel_offset = offset + (height - y - 1) * row_bytes + x * bytes;
let pixel_data = getd(pixel_offset as usize);
let red = ((pixel_data & red_mask) >> red_shift) as u8;
let green = ((pixel_data & green_mask) >> green_shift) as u8;
let blue = ((pixel_data & blue_mask) >> blue_shift) as u8;
let alpha = ((pixel_data & alpha_mask) >> alpha_shift) as u8;
if bytes == 3 {
ret.data.push(Color::rgb(red,green,blue));
} else if bytes == 4 {
ret.data.push(Color::rgba(red,green,blue,alpha));
}
}
}
} else {
ret = Self::default();
}
ret
}
/// Convert to slice for drawing
pub fn as_slice(&self) -> &[Color] {
&self.data
}
pub fn width(&self) -> usize {
self.w
}
pub fn height(&self) -> usize {
self.h
}
}
use redox::{Box, String, ToString, Vec};
use redox::rand_old::*;
use super::*;
/// A console char
pub struct ConsoleChar {
/// The char
character: char,
/// The color
color: Color,
}
/// A console window
pub struct ConsoleWindow {
/// The window
pub window: Box<Window>,
/// The char buffer
pub output: Vec<ConsoleChar>,
/// Previous commands
pub history: Vec<String>,
/// History index
pub history_i: usize,
/// Offset
pub offset: usize,
/// Scroll distance x
pub scroll_x: isize,
/// Scroll distance y
pub scroll_y: isize,
/// Wrap the text, if true
pub wrap: bool,
}
impl ConsoleWindow {
/// Create a new console window
pub fn new(x: isize, y: isize, w: usize, h: usize, title: &str) -> Box<Self> {
box ConsoleWindow {
window: Window::new(x, y, w, h, title).unwrap(),
output: Vec::new(),
history: vec!["".to_string()],
history_i: 0,
offset: 0,
scroll_x: 0,
scroll_y: 0,
wrap: true,
}
}
/// Set the window title
pub fn set_title(&mut self, title: &str) {
//TODO THIS IS A HACK, should use self.window.setTitle(title);
self.window = Window::new(self.window.x(),
self.window.y(),
self.window.width(),
self.window.height(),
title).unwrap();
}
/// Poll the window
pub fn poll(&mut self) -> Option<Event> {
self.window.poll()
}
/// Print to the window
pub fn print(&mut self, string: &str, color: Color) {
for c in string.chars() {
self.output.push(ConsoleChar {
character: c,
color: color,
});
}
}
/// Read input
pub fn read(&mut self) -> Option<String> {
while let Some(event) = self.poll() {
if let EventOption::Key(key_event) = event.to_option() {
if key_event.pressed {
match key_event.scancode {
K_BKSP => if self.offset > 0 {
self.history[self.history_i] = self.history[self.history_i][0 .. self.offset - 1].to_string() +
&self.history[self.history_i][self.offset ..];
self.offset -= 1;
},
K_DEL => if self.offset < self.history[self.history_i].len() {
self.history[self.history_i] =
self.history[self.history_i][0 .. self.offset].to_string() +
&self.history[self.history_i][self.offset + 1 .. self.history[self.history_i].len() - 1];
},
K_HOME => self.offset = 0,
K_UP => {
if self.history_i + 1 < self.history.len() {
self.history_i += 1;
}
self.offset = self.history[self.history_i].len();
}
K_LEFT => if self.offset > 0 {
self.offset -= 1;
},
K_RIGHT => if self.offset < self.history[self.history_i].len() {
self.offset += 1;
},
K_END => self.offset = self.history[self.history_i].len(),
K_DOWN => {
if self.history_i > 0 {
self.history_i -= 1;
}
self.offset = self.history[self.history_i].len();
}
_ => match key_event.character {
'\x00' => (),
'\n' => {
let command = self.history[self.history_i].clone();
self.offset = 0;
self.history_i = 0;
if !self.history[0].is_empty() {
self.history.insert(0, "".to_string());
}
while self.history.len() > 1000 {
self.history.pop();
}
return Some(command);
}
'\x1B' => break,
_ => {
self.history[self.history_i] = self.history[self.history_i][0 .. self.offset].to_string() +
&key_event.character.to_string() +
&self.history[self.history_i][self.offset ..];
self.offset += 1;
}
},
}
}
self.sync();
}
}
return None;
}
/// Redraw the window
pub fn sync(&mut self) {
let scroll_x = self.scroll_x;
let scroll_y = self.scroll_y;
let mut col = -scroll_x;
let cols = self.window.width() as isize / 8;
let mut row = -scroll_y;
let rows = self.window.height() as isize / 16;
{
self.window.set(Color::BLACK);
for c in self.output.iter() {
if self.wrap && col >= cols {
col = -scroll_x;
row += 1;
}
if c.character == '\n' {
col = -scroll_x;
row += 1;
} else if c.character == '\t' {
col += 8 - col % 8;
} else {
if col >= 0 && col < cols && row >= 0 && row < rows {
self.window.char(8 * col, 16 * row, c.character, c.color);
}
col += 1;
}
}
if col > -scroll_x {
col = -scroll_x;
row += 1;
}
if col >= 0 && col < cols && row >= 0 && row < rows {
self.window.char(8 * col, 16 * row, '#', Color::WHITE);
col += 2;
}
let mut i = 0;
for c in self.history[self.history_i].chars() {
if self.wrap && col >= cols {
col = -scroll_x;
row += 1;
}
if self.offset == i && col >= 0 && col < cols && row >= 0 && row < rows {
self.window.char(8 * col, 16 * row, '_', Color::WHITE);
}
if c == '\n' {
col = -scroll_x;
row += 1;
} else if c == '\t' {
col += 8 - col % 8;
} else {
if col >= 0 && col < cols && row >= 0 && row < rows {
self.window.char(8 * col, 16 * row, c, Color::WHITE);
}
col += 1;
}
i += 1;
}
if self.wrap && col >= cols {
col = -scroll_x;
row += 1;
}
if self.offset == i && col >= 0 && col < cols && row >= 0 && row < rows {
self.window.char(8 * col, 16 * row, '_', Color::WHITE);
}
}
self.window.sync();
if row >= rows {
self.scroll_y += row - rows + 1;
self.sync();
}
}
}
use core::char;
/// An optional event
#[derive(Copy, Clone)]
pub enum EventOption {
/// A mouse event
Mouse(MouseEvent),
/// A key event
Key(KeyEvent),
/// A quit request event
Quit(QuitEvent),
/// An unknown event
Unknown(Event),
/// No event
None,
}
/// An event
#[derive(Copy, Clone)]
#[repr(packed)]
pub struct Event {
pub code: char,
pub a: isize,
pub b: isize,
pub c: isize,
}
impl Event {
/// Create a null event
pub fn new() -> Event {
Event {
code: '\0',
a: 0,
b: 0,
c: 0,
}
}
/// Convert the event ot an optional event
// TODO: Consider doing this via a From trait.
pub fn to_option(self) -> EventOption {
match self.code {
'm' => EventOption::Mouse(MouseEvent::from_event(self)),
'k' => EventOption::Key(KeyEvent::from_event(self)),
'q' => EventOption::Quit(QuitEvent::from_event(self)),
'\0' => EventOption::None,
_ => EventOption::Unknown(self),
}
}
}
/// A event related to the mouse
#[derive(Copy, Clone)]
pub struct MouseEvent {
/// The x coordinate of the mouse
pub x: isize,
/// The y coordinate of the mouse
pub y: isize,
/// Was the left button pressed?
pub left_button: bool,
/// Was the middle button pressed?
pub middle_button: bool,
/// Was the right button pressed?
pub right_button: bool,
}
impl MouseEvent {
/// Convert to an `Event`
pub fn to_event(&self) -> Event {
Event {
code: 'm',
a: self.x,
b: self.y,
c: self.left_button as isize | (self.middle_button as isize) << 1 | (self.right_button as isize) << 2,
}
}
/// Convert an `Event` to a `MouseEvent`
pub fn from_event(event: Event) -> MouseEvent {
MouseEvent {
x: event.a,
y: event.b,
left_button: event.c & 1 == 1,
middle_button: event.c & 2 == 2,
right_button: event.c & 4 == 4,
}
}
}
/// Escape key
pub const K_ESC: u8 = 0x01;
/// Backspace key
pub const K_BKSP: u8 = 0x0E;
/// Tab key
pub const K_TAB: u8 = 0x0F;
/// Control key
pub const K_CTRL: u8 = 0x1D;
/// Alt key
pub const K_ALT: u8 = 0x38;
/// F1 key
pub const K_F1: u8 = 0x3B;
/// F2 key
pub const K_F2: u8 = 0x3C;
/// F3 key
pub const K_F3: u8 = 0x3D;
/// F4 key
pub const K_F4: u8 = 0x3E;
/// F5 key
pub const K_F5: u8 = 0x3F;
/// F6 key
pub const K_F6: u8 = 0x40;
/// F7 key
pub const K_F7: u8 = 0x41;
/// F8 key
pub const K_F8: u8 = 0x42;
/// F9 key
pub const K_F9: u8 = 0x43;
/// F10 key
pub const K_F10: u8 = 0x44;
/// Home key
pub const K_HOME: u8 = 0x47;
/// Up key
pub const K_UP: u8 = 0x48;
/// Page up key
pub const K_PGUP: u8 = 0x49;
/// Left key
pub const K_LEFT: u8 = 0x4B;
/// Right key
pub const K_RIGHT: u8 = 0x4D;
/// End key
pub const K_END: u8 = 0x4F;
/// Down key
pub const K_DOWN: u8 = 0x50;
/// Page down key
pub const K_PGDN: u8 = 0x51;
/// Delete key
pub const K_DEL: u8 = 0x53;
/// F11 key
pub const K_F11: u8 = 0x57;
/// F12 key
pub const K_F12: u8 = 0x58;
/// Left shift
pub const K_LEFT_SHIFT: u8 = 0x2A;
/// Right shift
pub const K_RIGHT_SHIFT: u8 = 0x36;
/// A key event (such as a pressed key)
#[derive(Copy, Clone)]
pub struct KeyEvent {
/// The charecter of the key
pub character: char,
/// The scancode of the key
pub scancode: u8,
/// Was it pressed?
pub pressed: bool,
}
impl KeyEvent {
/// Convert to an `Event`
pub fn to_event(&self) -> Event {
Event {
code: 'k',
a: self.character as isize,
b: self.scancode as isize,
c: self.pressed as isize,
}
}
/// Convert from an `Event`
pub fn from_event(event: Event) -> KeyEvent {
KeyEvent {
character: char::from_u32(event.a as u32).unwrap_or('\0'),
scancode: event.b as u8,
pressed: event.c > 0,
}
}
}
#[derive(Copy, Clone)]
pub struct QuitEvent;
impl QuitEvent {
pub fn to_event(&self) -> Event {
Event {
code: 'q',
a: 0,
b: 0,
c: 0,
}
}
pub fn from_event(_: Event) -> QuitEvent {
QuitEvent
}
}
/// A color
#[derive(Copy, Clone)]
pub struct Color {
pub data: u32,
}
impl Color {
/// Create a new color from RGB
pub fn rgb(r: u8, g: u8, b: u8) -> Self {
Color { data: 0xFF000000 | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32) }
}
/// Set the alpha
pub fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
Color { data: ((a as u32) << 24) | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32) }
}
// Why are these consts inside an impl?
pub const BLACK: Color = Color { data: 0xFF000000 };
pub const BLUE: Color = Color { data: 0xFF0000FF };
pub const GREEN: Color = Color { data: 0xFF00FF00 };
pub const RED: Color = Color { data: 0xFFFF0000 };
pub const WHITE: Color = Color { data: 0xFFFFFFFF };
}
pub mod color;
pub mod point;
pub mod size;
use redox::ops::{Add, Sub};
/// A point
#[derive(Copy, Clone)]
pub struct Point {
pub x: isize,
pub y: isize,
}
impl Point {
/// Create a new point
pub fn new(x: isize, y: isize) -> Self {
Point { x: x, y: y }
}
}
impl Add for Point {
type Output = Point;
fn add(self, other: Point) -> Self::Output {
Point {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
impl Sub for Point {
type Output = Point;
fn sub(self, other: Point) -> Self::Output {
Point {
x: self.x - other.x,
y: self.y - other.y,
}
}