1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
pub mod cli;
pub mod colours;
pub mod config;
pub mod editor;
pub mod grid;
pub mod gui;
pub mod input;
pub mod map;
pub mod snapping;
pub mod svg;
pub mod tool;
pub mod transform;
use crate::net::Connection;
use cli::CLI;
use config::Config;
use editor::Editor;
use float_cmp::F64Margin;
use gui::{DimensionIndicator, ToolSidebar};
use input::Input;
use raylib::prelude::*;
use snapping::Snapper;
use std::ffi::CString;
use std::io;
use std::net::{SocketAddr, TcpStream};
use transform::Transform;
/// Location of the file containing the style used for the raylib user interface.
pub const GUI_STYLE: &str = "assets/style/cyber.rgs";
/// Location of the graf karto configuration options file.
pub const CONFIG_FILE: &str = "config.ron";
/// The acceptable error that is used throughout the project for two floats to be considered equal.
/// If it is set too low, the editor might not work properly, if set too high, the granularity may
/// become too low for certain purposes.
pub const FLOAT_MARGIN: F64Margin = F64Margin {
epsilon: 10000. * f64::EPSILON,
ulps: 0,
};
pub fn run(server_address: SocketAddr) {
let (mut rl, thread) = raylib::init().resizable().title("Hello there!").build();
rl.set_target_fps(120);
rl.set_exit_key(None);
// Load the configuration file, if available.
let config = match Config::from_file(CONFIG_FILE) {
Ok(config) => config,
Err(err) => {
/* Create a default config file if it doesn't exist, otherwise leave the incorrectly
* formatted/corrupted or otherwise unreadable file alone.
*/
let config = Config::default();
if err.kind() == io::ErrorKind::NotFound {
warn!("Could not find a configuration file. Creating default.");
config
.write_file(CONFIG_FILE)
.expect("Could not write config file.");
} else {
error!(
"Could not read configuration file: {}\nUsing defaults for this run.",
err
);
}
config
}
};
// Load the preferred gui style
rl.gui_load_style(Some(
&CString::new(GUI_STYLE).expect("Could not create C string from style file name"),
));
// Connect to the server at the given address.
let server = TcpStream::connect(server_address).expect("Unable to connect to the server.");
info!(
"Connection to server on `{:?}` established",
server.peer_addr()
);
let server = Connection::new(server);
let mut input = Input::new(&rl);
config::register_bindings(&config, &mut input);
let mut editor = Editor::new(&mut rl, &thread, config, server);
let mut dimension_indicator = DimensionIndicator::new();
let mut tool_sidebar = ToolSidebar::new(&mut rl, &thread, &mut input);
let mut snapper = Snapper::default();
let mut cli = CLI::new(&mut input);
let mut transform = Transform::new();
let mut last_mouse_pos = rl.get_mouse_position();
while !rl.window_should_close() {
let screen_width = rl.get_screen_width();
let screen_height = rl.get_screen_height();
input.update(&mut rl);
// Move the canvas together with the mouse
if rl.is_mouse_button_down(MouseButton::MOUSE_MIDDLE_BUTTON) {
transform.move_by_px(&(rl.get_mouse_position() - last_mouse_pos).into());
}
// Update the last mouse position
last_mouse_pos = rl.get_mouse_position();
let mouse_wheel_move = rl.get_mouse_wheel_move();
if mouse_wheel_move != 0. {
// Zoom in for positive and zoom out for negative mouse wheel rotations.
let scale_factor = if mouse_wheel_move > 0. { 1.2 } else { 1. / 1.2 };
transform.try_zoom(
&rl.get_mouse_position().into(),
mouse_wheel_move.abs() as f64 * scale_factor,
);
}
cli.update(&mut editor, &mut input);
dimension_indicator.update(&mut editor, &mut rl);
snapper.update(&mut rl, cli.active());
editor.update(&mut rl, &transform, &snapper, &mut input);
tool_sidebar.update(screen_height as u16, &mut input);
// Drawing section
{
let mut d = rl.begin_drawing(&thread);
d.clear_background(Color::BLACK);
grid::draw_grid(&mut d, screen_width, screen_height, &transform);
editor.map().draw(&mut d, &transform);
editor.draw_tools(&mut d, &transform);
tool_sidebar.draw(&mut d, &mut editor);
snapper.draw(&mut d);
gui::position_indicator_draw(&mut d, last_mouse_pos.into(), &transform, &snapper);
dimension_indicator.draw(&mut d, &transform);
cli.draw(&mut d);
}
}
}
|