From fa92899e79d3554728667fd31662cb3aa5d4b277 Mon Sep 17 00:00:00 2001 From: HLMC Date: Tue, 24 Dec 2024 16:51:11 +0800 Subject: [PATCH 01/13] Fix: Modify chart parse & hitfx --- prpr/src/bin.rs | 5 +- prpr/src/core.rs | 14 +++++ prpr/src/core/chart.rs | 4 +- prpr/src/core/line.rs | 4 +- prpr/src/core/note.rs | 29 +++++++--- prpr/src/judge.rs | 26 +++++++-- prpr/src/parse/pec.rs | 6 +- prpr/src/parse/pgr.rs | 126 +++++++++++++++++++++++++++++++++++++---- prpr/src/parse/rpe.rs | 3 + 9 files changed, 188 insertions(+), 29 deletions(-) diff --git a/prpr/src/bin.rs b/prpr/src/bin.rs index 3041107e..99a8dd4e 100644 --- a/prpr/src/bin.rs +++ b/prpr/src/bin.rs @@ -322,6 +322,7 @@ impl BinaryData for Note { 1 => NoteKind::Hold { end_time: r.read()?, end_height: r.read()?, + start_height: r.read()?, }, 2 => NoteKind::Flick, 3 => NoteKind::Drag, @@ -335,10 +336,12 @@ impl BinaryData for Note { time: r.time()?, height: r.read()?, speed: if r.read()? { r.read::()? } else { 1. }, + end_speed: if r.read()? { r.read::()? } else { 1. }, above: r.read()?, multiple_hint: false, fake: r.read()?, judge: JudgeStatus::NotJudged, + format: r.read()?, }) } @@ -348,7 +351,7 @@ impl BinaryData for Note { NoteKind::Click => { w.write_val(0_u8)?; } - NoteKind::Hold { end_time, end_height } => { + NoteKind::Hold { end_time, end_height, start_height } => { w.write_val(1_u8)?; w.write_val(end_time)?; w.write_val(end_height)?; diff --git a/prpr/src/core.rs b/prpr/src/core.rs index 7f9d4dbf..dd22ad86 100644 --- a/prpr/src/core.rs +++ b/prpr/src/core.rs @@ -157,4 +157,18 @@ impl BpmList { let (beats, start_time, bpm) = &self.elements[self.cursor]; beats + (time - start_time) / (60. / bpm) } + + pub fn now_bpm(&mut self, time: f32) -> f32 { + while let Some(kf) = self.elements.get(self.cursor + 1) { + if kf.1 > time { + break; + } + self.cursor += 1; + } + while self.cursor != 0 && self.elements[self.cursor].1 > time { + self.cursor -= 1; + } + let (_beats, _start_time, bpm) = &self.elements[self.cursor]; + *bpm + } } diff --git a/prpr/src/core/chart.rs b/prpr/src/core/chart.rs index 35fe2bf7..22ed0f58 100644 --- a/prpr/src/core/chart.rs +++ b/prpr/src/core/chart.rs @@ -107,9 +107,11 @@ impl Chart { } // TODO optimize let trs = self.lines.iter().map(|it| it.now_transform(res, &self.lines)).collect::>(); + let mut guard = self.bpm_list.borrow_mut(); for (line, tr) in self.lines.iter_mut().zip(trs) { - line.update(res, tr); + line.update(res, tr, &mut guard); } + drop(guard); for effect in &mut self.extra.effects { effect.update(res); } diff --git a/prpr/src/core/line.rs b/prpr/src/core/line.rs index 7ef57781..39b1a3bb 100644 --- a/prpr/src/core/line.rs +++ b/prpr/src/core/line.rs @@ -157,7 +157,7 @@ pub struct JudgeLine { } impl JudgeLine { - pub fn update(&mut self, res: &mut Resource, tr: Matrix) { + pub fn update(&mut self, res: &mut Resource, tr: Matrix, bpm_list: &mut BpmList) { // self.object.set_time(res.time); // this is done by chart, chart has to calculate transform for us let rot = self.object.rotation.now(); self.height.set_time(res.time); @@ -165,7 +165,7 @@ impl JudgeLine { let mut ctrl_obj = self.ctrl_obj.borrow_mut(); self.cache.update_order.retain(|id| { let note = &mut self.notes[*id as usize]; - note.update(res, rot, &tr, &mut ctrl_obj, line_height); + note.update(res, rot, &tr, &mut ctrl_obj, line_height, bpm_list); !note.dead() }); drop(ctrl_obj); diff --git a/prpr/src/core/note.rs b/prpr/src/core/note.rs index 31f8cbe7..3c5370a8 100644 --- a/prpr/src/core/note.rs +++ b/prpr/src/core/note.rs @@ -2,6 +2,7 @@ use super::{chart::ChartSettings, BpmList, CtrlObject, JudgeLine, Matrix, Object pub use crate::{ judge::{HitSound, JudgeStatus}, parse::RPE_HEIGHT, + core::HEIGHT_RATIO, }; use macroquad::prelude::*; @@ -12,7 +13,7 @@ const BAD_TIME: f32 = 0.5; #[derive(Clone, Debug)] pub enum NoteKind { Click, - Hold { end_time: f32, end_height: f32 }, + Hold { end_time: f32, end_height: f32, start_height: f32 }, Flick, Drag, } @@ -35,12 +36,14 @@ pub struct Note { pub time: f32, pub height: f32, pub speed: f32, + pub end_speed: f32, /// From the other side of the line pub above: bool, pub multiple_hint: bool, pub fake: bool, pub judge: JudgeStatus, + pub format: bool, } pub struct RenderConfig<'a> { @@ -134,11 +137,12 @@ impl Note { // && self.ctrl_obj.is_default() } - pub fn update(&mut self, res: &mut Resource, parent_rot: f32, parent_tr: &Matrix, ctrl_obj: &mut CtrlObject, line_height: f32) { + pub fn update(&mut self, res: &mut Resource, parent_rot: f32, parent_tr: &Matrix, ctrl_obj: &mut CtrlObject, line_height: f32, bpm_list: &mut BpmList) { self.object.set_time(res.time); if let Some(color) = if let JudgeStatus::Hold(perfect, at, ..) = &mut self.judge { if res.time > *at { - *at += HOLD_PARTICLE_INTERVAL / res.config.speed; + let beat = 30. / bpm_list.now_bpm(self.time); + *at = res.time + beat / res.config.speed; Some(if *perfect { res.res_pack.info.fx_perfect() } else { @@ -207,7 +211,7 @@ impl Note { let base = height - line_height; if !config.draw_below - && ((res.time - FADEOUT_TIME >= self.time) || (self.fake && res.time >= self.time) || (self.time > res.time && base <= -1e-5)) + && ((res.time - FADEOUT_TIME >= self.time) || (self.fake && res.time >= self.time) || (self.time > res.time && base <= -0.0075)) && !matches!(self.kind, NoteKind::Hold { .. }) { return; @@ -231,7 +235,7 @@ impl Note { NoteKind::Click => { draw(res, *style.click); } - NoteKind::Hold { end_time, end_height } => { + NoteKind::Hold { end_time, end_height, start_height } => { res.with_model(self.now_transform(res, ctrl_obj, 0., 0.), |res| { let style = if res.config.double_hint && self.multiple_hint { &res.res_pack.note_style_mh @@ -251,14 +255,23 @@ impl Note { let h = if self.time <= res.time { line_height } else { height }; let bottom = h - line_height; - let top = end_height - line_height; - if res.time < self.time && bottom < -1e-6 && !config.settings.hold_partial_cover { + let top = if self.format { + let end_spd = self.end_speed * ctrl_obj.y.now_opt().unwrap_or(1.); + if end_spd == 0. { return }; + let time = if res.time >= self.time {res.time} else {self.time}; + let start_height = start_height / res.aspect_ratio * spd; + let hold_height = end_height - start_height; + let hold_line_height = (time - self.time) * end_spd / res.aspect_ratio / HEIGHT_RATIO; + bottom + hold_height - hold_line_height + } else { + end_height - line_height + }; + if res.time < self.time && bottom < -1e-6 && !config.settings.hold_partial_cover && !self.format { return; } let tex = &style.hold; let ratio = style.hold_ratio(); // body - // TODO (end_height - height) is not always total height draw_tex( res, **(if res.res_pack.info.hold_repeat { diff --git a/prpr/src/judge.rs b/prpr/src/judge.rs index 25ca3ef2..3ca65b25 100644 --- a/prpr/src/judge.rs +++ b/prpr/src/judge.rs @@ -854,18 +854,34 @@ impl Judge { } for (line_id, id) in judgements.into_iter() { self.commit(t, Judgement::Perfect, line_id as _, id, 0.); - let (note_transform, note_hitsound) = { + let (note_transform, note_hitsound, note_kind) = { let line = &mut chart.lines[line_id]; let note = &mut line.notes[id as usize]; let nt = if matches!(note.kind, NoteKind::Hold { .. }) { t } else { note.time }; line.object.set_time(nt); note.object.set_time(nt); - (note.object.now(res), note.hitsound.clone()) + (note.object.now(res), note.hitsound.clone(), note.kind.clone()) }; let line = &chart.lines[line_id]; - res.with_model(line.now_transform(res, &chart.lines) * note_transform, |res| { - res.emit_at_origin(line.notes[id as usize].rotation(&line), res.res_pack.info.fx_perfect()) - }); + match note_kind { + NoteKind::Click => { + //self.commit(t, judge_type, line_id as _, id, 0.); + res.with_model(line.now_transform(res, &chart.lines) * note_transform, |res| { + res.emit_at_origin(line.notes[id as usize].rotation(&line), res.res_pack.info.fx_perfect()) + + }); + } + NoteKind::Hold { .. } => { + //self.commit(t, judge_type, line_id as _, id, 0.); + } + _ => { + //self.commit(t, Judgement::Perfect, line_id as _, id, 0.); + res.with_model(line.now_transform(res, &chart.lines) * note_transform, |res| { + res.emit_at_origin(line.notes[id as usize].rotation(&line), res.res_pack.info.fx_perfect()) + + }); + }, + }; if !matches!(chart.lines[line_id].notes[id as usize].kind, NoteKind::Hold { .. }) { note_hitsound.play(res); } diff --git a/prpr/src/parse/pec.rs b/prpr/src/parse/pec.rs index 7161f99c..f2844864 100644 --- a/prpr/src/parse/pec.rs +++ b/prpr/src/parse/pec.rs @@ -143,9 +143,10 @@ fn parse_judge_line(mut pec: PECJudgeLine, id: usize, max_time: f32) -> Result Result { '2' => NoteKind::Hold { end_time: it.take_time(r)?, end_height: 0.0, + start_height: 0.0, }, '3' => NoteKind::Flick, '4' => NoteKind::Drag, @@ -268,11 +270,13 @@ pub fn parse_pec(source: &str, extra: ChartExtra) -> Result { time, height: 0.0, speed: 1.0, + end_speed: 1.0, above, multiple_hint: false, fake, judge: JudgeStatus::NotJudged, + format: false, }); if it.next() == Some("#") { last_note!().speed = it.take_f32()?; diff --git a/prpr/src/parse/pgr.rs b/prpr/src/parse/pgr.rs index 0646334f..e0226e59 100644 --- a/prpr/src/parse/pgr.rs +++ b/prpr/src/parse/pgr.rs @@ -8,6 +8,7 @@ use crate::{ }, ext::NotNanExt, judge::{HitSound, JudgeStatus}, + info::ChartFormat, }; use anyhow::{Context, Result}; use serde::Deserialize; @@ -80,11 +81,11 @@ macro_rules! validate_events { true } }); - for i in 0..($pgr.len() - 1) { - if $pgr[i].end_time != $pgr[i + 1].start_time { - ptl!(bail "event-not-contiguous"); - } - } + // for i in 0..($pgr.len() - 1) { + // if $pgr[i].end_time != $pgr[i + 1].start_time { + // ptl!(bail "event-not-contiguous"); + // } + // } // if $pgr.last().unwrap().end_time <= 900000000.0 { // bail!("End time is not great enough ({})", $pgr.last().unwrap().end_time); // } @@ -93,7 +94,7 @@ macro_rules! validate_events { fn parse_speed_events(r: f32, mut pgr: Vec, max_time: f32) -> Result<(AnimFloat, AnimFloat)> { validate_events!(pgr); - assert_eq!(pgr[0].start_time, 0.0); + pgr[0].start_time = 0.; let mut kfs = Vec::new(); let mut pos = 0.; kfs.extend(pgr[..pgr.len().saturating_sub(1)].iter().map(|it| { @@ -150,12 +151,43 @@ fn parse_move_events(r: f32, mut pgr: Vec) -> Result { Ok(AnimVector(AnimFloat::new(kf1), AnimFloat::new(kf2))) } +fn parse_move_events_fv1(r: f32, mut pgr: Vec) -> Result { + validate_events!(pgr); + let mut kf1 = Vec::>::new(); + let mut kf2 = Vec::>::new(); + for e in pgr { + let st = (e.start_time * r).max(0.); + let en = e.end_time * r; + if !kf1.last().map_or(false, |it| it.value == e.start) { + let start = (e.start - e.start % 1000.) / 1000.; + kf1.push(Keyframe::new(st, start, 2)); + } + if !kf2.last().map_or(false, |it| it.value == e.start2) { + let start2 = e.start % 1000.; + kf2.push(Keyframe::new(st, start2, 2)); + } + let end = (e.end - e.end % 1000.) / 1000.; + let end2 = e.end % 1000.; + kf1.push(Keyframe::new(en, end, 2)); + kf2.push(Keyframe::new(en, end2, 2)); + } + kf1.pop(); + kf2.pop(); + for kf in &mut kf1 { + kf.value = (-880. + kf.value * 2.) / 880.; + } + for kf in &mut kf2 { + kf.value = (-520. + kf.value * 2.) / 520.; + } + Ok(AnimVector(AnimFloat::new(kf1), AnimFloat::new(kf2))) +} + fn parse_notes(r: f32, mut pgr: Vec, speed: &mut AnimFloat, height: &mut AnimFloat, above: bool) -> Result> { // is_sorted is unstable... if pgr.is_empty() { return Ok(Vec::new()); } - pgr.sort_by_key(|it| it.time.not_nan()); + pgr.sort_by_key(|it| it.time as usize); pgr.into_iter() .map(|pgr| { let time = pgr.time * r; @@ -166,7 +198,9 @@ fn parse_notes(r: f32, mut pgr: Vec, speed: &mut AnimFloat, height: &mu let end_time = (pgr.time + pgr.hold_time) * r; height.set_time(end_time); let end_height = height.now(); - NoteKind::Hold { end_time, end_height } + height.set_time(time); + let start_height = height.now(); + NoteKind::Hold { end_time, end_height, start_height } } 4 => NoteKind::Flick, _ => ptl!(bail "unknown-note-type", "type" => pgr.kind), @@ -181,17 +215,18 @@ fn parse_notes(r: f32, mut pgr: Vec, speed: &mut AnimFloat, height: &mu hitsound, time, speed: if pgr.kind == 3 { - speed.set_time(time); - pgr.speed / speed.now() + 1. } else { pgr.speed }, + end_speed: pgr.speed, height: pgr.floor_position / HEIGHT_RATIO, above, multiple_hint: false, fake: false, judge: JudgeStatus::NotJudged, + format: true, }) }) .collect() @@ -227,8 +262,43 @@ fn parse_judge_line(pgr: PgrJudgeLine, max_time: f32) -> Result { }) } +fn parse_judge_line_fv1(pgr: PgrJudgeLine, max_time: f32) -> Result { + let r = 60. / 32. / pgr.bpm; + let (mut speed, mut height) = parse_speed_events(r, pgr.speed_events, max_time).context("Failed to parse speed events")?; + let notes_above = parse_notes(r, pgr.notes_above, &mut speed, &mut height, true).context("Failed to parse notes above")?; + let mut notes_below = parse_notes(r, pgr.notes_below, &mut speed, &mut height, false).context("Failed to parse notes below")?; + let mut notes = notes_above; + notes.append(&mut notes_below); + let cache = JudgeLineCache::new(&mut notes); + Ok(JudgeLine { + object: Object { + alpha: parse_float_events(r, pgr.alpha_events).with_context(|| ptl!("alpha-events-parse-failed"))?, + rotation: parse_float_events(r, pgr.rotate_events).with_context(|| ptl!("rotate-events-parse-failed"))?, + translation: parse_move_events_fv1(r, pgr.move_events).with_context(|| ptl!("move-events-parse-failed"))?, + ..Default::default() + }, + ctrl_obj: RefCell::default(), + kind: JudgeLineKind::Normal, + height, + incline: AnimFloat::default(), + notes, + color: Anim::default(), + parent: None, + z_index: 0, + show_below: false, + attach_ui: None, + + cache, + }) +} + pub fn parse_phigros(source: &str, extra: ChartExtra) -> Result { let pgr: PgrChart = serde_json::from_str(source).with_context(|| ptl!("json-parse-failed"))?; + let indices: Vec = (0..1).collect(); // pgr1.judge_line_list.len() + let mut bpm_values = Vec::new(); + for (index, judge_line) in indices.iter().zip(&pgr.judge_line_list) { + bpm_values.push((*index as f32, judge_line.bpm)); + } let max_time = *pgr .judge_line_list .iter() @@ -251,5 +321,39 @@ pub fn parse_phigros(source: &str, extra: ChartExtra) -> Result { .map(|(id, pgr)| parse_judge_line(pgr, max_time).with_context(|| ptl!("judge-line-location", "jlid" => id))) .collect::>>()?; process_lines(&mut lines); - Ok(Chart::new(pgr.offset, lines, BpmList::default(), ChartSettings::default(), extra, HashMap::new())) + Ok(Chart::new(pgr.offset, lines, BpmList::new(bpm_values), ChartSettings::default(), extra, HashMap::new())) } + +pub fn parse_phigros_fv1(source: &str, extra: ChartExtra) -> Result { + let pgr: PgrChart = serde_json::from_str(source).with_context(|| ptl!("json-parse-failed"))?; + let mut bpm_values = Vec::new(); + let indices: Vec = (0..1).collect(); + for (index, judge_line) in indices.iter().zip(&pgr.judge_line_list) { + bpm_values.push((*index as f32, judge_line.bpm)); + } + let r = BpmList::new(bpm_values); + + let max_time = *pgr + .judge_line_list + .iter() + .map(|line| { + line.notes_above + .iter() + .chain(line.notes_below.iter()) + .map(|note| note.time.not_nan()) + .max() + .unwrap_or_default() + * (60. / line.bpm / 32.) + }) + .max() + .unwrap_or_default() + + 1.; + let mut lines = pgr + .judge_line_list + .into_iter() + .enumerate() + .map(|(id, pgr)| parse_judge_line_fv1(pgr, max_time).with_context(|| ptl!("judge-line-location", "jlid" => id))) + .collect::>>()?; + process_lines(&mut lines); + Ok(Chart::new(pgr.offset, lines, r, ChartSettings::default(), extra,HashMap::new())) +} \ No newline at end of file diff --git a/prpr/src/parse/rpe.rs b/prpr/src/parse/rpe.rs index 3f0320a8..f85a7c02 100644 --- a/prpr/src/parse/rpe.rs +++ b/prpr/src/parse/rpe.rs @@ -339,6 +339,7 @@ async fn parse_notes( NoteKind::Hold { end_time, end_height: height.now(), + start_height: height.now(), } } 3 => NoteKind::Flick, @@ -396,11 +397,13 @@ async fn parse_notes( time, height: note_height, speed: note.speed, + end_speed: note.speed, above: note.above == 1, multiple_hint: false, fake: note.is_fake != 0, judge: JudgeStatus::NotJudged, + format: false, }) } Ok(notes) From 274ad3799e62f99d6a83980f4d867fe99b157396 Mon Sep 17 00:00:00 2001 From: HLMC Date: Wed, 25 Dec 2024 06:44:07 +0800 Subject: [PATCH 02/13] Fix: Modify note render --- prpr/src/bin.rs | 1 + prpr/src/core/note.rs | 4 ++-- prpr/src/info.rs | 1 + prpr/src/judge.rs | 32 +++++++++----------------------- prpr/src/parse.rs | 2 +- prpr/src/parse/pgr.rs | 8 +++----- prpr/src/scene/game.rs | 11 ++++++++--- 7 files changed, 25 insertions(+), 34 deletions(-) diff --git a/prpr/src/bin.rs b/prpr/src/bin.rs index 99a8dd4e..5f774c42 100644 --- a/prpr/src/bin.rs +++ b/prpr/src/bin.rs @@ -355,6 +355,7 @@ impl BinaryData for Note { w.write_val(1_u8)?; w.write_val(end_time)?; w.write_val(end_height)?; + w.write_val(start_height)?; } NoteKind::Flick => w.write_val(2_u8)?, NoteKind::Drag => w.write_val(3_u8)?, diff --git a/prpr/src/core/note.rs b/prpr/src/core/note.rs index 3c5370a8..f6a093ef 100644 --- a/prpr/src/core/note.rs +++ b/prpr/src/core/note.rs @@ -6,7 +6,7 @@ pub use crate::{ }; use macroquad::prelude::*; -const HOLD_PARTICLE_INTERVAL: f32 = 0.15; +//const HOLD_PARTICLE_INTERVAL: f32 = 0.15; const FADEOUT_TIME: f32 = 0.16; const BAD_TIME: f32 = 0.5; @@ -250,6 +250,7 @@ impl Note { return; } let end_height = end_height / res.aspect_ratio * spd; + let start_height = start_height / res.aspect_ratio * spd; let clip = !config.draw_below && config.settings.hold_partial_cover; @@ -259,7 +260,6 @@ impl Note { let end_spd = self.end_speed * ctrl_obj.y.now_opt().unwrap_or(1.); if end_spd == 0. { return }; let time = if res.time >= self.time {res.time} else {self.time}; - let start_height = start_height / res.aspect_ratio * spd; let hold_height = end_height - start_height; let hold_line_height = (time - self.time) * end_spd / res.aspect_ratio / HEIGHT_RATIO; bottom + hold_height - hold_line_height diff --git a/prpr/src/info.rs b/prpr/src/info.rs index 5e5e24ed..e5f67d04 100644 --- a/prpr/src/info.rs +++ b/prpr/src/info.rs @@ -10,6 +10,7 @@ pub enum ChartFormat { Rpe = 0, Pec, Pgr, + Pgr1, Pbc, } diff --git a/prpr/src/judge.rs b/prpr/src/judge.rs index 3ca65b25..58a9a90c 100644 --- a/prpr/src/judge.rs +++ b/prpr/src/judge.rs @@ -853,37 +853,23 @@ impl Judge { } } for (line_id, id) in judgements.into_iter() { - self.commit(t, Judgement::Perfect, line_id as _, id, 0.); - let (note_transform, note_hitsound, note_kind) = { + let (note_transform, note_hitsound) = { let line = &mut chart.lines[line_id]; let note = &mut line.notes[id as usize]; let nt = if matches!(note.kind, NoteKind::Hold { .. }) { t } else { note.time }; line.object.set_time(nt); note.object.set_time(nt); - (note.object.now(res), note.hitsound.clone(), note.kind.clone()) + (note.object.now(res), note.hitsound.clone()) }; let line = &chart.lines[line_id]; - match note_kind { - NoteKind::Click => { - //self.commit(t, judge_type, line_id as _, id, 0.); - res.with_model(line.now_transform(res, &chart.lines) * note_transform, |res| { - res.emit_at_origin(line.notes[id as usize].rotation(&line), res.res_pack.info.fx_perfect()) - - }); - } - NoteKind::Hold { .. } => { - //self.commit(t, judge_type, line_id as _, id, 0.); - } - _ => { - //self.commit(t, Judgement::Perfect, line_id as _, id, 0.); + if !matches!(chart.lines[line_id].notes[id as usize].kind, NoteKind::Hold { .. }) { + self.commit(t, Judgement::Perfect, line_id as _, id, 0.); res.with_model(line.now_transform(res, &chart.lines) * note_transform, |res| { - res.emit_at_origin(line.notes[id as usize].rotation(&line), res.res_pack.info.fx_perfect()) - + res.emit_at_origin(line.notes[id as usize].rotation(line), res.res_pack.info.fx_perfect()) }); - }, - }; - if !matches!(chart.lines[line_id].notes[id as usize].kind, NoteKind::Hold { .. }) { note_hitsound.play(res); + } else { + self.commit(t, Judgement::Perfect, line_id as _, id, 0.); } } } @@ -984,13 +970,13 @@ pub struct PlayResult { pub fn icon_index(score: u32, full_combo: bool) -> usize { match (score, full_combo) { + (1000000, _) => 7, + (_, true) => 6, (x, _) if x < 700000 => 0, (x, _) if x < 820000 => 1, (x, _) if x < 880000 => 2, (x, _) if x < 920000 => 3, (x, _) if x < 960000 => 4, - (1000000, _) => 7, (_, false) => 5, - (_, true) => 6, } } diff --git a/prpr/src/parse.rs b/prpr/src/parse.rs index ac03eba8..78e97d01 100644 --- a/prpr/src/parse.rs +++ b/prpr/src/parse.rs @@ -7,7 +7,7 @@ mod pec; pub use pec::parse_pec; mod pgr; -pub use pgr::parse_phigros; +pub use pgr::{parse_phigros, parse_phigros_fv1}; mod rpe; pub use rpe::{parse_rpe, RPE_HEIGHT, RPE_WIDTH}; diff --git a/prpr/src/parse/pgr.rs b/prpr/src/parse/pgr.rs index e0226e59..3305c463 100644 --- a/prpr/src/parse/pgr.rs +++ b/prpr/src/parse/pgr.rs @@ -8,7 +8,6 @@ use crate::{ }, ext::NotNanExt, judge::{HitSound, JudgeStatus}, - info::ChartFormat, }; use anyhow::{Context, Result}; use serde::Deserialize; @@ -182,7 +181,7 @@ fn parse_move_events_fv1(r: f32, mut pgr: Vec) -> Result { Ok(AnimVector(AnimFloat::new(kf1), AnimFloat::new(kf2))) } -fn parse_notes(r: f32, mut pgr: Vec, speed: &mut AnimFloat, height: &mut AnimFloat, above: bool) -> Result> { +fn parse_notes(r: f32, mut pgr: Vec, _speed: &mut AnimFloat, height: &mut AnimFloat, above: bool) -> Result> { // is_sorted is unstable... if pgr.is_empty() { return Ok(Vec::new()); @@ -196,10 +195,9 @@ fn parse_notes(r: f32, mut pgr: Vec, speed: &mut AnimFloat, height: &mu 2 => NoteKind::Drag, 3 => { let end_time = (pgr.time + pgr.hold_time) * r; - height.set_time(end_time); - let end_height = height.now(); height.set_time(time); let start_height = height.now(); + let end_height = start_height + (pgr.hold_time * pgr.speed * r / HEIGHT_RATIO); NoteKind::Hold { end_time, end_height, start_height } } 4 => NoteKind::Flick, @@ -255,7 +253,7 @@ fn parse_judge_line(pgr: PgrJudgeLine, max_time: f32) -> Result { color: Anim::default(), parent: None, z_index: 0, - show_below: true, + show_below: false, attach_ui: None, cache, diff --git a/prpr/src/scene/game.rs b/prpr/src/scene/game.rs index 99354ebc..ac1d787e 100644 --- a/prpr/src/scene/game.rs +++ b/prpr/src/scene/game.rs @@ -16,7 +16,7 @@ use crate::{ fs::FileSystem, info::{ChartFormat, ChartInfo}, judge::Judge, - parse::{parse_extra, parse_pec, parse_phigros, parse_rpe}, + parse::{parse_extra, parse_pec, parse_phigros, parse_phigros_fv1, parse_rpe}, task::Task, time::TimeManager, ui::{RectButton, TextPainter, Ui}, @@ -192,7 +192,11 @@ impl GameScene { if text.contains("\"META\"") { ChartFormat::Rpe } else { - ChartFormat::Pgr + if text.starts_with("{\"formatVersion\":3") { + ChartFormat::Pgr + } else { + ChartFormat::Pgr1 + } } } else { ChartFormat::Pec @@ -204,6 +208,7 @@ impl GameScene { let mut chart = match format { ChartFormat::Rpe => parse_rpe(&String::from_utf8_lossy(&bytes), fs, extra).await, ChartFormat::Pgr => parse_phigros(&String::from_utf8_lossy(&bytes), extra), + ChartFormat::Pgr1 => parse_phigros_fv1(&String::from_utf8_lossy(&bytes), extra), ChartFormat::Pec => parse_pec(&String::from_utf8_lossy(&bytes), extra), ChartFormat::Pbc => { let mut r = BinaryReader::new(Cursor::new(&bytes)); @@ -449,7 +454,7 @@ impl GameScene { let hw = 0.003; let height = eps * 1.2; - let dest = 2. * res.time / res.track_length; + let dest = (2. * res.time / res.track_length).max(0.).min(2.); ui.fill_rect(Rect::new(-1., top, dest, height), semi_white(0.6)); ui.fill_rect(Rect::new(-1. + dest - hw, top, hw * 2., height), WHITE); }); From 58ad7a71da9e28a2a63e9eacf4584ebdf5556a91 Mon Sep 17 00:00:00 2001 From: HLMC Date: Mon, 6 Jan 2025 13:36:06 +0800 Subject: [PATCH 03/13] ignore ./idea --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7b071798..b5cea9b6 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,4 @@ inner.rs /test /log* /build_event_debug.sh +/.idea From 9f6fdadb9b0c81d79441adfb5f98947eb80d45d6 Mon Sep 17 00:00:00 2001 From: HLMC Date: Mon, 6 Jan 2025 13:56:07 +0800 Subject: [PATCH 04/13] fix: note render, hitfx render, hold aggressive --- prpr/src/bin.rs | 27 +++++++++++++++++++++++++++ prpr/src/core.rs | 10 +++++++++- prpr/src/core/chart.rs | 4 ++-- prpr/src/core/line.rs | 21 +++++++++++++++++++-- prpr/src/core/note.rs | 21 +++++++++++++-------- prpr/src/parse/pec.rs | 3 ++- prpr/src/parse/pgr.rs | 18 ++++++++---------- prpr/src/parse/rpe.rs | 3 ++- 8 files changed, 82 insertions(+), 25 deletions(-) diff --git a/prpr/src/bin.rs b/prpr/src/bin.rs index 5f774c42..05605a02 100644 --- a/prpr/src/bin.rs +++ b/prpr/src/bin.rs @@ -17,6 +17,7 @@ use crate::{ }, judge::{HitSound, JudgeStatus}, parse::process_lines, + info::ChartFormat, }; use anyhow::{bail, Result}; use byteorder::{LittleEndian as LE, ReadBytesExt, WriteBytesExt}; @@ -154,6 +155,32 @@ impl BinaryData for bool { } } +impl BinaryData for ChartFormat { + fn read_binary(r: &mut BinaryReader) -> Result { + match r.read::()? { + 0 => Ok(ChartFormat::Rpe), + 1 => Ok(ChartFormat::Pec), + 2 => Ok(ChartFormat::Pgr), + 3 => Ok(ChartFormat::Pgr1), + 4 => Ok(ChartFormat::Pbc), + _ => bail!("invalid chart format"), + } + } + + fn write_binary(&self, w: &mut BinaryWriter) -> Result<()> { + w.write_val( + match self { + ChartFormat::Rpe => 0, + ChartFormat::Pec => 1, + ChartFormat::Pgr => 2, + ChartFormat::Pgr1 => 3, + ChartFormat::Pbc => 4, + } + )?; + Ok(()) + } +} + impl BinaryData for f32 { fn read_binary(r: &mut BinaryReader) -> Result { Ok(r.0.read_f32::()?) diff --git a/prpr/src/core.rs b/prpr/src/core.rs index dd22ad86..65550d80 100644 --- a/prpr/src/core.rs +++ b/prpr/src/core.rs @@ -123,6 +123,14 @@ impl BpmList { BpmList { elements, cursor: 0 } } + pub fn new_time(ranges: Vec<(f32, f32)>) -> Self { + let mut elements = Vec::new(); + for (time, bpm) in ranges { + elements.push((time, time, bpm)); + } + BpmList { elements, cursor: 0 } + } + /// Get the time in seconds for a given beats pub fn time_beats(&mut self, beats: f32) -> f32 { while let Some(kf) = self.elements.get(self.cursor + 1) { @@ -168,7 +176,7 @@ impl BpmList { while self.cursor != 0 && self.elements[self.cursor].1 > time { self.cursor -= 1; } - let (_beats, _start_time, bpm) = &self.elements[self.cursor]; + let (_, _, bpm) = &self.elements[self.cursor]; *bpm } } diff --git a/prpr/src/core/chart.rs b/prpr/src/core/chart.rs index 22ed0f58..63b12f6f 100644 --- a/prpr/src/core/chart.rs +++ b/prpr/src/core/chart.rs @@ -108,8 +108,8 @@ impl Chart { // TODO optimize let trs = self.lines.iter().map(|it| it.now_transform(res, &self.lines)).collect::>(); let mut guard = self.bpm_list.borrow_mut(); - for (line, tr) in self.lines.iter_mut().zip(trs) { - line.update(res, tr, &mut guard); + for (index, (line, tr)) in self.lines.iter_mut().zip(trs).enumerate() { + line.update(res, tr, &mut guard, index); } drop(guard); for effect in &mut self.extra.effects { diff --git a/prpr/src/core/line.rs b/prpr/src/core/line.rs index 39b1a3bb..1775a98e 100644 --- a/prpr/src/core/line.rs +++ b/prpr/src/core/line.rs @@ -4,6 +4,7 @@ use crate::{ ext::{draw_text_aligned, get_viewport, NotNanExt, SafeTexture}, judge::{JudgeStatus, LIMIT_BAD}, ui::Ui, + info::ChartFormat, }; use macroquad::prelude::*; use miniquad::{RenderPass, Texture, TextureParams, TextureWrap}; @@ -157,7 +158,7 @@ pub struct JudgeLine { } impl JudgeLine { - pub fn update(&mut self, res: &mut Resource, tr: Matrix, bpm_list: &mut BpmList) { + pub fn update(&mut self, res: &mut Resource, tr: Matrix, bpm_list: &mut BpmList, index: usize) { // self.object.set_time(res.time); // this is done by chart, chart has to calculate transform for us let rot = self.object.rotation.now(); self.height.set_time(res.time); @@ -165,7 +166,7 @@ impl JudgeLine { let mut ctrl_obj = self.ctrl_obj.borrow_mut(); self.cache.update_order.retain(|id| { let note = &mut self.notes[*id as usize]; - note.update(res, rot, &tr, &mut ctrl_obj, line_height, bpm_list); + note.update(res, rot, &tr, &mut ctrl_obj, line_height, bpm_list, index); !note.dead() }); drop(ctrl_obj); @@ -381,6 +382,14 @@ impl JudgeLine { let height_below = -p[0].y.min(p[1].y.min(p[2].y.min(p[3].y))) * res.aspect_ratio; let agg = res.config.aggressive; for note in self.notes.iter().take(self.cache.not_plain_count).filter(|it| it.above) { + let line_height = { + let mut height = self.height.clone(); + height.set_time(note.time.min(res.time)); + height.now() + }; + if agg && note.height - line_height + note.object.translation.1.now() > height_above / note.speed && matches!(note.format, ChartFormat::Pgr | ChartFormat::Rpe) { + break; + } note.render(res, &mut config, bpm_list); } for index in &self.cache.above_indices { @@ -398,6 +407,14 @@ impl JudgeLine { } res.with_model(Matrix::identity().append_nonuniform_scaling(&Vector::new(1.0, -1.0)), |res| { for note in self.notes.iter().take(self.cache.not_plain_count).filter(|it| !it.above) { + let line_height = { + let mut height = self.height.clone(); + height.set_time(note.time.min(res.time)); + height.now() + }; + if agg && note.height - line_height + note.object.translation.1.now() > height_below / note.speed && matches!(note.format, ChartFormat::Pgr | ChartFormat::Rpe) { + break; + } note.render(res, &mut config, bpm_list); } for index in &self.cache.below_indices { diff --git a/prpr/src/core/note.rs b/prpr/src/core/note.rs index f6a093ef..305757af 100644 --- a/prpr/src/core/note.rs +++ b/prpr/src/core/note.rs @@ -3,6 +3,7 @@ pub use crate::{ judge::{HitSound, JudgeStatus}, parse::RPE_HEIGHT, core::HEIGHT_RATIO, + info::ChartFormat, }; use macroquad::prelude::*; @@ -43,7 +44,7 @@ pub struct Note { pub multiple_hint: bool, pub fake: bool, pub judge: JudgeStatus, - pub format: bool, + pub format: ChartFormat, } pub struct RenderConfig<'a> { @@ -137,11 +138,13 @@ impl Note { // && self.ctrl_obj.is_default() } - pub fn update(&mut self, res: &mut Resource, parent_rot: f32, parent_tr: &Matrix, ctrl_obj: &mut CtrlObject, line_height: f32, bpm_list: &mut BpmList) { + pub fn update(&mut self, res: &mut Resource, parent_rot: f32, parent_tr: &Matrix, ctrl_obj: &mut CtrlObject, line_height: f32, bpm_list: &mut BpmList, index: usize) { self.object.set_time(res.time); - if let Some(color) = if let JudgeStatus::Hold(perfect, at, ..) = &mut self.judge { - if res.time > *at { - let beat = 30. / bpm_list.now_bpm(self.time); + if let Some(color) = if let JudgeStatus::Hold(perfect, ref mut at, ..) = &mut self.judge { + if res.time >= *at { + let beat = 30. / bpm_list.now_bpm( + if matches!(self.format, ChartFormat::Pgr) { index as f32 } else { self.time } + ); *at = res.time + beat / res.config.speed; Some(if *perfect { res.res_pack.info.fx_perfect() @@ -256,9 +259,11 @@ impl Note { let h = if self.time <= res.time { line_height } else { height }; let bottom = h - line_height; - let top = if self.format { + let top = if matches!(self.format, ChartFormat::Pgr) { let end_spd = self.end_speed * ctrl_obj.y.now_opt().unwrap_or(1.); - if end_spd == 0. { return }; + if end_spd == 0. { + return; + } let time = if res.time >= self.time {res.time} else {self.time}; let hold_height = end_height - start_height; let hold_line_height = (time - self.time) * end_spd / res.aspect_ratio / HEIGHT_RATIO; @@ -266,7 +271,7 @@ impl Note { } else { end_height - line_height }; - if res.time < self.time && bottom < -1e-6 && !config.settings.hold_partial_cover && !self.format { + if res.time < self.time && bottom < -1e-6 && !config.settings.hold_partial_cover && !matches!(self.format, ChartFormat::Pgr) { return; } let tex = &style.hold; diff --git a/prpr/src/parse/pec.rs b/prpr/src/parse/pec.rs index f2844864..e12b9bf7 100644 --- a/prpr/src/parse/pec.rs +++ b/prpr/src/parse/pec.rs @@ -8,6 +8,7 @@ use crate::{ }, ext::NotNanExt, judge::{HitSound, JudgeStatus}, + info::ChartFormat, }; use anyhow::{bail, Context, Result}; use std::{cell::RefCell, collections::HashMap}; @@ -276,7 +277,7 @@ pub fn parse_pec(source: &str, extra: ChartExtra) -> Result { multiple_hint: false, fake, judge: JudgeStatus::NotJudged, - format: false, + format: ChartFormat::Pec, }); if it.next() == Some("#") { last_note!().speed = it.take_f32()?; diff --git a/prpr/src/parse/pgr.rs b/prpr/src/parse/pgr.rs index 3305c463..f446a23c 100644 --- a/prpr/src/parse/pgr.rs +++ b/prpr/src/parse/pgr.rs @@ -8,6 +8,7 @@ use crate::{ }, ext::NotNanExt, judge::{HitSound, JudgeStatus}, + info::ChartFormat, }; use anyhow::{Context, Result}; use serde::Deserialize; @@ -224,7 +225,7 @@ fn parse_notes(r: f32, mut pgr: Vec, _speed: &mut AnimFloat, height: &m multiple_hint: false, fake: false, judge: JudgeStatus::NotJudged, - format: true, + format: ChartFormat::Pgr, }) }) .collect() @@ -292,10 +293,9 @@ fn parse_judge_line_fv1(pgr: PgrJudgeLine, max_time: f32) -> Result { pub fn parse_phigros(source: &str, extra: ChartExtra) -> Result { let pgr: PgrChart = serde_json::from_str(source).with_context(|| ptl!("json-parse-failed"))?; - let indices: Vec = (0..1).collect(); // pgr1.judge_line_list.len() let mut bpm_values = Vec::new(); - for (index, judge_line) in indices.iter().zip(&pgr.judge_line_list) { - bpm_values.push((*index as f32, judge_line.bpm)); + for (index, judge_line) in pgr.judge_line_list.iter().enumerate() { + bpm_values.push((index as f32, judge_line.bpm)); } let max_time = *pgr .judge_line_list @@ -319,17 +319,15 @@ pub fn parse_phigros(source: &str, extra: ChartExtra) -> Result { .map(|(id, pgr)| parse_judge_line(pgr, max_time).with_context(|| ptl!("judge-line-location", "jlid" => id))) .collect::>>()?; process_lines(&mut lines); - Ok(Chart::new(pgr.offset, lines, BpmList::new(bpm_values), ChartSettings::default(), extra, HashMap::new())) + Ok(Chart::new(pgr.offset, lines, BpmList::new_time(bpm_values), ChartSettings::default(), extra, HashMap::new())) } pub fn parse_phigros_fv1(source: &str, extra: ChartExtra) -> Result { let pgr: PgrChart = serde_json::from_str(source).with_context(|| ptl!("json-parse-failed"))?; let mut bpm_values = Vec::new(); - let indices: Vec = (0..1).collect(); - for (index, judge_line) in indices.iter().zip(&pgr.judge_line_list) { - bpm_values.push((*index as f32, judge_line.bpm)); + for (index, judge_line) in pgr.judge_line_list.iter().enumerate() { + bpm_values.push((index as f32, judge_line.bpm)); } - let r = BpmList::new(bpm_values); let max_time = *pgr .judge_line_list @@ -353,5 +351,5 @@ pub fn parse_phigros_fv1(source: &str, extra: ChartExtra) -> Result { .map(|(id, pgr)| parse_judge_line_fv1(pgr, max_time).with_context(|| ptl!("judge-line-location", "jlid" => id))) .collect::>>()?; process_lines(&mut lines); - Ok(Chart::new(pgr.offset, lines, r, ChartSettings::default(), extra,HashMap::new())) + Ok(Chart::new(pgr.offset, lines, BpmList::new_time(bpm_values), ChartSettings::default(), extra,HashMap::new())) } \ No newline at end of file diff --git a/prpr/src/parse/rpe.rs b/prpr/src/parse/rpe.rs index f85a7c02..1380cb68 100644 --- a/prpr/src/parse/rpe.rs +++ b/prpr/src/parse/rpe.rs @@ -10,6 +10,7 @@ use crate::{ ext::{NotNanExt, SafeTexture}, fs::FileSystem, judge::{HitSound, JudgeStatus}, + info::ChartFormat, }; use anyhow::{Context, Result}; use image::{codecs::gif, AnimationDecoder, DynamicImage, ImageError}; @@ -403,7 +404,7 @@ async fn parse_notes( multiple_hint: false, fake: note.is_fake != 0, judge: JudgeStatus::NotJudged, - format: false, + format: ChartFormat::Rpe, }) } Ok(notes) From 0983e8711734cb85e09975ac1abf917dfb855754 Mon Sep 17 00:00:00 2001 From: HLMC Date: Mon, 6 Jan 2025 14:32:01 +0800 Subject: [PATCH 05/13] refactor: remove shit --- prpr/src/bin.rs | 7 +++---- prpr/src/core/note.rs | 10 ++++------ prpr/src/parse/pec.rs | 6 ++---- prpr/src/parse/pgr.rs | 16 +++++++++------- prpr/src/parse/rpe.rs | 3 +-- 5 files changed, 19 insertions(+), 23 deletions(-) diff --git a/prpr/src/bin.rs b/prpr/src/bin.rs index 05605a02..91d3f85c 100644 --- a/prpr/src/bin.rs +++ b/prpr/src/bin.rs @@ -349,7 +349,7 @@ impl BinaryData for Note { 1 => NoteKind::Hold { end_time: r.read()?, end_height: r.read()?, - start_height: r.read()?, + end_speed: if r.read()? { r.read::()? } else { 1. }, }, 2 => NoteKind::Flick, 3 => NoteKind::Drag, @@ -363,7 +363,6 @@ impl BinaryData for Note { time: r.time()?, height: r.read()?, speed: if r.read()? { r.read::()? } else { 1. }, - end_speed: if r.read()? { r.read::()? } else { 1. }, above: r.read()?, multiple_hint: false, fake: r.read()?, @@ -378,11 +377,11 @@ impl BinaryData for Note { NoteKind::Click => { w.write_val(0_u8)?; } - NoteKind::Hold { end_time, end_height, start_height } => { + NoteKind::Hold { end_time, end_height, end_speed } => { w.write_val(1_u8)?; w.write_val(end_time)?; w.write_val(end_height)?; - w.write_val(start_height)?; + w.write_val(end_speed)?; } NoteKind::Flick => w.write_val(2_u8)?, NoteKind::Drag => w.write_val(3_u8)?, diff --git a/prpr/src/core/note.rs b/prpr/src/core/note.rs index 305757af..752bb875 100644 --- a/prpr/src/core/note.rs +++ b/prpr/src/core/note.rs @@ -14,7 +14,7 @@ const BAD_TIME: f32 = 0.5; #[derive(Clone, Debug)] pub enum NoteKind { Click, - Hold { end_time: f32, end_height: f32, start_height: f32 }, + Hold { end_time: f32, end_height: f32, end_speed: f32 }, Flick, Drag, } @@ -37,7 +37,6 @@ pub struct Note { pub time: f32, pub height: f32, pub speed: f32, - pub end_speed: f32, /// From the other side of the line pub above: bool, @@ -238,7 +237,7 @@ impl Note { NoteKind::Click => { draw(res, *style.click); } - NoteKind::Hold { end_time, end_height, start_height } => { + NoteKind::Hold { end_time, end_height, end_speed } => { res.with_model(self.now_transform(res, ctrl_obj, 0., 0.), |res| { let style = if res.config.double_hint && self.multiple_hint { &res.res_pack.note_style_mh @@ -253,19 +252,18 @@ impl Note { return; } let end_height = end_height / res.aspect_ratio * spd; - let start_height = start_height / res.aspect_ratio * spd; let clip = !config.draw_below && config.settings.hold_partial_cover; let h = if self.time <= res.time { line_height } else { height }; let bottom = h - line_height; let top = if matches!(self.format, ChartFormat::Pgr) { - let end_spd = self.end_speed * ctrl_obj.y.now_opt().unwrap_or(1.); + let end_spd = end_speed * ctrl_obj.y.now_opt().unwrap_or(1.); if end_spd == 0. { return; } let time = if res.time >= self.time {res.time} else {self.time}; - let hold_height = end_height - start_height; + let hold_height = end_height - height; let hold_line_height = (time - self.time) * end_spd / res.aspect_ratio / HEIGHT_RATIO; bottom + hold_height - hold_line_height } else { diff --git a/prpr/src/parse/pec.rs b/prpr/src/parse/pec.rs index e12b9bf7..42a1c9c7 100644 --- a/prpr/src/parse/pec.rs +++ b/prpr/src/parse/pec.rs @@ -144,10 +144,9 @@ fn parse_judge_line(mut pec: PECJudgeLine, id: usize, max_time: f32) -> Result Result { '2' => NoteKind::Hold { end_time: it.take_time(r)?, end_height: 0.0, - start_height: 0.0, + end_speed: 1.0, }, '3' => NoteKind::Flick, '4' => NoteKind::Drag, @@ -271,7 +270,6 @@ pub fn parse_pec(source: &str, extra: ChartExtra) -> Result { time, height: 0.0, speed: 1.0, - end_speed: 1.0, above, multiple_hint: false, diff --git a/prpr/src/parse/pgr.rs b/prpr/src/parse/pgr.rs index f446a23c..977e8faa 100644 --- a/prpr/src/parse/pgr.rs +++ b/prpr/src/parse/pgr.rs @@ -45,7 +45,7 @@ pub struct PgrNote { position_x: f32, hold_time: f32, speed: f32, - floor_position: f32, + _floor_position: f32, } #[derive(Deserialize)] @@ -191,15 +191,18 @@ fn parse_notes(r: f32, mut pgr: Vec, _speed: &mut AnimFloat, height: &m pgr.into_iter() .map(|pgr| { let time = pgr.time * r; + let height = { + height.set_time(time); + height.now() + }; let kind = match pgr.kind { 1 => NoteKind::Click, 2 => NoteKind::Drag, 3 => { let end_time = (pgr.time + pgr.hold_time) * r; - height.set_time(time); - let start_height = height.now(); - let end_height = start_height + (pgr.hold_time * pgr.speed * r / HEIGHT_RATIO); - NoteKind::Hold { end_time, end_height, start_height } + let end_height = height + (pgr.hold_time * pgr.speed * r / HEIGHT_RATIO); + let end_speed = pgr.speed; + NoteKind::Hold { end_time, end_height, end_speed } } 4 => NoteKind::Flick, _ => ptl!(bail "unknown-note-type", "type" => pgr.kind), @@ -218,8 +221,7 @@ fn parse_notes(r: f32, mut pgr: Vec, _speed: &mut AnimFloat, height: &m } else { pgr.speed }, - end_speed: pgr.speed, - height: pgr.floor_position / HEIGHT_RATIO, + height, above, multiple_hint: false, diff --git a/prpr/src/parse/rpe.rs b/prpr/src/parse/rpe.rs index 1380cb68..ee22aa7b 100644 --- a/prpr/src/parse/rpe.rs +++ b/prpr/src/parse/rpe.rs @@ -340,7 +340,7 @@ async fn parse_notes( NoteKind::Hold { end_time, end_height: height.now(), - start_height: height.now(), + end_speed: note.speed, } } 3 => NoteKind::Flick, @@ -398,7 +398,6 @@ async fn parse_notes( time, height: note_height, speed: note.speed, - end_speed: note.speed, above: note.above == 1, multiple_hint: false, From a7261f367f685ee3a9ab484f7c64956cb852ee21 Mon Sep 17 00:00:00 2001 From: HLMC Date: Sun, 12 Jan 2025 14:38:39 +0800 Subject: [PATCH 06/13] fix: cover pos --- prpr/src/core/note.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prpr/src/core/note.rs b/prpr/src/core/note.rs index 752bb875..cc5804a9 100644 --- a/prpr/src/core/note.rs +++ b/prpr/src/core/note.rs @@ -213,7 +213,7 @@ impl Note { let base = height - line_height; if !config.draw_below - && ((res.time - FADEOUT_TIME >= self.time) || (self.fake && res.time >= self.time) || (self.time > res.time && base <= -0.0075)) + && ((res.time - FADEOUT_TIME >= self.time) || (self.fake && res.time >= self.time) || (self.time > res.time && base <= -0.001)) && !matches!(self.kind, NoteKind::Hold { .. }) { return; From 5c53fdf110d3b2d34b59e10dee885a7a716ad4b2 Mon Sep 17 00:00:00 2001 From: HLMC Date: Mon, 27 Jan 2025 19:07:48 +0800 Subject: [PATCH 07/13] remove shit --- prpr/src/bin.rs | 1 - prpr/src/core/line.rs | 4 ++-- prpr/src/core/note.rs | 7 +++---- prpr/src/core/resource.rs | 4 ++++ prpr/src/parse/pec.rs | 2 -- prpr/src/parse/pgr.rs | 2 -- prpr/src/parse/rpe.rs | 2 -- prpr/src/scene/game.rs | 3 +-- 8 files changed, 10 insertions(+), 15 deletions(-) diff --git a/prpr/src/bin.rs b/prpr/src/bin.rs index 91d3f85c..3e4f2e2b 100644 --- a/prpr/src/bin.rs +++ b/prpr/src/bin.rs @@ -367,7 +367,6 @@ impl BinaryData for Note { multiple_hint: false, fake: r.read()?, judge: JudgeStatus::NotJudged, - format: r.read()?, }) } diff --git a/prpr/src/core/line.rs b/prpr/src/core/line.rs index 1775a98e..5c88eef1 100644 --- a/prpr/src/core/line.rs +++ b/prpr/src/core/line.rs @@ -387,7 +387,7 @@ impl JudgeLine { height.set_time(note.time.min(res.time)); height.now() }; - if agg && note.height - line_height + note.object.translation.1.now() > height_above / note.speed && matches!(note.format, ChartFormat::Pgr | ChartFormat::Rpe) { + if agg && note.height - line_height + note.object.translation.1.now() > height_above / note.speed && matches!(res.chart_format, ChartFormat::Pgr | ChartFormat::Rpe) { break; } note.render(res, &mut config, bpm_list); @@ -412,7 +412,7 @@ impl JudgeLine { height.set_time(note.time.min(res.time)); height.now() }; - if agg && note.height - line_height + note.object.translation.1.now() > height_below / note.speed && matches!(note.format, ChartFormat::Pgr | ChartFormat::Rpe) { + if agg && note.height - line_height + note.object.translation.1.now() > height_below / note.speed && matches!(res.chart_format, ChartFormat::Pgr | ChartFormat::Rpe) { break; } note.render(res, &mut config, bpm_list); diff --git a/prpr/src/core/note.rs b/prpr/src/core/note.rs index cc5804a9..ab5d8418 100644 --- a/prpr/src/core/note.rs +++ b/prpr/src/core/note.rs @@ -43,7 +43,6 @@ pub struct Note { pub multiple_hint: bool, pub fake: bool, pub judge: JudgeStatus, - pub format: ChartFormat, } pub struct RenderConfig<'a> { @@ -142,7 +141,7 @@ impl Note { if let Some(color) = if let JudgeStatus::Hold(perfect, ref mut at, ..) = &mut self.judge { if res.time >= *at { let beat = 30. / bpm_list.now_bpm( - if matches!(self.format, ChartFormat::Pgr) { index as f32 } else { self.time } + if matches!(res.chart_format, ChartFormat::Pgr) { index as f32 } else { self.time } ); *at = res.time + beat / res.config.speed; Some(if *perfect { @@ -257,7 +256,7 @@ impl Note { let h = if self.time <= res.time { line_height } else { height }; let bottom = h - line_height; - let top = if matches!(self.format, ChartFormat::Pgr) { + let top = if matches!(res.chart_format, ChartFormat::Pgr) { let end_spd = end_speed * ctrl_obj.y.now_opt().unwrap_or(1.); if end_spd == 0. { return; @@ -269,7 +268,7 @@ impl Note { } else { end_height - line_height }; - if res.time < self.time && bottom < -1e-6 && !config.settings.hold_partial_cover && !matches!(self.format, ChartFormat::Pgr) { + if res.time < self.time && bottom < -1e-6 && !config.settings.hold_partial_cover && !matches!(res.chart_format, ChartFormat::Pgr) { return; } let tex = &style.hold; diff --git a/prpr/src/core/resource.rs b/prpr/src/core/resource.rs index e6de48f5..b5d4a05c 100644 --- a/prpr/src/core/resource.rs +++ b/prpr/src/core/resource.rs @@ -18,6 +18,7 @@ use std::{ path::Path, sync::atomic::AtomicU32, }; +use crate::info::ChartFormat; pub const MAX_SIZE: usize = 64; // needs tweaking pub static DPI_VALUE: AtomicU32 = AtomicU32::new(250); @@ -344,6 +345,7 @@ pub type SfxMap = HashMap; pub struct Resource { pub config: Config, + pub chart_format: ChartFormat, pub info: ChartInfo, pub aspect_ratio: f32, pub dpi: u32, @@ -411,6 +413,7 @@ impl Resource { pub async fn new( config: Config, + chart_format: ChartFormat, info: ChartInfo, mut fs: Box, player: Option, @@ -451,6 +454,7 @@ impl Resource { macroquad::window::gl_set_drawcall_buffer_capacity(MAX_SIZE * 4, MAX_SIZE * 6); Ok(Self { config, + chart_format, info, aspect_ratio, dpi: DPI_VALUE.load(std::sync::atomic::Ordering::SeqCst), diff --git a/prpr/src/parse/pec.rs b/prpr/src/parse/pec.rs index 42a1c9c7..6a61a687 100644 --- a/prpr/src/parse/pec.rs +++ b/prpr/src/parse/pec.rs @@ -8,7 +8,6 @@ use crate::{ }, ext::NotNanExt, judge::{HitSound, JudgeStatus}, - info::ChartFormat, }; use anyhow::{bail, Context, Result}; use std::{cell::RefCell, collections::HashMap}; @@ -275,7 +274,6 @@ pub fn parse_pec(source: &str, extra: ChartExtra) -> Result { multiple_hint: false, fake, judge: JudgeStatus::NotJudged, - format: ChartFormat::Pec, }); if it.next() == Some("#") { last_note!().speed = it.take_f32()?; diff --git a/prpr/src/parse/pgr.rs b/prpr/src/parse/pgr.rs index 977e8faa..1eccd97e 100644 --- a/prpr/src/parse/pgr.rs +++ b/prpr/src/parse/pgr.rs @@ -8,7 +8,6 @@ use crate::{ }, ext::NotNanExt, judge::{HitSound, JudgeStatus}, - info::ChartFormat, }; use anyhow::{Context, Result}; use serde::Deserialize; @@ -227,7 +226,6 @@ fn parse_notes(r: f32, mut pgr: Vec, _speed: &mut AnimFloat, height: &m multiple_hint: false, fake: false, judge: JudgeStatus::NotJudged, - format: ChartFormat::Pgr, }) }) .collect() diff --git a/prpr/src/parse/rpe.rs b/prpr/src/parse/rpe.rs index ee22aa7b..84084a7d 100644 --- a/prpr/src/parse/rpe.rs +++ b/prpr/src/parse/rpe.rs @@ -10,7 +10,6 @@ use crate::{ ext::{NotNanExt, SafeTexture}, fs::FileSystem, judge::{HitSound, JudgeStatus}, - info::ChartFormat, }; use anyhow::{Context, Result}; use image::{codecs::gif, AnimationDecoder, DynamicImage, ImageError}; @@ -403,7 +402,6 @@ async fn parse_notes( multiple_hint: false, fake: note.is_fake != 0, judge: JudgeStatus::NotJudged, - format: ChartFormat::Rpe, }) } Ok(notes) diff --git a/prpr/src/scene/game.rs b/prpr/src/scene/game.rs index ac1d787e..f0c5ae8b 100644 --- a/prpr/src/scene/game.rs +++ b/prpr/src/scene/game.rs @@ -123,7 +123,6 @@ pub struct GameScene { pub gl: InternalGlContext<'static>, player: Option, chart_bytes: Vec, - chart_format: ChartFormat, info_offset: f32, effects: Vec, @@ -253,6 +252,7 @@ impl GameScene { let info_offset = info.offset; let mut res = Resource::new( config, + chart_format, info, fs, player.as_ref().and_then(|it| it.avatar.clone()), @@ -286,7 +286,6 @@ impl GameScene { gl: unsafe { get_internal_gl() }, player, chart_bytes, - chart_format, effects, info_offset, From c07e380b7b564eee9caddd5a40ca7a81e4d047f5 Mon Sep 17 00:00:00 2001 From: HLMC Date: Sat, 8 Feb 2025 15:46:05 +0800 Subject: [PATCH 08/13] revert bin.rs --- prpr/src/bin.rs | 31 +------------------------------ prpr/src/core/line.rs | 18 +----------------- prpr/src/core/note.rs | 10 +++++----- prpr/src/parse/pec.rs | 3 +-- prpr/src/parse/pgr.rs | 9 ++------- prpr/src/parse/rpe.rs | 1 - 6 files changed, 10 insertions(+), 62 deletions(-) diff --git a/prpr/src/bin.rs b/prpr/src/bin.rs index 3e4f2e2b..3041107e 100644 --- a/prpr/src/bin.rs +++ b/prpr/src/bin.rs @@ -17,7 +17,6 @@ use crate::{ }, judge::{HitSound, JudgeStatus}, parse::process_lines, - info::ChartFormat, }; use anyhow::{bail, Result}; use byteorder::{LittleEndian as LE, ReadBytesExt, WriteBytesExt}; @@ -155,32 +154,6 @@ impl BinaryData for bool { } } -impl BinaryData for ChartFormat { - fn read_binary(r: &mut BinaryReader) -> Result { - match r.read::()? { - 0 => Ok(ChartFormat::Rpe), - 1 => Ok(ChartFormat::Pec), - 2 => Ok(ChartFormat::Pgr), - 3 => Ok(ChartFormat::Pgr1), - 4 => Ok(ChartFormat::Pbc), - _ => bail!("invalid chart format"), - } - } - - fn write_binary(&self, w: &mut BinaryWriter) -> Result<()> { - w.write_val( - match self { - ChartFormat::Rpe => 0, - ChartFormat::Pec => 1, - ChartFormat::Pgr => 2, - ChartFormat::Pgr1 => 3, - ChartFormat::Pbc => 4, - } - )?; - Ok(()) - } -} - impl BinaryData for f32 { fn read_binary(r: &mut BinaryReader) -> Result { Ok(r.0.read_f32::()?) @@ -349,7 +322,6 @@ impl BinaryData for Note { 1 => NoteKind::Hold { end_time: r.read()?, end_height: r.read()?, - end_speed: if r.read()? { r.read::()? } else { 1. }, }, 2 => NoteKind::Flick, 3 => NoteKind::Drag, @@ -376,11 +348,10 @@ impl BinaryData for Note { NoteKind::Click => { w.write_val(0_u8)?; } - NoteKind::Hold { end_time, end_height, end_speed } => { + NoteKind::Hold { end_time, end_height } => { w.write_val(1_u8)?; w.write_val(end_time)?; w.write_val(end_height)?; - w.write_val(end_speed)?; } NoteKind::Flick => w.write_val(2_u8)?, NoteKind::Drag => w.write_val(3_u8)?, diff --git a/prpr/src/core/line.rs b/prpr/src/core/line.rs index 5c88eef1..ab0433f4 100644 --- a/prpr/src/core/line.rs +++ b/prpr/src/core/line.rs @@ -1,4 +1,4 @@ -use super::{chart::ChartSettings, object::CtrlObject, Anim, AnimFloat, BpmList, Matrix, Note, Object, Point, RenderConfig, Resource, Vector}; +use super::{chart::ChartSettings, object::CtrlObject, Anim, AnimFloat, BpmList, Matrix, Note, NoteKind, Object, Point, RenderConfig, Resource, Vector}; use crate::{ config::Mods, ext::{draw_text_aligned, get_viewport, NotNanExt, SafeTexture}, @@ -382,14 +382,6 @@ impl JudgeLine { let height_below = -p[0].y.min(p[1].y.min(p[2].y.min(p[3].y))) * res.aspect_ratio; let agg = res.config.aggressive; for note in self.notes.iter().take(self.cache.not_plain_count).filter(|it| it.above) { - let line_height = { - let mut height = self.height.clone(); - height.set_time(note.time.min(res.time)); - height.now() - }; - if agg && note.height - line_height + note.object.translation.1.now() > height_above / note.speed && matches!(res.chart_format, ChartFormat::Pgr | ChartFormat::Rpe) { - break; - } note.render(res, &mut config, bpm_list); } for index in &self.cache.above_indices { @@ -407,14 +399,6 @@ impl JudgeLine { } res.with_model(Matrix::identity().append_nonuniform_scaling(&Vector::new(1.0, -1.0)), |res| { for note in self.notes.iter().take(self.cache.not_plain_count).filter(|it| !it.above) { - let line_height = { - let mut height = self.height.clone(); - height.set_time(note.time.min(res.time)); - height.now() - }; - if agg && note.height - line_height + note.object.translation.1.now() > height_below / note.speed && matches!(res.chart_format, ChartFormat::Pgr | ChartFormat::Rpe) { - break; - } note.render(res, &mut config, bpm_list); } for index in &self.cache.below_indices { diff --git a/prpr/src/core/note.rs b/prpr/src/core/note.rs index ab5d8418..2e114741 100644 --- a/prpr/src/core/note.rs +++ b/prpr/src/core/note.rs @@ -14,7 +14,7 @@ const BAD_TIME: f32 = 0.5; #[derive(Clone, Debug)] pub enum NoteKind { Click, - Hold { end_time: f32, end_height: f32, end_speed: f32 }, + Hold { end_time: f32, end_height: f32 }, Flick, Drag, } @@ -205,7 +205,8 @@ impl Note { self.init_ctrl_obj(ctrl_obj, config.line_height); let mut color = self.object.now_color(); color.a *= res.alpha * ctrl_obj.alpha.now_opt().unwrap_or(1.); - let spd = self.speed * ctrl_obj.y.now_opt().unwrap_or(1.); + let end_spd = self.speed * ctrl_obj.y.now_opt().unwrap_or(1.); + let spd = if matches!(res.chart_format, ChartFormat::Pgr | ChartFormat::Pgr1) && matches!(self.kind, NoteKind::Hold { .. }) { 1. } else { end_spd }; let line_height = config.line_height / res.aspect_ratio * spd; let height = self.height / res.aspect_ratio * spd; @@ -236,7 +237,7 @@ impl Note { NoteKind::Click => { draw(res, *style.click); } - NoteKind::Hold { end_time, end_height, end_speed } => { + NoteKind::Hold { end_time, end_height } => { res.with_model(self.now_transform(res, ctrl_obj, 0., 0.), |res| { let style = if res.config.double_hint && self.multiple_hint { &res.res_pack.note_style_mh @@ -257,8 +258,7 @@ impl Note { let h = if self.time <= res.time { line_height } else { height }; let bottom = h - line_height; let top = if matches!(res.chart_format, ChartFormat::Pgr) { - let end_spd = end_speed * ctrl_obj.y.now_opt().unwrap_or(1.); - if end_spd == 0. { + if end_spd == 0. { return; } let time = if res.time >= self.time {res.time} else {self.time}; diff --git a/prpr/src/parse/pec.rs b/prpr/src/parse/pec.rs index 6a61a687..7161f99c 100644 --- a/prpr/src/parse/pec.rs +++ b/prpr/src/parse/pec.rs @@ -143,7 +143,7 @@ fn parse_judge_line(mut pec: PECJudgeLine, id: usize, max_time: f32) -> Result Result { '2' => NoteKind::Hold { end_time: it.take_time(r)?, end_height: 0.0, - end_speed: 1.0, }, '3' => NoteKind::Flick, '4' => NoteKind::Drag, diff --git a/prpr/src/parse/pgr.rs b/prpr/src/parse/pgr.rs index 1eccd97e..3d06a666 100644 --- a/prpr/src/parse/pgr.rs +++ b/prpr/src/parse/pgr.rs @@ -200,8 +200,7 @@ fn parse_notes(r: f32, mut pgr: Vec, _speed: &mut AnimFloat, height: &m 3 => { let end_time = (pgr.time + pgr.hold_time) * r; let end_height = height + (pgr.hold_time * pgr.speed * r / HEIGHT_RATIO); - let end_speed = pgr.speed; - NoteKind::Hold { end_time, end_height, end_speed } + NoteKind::Hold { end_time, end_height } } 4 => NoteKind::Flick, _ => ptl!(bail "unknown-note-type", "type" => pgr.kind), @@ -215,11 +214,7 @@ fn parse_notes(r: f32, mut pgr: Vec, _speed: &mut AnimFloat, height: &m kind, hitsound, time, - speed: if pgr.kind == 3 { - 1. - } else { - pgr.speed - }, + speed: pgr.speed, height, above, diff --git a/prpr/src/parse/rpe.rs b/prpr/src/parse/rpe.rs index 84084a7d..3f0320a8 100644 --- a/prpr/src/parse/rpe.rs +++ b/prpr/src/parse/rpe.rs @@ -339,7 +339,6 @@ async fn parse_notes( NoteKind::Hold { end_time, end_height: height.now(), - end_speed: note.speed, } } 3 => NoteKind::Flick, From 76f2a64589e7dc50361b07d4fd8deab98c31028f Mon Sep 17 00:00:00 2001 From: HLMC Date: Sat, 8 Feb 2025 15:47:28 +0800 Subject: [PATCH 09/13] Update line.rs --- prpr/src/core/line.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/prpr/src/core/line.rs b/prpr/src/core/line.rs index ab0433f4..83c4f9c7 100644 --- a/prpr/src/core/line.rs +++ b/prpr/src/core/line.rs @@ -1,10 +1,9 @@ -use super::{chart::ChartSettings, object::CtrlObject, Anim, AnimFloat, BpmList, Matrix, Note, NoteKind, Object, Point, RenderConfig, Resource, Vector}; +use super::{chart::ChartSettings, object::CtrlObject, Anim, AnimFloat, BpmList, Matrix, Note, Object, Point, RenderConfig, Resource, Vector}; use crate::{ config::Mods, ext::{draw_text_aligned, get_viewport, NotNanExt, SafeTexture}, judge::{JudgeStatus, LIMIT_BAD}, ui::Ui, - info::ChartFormat, }; use macroquad::prelude::*; use miniquad::{RenderPass, Texture, TextureParams, TextureWrap}; From d842ff54c7308e3c56342228e55221ec13c01006 Mon Sep 17 00:00:00 2001 From: HLMC Date: Sat, 8 Feb 2025 15:54:49 +0800 Subject: [PATCH 10/13] fix: format version --- prpr/src/core/note.rs | 2 +- prpr/src/info.rs | 1 - prpr/src/parse.rs | 2 +- prpr/src/parse/pgr.rs | 76 ++++++------------------------------------ prpr/src/scene/game.rs | 9 ++--- 5 files changed, 15 insertions(+), 75 deletions(-) diff --git a/prpr/src/core/note.rs b/prpr/src/core/note.rs index 2e114741..f0615743 100644 --- a/prpr/src/core/note.rs +++ b/prpr/src/core/note.rs @@ -206,7 +206,7 @@ impl Note { let mut color = self.object.now_color(); color.a *= res.alpha * ctrl_obj.alpha.now_opt().unwrap_or(1.); let end_spd = self.speed * ctrl_obj.y.now_opt().unwrap_or(1.); - let spd = if matches!(res.chart_format, ChartFormat::Pgr | ChartFormat::Pgr1) && matches!(self.kind, NoteKind::Hold { .. }) { 1. } else { end_spd }; + let spd = if matches!(res.chart_format, ChartFormat::Pgr) && matches!(self.kind, NoteKind::Hold { .. }) { 1. } else { end_spd }; let line_height = config.line_height / res.aspect_ratio * spd; let height = self.height / res.aspect_ratio * spd; diff --git a/prpr/src/info.rs b/prpr/src/info.rs index e5f67d04..5e5e24ed 100644 --- a/prpr/src/info.rs +++ b/prpr/src/info.rs @@ -10,7 +10,6 @@ pub enum ChartFormat { Rpe = 0, Pec, Pgr, - Pgr1, Pbc, } diff --git a/prpr/src/parse.rs b/prpr/src/parse.rs index 78e97d01..ac03eba8 100644 --- a/prpr/src/parse.rs +++ b/prpr/src/parse.rs @@ -7,7 +7,7 @@ mod pec; pub use pec::parse_pec; mod pgr; -pub use pgr::{parse_phigros, parse_phigros_fv1}; +pub use pgr::parse_phigros; mod rpe; pub use rpe::{parse_rpe, RPE_HEIGHT, RPE_WIDTH}; diff --git a/prpr/src/parse/pgr.rs b/prpr/src/parse/pgr.rs index 3d06a666..94d612e4 100644 --- a/prpr/src/parse/pgr.rs +++ b/prpr/src/parse/pgr.rs @@ -66,6 +66,7 @@ struct PgrJudgeLine { #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct PgrChart { + format_version: u32, offset: f32, judge_line_list: Vec, } @@ -226,7 +227,7 @@ fn parse_notes(r: f32, mut pgr: Vec, _speed: &mut AnimFloat, height: &m .collect() } -fn parse_judge_line(pgr: PgrJudgeLine, max_time: f32) -> Result { +fn parse_judge_line(pgr: PgrJudgeLine, max_time: f32, format_version: u32) -> Result { let r = 60. / pgr.bpm / 32.; let (mut speed, mut height) = parse_speed_events(r, pgr.speed_events, max_time).context("Failed to parse speed events")?; let notes_above = parse_notes(r, pgr.notes_above, &mut speed, &mut height, true).context("Failed to parse notes above")?; @@ -238,37 +239,13 @@ fn parse_judge_line(pgr: PgrJudgeLine, max_time: f32) -> Result { object: Object { alpha: parse_float_events(r, pgr.alpha_events).with_context(|| ptl!("alpha-events-parse-failed"))?, rotation: parse_float_events(r, pgr.rotate_events).with_context(|| ptl!("rotate-events-parse-failed"))?, - translation: parse_move_events(r, pgr.move_events).with_context(|| ptl!("move-events-parse-failed"))?, - ..Default::default() - }, - ctrl_obj: RefCell::default(), - kind: JudgeLineKind::Normal, - height, - incline: AnimFloat::default(), - notes, - color: Anim::default(), - parent: None, - z_index: 0, - show_below: false, - attach_ui: None, - - cache, - }) -} - -fn parse_judge_line_fv1(pgr: PgrJudgeLine, max_time: f32) -> Result { - let r = 60. / 32. / pgr.bpm; - let (mut speed, mut height) = parse_speed_events(r, pgr.speed_events, max_time).context("Failed to parse speed events")?; - let notes_above = parse_notes(r, pgr.notes_above, &mut speed, &mut height, true).context("Failed to parse notes above")?; - let mut notes_below = parse_notes(r, pgr.notes_below, &mut speed, &mut height, false).context("Failed to parse notes below")?; - let mut notes = notes_above; - notes.append(&mut notes_below); - let cache = JudgeLineCache::new(&mut notes); - Ok(JudgeLine { - object: Object { - alpha: parse_float_events(r, pgr.alpha_events).with_context(|| ptl!("alpha-events-parse-failed"))?, - rotation: parse_float_events(r, pgr.rotate_events).with_context(|| ptl!("rotate-events-parse-failed"))?, - translation: parse_move_events_fv1(r, pgr.move_events).with_context(|| ptl!("move-events-parse-failed"))?, + translation: { + match format_version { + 1 => parse_move_events_fv1(r, pgr.move_events).with_context(|| ptl!("move-events-parse-failed"))?, + 3 => parse_move_events(r, pgr.move_events).with_context(|| ptl!("move-events-parse-failed"))?, + _ => ptl!(bail "unknown-format-version"), + } + }, ..Default::default() }, ctrl_obj: RefCell::default(), @@ -288,6 +265,7 @@ fn parse_judge_line_fv1(pgr: PgrJudgeLine, max_time: f32) -> Result { pub fn parse_phigros(source: &str, extra: ChartExtra) -> Result { let pgr: PgrChart = serde_json::from_str(source).with_context(|| ptl!("json-parse-failed"))?; + let format_version = pgr.format_version; let mut bpm_values = Vec::new(); for (index, judge_line) in pgr.judge_line_list.iter().enumerate() { bpm_values.push((index as f32, judge_line.bpm)); @@ -311,40 +289,8 @@ pub fn parse_phigros(source: &str, extra: ChartExtra) -> Result { .judge_line_list .into_iter() .enumerate() - .map(|(id, pgr)| parse_judge_line(pgr, max_time).with_context(|| ptl!("judge-line-location", "jlid" => id))) + .map(|(id, pgr)| parse_judge_line(pgr, max_time, format_version).with_context(|| ptl!("judge-line-location", "jlid" => id))) .collect::>>()?; process_lines(&mut lines); Ok(Chart::new(pgr.offset, lines, BpmList::new_time(bpm_values), ChartSettings::default(), extra, HashMap::new())) } - -pub fn parse_phigros_fv1(source: &str, extra: ChartExtra) -> Result { - let pgr: PgrChart = serde_json::from_str(source).with_context(|| ptl!("json-parse-failed"))?; - let mut bpm_values = Vec::new(); - for (index, judge_line) in pgr.judge_line_list.iter().enumerate() { - bpm_values.push((index as f32, judge_line.bpm)); - } - - let max_time = *pgr - .judge_line_list - .iter() - .map(|line| { - line.notes_above - .iter() - .chain(line.notes_below.iter()) - .map(|note| note.time.not_nan()) - .max() - .unwrap_or_default() - * (60. / line.bpm / 32.) - }) - .max() - .unwrap_or_default() - + 1.; - let mut lines = pgr - .judge_line_list - .into_iter() - .enumerate() - .map(|(id, pgr)| parse_judge_line_fv1(pgr, max_time).with_context(|| ptl!("judge-line-location", "jlid" => id))) - .collect::>>()?; - process_lines(&mut lines); - Ok(Chart::new(pgr.offset, lines, BpmList::new_time(bpm_values), ChartSettings::default(), extra,HashMap::new())) -} \ No newline at end of file diff --git a/prpr/src/scene/game.rs b/prpr/src/scene/game.rs index f0c5ae8b..1e017c4b 100644 --- a/prpr/src/scene/game.rs +++ b/prpr/src/scene/game.rs @@ -16,7 +16,7 @@ use crate::{ fs::FileSystem, info::{ChartFormat, ChartInfo}, judge::Judge, - parse::{parse_extra, parse_pec, parse_phigros, parse_phigros_fv1, parse_rpe}, + parse::{parse_extra, parse_pec, parse_phigros, parse_rpe}, task::Task, time::TimeManager, ui::{RectButton, TextPainter, Ui}, @@ -191,11 +191,7 @@ impl GameScene { if text.contains("\"META\"") { ChartFormat::Rpe } else { - if text.starts_with("{\"formatVersion\":3") { - ChartFormat::Pgr - } else { - ChartFormat::Pgr1 - } + ChartFormat::Pgr } } else { ChartFormat::Pec @@ -207,7 +203,6 @@ impl GameScene { let mut chart = match format { ChartFormat::Rpe => parse_rpe(&String::from_utf8_lossy(&bytes), fs, extra).await, ChartFormat::Pgr => parse_phigros(&String::from_utf8_lossy(&bytes), extra), - ChartFormat::Pgr1 => parse_phigros_fv1(&String::from_utf8_lossy(&bytes), extra), ChartFormat::Pec => parse_pec(&String::from_utf8_lossy(&bytes), extra), ChartFormat::Pbc => { let mut r = BinaryReader::new(Cursor::new(&bytes)); From 8bb60f2b838864066e2d1ee8a4982721959366f0 Mon Sep 17 00:00:00 2001 From: HLMC Date: Sat, 8 Feb 2025 16:11:46 +0800 Subject: [PATCH 11/13] use not nan for note sort --- prpr/src/parse/pgr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prpr/src/parse/pgr.rs b/prpr/src/parse/pgr.rs index 94d612e4..01cbf186 100644 --- a/prpr/src/parse/pgr.rs +++ b/prpr/src/parse/pgr.rs @@ -187,7 +187,7 @@ fn parse_notes(r: f32, mut pgr: Vec, _speed: &mut AnimFloat, height: &m if pgr.is_empty() { return Ok(Vec::new()); } - pgr.sort_by_key(|it| it.time as usize); + pgr.sort_by_key(|it| it.time.not_nan()); pgr.into_iter() .map(|pgr| { let time = pgr.time * r; From 9d7699a559970684f035cc4c0ed806dc6bd2ecc3 Mon Sep 17 00:00:00 2001 From: HLMC Date: Tue, 11 Feb 2025 15:29:10 +0800 Subject: [PATCH 12/13] use #allow --- prpr/src/parse/pgr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prpr/src/parse/pgr.rs b/prpr/src/parse/pgr.rs index f5c98e36..107db30d 100644 --- a/prpr/src/parse/pgr.rs +++ b/prpr/src/parse/pgr.rs @@ -44,7 +44,7 @@ pub struct PgrNote { position_x: f32, hold_time: f32, speed: f32, - _floor_position: f32, + #[allow(unused)]floor_position: f32, } #[derive(Deserialize)] From 9e405a2d75874450f6a572e84b39dbe6270dfc92 Mon Sep 17 00:00:00 2001 From: HLMC Date: Tue, 11 Feb 2025 15:29:40 +0800 Subject: [PATCH 13/13] modify all perfect --- prpr/src/judge.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prpr/src/judge.rs b/prpr/src/judge.rs index 58a9a90c..e47c57ce 100644 --- a/prpr/src/judge.rs +++ b/prpr/src/judge.rs @@ -970,7 +970,7 @@ pub struct PlayResult { pub fn icon_index(score: u32, full_combo: bool) -> usize { match (score, full_combo) { - (1000000, _) => 7, + (1000000, true) => 7, (_, true) => 6, (x, _) if x < 700000 => 0, (x, _) if x < 820000 => 1,