pub mod bmp;
pub mod bpm;
pub mod control_flow;
pub mod judge;
pub mod metadata;
pub mod music_info;
pub mod notes;
pub mod obj;
pub mod option;
pub mod repr;
pub mod resources;
pub mod scroll;
pub mod section_len;
pub mod speed;
pub mod sprite;
pub mod stop;
pub mod text;
pub mod video;
pub mod volume;
pub mod wav;
pub use notes::Notes;
pub use crate::bms::command::StringValue;
use std::fmt::Debug;
use crate::bms::command::time::ObjTime;
use crate::bms::prelude::*;
use self::{
bmp::BmpObjects, bpm::BpmObjects, control_flow::RandomizedObjects, judge::JudgeObjects,
metadata::Metadata, music_info::MusicInfo, repr::BmsSourceRepresentation,
scroll::ScrollObjects, section_len::SectionLenObjects, speed::SpeedObjects, sprite::Sprites,
stop::StopObjects, text::TextObjects, video::Video, volume::VolumeObjects, wav::WavObjects,
};
use self::{option::OptionObjects, resources::Resources};
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Bms {
pub bmp: BmpObjects,
pub bpm: BpmObjects,
pub judge: JudgeObjects,
pub metadata: Metadata,
pub music_info: MusicInfo,
pub option: OptionObjects,
pub repr: BmsSourceRepresentation,
pub resources: Resources,
pub scroll: ScrollObjects,
pub section_len: SectionLenObjects,
pub speed: SpeedObjects,
pub sprite: Sprites,
pub stop: StopObjects,
pub text: TextObjects,
pub video: Video,
pub volume: VolumeObjects,
pub wav: WavObjects,
pub randomized: Vec<RandomizedObjects>,
}
impl Bms {
#[must_use]
pub const fn notes(&self) -> &Notes {
&self.wav.notes
}
#[must_use]
pub fn last_obj_time(&self) -> Option<ObjTime> {
let obj_last = self.wav.notes.last_obj_time();
let bpm_last = self.bpm.last_obj_time();
let section_len_last = self.section_len.last_obj_time();
let stop_last = self.stop.last_obj_time();
let bga_last = self.bmp.last_obj_time();
[obj_last, bpm_last, section_len_last, stop_last, bga_last]
.into_iter()
.max()
.flatten()
}
#[must_use]
pub fn resolution_for_pulses(&self) -> u64 {
use num::Integer;
let mut hyp_resolution = 1u64;
for obj in self.wav.notes.all_notes() {
hyp_resolution = hyp_resolution.lcm(&obj.offset.denominator().get());
}
hyp_resolution
}
#[must_use]
pub fn union(&self, other: &Bms) -> Self {
let mut res = self.clone();
res.union_inplace(other);
res
}
pub fn union_inplace(&mut self, other: &Bms) {
self.bmp.bmp_files.extend(other.bmp.bmp_files.clone());
self.bmp.bga_changes.extend(other.bmp.bga_changes.clone());
if other.bmp.poor_bmp.is_some() {
self.bmp.poor_bmp.clone_from(&other.bmp.poor_bmp);
}
self.bmp.atbga_defs.extend(other.bmp.atbga_defs.clone());
self.bmp.bga_defs.extend(other.bmp.bga_defs.clone());
self.bmp.swbga_events.extend(other.bmp.swbga_events.clone());
self.bmp.argb_defs.extend(other.bmp.argb_defs.clone());
for (k, v) in &other.bmp.bga_opacity_changes {
self.bmp
.bga_opacity_changes
.entry(*k)
.or_default()
.extend(v.clone());
}
for (k, v) in &other.bmp.bga_argb_changes {
self.bmp
.bga_argb_changes
.entry(*k)
.or_default()
.extend(v.clone());
}
self.bmp
.bga_keybound_events
.extend(other.bmp.bga_keybound_events.clone());
self.bpm.bpm_changes.extend(other.bpm.bpm_changes.clone());
if other.bpm.bpm.is_some() {
self.bpm.bpm.clone_from(&other.bpm.bpm);
}
if other.bpm.base_bpm.is_some() {
self.bpm.base_bpm.clone_from(&other.bpm.base_bpm);
}
self.bpm.bpm_defs.extend(other.bpm.bpm_defs.clone());
self.bpm
.bpm_changes_u8
.extend(other.bpm.bpm_changes_u8.clone());
if other.judge.rank.is_some() {
self.judge.rank = other.judge.rank;
}
if other.judge.total.is_some() {
self.judge.total.clone_from(&other.judge.total);
}
self.judge
.exrank_defs
.extend(other.judge.exrank_defs.clone());
self.judge
.judge_events
.extend(other.judge.judge_events.clone());
if other.metadata.player.is_some() {
self.metadata.player = other.metadata.player;
}
if other.metadata.play_level.is_some() {
self.metadata.play_level = other.metadata.play_level;
}
if other.metadata.difficulty.is_some() {
self.metadata.difficulty = other.metadata.difficulty;
}
if other.metadata.email.is_some() {
self.metadata.email.clone_from(&other.metadata.email);
}
if other.metadata.url.is_some() {
self.metadata.url.clone_from(&other.metadata.url);
}
if other.metadata.wav_path_root.is_some() {
self.metadata
.wav_path_root
.clone_from(&other.metadata.wav_path_root);
}
if other.metadata.divide_prop.is_some() {
self.metadata
.divide_prop
.clone_from(&other.metadata.divide_prop);
}
if other.metadata.is_octave {
self.metadata.is_octave = true;
}
if other.music_info.genre.is_some() {
self.music_info.genre.clone_from(&other.music_info.genre);
}
if other.music_info.title.is_some() {
self.music_info.title.clone_from(&other.music_info.title);
}
if other.music_info.subtitle.is_some() {
self.music_info
.subtitle
.clone_from(&other.music_info.subtitle);
}
if other.music_info.artist.is_some() {
self.music_info.artist.clone_from(&other.music_info.artist);
}
if other.music_info.sub_artist.is_some() {
self.music_info
.sub_artist
.clone_from(&other.music_info.sub_artist);
}
if other.music_info.maker.is_some() {
self.music_info.maker.clone_from(&other.music_info.maker);
}
if other.music_info.comment.is_some() {
self.music_info
.comment
.clone_from(&other.music_info.comment);
}
if other.music_info.preview_music.is_some() {
self.music_info
.preview_music
.clone_from(&other.music_info.preview_music);
}
if other.option.options.is_some() {
self.option.options.clone_from(&other.option.options);
}
self.option
.change_options
.extend(other.option.change_options.clone());
self.option
.option_events
.extend(other.option.option_events.clone());
if other.repr.ln_type != LnType::default() {
self.repr.ln_type = other.repr.ln_type;
}
if other.repr.ln_mode != LnMode::default() {
self.repr.ln_mode = other.repr.ln_mode;
}
if other.repr.charset.is_some() {
self.repr.charset.clone_from(&other.repr.charset);
}
self.repr
.raw_command_lines
.extend(other.repr.raw_command_lines.clone());
self.repr
.non_command_lines
.extend(other.repr.non_command_lines.clone());
if other.repr.case_sensitive_obj_id {
self.repr.case_sensitive_obj_id = true;
}
if other.resources.midi_file.is_some() {
self.resources
.midi_file
.clone_from(&other.resources.midi_file);
}
self.resources.cdda.extend(other.resources.cdda.clone());
self.resources
.materials_wav
.extend(other.resources.materials_wav.clone());
self.resources
.materials_bmp
.extend(other.resources.materials_bmp.clone());
if other.resources.materials_path.is_some() {
self.resources
.materials_path
.clone_from(&other.resources.materials_path);
}
self.scroll
.scrolling_factor_changes
.extend(other.scroll.scrolling_factor_changes.clone());
self.scroll
.scroll_defs
.extend(other.scroll.scroll_defs.clone());
self.section_len
.section_len_changes
.extend(other.section_len.section_len_changes.clone());
self.speed
.speed_factor_changes
.extend(other.speed.speed_factor_changes.clone());
self.speed.speed_defs.extend(other.speed.speed_defs.clone());
if other.sprite.back_bmp.is_some() {
self.sprite.back_bmp.clone_from(&other.sprite.back_bmp);
}
if other.sprite.stage_file.is_some() {
self.sprite.stage_file.clone_from(&other.sprite.stage_file);
}
if other.sprite.banner.is_some() {
self.sprite.banner.clone_from(&other.sprite.banner);
}
self.sprite
.extchr_events
.extend(other.sprite.extchr_events.clone());
if other.sprite.char_file.is_some() {
self.sprite.char_file.clone_from(&other.sprite.char_file);
}
self.stop.stop_defs.extend(other.stop.stop_defs.clone());
self.stop.stp_events.extend(other.stop.stp_events.clone());
for stop in other.stop.stops.values() {
self.stop
.push_stop(stop.clone(), &AlwaysUseNewer)
.expect("AlwaysUseNewer should never error");
}
self.text.text_events.extend(other.text.text_events.clone());
if other.video.video_file.is_some() {
self.video.video_file.clone_from(&other.video.video_file);
}
if other.video.video_colors.is_some() {
self.video.video_colors = other.video.video_colors;
}
if other.video.video_dly.is_some() {
self.video.video_dly.clone_from(&other.video.video_dly);
}
if other.video.video_fs.is_some() {
self.video.video_fs.clone_from(&other.video.video_fs);
}
self.video.seek_defs.extend(other.video.seek_defs.clone());
self.video
.seek_events
.extend(other.video.seek_events.clone());
self.volume
.bgm_volume_changes
.extend(other.volume.bgm_volume_changes.clone());
self.volume
.key_volume_changes
.extend(other.volume.key_volume_changes.clone());
self.wav.wav_files.extend(other.wav.wav_files.clone());
for note in other.wav.notes.all_notes() {
self.wav.notes.push_note(note.clone());
}
self.randomized.extend(other.randomized.clone());
}
}