draw ticks
This commit is contained in:
parent
448b8e4356
commit
300208e21a
4 changed files with 97 additions and 21 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -1037,8 +1037,8 @@ checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libosu"
|
name = "libosu"
|
||||||
version = "0.0.12"
|
version = "0.0.13"
|
||||||
source = "git+https://github.com/iptq/libosu?rev=332b7a55559c0257cc4d39577240b1cab5ed3d07#332b7a55559c0257cc4d39577240b1cab5ed3d07"
|
source = "git+https://github.com/iptq/libosu?rev=dee4d05eeaba1313a17eefbbd7679a947b52fbc1#dee4d05eeaba1313a17eefbbd7679a947b52fbc1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
|
|
|
@ -20,4 +20,4 @@ ordered-float = "2.0.1"
|
||||||
|
|
||||||
[dependencies.libosu]
|
[dependencies.libosu]
|
||||||
git = "https://github.com/iptq/libosu"
|
git = "https://github.com/iptq/libosu"
|
||||||
rev = "332b7a55559c0257cc4d39577240b1cab5ed3d07"
|
rev = "dee4d05eeaba1313a17eefbbd7679a947b52fbc1"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
mod timeline;
|
|
||||||
mod sliders;
|
mod sliders;
|
||||||
|
mod timeline;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
@ -114,8 +114,6 @@ impl Game {
|
||||||
color: Color,
|
color: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.draw_timeline(ctx, time)?;
|
|
||||||
|
|
||||||
let mut playfield_hitobjects = Vec::new();
|
let mut playfield_hitobjects = Vec::new();
|
||||||
let preempt = (self.beatmap.inner.difficulty.approach_preempt() as f64) / 1000.0;
|
let preempt = (self.beatmap.inner.difficulty.approach_preempt() as f64) / 1000.0;
|
||||||
let fade_in = (self.beatmap.inner.difficulty.approach_fade_time() as f64) / 1000.0;
|
let fade_in = (self.beatmap.inner.difficulty.approach_fade_time() as f64) / 1000.0;
|
||||||
|
@ -164,6 +162,8 @@ impl Game {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.draw_timeline(ctx, time)?;
|
||||||
|
|
||||||
let cs_scale = PLAYFIELD_BOUNDS.w / 640.0;
|
let cs_scale = PLAYFIELD_BOUNDS.w / 640.0;
|
||||||
let osupx_scale_x = PLAYFIELD_BOUNDS.w / 512.0;
|
let osupx_scale_x = PLAYFIELD_BOUNDS.w / 512.0;
|
||||||
let osupx_scale_y = PLAYFIELD_BOUNDS.h / 384.0;
|
let osupx_scale_y = PLAYFIELD_BOUNDS.h / 384.0;
|
||||||
|
|
|
@ -1,34 +1,108 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use ggez::{
|
use ggez::{
|
||||||
graphics::{self, DrawParam, Mesh, Rect},
|
graphics::{self, Color, DrawParam, Mesh, Rect, WHITE},
|
||||||
nalgebra::Point2,
|
nalgebra::Point2,
|
||||||
Context,
|
Context,
|
||||||
};
|
};
|
||||||
|
use libosu::TimingPointKind;
|
||||||
|
|
||||||
use crate::hit_object::HitObjectExt;
|
use crate::hit_object::HitObjectExt;
|
||||||
|
|
||||||
use super::Game;
|
use super::Game;
|
||||||
|
|
||||||
pub const TIMELINE_BOUNDS: Rect = Rect::new(0.0, 0.0, 1024.0, 108.0);
|
pub const BOUNDS: Rect = Rect::new(0.0, 54.0, 768.0, 54.0);
|
||||||
|
|
||||||
|
pub const RED: Color = Color::new(1.0, 0.0, 0.0, 1.0);
|
||||||
|
pub const BLUE: Color = Color::new(0.0, 0.0, 1.0, 1.0);
|
||||||
|
pub const TICKS: &[&[(Color, f32)]] = &[
|
||||||
|
&[],
|
||||||
|
&[],
|
||||||
|
&[],
|
||||||
|
&[],
|
||||||
|
&[(WHITE, 1.0), (BLUE, 0.5), (RED, 0.5), (BLUE, 0.5)],
|
||||||
|
];
|
||||||
|
|
||||||
impl Game {
|
impl Game {
|
||||||
pub(super) fn draw_timeline(&self, ctx: &mut Context, time: f64) -> Result<()> {
|
pub(super) fn draw_timeline(&self, ctx: &mut Context, time: f64) -> Result<()> {
|
||||||
let timeline_span = 6.0 / self.beatmap.inner.timeline_zoom;
|
let timeline_span = 6.0 / self.beatmap.inner.timeline_zoom;
|
||||||
let timeline_current_line_x = TIMELINE_BOUNDS.x + TIMELINE_BOUNDS.w * 0.5;
|
let timeline_left = time - timeline_span / 2.0;
|
||||||
|
let timeline_right = time + timeline_span / 2.0;
|
||||||
|
let timeline_current_line_x = BOUNDS.x + BOUNDS.w * 0.5;
|
||||||
|
|
||||||
|
// the vertical line
|
||||||
let current_line = Mesh::new_line(
|
let current_line = Mesh::new_line(
|
||||||
ctx,
|
ctx,
|
||||||
&[
|
&[
|
||||||
Point2::new(timeline_current_line_x, TIMELINE_BOUNDS.y),
|
Point2::new(timeline_current_line_x, BOUNDS.y),
|
||||||
Point2::new(
|
Point2::new(timeline_current_line_x, BOUNDS.y + BOUNDS.h),
|
||||||
timeline_current_line_x,
|
|
||||||
TIMELINE_BOUNDS.y + TIMELINE_BOUNDS.h,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
2.0,
|
2.0,
|
||||||
graphics::WHITE,
|
graphics::WHITE,
|
||||||
)?;
|
)?;
|
||||||
graphics::draw(ctx, ¤t_line, DrawParam::default())?;
|
graphics::draw(ctx, ¤t_line, DrawParam::default())?;
|
||||||
|
|
||||||
|
// timing sections in this little span
|
||||||
|
let mut last_uninherited = None;
|
||||||
|
for timing_points in self.beatmap.inner.timing_points.windows(2) {
|
||||||
|
let (fst, snd) = (&timing_points[0], &timing_points[1]);
|
||||||
|
let fst_time = fst.time.as_seconds();
|
||||||
|
let snd_time = snd.time.as_seconds();
|
||||||
|
if let TimingPointKind::Uninherited(info) = &fst.kind {
|
||||||
|
last_uninherited = Some(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(last_uninherited) = last_uninherited {
|
||||||
|
if (fst_time >= timeline_left && fst_time <= timeline_right)
|
||||||
|
|| (snd_time >= timeline_left && snd_time <= timeline_right)
|
||||||
|
|| (fst_time < timeline_left && snd_time > timeline_right)
|
||||||
|
{
|
||||||
|
// TODO: optimize this
|
||||||
|
let mut time = fst.time.as_seconds();
|
||||||
|
let beat = last_uninherited.mpb / 1000.0;
|
||||||
|
let ticks = TICKS[last_uninherited.meter as usize];
|
||||||
|
'outer: loop {
|
||||||
|
for i in 0..last_uninherited.meter as usize {
|
||||||
|
let tick_time = time + beat * i as f64 / last_uninherited.meter as f64;
|
||||||
|
if tick_time > snd_time.min(timeline_right) {
|
||||||
|
break 'outer;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (color, height) = ticks[i];
|
||||||
|
let percent =
|
||||||
|
(tick_time - timeline_left) / (timeline_right - timeline_left);
|
||||||
|
let x = percent as f32 * BOUNDS.w + BOUNDS.x;
|
||||||
|
let y2 = BOUNDS.y + BOUNDS.h;
|
||||||
|
let y1 = y2 - BOUNDS.h * 0.3 * height;
|
||||||
|
let tick = Mesh::new_line(
|
||||||
|
ctx,
|
||||||
|
&[Point2::new(x, y1), Point2::new(x, y2)],
|
||||||
|
1.0,
|
||||||
|
color,
|
||||||
|
)?;
|
||||||
|
graphics::draw(ctx, &tick, DrawParam::default())?;
|
||||||
|
}
|
||||||
|
time += beat;
|
||||||
|
|
||||||
|
if time >= snd_time.min(timeline_right) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw a bottom line for the timeline
|
||||||
|
let bottom_line = Mesh::new_line(
|
||||||
|
ctx,
|
||||||
|
&[
|
||||||
|
Point2::new(BOUNDS.x, BOUNDS.y + BOUNDS.h),
|
||||||
|
Point2::new(BOUNDS.x + BOUNDS.w, BOUNDS.y + BOUNDS.h),
|
||||||
|
],
|
||||||
|
2.0,
|
||||||
|
graphics::WHITE,
|
||||||
|
)?;
|
||||||
|
graphics::draw(ctx, &bottom_line, DrawParam::default())?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +117,8 @@ impl Game {
|
||||||
let timeline_right = time + timeline_span / 2.0;
|
let timeline_right = time + timeline_span / 2.0;
|
||||||
|
|
||||||
let ho_time = (ho.inner.start_time.0 as f64) / 1000.0;
|
let ho_time = (ho.inner.start_time.0 as f64) / 1000.0;
|
||||||
|
let end_time = (self.beatmap.inner.get_hitobject_end_time(&ho.inner).0 as f64) / 1000.0;
|
||||||
|
|
||||||
let color = self.beatmap.inner.colors[ho.color_idx];
|
let color = self.beatmap.inner.colors[ho.color_idx];
|
||||||
let color = graphics::Color::new(
|
let color = graphics::Color::new(
|
||||||
color.red as f32 / 256.0,
|
color.red as f32 / 256.0,
|
||||||
|
@ -51,23 +127,23 @@ impl Game {
|
||||||
1.0,
|
1.0,
|
||||||
);
|
);
|
||||||
|
|
||||||
if ho_time >= timeline_left && ho_time <= timeline_right {
|
if end_time >= timeline_left && ho_time <= timeline_right {
|
||||||
let timeline_percent = (ho_time - timeline_left) / (timeline_right - timeline_left);
|
let timeline_percent = (ho_time - timeline_left) / (timeline_right - timeline_left);
|
||||||
let timeline_x = timeline_percent as f32 * TIMELINE_BOUNDS.w + TIMELINE_BOUNDS.x;
|
let timeline_x = timeline_percent as f32 * BOUNDS.w + BOUNDS.x;
|
||||||
let timeline_y = TIMELINE_BOUNDS.y;
|
let timeline_y = BOUNDS.y;
|
||||||
self.skin.hitcircle.draw(
|
self.skin.hitcircle.draw(
|
||||||
ctx,
|
ctx,
|
||||||
(TIMELINE_BOUNDS.h, TIMELINE_BOUNDS.h),
|
(BOUNDS.h, BOUNDS.h),
|
||||||
DrawParam::default()
|
DrawParam::default()
|
||||||
.dest([timeline_x, timeline_y + TIMELINE_BOUNDS.h / 2.0])
|
.dest([timeline_x, timeline_y + BOUNDS.h / 2.0])
|
||||||
.offset([0.5, 0.0])
|
.offset([0.5, 0.0])
|
||||||
.color(color),
|
.color(color),
|
||||||
)?;
|
)?;
|
||||||
self.skin.hitcircleoverlay.draw(
|
self.skin.hitcircleoverlay.draw(
|
||||||
ctx,
|
ctx,
|
||||||
(TIMELINE_BOUNDS.h, TIMELINE_BOUNDS.h),
|
(BOUNDS.h, BOUNDS.h),
|
||||||
DrawParam::default()
|
DrawParam::default()
|
||||||
.dest([timeline_x, timeline_y + TIMELINE_BOUNDS.h / 2.0])
|
.dest([timeline_x, timeline_y + BOUNDS.h / 2.0])
|
||||||
.offset([0.5, 0.0]),
|
.offset([0.5, 0.0]),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue