Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement an Event System #808

Merged
merged 1 commit into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ bytemuck = { version = "1.9.1", default-features = false }
bytemuck_derive = { version = "1.4.1", default_features = false }
cfg-if = "1.0.0"
itoa = { version = "1.0.3", default-features = false }
time = { version = "0.3.3", default-features = false }
time = { version = "0.3.36", default-features = false }
hashbrown = "0.14.0"
libm = "0.2.1"
livesplit-hotkey = { path = "crates/livesplit-hotkey", version = "0.7.0", default-features = false }
Expand Down
4 changes: 2 additions & 2 deletions capi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ web-sys = { version = "0.3.28", optional = true }
default = ["image-shrinking"]
image-shrinking = ["livesplit-core/image-shrinking"]
software-rendering = ["livesplit-core/software-rendering"]
wasm-web = ["livesplit-core/wasm-web"]
wasm-web = ["livesplit-core/wasm-web", "wasm-bindgen", "web-sys"]
auto-splitting = ["livesplit-core/auto-splitting"]
assume-str-parameters-are-utf8 = []
web-rendering = ["wasm-web", "livesplit-core/web-rendering", "wasm-bindgen", "web-sys"]
web-rendering = ["wasm-web", "livesplit-core/web-rendering"]
2 changes: 1 addition & 1 deletion capi/src/auto_splitting_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::shared_timer::OwnedSharedTimer;
use std::{os::raw::c_char, path::PathBuf};

#[cfg(feature = "auto-splitting")]
use livesplit_core::auto_splitting::Runtime as AutoSplittingRuntime;
type AutoSplittingRuntime = livesplit_core::auto_splitting::Runtime<livesplit_core::SharedTimer>;

#[cfg(not(feature = "auto-splitting"))]
use livesplit_core::SharedTimer;
Expand Down
10 changes: 4 additions & 6 deletions capi/src/delta_component.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
//! The Delta Component is a component that shows the how far ahead or behind
//! the current attempt is compared to the chosen comparison.
//! The Delta Component is a component that shows how far ahead or behind the
//! current attempt is compared to the chosen comparison.

use super::{output_vec, Json};
use crate::component::OwnedComponent;
use crate::key_value_component_state::OwnedKeyValueComponentState;
use livesplit_core::component::delta::Component as DeltaComponent;
use livesplit_core::{GeneralLayoutSettings, Timer};
use crate::{component::OwnedComponent, key_value_component_state::OwnedKeyValueComponentState};
use livesplit_core::{component::delta::Component as DeltaComponent, GeneralLayoutSettings, Timer};

/// type
pub type OwnedDeltaComponent = Box<DeltaComponent>;
Expand Down
110 changes: 110 additions & 0 deletions capi/src/event_sink.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
//! An event sink accepts events that are meant to be passed to the timer. The
//! events usually come from the hotkey system, an auto splitter, the UI, or
//! through a network connection. The UI usually provides the implementation for
//! this, forwarding all the events to the actual timer. It is able to intercept
//! the events and for example ask the user for confirmation before applying
//! them. Other handling is possible such as automatically saving the splits or
//! notifying a server about changes happening in the run.

use std::sync::Arc;

use crate::shared_timer::OwnedSharedTimer;

/// type
#[derive(Clone)]
pub struct EventSink(pub(crate) Arc<dyn EventSinkAndQuery>);

/// type
pub type OwnedEventSink = Box<EventSink>;

/// Creates a new Event Sink.
#[no_mangle]
pub extern "C" fn EventSink_from_timer(timer: OwnedSharedTimer) -> OwnedEventSink {
Box::new(EventSink(Arc::new(*timer)))
}

/// drop
#[no_mangle]
pub extern "C" fn EventSink_drop(this: OwnedEventSink) {
drop(this);
}

pub(crate) trait EventSinkAndQuery:
livesplit_core::event::Sink + livesplit_core::event::TimerQuery + Send + Sync + 'static
{
}

impl<T> EventSinkAndQuery for T where
T: livesplit_core::event::Sink + livesplit_core::event::TimerQuery + Send + Sync + 'static
{
}

impl livesplit_core::event::Sink for EventSink {
fn start(&self) {
self.0.start()
}

fn split(&self) {
self.0.split()
}

fn split_or_start(&self) {
self.0.split_or_start()
}

fn reset(&self, save_attempt: Option<bool>) {
self.0.reset(save_attempt)
}

fn undo_split(&self) {
self.0.undo_split()
}

fn skip_split(&self) {
self.0.skip_split()
}

fn toggle_pause_or_start(&self) {
self.0.toggle_pause_or_start()
}

fn pause(&self) {
self.0.pause()
}

fn resume(&self) {
self.0.resume()
}

fn undo_all_pauses(&self) {
self.0.undo_all_pauses()
}

fn switch_to_previous_comparison(&self) {
self.0.switch_to_previous_comparison()
}

fn switch_to_next_comparison(&self) {
self.0.switch_to_next_comparison()
}

fn toggle_timing_method(&self) {
self.0.toggle_timing_method()
}

fn set_game_time(&self, time: livesplit_core::TimeSpan) {
self.0.set_game_time(time)
}

fn pause_game_time(&self) {
self.0.pause_game_time()
}

fn resume_game_time(&self) {
self.0.resume_game_time()
}

fn set_custom_variable(&self, name: &str, value: &str) {
self.0.set_custom_variable(name, value)
}
}
14 changes: 8 additions & 6 deletions capi/src/hotkey_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@

use std::{os::raw::c_char, str::FromStr};

use crate::{hotkey_config::OwnedHotkeyConfig, output_str, shared_timer::OwnedSharedTimer, str};
use livesplit_core::{hotkey::KeyCode, HotkeySystem};
use crate::{event_sink::EventSink, hotkey_config::OwnedHotkeyConfig, output_str, str};
use livesplit_core::hotkey::KeyCode;

type HotkeySystem = livesplit_core::HotkeySystem<EventSink>;

/// type
pub type OwnedHotkeySystem = Box<HotkeySystem>;
Expand All @@ -16,18 +18,18 @@ pub type NullableOwnedHotkeySystem = Option<OwnedHotkeySystem>;

/// Creates a new Hotkey System for a Timer with the default hotkeys.
#[no_mangle]
pub extern "C" fn HotkeySystem_new(shared_timer: OwnedSharedTimer) -> NullableOwnedHotkeySystem {
HotkeySystem::new(*shared_timer).ok().map(Box::new)
pub extern "C" fn HotkeySystem_new(event_sink: &EventSink) -> NullableOwnedHotkeySystem {
HotkeySystem::new(event_sink.clone()).ok().map(Box::new)
}

/// Creates a new Hotkey System for a Timer with a custom configuration for the
/// hotkeys.
#[no_mangle]
pub extern "C" fn HotkeySystem_with_config(
shared_timer: OwnedSharedTimer,
event_sink: &EventSink,
config: OwnedHotkeyConfig,
) -> NullableOwnedHotkeySystem {
HotkeySystem::with_config(*shared_timer, *config)
HotkeySystem::with_config(event_sink.clone(), *config)
.ok()
.map(Box::new)
}
Expand Down
3 changes: 3 additions & 0 deletions capi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub mod current_pace_component;
pub mod delta_component;
pub mod detailed_timer_component;
pub mod detailed_timer_component_state;
pub mod event_sink;
pub mod fuzzy_list;
pub mod general_layout_settings;
pub mod graph_component;
Expand Down Expand Up @@ -83,6 +84,8 @@ pub mod timer_write_lock;
pub mod title_component;
pub mod title_component_state;
pub mod total_playtime_component;
#[cfg(all(target_family = "wasm", feature = "wasm-web"))]
pub mod web_event_sink;
#[cfg(all(target_family = "wasm", feature = "web-rendering"))]
pub mod web_rendering;

Expand Down
6 changes: 6 additions & 0 deletions capi/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,12 @@ pub extern "C" fn Run_segment(this: &Run, index: usize) -> &Segment {
this.segment(index)
}

/// Returns the amount of segments in this Run.
#[no_mangle]
pub extern "C" fn Run_segments_len(this: &Run) -> usize {
this.segments().len()
}

/// Returns the amount attempt history elements are stored in this Run.
#[no_mangle]
pub extern "C" fn Run_attempt_history_len(this: &Run) -> usize {
Expand Down
2 changes: 1 addition & 1 deletion capi/src/segment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub type OwnedSegment = Box<Segment>;

/// Creates a new Segment with the name given.
#[no_mangle]
pub unsafe extern "C" fn Segment_new(name: &c_char) -> OwnedSegment {
pub unsafe extern "C" fn Segment_new(name: *const c_char) -> OwnedSegment {
Box::new(Segment::new(str(name)))
}

Expand Down
20 changes: 19 additions & 1 deletion capi/src/timer.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! A Timer provides all the capabilities necessary for doing speedrun attempts.

use super::{output_str, output_time, output_time_span, output_vec};
use super::{output_str, output_time, output_time_span, output_vec, str};
use crate::{
run::{NullableOwnedRun, OwnedRun},
shared_timer::OwnedSharedTimer,
Expand Down Expand Up @@ -204,6 +204,12 @@ pub extern "C" fn Timer_set_current_timing_method(this: &mut Timer, method: Timi
this.set_current_timing_method(method);
}

/// Toggles between the Real Time and Game Time timing methods.
#[no_mangle]
pub extern "C" fn Timer_toggle_timing_method(this: &mut Timer) {
this.toggle_timing_method();
}

/// Returns the current comparison that is being compared against. This may
/// be a custom comparison or one of the Comparison Generators.
#[no_mangle]
Expand Down Expand Up @@ -287,6 +293,18 @@ pub extern "C" fn Timer_set_loading_times(this: &mut Timer, time: &TimeSpan) {
this.set_loading_times(*time);
}

/// Sets the value of a custom variable with the name specified. If the variable
/// does not exist, a temporary variable gets created that will not be stored in
/// the splits file.
#[no_mangle]
pub unsafe extern "C" fn Timer_set_custom_variable(
this: &mut Timer,
name: *const c_char,
value: *const c_char,
) {
this.set_custom_variable(str(name), str(value));
}

/// Returns the current Timer Phase.
#[no_mangle]
pub extern "C" fn Timer_current_phase(this: &Timer) -> TimerPhase {
Expand Down
Loading
Loading