slider construction
This commit is contained in:
parent
d543ab4565
commit
b8752dfd51
7 changed files with 164 additions and 47 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -1455,11 +1455,12 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libosu"
|
name = "libosu"
|
||||||
version = "0.0.16"
|
version = "0.0.16"
|
||||||
source = "git+https://github.com/iptq/libosu?rev=0229c52759ffb70322384e53abb0112cb52e49ae#0229c52759ffb70322384e53abb0112cb52e49ae"
|
source = "git+https://github.com/iptq/libosu?rev=81677d5ed88936c4a3e64af951ff0ae523c2d403#81677d5ed88936c4a3e64af951ff0ae523c2d403"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"derive_more",
|
"derive_more",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
"log",
|
||||||
"num",
|
"num",
|
||||||
"num-derive",
|
"num-derive",
|
||||||
"num-rational",
|
"num-rational",
|
||||||
|
|
|
@ -26,7 +26,7 @@ image = "0.23.12"
|
||||||
|
|
||||||
[dependencies.libosu]
|
[dependencies.libosu]
|
||||||
git = "https://github.com/iptq/libosu"
|
git = "https://github.com/iptq/libosu"
|
||||||
rev = "0229c52759ffb70322384e53abb0112cb52e49ae"
|
rev = "81677d5ed88936c4a3e64af951ff0ae523c2d403"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
clippy = []
|
clippy = []
|
||||||
|
|
|
@ -16,9 +16,9 @@ macro_rules! extern_log {
|
||||||
}
|
}
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
$vis unsafe fn $name ($($arg: $argty,)*) $(-> $ty)? {
|
$vis unsafe fn $name ($($arg: $argty,)*) $(-> $ty)? {
|
||||||
log::debug!("entering {} ({:?})", stringify!($name), ($($arg,)*));
|
log::trace!("entering {} ({:?})", stringify!($name), ($($arg,)*));
|
||||||
let result = paste::expr! { self::[< __inner_ffi_ $name >]::$name($($arg,)*) };
|
let result = paste::expr! { self::[< __inner_ffi_ $name >]::$name($($arg,)*) };
|
||||||
log::debug!("exiting {} => {:?}", stringify!($name), result);
|
log::trace!("exiting {} => {:?}", stringify!($name), result);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
|
|
|
@ -75,11 +75,7 @@ impl BeatmapExt {
|
||||||
let object_n_pos: Point<f64> = object_n.inner.pos.to_float().unwrap();
|
let object_n_pos: Point<f64> = object_n.inner.pos.to_float().unwrap();
|
||||||
if stack_base_pos.distance(object_n_pos) < STACK_DISTANCE
|
if stack_base_pos.distance(object_n_pos) < STACK_DISTANCE
|
||||||
|| (stack_base_obj.inner.kind.is_slider()
|
|| (stack_base_obj.inner.kind.is_slider()
|
||||||
&& stack_base_obj
|
&& stack_base_obj.inner.end_pos().distance(object_n_pos)
|
||||||
.inner
|
|
||||||
.end_pos()
|
|
||||||
.unwrap()
|
|
||||||
.distance(object_n_pos)
|
|
||||||
< STACK_DISTANCE)
|
< STACK_DISTANCE)
|
||||||
{
|
{
|
||||||
stack_base_idx = n;
|
stack_base_idx = n;
|
||||||
|
@ -146,7 +142,6 @@ impl BeatmapExt {
|
||||||
&& self.hit_objects[n]
|
&& self.hit_objects[n]
|
||||||
.inner
|
.inner
|
||||||
.end_pos()
|
.end_pos()
|
||||||
.unwrap()
|
|
||||||
.distance(self.hit_objects[iidx].inner.pos.to_float().unwrap())
|
.distance(self.hit_objects[iidx].inner.pos.to_float().unwrap())
|
||||||
< STACK_DISTANCE
|
< STACK_DISTANCE
|
||||||
{
|
{
|
||||||
|
@ -157,7 +152,6 @@ impl BeatmapExt {
|
||||||
if self.hit_objects[n]
|
if self.hit_objects[n]
|
||||||
.inner
|
.inner
|
||||||
.end_pos()
|
.end_pos()
|
||||||
.unwrap()
|
|
||||||
.distance(self.hit_objects[j].inner.pos.to_float().unwrap())
|
.distance(self.hit_objects[j].inner.pos.to_float().unwrap())
|
||||||
< STACK_DISTANCE
|
< STACK_DISTANCE
|
||||||
{
|
{
|
||||||
|
@ -202,7 +196,6 @@ impl BeatmapExt {
|
||||||
if self.hit_objects[n]
|
if self.hit_objects[n]
|
||||||
.inner
|
.inner
|
||||||
.end_pos()
|
.end_pos()
|
||||||
.unwrap()
|
|
||||||
.distance(self.hit_objects[iidx].inner.pos.to_float().unwrap())
|
.distance(self.hit_objects[iidx].inner.pos.to_float().unwrap())
|
||||||
< STACK_DISTANCE
|
< STACK_DISTANCE
|
||||||
{
|
{
|
||||||
|
|
105
src/game/mod.rs
105
src/game/mod.rs
|
@ -22,10 +22,10 @@ use ggez::{
|
||||||
use image::io::Reader as ImageReader;
|
use image::io::Reader as ImageReader;
|
||||||
use libosu::{
|
use libosu::{
|
||||||
beatmap::Beatmap,
|
beatmap::Beatmap,
|
||||||
hitobject::{HitObjectKind, SpinnerInfo},
|
hitobject::{HitObjectKind, SliderSplineKind, SpinnerInfo},
|
||||||
math::Point,
|
math::Point,
|
||||||
spline::Spline,
|
spline::Spline,
|
||||||
timing::{TimingPoint, TimingPointKind},
|
timing::{TimestampMillis, TimingPoint, TimingPointKind},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::audio::{AudioEngine, Sound};
|
use crate::audio::{AudioEngine, Sound};
|
||||||
|
@ -65,6 +65,7 @@ pub struct Game {
|
||||||
combo_colors: Vec<Color>,
|
combo_colors: Vec<Color>,
|
||||||
selected_objects: Vec<usize>,
|
selected_objects: Vec<usize>,
|
||||||
tool: Tool,
|
tool: Tool,
|
||||||
|
partial_slider_state: Option<(SliderSplineKind, Vec<Point<i32>>)>,
|
||||||
|
|
||||||
keymap: HashSet<KeyCode>,
|
keymap: HashSet<KeyCode>,
|
||||||
mouse_pos: (f32, f32),
|
mouse_pos: (f32, f32),
|
||||||
|
@ -101,6 +102,7 @@ impl Game {
|
||||||
left_drag_start: None,
|
left_drag_start: None,
|
||||||
right_drag_start: None,
|
right_drag_start: None,
|
||||||
tool: Tool::Select,
|
tool: Tool::Select,
|
||||||
|
partial_slider_state: None,
|
||||||
current_uninherited_timing_point: None,
|
current_uninherited_timing_point: None,
|
||||||
current_inherited_timing_point: None,
|
current_inherited_timing_point: None,
|
||||||
})
|
})
|
||||||
|
@ -195,6 +197,7 @@ impl Game {
|
||||||
self.draw_grid(ctx)?;
|
self.draw_grid(ctx)?;
|
||||||
|
|
||||||
let time = self.song.as_ref().unwrap().position()?;
|
let time = self.song.as_ref().unwrap().position()?;
|
||||||
|
let time_millis = TimestampMillis((time * 1000.0) as i32);
|
||||||
let text = Text::new(format!("time: {:.4}, mouse: {:?}", time, self.mouse_pos).as_ref());
|
let text = Text::new(format!("time: {:.4}, mouse: {:?}", time, self.mouse_pos).as_ref());
|
||||||
graphics::queue_text(ctx, &text, [0.0, 0.0], Some(WHITE));
|
graphics::queue_text(ctx, &text, [0.0, 0.0], Some(WHITE));
|
||||||
graphics::draw_queued_text(ctx, DrawParam::default(), None, FilterMode::Linear)?;
|
graphics::draw_queued_text(ctx, DrawParam::default(), None, FilterMode::Linear)?;
|
||||||
|
@ -238,7 +241,8 @@ impl Game {
|
||||||
end_time: spinner_end,
|
end_time: spinner_end,
|
||||||
}) => end_time = (spinner_end.0 as f64) / 1000.0,
|
}) => end_time = (spinner_end.0 as f64) / 1000.0,
|
||||||
};
|
};
|
||||||
if ho_time - preempt < time && time < end_time {
|
|
||||||
|
if ho_time - preempt <= time && time <= end_time {
|
||||||
playfield_hitobjects.push(DrawInfo {
|
playfield_hitobjects.push(DrawInfo {
|
||||||
hit_object: ho,
|
hit_object: ho,
|
||||||
opacity,
|
opacity,
|
||||||
|
@ -273,19 +277,18 @@ impl Game {
|
||||||
|
|
||||||
let mut color = color;
|
let mut color = color;
|
||||||
color.a = 0.6 * draw_info.opacity as f32;
|
color.a = 0.6 * draw_info.opacity as f32;
|
||||||
let spline = Game::render_slider(
|
Game::render_slider_body(
|
||||||
&mut self.slider_cache,
|
&mut self.slider_cache,
|
||||||
info,
|
info,
|
||||||
control_points.as_ref(),
|
control_points.as_ref(),
|
||||||
ctx,
|
ctx,
|
||||||
PLAYFIELD_BOUNDS,
|
PLAYFIELD_BOUNDS,
|
||||||
&self.beatmap.inner,
|
&self.beatmap.inner,
|
||||||
&ho.inner,
|
|
||||||
color,
|
color,
|
||||||
)?;
|
)?;
|
||||||
slider_info = Some((info, control_points));
|
slider_info = Some((info, control_points));
|
||||||
|
|
||||||
let end_pos = ho.inner.end_pos().unwrap();
|
let end_pos = ho.inner.end_pos();
|
||||||
let end_pos = [
|
let end_pos = [
|
||||||
PLAYFIELD_BOUNDS.x + osupx_scale_x * end_pos.x as f32,
|
PLAYFIELD_BOUNDS.x + osupx_scale_x * end_pos.x as f32,
|
||||||
PLAYFIELD_BOUNDS.y + osupx_scale_y * end_pos.y as f32,
|
PLAYFIELD_BOUNDS.y + osupx_scale_y * end_pos.y as f32,
|
||||||
|
@ -363,6 +366,9 @@ impl Game {
|
||||||
|
|
||||||
// draw whatever tool user is using
|
// draw whatever tool user is using
|
||||||
let (mx, my) = self.mouse_pos;
|
let (mx, my) = self.mouse_pos;
|
||||||
|
let pos_x = (mx - PLAYFIELD_BOUNDS.x) / PLAYFIELD_BOUNDS.w * 512.0;
|
||||||
|
let pos_y = (my - PLAYFIELD_BOUNDS.y) / PLAYFIELD_BOUNDS.h * 384.0;
|
||||||
|
let mouse_pos = Point::new(pos_x as i32, pos_y as i32);
|
||||||
match self.tool {
|
match self.tool {
|
||||||
Tool::Select => {
|
Tool::Select => {
|
||||||
let (mx, my) = self.mouse_pos;
|
let (mx, my) = self.mouse_pos;
|
||||||
|
@ -399,6 +405,68 @@ impl Game {
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Tool::Slider => {
|
||||||
|
let color = Color::new(1.0, 1.0, 1.0, 0.4);
|
||||||
|
if let Some((kind, nodes)) = &self.partial_slider_state {
|
||||||
|
let mut nodes2 = nodes.clone();
|
||||||
|
let mut kind = *kind;
|
||||||
|
if let Some(last) = nodes2.last() {
|
||||||
|
if mouse_pos != *last {
|
||||||
|
nodes2.push(mouse_pos);
|
||||||
|
if kind == SliderSplineKind::Linear && nodes2.len() == 3 {
|
||||||
|
kind = SliderSplineKind::Perfect;
|
||||||
|
} else if kind == SliderSplineKind::Perfect && nodes2.len() == 4 {
|
||||||
|
kind = SliderSplineKind::Bezier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if nodes2.len() > 1 && !(nodes2.len() == 2 && nodes2[0] == nodes2[1]) {
|
||||||
|
let slider_velocity =
|
||||||
|
self.beatmap.inner.get_slider_velocity_at_time(time_millis);
|
||||||
|
let slider_multiplier = self.beatmap.inner.difficulty.slider_multiplier;
|
||||||
|
let pixels_per_beat = slider_multiplier * 100.0 * slider_velocity;
|
||||||
|
let pixels_per_tick = pixels_per_beat / 4.0; // TODO: FIX!!!
|
||||||
|
|
||||||
|
let mut spline = Spline::from_control(kind, &nodes2, None);
|
||||||
|
let len = spline.pixel_length();
|
||||||
|
debug!("original len: {}", len);
|
||||||
|
let num_ticks = (len / pixels_per_tick).floor();
|
||||||
|
debug!("num ticks: {}", num_ticks);
|
||||||
|
|
||||||
|
let fixed_len = num_ticks * pixels_per_tick;
|
||||||
|
debug!("fixed len: {}", fixed_len);
|
||||||
|
spline.truncate(fixed_len);
|
||||||
|
|
||||||
|
debug!("len: {}", spline.pixel_length());
|
||||||
|
Game::render_spline(
|
||||||
|
ctx,
|
||||||
|
&self.beatmap.inner,
|
||||||
|
&spline,
|
||||||
|
PLAYFIELD_BOUNDS,
|
||||||
|
color,
|
||||||
|
)?;
|
||||||
|
debug!("done rendering slider body");
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::render_slider_wireframe(ctx, &nodes2, PLAYFIELD_BOUNDS)?;
|
||||||
|
debug!("done rendering slider wireframe");
|
||||||
|
} else {
|
||||||
|
if rect_contains(&PLAYFIELD_BOUNDS, mx, my) {
|
||||||
|
let pos = [mx, my];
|
||||||
|
self.skin.hitcircle.draw(
|
||||||
|
ctx,
|
||||||
|
(cs_real * 2.0, cs_real * 2.0),
|
||||||
|
DrawParam::default().dest(pos).color(color),
|
||||||
|
)?;
|
||||||
|
self.skin.hitcircleoverlay.draw(
|
||||||
|
ctx,
|
||||||
|
(cs_real * 2.0, cs_real * 2.0),
|
||||||
|
DrawParam::default().dest(pos).color(color),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,6 +550,10 @@ impl Game {
|
||||||
|
|
||||||
fn handle_click(&mut self, btn: MouseButton, x: f32, y: f32) -> Result<()> {
|
fn handle_click(&mut self, btn: MouseButton, x: f32, y: f32) -> Result<()> {
|
||||||
println!("handled click {}", self.song.is_some());
|
println!("handled click {}", self.song.is_some());
|
||||||
|
let pos_x = (x - PLAYFIELD_BOUNDS.x) / PLAYFIELD_BOUNDS.w * 512.0;
|
||||||
|
let pos_y = (y - PLAYFIELD_BOUNDS.y) / PLAYFIELD_BOUNDS.h * 384.0;
|
||||||
|
let pos = Point::new(pos_x as i32, pos_y as i32);
|
||||||
|
|
||||||
if let Some(song) = &self.song {
|
if let Some(song) = &self.song {
|
||||||
println!("song exists! {:?} {:?}", btn, self.tool);
|
println!("song exists! {:?} {:?}", btn, self.tool);
|
||||||
if let (MouseButton::Left, Tool::Select) = (btn, &self.tool) {
|
if let (MouseButton::Left, Tool::Select) = (btn, &self.tool) {
|
||||||
|
@ -504,18 +576,16 @@ impl Game {
|
||||||
timing::TimestampMillis,
|
timing::TimestampMillis,
|
||||||
};
|
};
|
||||||
|
|
||||||
let pos_x = (x - PLAYFIELD_BOUNDS.x) / PLAYFIELD_BOUNDS.w * 512.0;
|
|
||||||
let pos_y = (y - PLAYFIELD_BOUNDS.y) / PLAYFIELD_BOUNDS.h * 384.0;
|
|
||||||
let inner = HitObject {
|
let inner = HitObject {
|
||||||
start_time: TimestampMillis(time),
|
start_time: TimestampMillis(time),
|
||||||
pos: Point::new(pos_x as i32, pos_y as i32),
|
pos,
|
||||||
kind: HitObjectKind::Circle,
|
kind: HitObjectKind::Circle,
|
||||||
new_combo: false,
|
new_combo: false,
|
||||||
skip_color: 0,
|
skip_color: 0,
|
||||||
additions: Additions::empty(),
|
additions: Additions::empty(),
|
||||||
sample_info: SampleInfo::default(),
|
sample_info: SampleInfo::default(),
|
||||||
timing_point: None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let new_obj = HitObjectExt {
|
let new_obj = HitObjectExt {
|
||||||
inner,
|
inner,
|
||||||
stacking: 0,
|
stacking: 0,
|
||||||
|
@ -529,6 +599,21 @@ impl Game {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if let (MouseButton::Left, Tool::Slider) = (btn, &self.tool) {
|
||||||
|
if let Some((ref mut kind, ref mut nodes)) = &mut self.partial_slider_state {
|
||||||
|
nodes.push(pos);
|
||||||
|
if *kind == SliderSplineKind::Linear && nodes.len() == 3 {
|
||||||
|
*kind = SliderSplineKind::Perfect;
|
||||||
|
} else if *kind == SliderSplineKind::Perfect && nodes.len() == 4 {
|
||||||
|
*kind = SliderSplineKind::Bezier;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.partial_slider_state = Some((SliderSplineKind::Linear, vec![pos]));
|
||||||
|
}
|
||||||
|
} else if let (MouseButton::Right, Tool::Slider) = (btn, &self.tool) {
|
||||||
|
if let Some(_) = &mut self.partial_slider_state {
|
||||||
|
self.partial_slider_state = None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -17,25 +17,13 @@ use libosu::{
|
||||||
use super::{Game, SliderCache};
|
use super::{Game, SliderCache};
|
||||||
|
|
||||||
impl Game {
|
impl Game {
|
||||||
pub fn render_slider<'a>(
|
pub fn render_spline(
|
||||||
slider_cache: &'a mut SliderCache,
|
|
||||||
slider_info: &SliderInfo,
|
|
||||||
control_points: &[Point<i32>],
|
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
rect: Rect,
|
|
||||||
beatmap: &Beatmap,
|
beatmap: &Beatmap,
|
||||||
slider: &HitObject,
|
spline: &Spline,
|
||||||
|
rect: Rect,
|
||||||
color: Color,
|
color: Color,
|
||||||
) -> Result<&'a Spline> {
|
) -> Result<()> {
|
||||||
let spline = if slider_cache.contains_key(control_points) {
|
|
||||||
slider_cache.get(control_points).unwrap()
|
|
||||||
} else {
|
|
||||||
let new_spline =
|
|
||||||
Spline::from_control(slider_info.kind, control_points, slider_info.pixel_length);
|
|
||||||
slider_cache.insert(control_points.to_vec(), new_spline);
|
|
||||||
slider_cache.get(control_points).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let cs_scale = rect.w / 640.0;
|
let cs_scale = rect.w / 640.0;
|
||||||
let osupx_scale_x = rect.w as f64 / 512.0;
|
let osupx_scale_x = rect.w as f64 / 512.0;
|
||||||
let osupx_scale_y = rect.h as f64 / 384.0;
|
let osupx_scale_y = rect.h as f64 / 384.0;
|
||||||
|
@ -95,7 +83,52 @@ impl Game {
|
||||||
graphics::set_canvas(ctx, None);
|
graphics::set_canvas(ctx, None);
|
||||||
graphics::draw(ctx, &canvas, DrawParam::default().color(color))?;
|
graphics::draw(ctx, &canvas, DrawParam::default().color(color))?;
|
||||||
|
|
||||||
Ok(spline)
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_slider_body<'a>(
|
||||||
|
slider_cache: &'a mut SliderCache,
|
||||||
|
slider_info: &SliderInfo,
|
||||||
|
control_points: &[Point<i32>],
|
||||||
|
ctx: &mut Context,
|
||||||
|
rect: Rect,
|
||||||
|
beatmap: &Beatmap,
|
||||||
|
color: Color,
|
||||||
|
) -> Result<()> {
|
||||||
|
debug!(
|
||||||
|
"Rendering slider body with control points {:?}",
|
||||||
|
control_points
|
||||||
|
);
|
||||||
|
|
||||||
|
if control_points.len() < 2
|
||||||
|
|| (control_points.len() == 2 && control_points[0] == control_points[1])
|
||||||
|
{
|
||||||
|
debug!("Slider too short, not rendering!");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let spline = if slider_cache.contains_key(control_points) {
|
||||||
|
slider_cache.get(control_points).expect("just checked")
|
||||||
|
} else {
|
||||||
|
let new_spline = Spline::from_control(
|
||||||
|
slider_info.kind,
|
||||||
|
control_points,
|
||||||
|
Some(slider_info.pixel_length),
|
||||||
|
);
|
||||||
|
slider_cache.insert(control_points.to_vec(), new_spline);
|
||||||
|
slider_cache.get(control_points).expect("just inserted it")
|
||||||
|
};
|
||||||
|
debug!("spline length: {}", spline.spline_points.len());
|
||||||
|
|
||||||
|
if spline.spline_points.len() < 2
|
||||||
|
|| (spline.spline_points.len() == 2
|
||||||
|
&& spline.spline_points[0] == spline.spline_points[1])
|
||||||
|
{
|
||||||
|
debug!("Slider too short, not rendering!");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::render_spline(ctx, beatmap, spline, rect, color)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_slider_wireframe(
|
pub fn render_slider_wireframe(
|
||||||
|
@ -116,13 +149,17 @@ impl Game {
|
||||||
.collect::<Vec<Point2<_>>>();
|
.collect::<Vec<Point2<_>>>();
|
||||||
|
|
||||||
// draw control points wireframe
|
// draw control points wireframe
|
||||||
let frame = Mesh::new_polyline(
|
if control_points.len() > 1
|
||||||
ctx,
|
&& !(control_points.len() == 2 && control_points[0] == control_points[1])
|
||||||
DrawMode::Stroke(StrokeOptions::default()),
|
{
|
||||||
&points_mapped,
|
let frame = Mesh::new_polyline(
|
||||||
graphics::WHITE,
|
ctx,
|
||||||
)?;
|
DrawMode::Stroke(StrokeOptions::default()),
|
||||||
graphics::draw(ctx, &frame, DrawParam::default())?;
|
&points_mapped,
|
||||||
|
graphics::WHITE,
|
||||||
|
)?;
|
||||||
|
graphics::draw(ctx, &frame, DrawParam::default())?;
|
||||||
|
}
|
||||||
|
|
||||||
// draw points on wireframe
|
// draw points on wireframe
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
|
|
@ -41,8 +41,9 @@ fn main() -> Result<()> {
|
||||||
let opt = Opt::from_args();
|
let opt = Opt::from_args();
|
||||||
stderrlog::new()
|
stderrlog::new()
|
||||||
.module("editor")
|
.module("editor")
|
||||||
.module("bass_sys")
|
.module("libosu::spline")
|
||||||
.verbosity(opt.verbose)
|
.verbosity(opt.verbose)
|
||||||
|
.show_module_names(true)
|
||||||
.init()
|
.init()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue