Add imgui into the editor
This commit is contained in:
parent
70072b5e1a
commit
c5c219337e
13 changed files with 396 additions and 224 deletions
184
Cargo.lock
generated
184
Cargo.lock
generated
|
@ -714,20 +714,6 @@ dependencies = [
|
|||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-queue",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.2"
|
||||
|
@ -762,16 +748,6 @@ dependencies = [
|
|||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b979d76c9fcb84dffc80a73f7290da0f83e4c95773494674cb44b76d13a7a110"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.6"
|
||||
|
@ -996,13 +972,16 @@ dependencies = [
|
|||
"anyhow",
|
||||
"bass-sys",
|
||||
"framework",
|
||||
"gfx_core",
|
||||
"gfx_device_gl",
|
||||
"ggez",
|
||||
"image",
|
||||
"imgui",
|
||||
"imgui-gfx-renderer",
|
||||
"imgui-winit-support",
|
||||
"libosu",
|
||||
"log",
|
||||
"num 0.4.0",
|
||||
"num",
|
||||
"ordered-float 2.10.0",
|
||||
"stderrlog",
|
||||
"structopt",
|
||||
|
@ -1014,16 +993,6 @@ version = "1.6.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
|
||||
dependencies = [
|
||||
"log",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "error-chain"
|
||||
version = "0.12.4"
|
||||
|
@ -1611,6 +1580,17 @@ dependencies = [
|
|||
"parking_lot 0.11.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "imgui-gfx-renderer"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a61820483efd1d881b5bbc205def957bb2c148d9daf956ae7029f3399c03eab"
|
||||
dependencies = [
|
||||
"gfx",
|
||||
"imgui",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "imgui-sys"
|
||||
version = "0.8.2"
|
||||
|
@ -1628,7 +1608,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "30d8cb426a6ee9f1be8e379b18b9085585887056fcfbc2d66bddb2c355944624"
|
||||
dependencies = [
|
||||
"imgui",
|
||||
"winit 0.25.0",
|
||||
"winit 0.26.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1816,23 +1796,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libosu"
|
||||
version = "0.0.16"
|
||||
source = "git+https://github.com/iptq/libosu?rev=81677d5ed88936c4a3e64af951ff0ae523c2d403#81677d5ed88936c4a3e64af951ff0ae523c2d403"
|
||||
version = "0.0.26"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"derive_more",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"num 0.3.1",
|
||||
"num",
|
||||
"num-derive",
|
||||
"num-rational 0.3.2",
|
||||
"num-traits",
|
||||
"ordered-float 2.10.0",
|
||||
"quickcheck",
|
||||
"quickcheck_macros",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
|
@ -2113,19 +2088,6 @@ dependencies = [
|
|||
"winapi 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.7.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"miow 0.3.7",
|
||||
"ntapi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.0"
|
||||
|
@ -2151,18 +2113,6 @@ dependencies = [
|
|||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio-misc"
|
||||
version = "1.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b47412f3a52115b936ff2a229b803498c7b4d332adeb87c2f1498c9da54c398c"
|
||||
dependencies = [
|
||||
"crossbeam",
|
||||
"crossbeam-queue",
|
||||
"log",
|
||||
"mio 0.7.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.2.2"
|
||||
|
@ -2430,45 +2380,20 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
|
||||
dependencies = [
|
||||
"num-bigint 0.3.3",
|
||||
"num-complex 0.3.1",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational 0.3.2",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606"
|
||||
dependencies = [
|
||||
"num-bigint 0.4.3",
|
||||
"num-complex 0.4.0",
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational 0.4.0",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.3"
|
||||
|
@ -2480,15 +2405,6 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.0"
|
||||
|
@ -2537,7 +2453,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-bigint 0.3.3",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
@ -2549,7 +2464,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-bigint 0.4.3",
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
@ -2729,6 +2644,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2975,28 +2891,6 @@ dependencies = [
|
|||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quickcheck"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6"
|
||||
dependencies = [
|
||||
"env_logger",
|
||||
"log",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quickcheck_macros"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b22a693222d716a9587786f37ac3f6b4faedb5b80c23914e7303ff5a1d8016e9"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.36",
|
||||
"quote 1.0.14",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.13"
|
||||
|
@ -4292,38 +4186,6 @@ dependencies = [
|
|||
"x11-dl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winit"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79610794594d5e86be473ef7763f604f2159cbac8c94debd00df8fb41e86c2f8"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cocoa 0.24.0",
|
||||
"core-foundation 0.9.2",
|
||||
"core-graphics 0.22.3",
|
||||
"core-video-sys",
|
||||
"dispatch",
|
||||
"instant",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"mio 0.7.14",
|
||||
"mio-misc",
|
||||
"ndk 0.3.0",
|
||||
"ndk-glue 0.3.0",
|
||||
"ndk-sys",
|
||||
"objc",
|
||||
"parking_lot 0.11.2",
|
||||
"percent-encoding",
|
||||
"raw-window-handle 0.3.4",
|
||||
"scopeguard",
|
||||
"smithay-client-toolkit 0.12.3",
|
||||
"wayland-client 0.28.6",
|
||||
"winapi 0.3.9",
|
||||
"x11-dl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winit"
|
||||
version = "0.26.1"
|
||||
|
|
|
@ -26,12 +26,14 @@ ordered-float = "2.10.0"
|
|||
structopt = "0.3.25"
|
||||
image = "0.23.14"
|
||||
imgui = "0.8.2"
|
||||
imgui-winit-support = "0.8.2"
|
||||
imgui-winit-support = { version = "0.8.2", features = ["winit-26"], default-features = false }
|
||||
framework = { path = "framework" }
|
||||
imgui-gfx-renderer = "0.8.2"
|
||||
gfx_core = "0.9.2"
|
||||
gfx_device_gl = "0.16.2"
|
||||
|
||||
[dependencies.libosu]
|
||||
git = "https://github.com/iptq/libosu"
|
||||
rev = "81677d5ed88936c4a3e64af951ff0ae523c2d403"
|
||||
path = "../libosu"
|
||||
|
||||
[features]
|
||||
clippy = []
|
||||
|
|
2
run.sh
2
run.sh
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
export LD_LIBRARY_PATH=$(pwd)/bass-sys/linux/bass24/x64
|
||||
echo $LD_LIBRARY_PATH
|
||||
exec cargo run --release "$@"
|
||||
exec mold -run cargo run --release "$@"
|
||||
|
|
|
@ -62,12 +62,15 @@ impl BeatmapExt {
|
|||
break;
|
||||
}
|
||||
|
||||
let end_time = self.inner.get_hitobject_end_time(&stack_base_obj.inner);
|
||||
let stack_threshold =
|
||||
self.inner.difficulty.approach_preempt() as f64 * self.inner.stack_leniency;
|
||||
let end_time = self
|
||||
.inner
|
||||
.get_hitobject_end_time(&stack_base_obj.inner)
|
||||
.unwrap();
|
||||
let stack_threshold = self.inner.difficulty.approach_preempt().as_seconds()
|
||||
* self.inner.stack_leniency;
|
||||
|
||||
// We are no longer within stacking range of the next object.
|
||||
if (object_n.inner.start_time.0 - end_time.0) as f64 > stack_threshold {
|
||||
if (object_n.inner.start_time.0 as f64 - end_time) > stack_threshold {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -114,7 +117,7 @@ impl BeatmapExt {
|
|||
}
|
||||
|
||||
let stack_threshold =
|
||||
self.inner.difficulty.approach_preempt() as f64 * self.inner.stack_leniency;
|
||||
self.inner.difficulty.approach_preempt().as_seconds() * self.inner.stack_leniency;
|
||||
|
||||
match object_i.inner.kind {
|
||||
HitObjectKind::Circle => {
|
||||
|
@ -125,9 +128,10 @@ impl BeatmapExt {
|
|||
|
||||
let end_time = self
|
||||
.inner
|
||||
.get_hitobject_end_time(&self.hit_objects[n].inner);
|
||||
.get_hitobject_end_time(&self.hit_objects[n].inner)
|
||||
.unwrap();
|
||||
|
||||
if (self.hit_objects[iidx].inner.start_time.0 - end_time.0) as f64
|
||||
if (self.hit_objects[iidx].inner.start_time.0 as f64 - end_time)
|
||||
> stack_threshold
|
||||
{
|
||||
break;
|
||||
|
|
|
@ -22,6 +22,7 @@ impl EventHandler for Game {
|
|||
_: f32,
|
||||
) -> GameResult {
|
||||
self.mouse_pos = (x, y);
|
||||
self.imgui.update_mouse_pos(x, y);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -32,6 +33,9 @@ impl EventHandler for Game {
|
|||
x: f32,
|
||||
y: f32,
|
||||
) -> GameResult {
|
||||
self.imgui.update_mouse_down(btn);
|
||||
// TODO: figure out if the UI handled anything, and then whether or not to keep going into
|
||||
// letting the rest of the code handle the mouse press or not
|
||||
match btn {
|
||||
MouseButton::Left => {
|
||||
use super::seeker::BOUNDS;
|
||||
|
@ -57,6 +61,7 @@ impl EventHandler for Game {
|
|||
x: f32,
|
||||
y: f32,
|
||||
) -> GameResult {
|
||||
self.imgui.update_mouse_up(btn);
|
||||
match btn {
|
||||
MouseButton::Left => {
|
||||
if let Some((px, py)) = self.left_drag_start {
|
||||
|
@ -84,8 +89,9 @@ impl EventHandler for Game {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn key_up_event(&mut self, _: &mut Context, keycode: KeyCode, _: KeyMods) -> GameResult {
|
||||
fn key_up_event(&mut self, _: &mut Context, keycode: KeyCode, keymods: KeyMods) -> GameResult {
|
||||
use KeyCode::*;
|
||||
self.imgui.update_key_up(keycode, keymods);
|
||||
|
||||
match keycode {
|
||||
Space => self.toggle_playing(),
|
||||
|
@ -103,10 +109,11 @@ impl EventHandler for Game {
|
|||
&mut self,
|
||||
_: &mut Context,
|
||||
keycode: KeyCode,
|
||||
mods: KeyMods,
|
||||
keymods: KeyMods,
|
||||
_: bool,
|
||||
) -> GameResult {
|
||||
use KeyCode::*;
|
||||
self.imgui.update_key_down(keycode, keymods);
|
||||
|
||||
self.keymap.insert(keycode);
|
||||
match keycode {
|
||||
|
@ -120,7 +127,7 @@ impl EventHandler for Game {
|
|||
..
|
||||
}) = &self.current_uninherited_timing_point
|
||||
{
|
||||
let steps = -if mods.contains(KeyMods::SHIFT) {
|
||||
let steps = -if keymods.contains(KeyMods::SHIFT) {
|
||||
info.meter as i32
|
||||
} else {
|
||||
1
|
||||
|
@ -134,7 +141,7 @@ impl EventHandler for Game {
|
|||
..
|
||||
}) = &self.current_uninherited_timing_point
|
||||
{
|
||||
let steps = if mods.contains(KeyMods::SHIFT) {
|
||||
let steps = if keymods.contains(KeyMods::SHIFT) {
|
||||
info.meter as i32
|
||||
} else {
|
||||
1
|
||||
|
|
|
@ -61,7 +61,7 @@ impl Game {
|
|||
}
|
||||
|
||||
pub(super) fn toggle_grid(&mut self) {
|
||||
use libosu::enums::GridSize::*;
|
||||
use libosu::data::GridSize::*;
|
||||
self.beatmap.inner.grid_size = match self.beatmap.inner.grid_size {
|
||||
Tiny => Small,
|
||||
Small => Medium,
|
||||
|
|
115
src/game/mod.rs
115
src/game/mod.rs
|
@ -22,17 +22,20 @@ use ggez::{
|
|||
Context,
|
||||
};
|
||||
use image::io::Reader as ImageReader;
|
||||
use imgui::Window;
|
||||
use imgui_winit_support::WinitPlatform;
|
||||
use libosu::{
|
||||
beatmap::Beatmap,
|
||||
hitobject::{HitObjectKind, SliderSplineKind, SpinnerInfo},
|
||||
math::Point,
|
||||
spline::Spline,
|
||||
timing::{TimestampMillis, TimingPoint, TimingPointKind},
|
||||
timing::{Millis, TimingPoint, TimingPointKind},
|
||||
};
|
||||
|
||||
use crate::audio::{AudioEngine, Sound};
|
||||
use crate::beatmap::{BeatmapExt, STACK_DISTANCE};
|
||||
use crate::hitobject::HitObjectExt;
|
||||
use crate::imgui_wrapper::ImGuiWrapper;
|
||||
use crate::skin::Skin;
|
||||
use crate::utils::{self, rect_contains};
|
||||
|
||||
|
@ -47,7 +50,7 @@ pub const DEFAULT_COLORS: &[(f32, f32, f32)] = &[
|
|||
pub type SliderCache = HashMap<Vec<Point<i32>>, Spline>;
|
||||
|
||||
pub struct PartialSliderState {
|
||||
start_time: TimestampMillis,
|
||||
start_time: Millis,
|
||||
kind: SliderSplineKind,
|
||||
control_points: Vec<Point<i32>>,
|
||||
pixel_length: f64,
|
||||
|
@ -62,6 +65,7 @@ pub enum Tool {
|
|||
|
||||
pub struct Game {
|
||||
is_playing: bool,
|
||||
imgui: ImGuiWrapper,
|
||||
audio_engine: AudioEngine,
|
||||
song: Option<Sound>,
|
||||
beatmap: BeatmapExt,
|
||||
|
@ -85,7 +89,7 @@ pub struct Game {
|
|||
}
|
||||
|
||||
impl Game {
|
||||
pub fn new() -> Result<Game> {
|
||||
pub fn new(imgui: ImGuiWrapper) -> Result<Game> {
|
||||
let audio_engine = AudioEngine::new()?;
|
||||
let skin = Skin::new();
|
||||
|
||||
|
@ -94,6 +98,7 @@ impl Game {
|
|||
|
||||
Ok(Game {
|
||||
is_playing: false,
|
||||
imgui,
|
||||
audio_engine,
|
||||
beatmap,
|
||||
song: None,
|
||||
|
@ -208,7 +213,7 @@ impl Game {
|
|||
self.draw_grid(ctx)?;
|
||||
|
||||
let time = self.song.as_ref().unwrap().position()?;
|
||||
let time_millis = TimestampMillis((time * 1000.0) as i32);
|
||||
let time_millis = Millis::from_seconds(time);
|
||||
let text = Text::new(
|
||||
format!(
|
||||
"tool: {:?} time: {:.4}, mouse: {:?}",
|
||||
|
@ -221,20 +226,39 @@ impl Game {
|
|||
|
||||
struct DrawInfo<'a> {
|
||||
hit_object: &'a HitObjectExt,
|
||||
opacity: f64,
|
||||
fade_opacity: f64,
|
||||
end_time: f64,
|
||||
color: Color,
|
||||
/// Whether or not the circle (slider head for sliders) should appear to have already
|
||||
/// been hit in the editor after the object's time has already come.
|
||||
circle_is_hit: bool,
|
||||
}
|
||||
|
||||
// figure out what objects will be visible on the screen at the current instant
|
||||
// 1.5 cus editor so people can see objects for longer durations
|
||||
let mut playfield_hitobjects = Vec::new();
|
||||
let preempt = 1.5 * (self.beatmap.inner.difficulty.approach_preempt() as f64) / 1000.0;
|
||||
let fade_in = 1.5 * (self.beatmap.inner.difficulty.approach_fade_time() as f64) / 1000.0;
|
||||
let preempt = 1.5
|
||||
* self
|
||||
.beatmap
|
||||
.inner
|
||||
.difficulty
|
||||
.approach_preempt()
|
||||
.as_seconds();
|
||||
let fade_in = 1.5
|
||||
* self
|
||||
.beatmap
|
||||
.inner
|
||||
.difficulty
|
||||
.approach_fade_time()
|
||||
.as_seconds();
|
||||
let fade_out_time = fade_in; // TODO: figure out what this number actually is
|
||||
let fade_out_offset = preempt; // TODO: figure out what this number actually is
|
||||
|
||||
// TODO: tighten this loop even more by binary searching for the start of the timeline and
|
||||
// playfield hitobjects rather than looping through the entire beatmap, better yet, just
|
||||
// keeping track of the old index will probably be much faster
|
||||
for ho in self.beatmap.hit_objects.iter().rev() {
|
||||
let ho_time = (ho.inner.start_time.0 as f64) / 1000.0;
|
||||
let ho_time = ho.inner.start_time.as_seconds();
|
||||
let color = self.combo_colors[ho.color_idx];
|
||||
|
||||
// draw in timeline
|
||||
|
@ -242,29 +266,41 @@ impl Game {
|
|||
|
||||
// draw hitobject in playfield
|
||||
let end_time;
|
||||
let opacity = if time > ho_time - fade_in {
|
||||
1.0
|
||||
} else {
|
||||
// TODO: calculate ease
|
||||
(time - (ho_time - preempt)) / fade_in
|
||||
};
|
||||
match ho.inner.kind {
|
||||
HitObjectKind::Circle => end_time = ho_time,
|
||||
HitObjectKind::Slider(_) => {
|
||||
let duration = self.beatmap.inner.get_slider_duration(&ho.inner).unwrap();
|
||||
end_time = ho_time + duration / 1000.0;
|
||||
end_time = ho_time + duration;
|
||||
}
|
||||
HitObjectKind::Spinner(SpinnerInfo {
|
||||
end_time: spinner_end,
|
||||
}) => end_time = (spinner_end.0 as f64) / 1000.0,
|
||||
}) => end_time = spinner_end.as_seconds(),
|
||||
};
|
||||
|
||||
if ho_time - preempt <= time && time <= end_time {
|
||||
let fade_opacity = if time <= ho_time - fade_in {
|
||||
// before the hitobject's time arrives, it fades in
|
||||
// TODO: calculate ease
|
||||
(time - (ho_time - preempt)) / fade_in
|
||||
} else if time < ho_time + fade_out_time {
|
||||
// while the object is on screen the opacity should be 1
|
||||
1.0
|
||||
} else if time < end_time + fade_out_offset {
|
||||
// after the hitobject's time, it fades out
|
||||
// TODO: calculate ease
|
||||
((end_time + fade_out_offset) - time) / fade_out_time
|
||||
} else {
|
||||
// completely faded out
|
||||
0.0
|
||||
};
|
||||
let circle_is_hit = time > ho_time;
|
||||
|
||||
if ho_time - preempt <= time && time <= end_time + fade_out_offset {
|
||||
playfield_hitobjects.push(DrawInfo {
|
||||
hit_object: ho,
|
||||
opacity,
|
||||
fade_opacity,
|
||||
end_time,
|
||||
color,
|
||||
circle_is_hit,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -279,21 +315,20 @@ impl Game {
|
|||
|
||||
for draw_info in playfield_hitobjects.iter() {
|
||||
let ho = draw_info.hit_object;
|
||||
let ho_time = (ho.inner.start_time.0 as f64) / 1000.0;
|
||||
let ho_time = ho.inner.start_time.as_seconds();
|
||||
let stacking = ho.stacking as f32 * STACK_DISTANCE as f32;
|
||||
let pos = [
|
||||
PLAYFIELD_BOUNDS.x + osupx_scale_x * (ho.inner.pos.x as f32 - stacking),
|
||||
PLAYFIELD_BOUNDS.y + osupx_scale_y * (ho.inner.pos.y as f32 - stacking),
|
||||
];
|
||||
let color = draw_info.color;
|
||||
let mut color = draw_info.color;
|
||||
color.a = 0.6 * draw_info.fade_opacity as f32;
|
||||
|
||||
let mut slider_info = None;
|
||||
if let HitObjectKind::Slider(info) = &ho.inner.kind {
|
||||
let mut control_points = vec![ho.inner.pos];
|
||||
control_points.extend(&info.control_points);
|
||||
|
||||
let mut color = color;
|
||||
color.a = 0.6 * draw_info.opacity as f32;
|
||||
Game::render_slider_body(
|
||||
&mut self.slider_cache,
|
||||
info,
|
||||
|
@ -323,6 +358,7 @@ impl Game {
|
|||
}
|
||||
|
||||
// draw main hitcircle
|
||||
let faded_color = Color::new(1.0, 1.0, 1.0, 0.6 * draw_info.fade_opacity as f32);
|
||||
self.skin.hitcircle.draw(
|
||||
ctx,
|
||||
(cs_real * 2.0, cs_real * 2.0),
|
||||
|
@ -331,15 +367,15 @@ impl Game {
|
|||
self.skin.hitcircleoverlay.draw(
|
||||
ctx,
|
||||
(cs_real * 2.0, cs_real * 2.0),
|
||||
DrawParam::default().dest(pos),
|
||||
DrawParam::default().dest(pos).color(faded_color),
|
||||
)?;
|
||||
|
||||
// draw numbers
|
||||
self.draw_numbers_on_circle(ctx, ho.number, pos, cs_real)?;
|
||||
self.draw_numbers_on_circle(ctx, ho.number, pos, cs_real, faded_color)?;
|
||||
|
||||
if let Some((info, control_points)) = slider_info {
|
||||
let spline = self.slider_cache.get(&control_points).unwrap();
|
||||
Game::render_slider_wireframe(ctx, &control_points, PLAYFIELD_BOUNDS)?;
|
||||
Game::render_slider_wireframe(ctx, &control_points, PLAYFIELD_BOUNDS, faded_color)?;
|
||||
|
||||
if time > ho_time && time < draw_info.end_time {
|
||||
let elapsed_time = time - ho_time;
|
||||
|
@ -381,6 +417,19 @@ impl Game {
|
|||
|
||||
self.draw_seeker(ctx)?;
|
||||
|
||||
let mut show = true;
|
||||
self.imgui.render(ctx, 1.0, |ui| {
|
||||
// Window
|
||||
Window::new("Hello world")
|
||||
.size([300.0, 600.0], imgui::Condition::FirstUseEver)
|
||||
.position([50.0, 50.0], imgui::Condition::FirstUseEver)
|
||||
.build(&ui, || {
|
||||
// Your window stuff here!
|
||||
ui.text("Hi from this label!");
|
||||
});
|
||||
ui.show_demo_window(&mut show);
|
||||
});
|
||||
|
||||
// draw whatever tool user is using
|
||||
let (mx, my) = self.mouse_pos;
|
||||
let pos_x = (mx - PLAYFIELD_BOUNDS.x) / PLAYFIELD_BOUNDS.w * 512.0;
|
||||
|
@ -463,7 +512,7 @@ impl Game {
|
|||
debug!("done rendering slider body");
|
||||
}
|
||||
|
||||
Game::render_slider_wireframe(ctx, &nodes, PLAYFIELD_BOUNDS)?;
|
||||
Game::render_slider_wireframe(ctx, &nodes, PLAYFIELD_BOUNDS, Color::WHITE)?;
|
||||
debug!("done rendering slider wireframe");
|
||||
} else {
|
||||
if rect_contains(&PLAYFIELD_BOUNDS, mx, my) {
|
||||
|
@ -498,7 +547,7 @@ impl Game {
|
|||
let pos = song.position()?;
|
||||
|
||||
if let Some(timing_point) = self.beatmap.inner.timing_points.first() {
|
||||
if pos < timing_point.time.as_seconds().0.into_inner() {
|
||||
if pos < timing_point.time.as_seconds() {
|
||||
if let TimingPointKind::Uninherited(_) = &timing_point.kind {
|
||||
self.current_uninherited_timing_point = Some(timing_point.clone());
|
||||
}
|
||||
|
@ -508,7 +557,7 @@ impl Game {
|
|||
let mut found_uninherited = false;
|
||||
let mut found_inherited = false;
|
||||
for timing_point in self.beatmap.inner.timing_points.iter() {
|
||||
if pos < timing_point.time.as_seconds().0.into_inner() {
|
||||
if pos < timing_point.time.as_seconds() {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -542,7 +591,7 @@ impl Game {
|
|||
..
|
||||
}) = &self.current_uninherited_timing_point
|
||||
{
|
||||
let diff = pos - time.as_seconds().0.into_inner();
|
||||
let diff = pos - time.as_seconds();
|
||||
let tick = info.mpb / 1000.0 / info.meter as f64;
|
||||
let beats = (diff / tick).round();
|
||||
let frac = diff - beats * tick;
|
||||
|
@ -571,17 +620,17 @@ impl Game {
|
|||
if let Some(song) = &self.song {
|
||||
println!("song exists! {:?} {:?}", btn, self.tool);
|
||||
let time = song.position()?;
|
||||
let time_millis = TimestampMillis((time * 1000.0) as i32);
|
||||
let time_millis = Millis::from_seconds(time);
|
||||
|
||||
if let (MouseButton::Left, Tool::Select) = (btn, &self.tool) {
|
||||
} else if let (MouseButton::Left, Tool::Circle) = (btn, &self.tool) {
|
||||
println!("left, circle, {:?} {} {}", PLAYFIELD_BOUNDS, x, y);
|
||||
if rect_contains(&PLAYFIELD_BOUNDS, x, y) {
|
||||
let time = (song.position()? * 1000.0) as i32;
|
||||
let time = Millis::from_seconds(song.position()?);
|
||||
match self
|
||||
.beatmap
|
||||
.hit_objects
|
||||
.binary_search_by_key(&time, |ho| ho.inner.start_time.0)
|
||||
.binary_search_by_key(&time, |ho| ho.inner.start_time)
|
||||
{
|
||||
Ok(v) => {
|
||||
println!("unfortunately already found at idx {}", v);
|
||||
|
@ -593,7 +642,7 @@ impl Game {
|
|||
};
|
||||
|
||||
let inner = HitObject {
|
||||
start_time: TimestampMillis(time),
|
||||
start_time: time,
|
||||
pos,
|
||||
kind: HitObjectKind::Circle,
|
||||
new_combo: false,
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
use anyhow::Result;
|
||||
use ggez::{graphics::DrawParam, Context};
|
||||
use ggez::{
|
||||
graphics::{Color, DrawParam},
|
||||
Context,
|
||||
};
|
||||
|
||||
use super::Game;
|
||||
|
||||
|
@ -10,6 +13,7 @@ impl Game {
|
|||
number: usize,
|
||||
pos: [f32; 2],
|
||||
cs: f32,
|
||||
color: Color,
|
||||
) -> Result<()> {
|
||||
let number = number.to_string();
|
||||
let digits = number.len();
|
||||
|
@ -53,7 +57,7 @@ impl Game {
|
|||
digit.draw(
|
||||
ctx,
|
||||
(w, real_height),
|
||||
DrawParam::default().dest([real_x, real_y]),
|
||||
DrawParam::default().dest([real_x, real_y]).color(color),
|
||||
)?;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ impl Game {
|
|||
TimingPointKind::Uninherited(_) => Color::new(0.8, 0.0, 0.0, 0.6),
|
||||
};
|
||||
|
||||
let percent = timing_point.time.as_seconds().0.into_inner() / len;
|
||||
let percent = timing_point.time.as_seconds() / len;
|
||||
let x = percent as f32 * BOUNDS.w;
|
||||
|
||||
let line = Mesh::new_line(
|
||||
|
|
|
@ -130,6 +130,7 @@ impl Game {
|
|||
ctx: &mut Context,
|
||||
control_points: &[Point<i32>],
|
||||
rect: Rect,
|
||||
color: Color,
|
||||
) -> Result<()> {
|
||||
let osupx_scale_x = rect.w as f32 / 512.0;
|
||||
let osupx_scale_y = rect.h as f32 / 384.0;
|
||||
|
@ -151,7 +152,7 @@ impl Game {
|
|||
ctx,
|
||||
DrawMode::Stroke(StrokeOptions::default()),
|
||||
&points_mapped,
|
||||
Color::WHITE,
|
||||
color,
|
||||
)?;
|
||||
graphics::draw(ctx, &frame, DrawParam::default())?;
|
||||
}
|
||||
|
@ -160,7 +161,7 @@ impl Game {
|
|||
let mut i = 0;
|
||||
while i < points_mapped.len() {
|
||||
let fst = points_mapped[i];
|
||||
let mut color = Color::WHITE;
|
||||
let mut color = color;
|
||||
if i < points_mapped.len() - 1 {
|
||||
let snd = points_mapped[i + 1];
|
||||
if fst.eq(&snd) {
|
||||
|
|
|
@ -56,13 +56,13 @@ impl Game {
|
|||
&uninherited_timing_points[i],
|
||||
uninherited_timing_points.get(i + 1),
|
||||
);
|
||||
let fst_time = fst.time.as_seconds().0.into_inner();
|
||||
let fst_time = fst.time.as_seconds();
|
||||
if let TimingPointKind::Uninherited(info) = &fst.kind {
|
||||
last_uninherited = Some(info);
|
||||
}
|
||||
|
||||
let snd_time = if let Some(snd) = snd {
|
||||
let snd_time = snd.time.as_seconds().0.into_inner();
|
||||
let snd_time = snd.time.as_seconds();
|
||||
if snd_time >= timeline_left && snd_time <= timeline_right {
|
||||
Some(snd_time)
|
||||
} else {
|
||||
|
@ -85,7 +85,7 @@ impl Game {
|
|||
let beat = last_uninherited.mpb / 1000.0;
|
||||
let ticks = TICKS[last_uninherited.meter as usize];
|
||||
|
||||
let mut time = fst.time.as_seconds().0.into_inner();
|
||||
let mut time = fst.time.as_seconds();
|
||||
let passed_measures = ((timeline_left - time) / beat).floor();
|
||||
time += passed_measures * beat;
|
||||
|
||||
|
@ -158,9 +158,7 @@ impl Game {
|
|||
.beatmap
|
||||
.inner
|
||||
.get_hitobject_end_time(&ho.inner)
|
||||
.as_seconds()
|
||||
.0
|
||||
.into_inner();
|
||||
.unwrap();
|
||||
|
||||
let color = self.combo_colors[ho.color_idx];
|
||||
|
||||
|
@ -274,6 +272,7 @@ impl Game {
|
|||
ho.number,
|
||||
[head_x, timeline_y + BOUNDS.h / 2.0],
|
||||
BOUNDS.h / 2.0,
|
||||
Color::WHITE,
|
||||
)?;
|
||||
}
|
||||
|
||||
|
|
217
src/imgui_wrapper.rs
Normal file
217
src/imgui_wrapper.rs
Normal file
|
@ -0,0 +1,217 @@
|
|||
// Based on https://github.com/iolivia/imgui-ggez-starter with modifications.
|
||||
//
|
||||
// Copyright (c) 2019 Olivia Ifrim
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
use ggez::event::{KeyCode, KeyMods, MouseButton};
|
||||
use ggez::graphics;
|
||||
use ggez::Context;
|
||||
|
||||
use gfx_core::{handle::RenderTargetView, memory::Typed};
|
||||
use gfx_device_gl;
|
||||
|
||||
use imgui::{Context as ImContext, Key, Ui, Window};
|
||||
use imgui_gfx_renderer::*;
|
||||
|
||||
use std::time::Instant;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug, Default)]
|
||||
struct MouseState {
|
||||
pos: (i32, i32),
|
||||
/// mouse buttons: (left, right, middle)
|
||||
pressed: (bool, bool, bool),
|
||||
wheel: f32,
|
||||
wheel_h: f32,
|
||||
}
|
||||
|
||||
pub struct ImGuiWrapper {
|
||||
pub imgui: ImContext,
|
||||
pub renderer: Renderer<gfx_core::format::Rgba8, gfx_device_gl::Resources>,
|
||||
last_frame: Instant,
|
||||
mouse_state: MouseState,
|
||||
}
|
||||
|
||||
impl ImGuiWrapper {
|
||||
pub fn new(ctx: &mut Context) -> Self {
|
||||
// Create the imgui object
|
||||
let mut imgui = ImContext::create();
|
||||
imgui.set_ini_filename(None);
|
||||
let (factory, gfx_device, _, _, _) = graphics::gfx_objects(ctx);
|
||||
|
||||
// Shaders
|
||||
let shaders = {
|
||||
let version = gfx_device.get_info().shading_language;
|
||||
if version.is_embedded {
|
||||
if version.major >= 3 {
|
||||
Shaders::GlSlEs300
|
||||
} else {
|
||||
Shaders::GlSlEs100
|
||||
}
|
||||
} else if version.major >= 4 {
|
||||
Shaders::GlSl400
|
||||
} else if version.major >= 3 {
|
||||
Shaders::GlSl130
|
||||
} else {
|
||||
Shaders::GlSl110
|
||||
}
|
||||
};
|
||||
|
||||
// Renderer
|
||||
let mut renderer = Renderer::init(&mut imgui, &mut *factory, shaders).unwrap();
|
||||
|
||||
{
|
||||
let mut io = imgui.io_mut();
|
||||
io[Key::Tab] = KeyCode::Tab as _;
|
||||
io[Key::LeftArrow] = KeyCode::Left as _;
|
||||
io[Key::RightArrow] = KeyCode::Right as _;
|
||||
io[Key::UpArrow] = KeyCode::Up as _;
|
||||
io[Key::DownArrow] = KeyCode::Down as _;
|
||||
io[Key::PageUp] = KeyCode::PageUp as _;
|
||||
io[Key::PageDown] = KeyCode::PageDown as _;
|
||||
io[Key::Home] = KeyCode::Home as _;
|
||||
io[Key::End] = KeyCode::End as _;
|
||||
io[Key::Insert] = KeyCode::Insert as _;
|
||||
io[Key::Delete] = KeyCode::Delete as _;
|
||||
io[Key::Backspace] = KeyCode::Back as _;
|
||||
io[Key::Space] = KeyCode::Space as _;
|
||||
io[Key::Enter] = KeyCode::Return as _;
|
||||
io[Key::Escape] = KeyCode::Escape as _;
|
||||
io[Key::KeyPadEnter] = KeyCode::NumpadEnter as _;
|
||||
io[Key::A] = KeyCode::A as _;
|
||||
io[Key::C] = KeyCode::C as _;
|
||||
io[Key::V] = KeyCode::V as _;
|
||||
io[Key::X] = KeyCode::X as _;
|
||||
io[Key::Y] = KeyCode::Y as _;
|
||||
io[Key::Z] = KeyCode::Z as _;
|
||||
}
|
||||
|
||||
// Create instance
|
||||
Self {
|
||||
imgui,
|
||||
renderer,
|
||||
last_frame: Instant::now(),
|
||||
mouse_state: MouseState::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render<F>(&mut self, ctx: &mut Context, hidpi_factor: f32, run_ui: F)
|
||||
where
|
||||
F: FnOnce(&Ui),
|
||||
{
|
||||
// Update mouse
|
||||
self.update_mouse();
|
||||
|
||||
// Create new frame
|
||||
let now = Instant::now();
|
||||
let delta = now - self.last_frame;
|
||||
let delta_s = delta.as_secs() as f32 + delta.subsec_nanos() as f32 / 1_000_000_000.0;
|
||||
self.last_frame = now;
|
||||
|
||||
let (draw_width, draw_height) = graphics::drawable_size(ctx);
|
||||
self.imgui.io_mut().display_size = [draw_width, draw_height];
|
||||
self.imgui.io_mut().display_framebuffer_scale = [hidpi_factor, hidpi_factor];
|
||||
self.imgui.io_mut().delta_time = delta_s;
|
||||
|
||||
let ui = self.imgui.frame();
|
||||
run_ui(&ui);
|
||||
|
||||
// Render
|
||||
let (factory, _, encoder, _, render_target) = graphics::gfx_objects(ctx);
|
||||
let draw_data = ui.render();
|
||||
self.renderer
|
||||
.render(
|
||||
&mut *factory,
|
||||
encoder,
|
||||
&mut RenderTargetView::new(render_target.clone()),
|
||||
draw_data,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn update_mouse(&mut self) {
|
||||
self.imgui.io_mut().mouse_pos =
|
||||
[self.mouse_state.pos.0 as f32, self.mouse_state.pos.1 as f32];
|
||||
|
||||
self.imgui.io_mut().mouse_down = [
|
||||
self.mouse_state.pressed.0,
|
||||
self.mouse_state.pressed.1,
|
||||
self.mouse_state.pressed.2,
|
||||
false,
|
||||
false,
|
||||
];
|
||||
|
||||
self.imgui.io_mut().mouse_wheel = self.mouse_state.wheel;
|
||||
self.mouse_state.wheel = 0.0;
|
||||
|
||||
self.imgui.io_mut().mouse_wheel_h = self.mouse_state.wheel_h;
|
||||
self.mouse_state.wheel_h = 0.0;
|
||||
}
|
||||
|
||||
pub fn update_mouse_pos(&mut self, x: f32, y: f32) {
|
||||
self.mouse_state.pos = (x as i32, y as i32);
|
||||
}
|
||||
|
||||
pub fn update_mouse_down(&mut self, button: MouseButton) {
|
||||
match button {
|
||||
MouseButton::Left => self.mouse_state.pressed.0 = true,
|
||||
MouseButton::Right => self.mouse_state.pressed.1 = true,
|
||||
MouseButton::Middle => self.mouse_state.pressed.2 = true,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_mouse_up(&mut self, button: MouseButton) {
|
||||
match button {
|
||||
MouseButton::Left => self.mouse_state.pressed.0 = false,
|
||||
MouseButton::Right => self.mouse_state.pressed.1 = false,
|
||||
MouseButton::Middle => self.mouse_state.pressed.2 = false,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_key_down(&mut self, key: KeyCode, mods: KeyMods) {
|
||||
self.imgui.io_mut().key_shift = mods.contains(KeyMods::SHIFT);
|
||||
self.imgui.io_mut().key_ctrl = mods.contains(KeyMods::CTRL);
|
||||
self.imgui.io_mut().key_alt = mods.contains(KeyMods::ALT);
|
||||
self.imgui.io_mut().keys_down[key as usize] = true;
|
||||
}
|
||||
|
||||
pub fn update_key_up(&mut self, key: KeyCode, mods: KeyMods) {
|
||||
if mods.contains(KeyMods::SHIFT) {
|
||||
self.imgui.io_mut().key_shift = false;
|
||||
}
|
||||
if mods.contains(KeyMods::CTRL) {
|
||||
self.imgui.io_mut().key_ctrl = false;
|
||||
}
|
||||
if mods.contains(KeyMods::ALT) {
|
||||
self.imgui.io_mut().key_alt = false;
|
||||
}
|
||||
self.imgui.io_mut().keys_down[key as usize] = false;
|
||||
}
|
||||
|
||||
pub fn update_text(&mut self, val: char) {
|
||||
self.imgui.io_mut().add_input_character(val);
|
||||
}
|
||||
|
||||
pub fn update_scroll(&mut self, x: f32, y: f32) {
|
||||
self.mouse_state.wheel += y;
|
||||
self.mouse_state.wheel_h += x;
|
||||
}
|
||||
}
|
33
src/main.rs
33
src/main.rs
|
@ -11,6 +11,7 @@ mod audio;
|
|||
mod beatmap;
|
||||
mod game;
|
||||
mod hitobject;
|
||||
mod imgui_wrapper;
|
||||
mod skin;
|
||||
mod utils;
|
||||
|
||||
|
@ -19,8 +20,12 @@ use std::path::PathBuf;
|
|||
use anyhow::Result;
|
||||
use ggez::{
|
||||
conf::{WindowMode, WindowSetup},
|
||||
event, ContextBuilder,
|
||||
event, graphics, ContextBuilder,
|
||||
};
|
||||
use imgui::{Context as ImContext, FontConfig, FontSource};
|
||||
use imgui_gfx_renderer::{Renderer, Shaders};
|
||||
use imgui_winit_support::{HiDpiMode, WinitPlatform};
|
||||
use imgui_wrapper::ImGuiWrapper;
|
||||
use structopt::StructOpt;
|
||||
|
||||
use crate::game::Game;
|
||||
|
@ -52,9 +57,31 @@ fn main() -> Result<()> {
|
|||
.window_setup(WindowSetup::default().title("OSU editor"))
|
||||
.window_mode(WindowMode::default().dimensions(1024.0, 768.0));
|
||||
|
||||
let (mut ctx, mut event_loop) = cb.build()?;
|
||||
let mut game = Game::new()?;
|
||||
let (mut ctx, event_loop) = cb.build()?;
|
||||
|
||||
let imgui = ImGuiWrapper::new(&mut ctx);
|
||||
|
||||
// let font_size = 13.0;
|
||||
// imgui.fonts().add_font(&[FontSource::TtfData {
|
||||
// data: include_bytes!("../resources/Roboto-Regular.ttf"),
|
||||
// size_pixels: font_size,
|
||||
// config: Some(FontConfig {
|
||||
// // As imgui-glium-renderer isn't gamma-correct with
|
||||
// // it's font rendering, we apply an arbitrary
|
||||
// // multiplier to make the font a bit "heavier". With
|
||||
// // default imgui-glow-renderer this is unnecessary.
|
||||
// rasterizer_multiply: 1.5,
|
||||
// // Oversampling font helps improve text rendering at
|
||||
// // expense of larger font atlas texture.
|
||||
// oversample_h: 4,
|
||||
// oversample_v: 4,
|
||||
// ..FontConfig::default()
|
||||
// }),
|
||||
// }]);
|
||||
|
||||
let mut game = Game::new(imgui)?;
|
||||
game.skin.load_all(&mut ctx)?;
|
||||
// platform.attach_window();
|
||||
|
||||
if let Some(path) = opt.path {
|
||||
game.load_beatmap(&mut ctx, path)?;
|
||||
|
|
Loading…
Reference in a new issue