core: Add support for pressing multiple mouse buttons
This commit is contained in:
parent
368a95cf3b
commit
392101611e
|
@ -293,6 +293,20 @@ impl InputManager {
|
||||||
pub fn is_mouse_down(&self, button: MouseButton) -> bool {
|
pub fn is_mouse_down(&self, button: MouseButton) -> bool {
|
||||||
self.is_key_down(button.into())
|
self.is_key_down(button.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_mouse_down_buttons(&self) -> HashSet<MouseButton> {
|
||||||
|
let mut buttons = HashSet::new();
|
||||||
|
if self.is_mouse_down(MouseButton::Left) {
|
||||||
|
buttons.insert(MouseButton::Left);
|
||||||
|
}
|
||||||
|
if self.is_mouse_down(MouseButton::Middle) {
|
||||||
|
buttons.insert(MouseButton::Middle);
|
||||||
|
}
|
||||||
|
if self.is_mouse_down(MouseButton::Right) {
|
||||||
|
buttons.insert(MouseButton::Right);
|
||||||
|
}
|
||||||
|
buttons
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for InputManager {
|
impl Default for InputManager {
|
||||||
|
|
|
@ -523,7 +523,7 @@ impl KeyCode {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Subset of `KeyCode` that contains only mouse buttons.
|
/// Subset of `KeyCode` that contains only mouse buttons.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum MouseButton {
|
pub enum MouseButton {
|
||||||
Unknown = KeyCode::Unknown as isize,
|
Unknown = KeyCode::Unknown as isize,
|
||||||
Left = KeyCode::MouseLeft as isize,
|
Left = KeyCode::MouseLeft as isize,
|
||||||
|
|
|
@ -57,7 +57,7 @@ use ruffle_render::quality::StageQuality;
|
||||||
use ruffle_render::transform::TransformStack;
|
use ruffle_render::transform::TransformStack;
|
||||||
use ruffle_video::backend::VideoBackend;
|
use ruffle_video::backend::VideoBackend;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, HashSet, VecDeque};
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
use std::rc::{Rc, Weak as RcWeak};
|
use std::rc::{Rc, Weak as RcWeak};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
@ -117,6 +117,28 @@ pub struct MouseData<'gc> {
|
||||||
|
|
||||||
/// If the mouse is down, the object that the mouse is currently pressing.
|
/// If the mouse is down, the object that the mouse is currently pressing.
|
||||||
pub pressed: Option<InteractiveObject<'gc>>,
|
pub pressed: Option<InteractiveObject<'gc>>,
|
||||||
|
pub right_pressed: Option<InteractiveObject<'gc>>,
|
||||||
|
pub middle_pressed: Option<InteractiveObject<'gc>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'gc> MouseData<'gc> {
|
||||||
|
pub fn pressed(&self, button: MouseButton) -> Option<InteractiveObject<'gc>> {
|
||||||
|
match button {
|
||||||
|
MouseButton::Unknown => None,
|
||||||
|
MouseButton::Left => self.pressed,
|
||||||
|
MouseButton::Right => self.right_pressed,
|
||||||
|
MouseButton::Middle => self.middle_pressed,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_pressed(&mut self, button: MouseButton, value: Option<InteractiveObject<'gc>>) {
|
||||||
|
match button {
|
||||||
|
MouseButton::Unknown => {}
|
||||||
|
MouseButton::Left => self.pressed = value,
|
||||||
|
MouseButton::Right => self.right_pressed = value,
|
||||||
|
MouseButton::Middle => self.middle_pressed = value,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Collect)]
|
#[derive(Collect)]
|
||||||
|
@ -924,10 +946,14 @@ impl Player {
|
||||||
_ => event,
|
_ => event,
|
||||||
};
|
};
|
||||||
|
|
||||||
let prev_is_mouse_down = self.input.is_mouse_down(MouseButton::Left);
|
let prev_mouse_buttons = self.input.get_mouse_down_buttons();
|
||||||
self.input.handle_event(&event);
|
self.input.handle_event(&event);
|
||||||
let is_mouse_button_changed =
|
let changed_mouse_buttons = self
|
||||||
self.input.is_mouse_down(MouseButton::Left) != prev_is_mouse_down;
|
.input
|
||||||
|
.get_mouse_down_buttons()
|
||||||
|
.symmetric_difference(&prev_mouse_buttons)
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
|
||||||
if cfg!(feature = "avm_debug") {
|
if cfg!(feature = "avm_debug") {
|
||||||
match event {
|
match event {
|
||||||
|
@ -1215,7 +1241,7 @@ impl Player {
|
||||||
let is_mouse_moved = prev_mouse_position != self.mouse_position;
|
let is_mouse_moved = prev_mouse_position != self.mouse_position;
|
||||||
|
|
||||||
// This fires button rollover/press events, which should run after the above mouseMove events.
|
// This fires button rollover/press events, which should run after the above mouseMove events.
|
||||||
if self.update_mouse_state(is_mouse_button_changed, is_mouse_moved) {
|
if self.update_mouse_state(&changed_mouse_buttons, is_mouse_moved) {
|
||||||
self.needs_render = true;
|
self.needs_render = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1237,7 +1263,7 @@ impl Player {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let PlayerEvent::MouseLeave = event {
|
if let PlayerEvent::MouseLeave = event {
|
||||||
if self.update_mouse_state(is_mouse_button_changed, true) {
|
if self.update_mouse_state(&changed_mouse_buttons, true) {
|
||||||
self.needs_render = true;
|
self.needs_render = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1335,7 +1361,11 @@ impl Player {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates the hover state of buttons.
|
/// Updates the hover state of buttons.
|
||||||
fn update_mouse_state(&mut self, is_mouse_button_changed: bool, is_mouse_moved: bool) -> bool {
|
fn update_mouse_state(
|
||||||
|
&mut self,
|
||||||
|
changed_mouse_buttons: &HashSet<MouseButton>,
|
||||||
|
is_mouse_moved: bool,
|
||||||
|
) -> bool {
|
||||||
let mut new_cursor = self.mouse_cursor;
|
let mut new_cursor = self.mouse_cursor;
|
||||||
let mut mouse_cursor_needs_check = self.mouse_cursor_needs_check;
|
let mut mouse_cursor_needs_check = self.mouse_cursor_needs_check;
|
||||||
let mouse_in_stage = self.mouse_in_stage();
|
let mouse_in_stage = self.mouse_in_stage();
|
||||||
|
@ -1345,8 +1375,9 @@ impl Player {
|
||||||
let needs_render = self.mutate_with_update_context(|context| {
|
let needs_render = self.mutate_with_update_context(|context| {
|
||||||
// Objects may be hovered using Tab,
|
// Objects may be hovered using Tab,
|
||||||
// skip mouse hover when it's not necessary.
|
// skip mouse hover when it's not necessary.
|
||||||
let mut skip_mouse_hover =
|
let mut skip_mouse_hover = !is_mouse_moved
|
||||||
!is_mouse_moved && !is_mouse_button_changed && context.mouse_data.hovered.is_some();
|
&& changed_mouse_buttons.is_empty()
|
||||||
|
&& context.mouse_data.hovered.is_some();
|
||||||
|
|
||||||
let new_over_object = if mouse_in_stage {
|
let new_over_object = if mouse_in_stage {
|
||||||
run_mouse_pick(context, true)
|
run_mouse_pick(context, true)
|
||||||
|
@ -1420,7 +1451,7 @@ impl Player {
|
||||||
context.mouse_data.hovered.is_none() && context.mouse_data.pressed.is_none();
|
context.mouse_data.hovered.is_none() && context.mouse_data.pressed.is_none();
|
||||||
if !object_removed {
|
if !object_removed {
|
||||||
mouse_cursor_needs_check = false;
|
mouse_cursor_needs_check = false;
|
||||||
if is_mouse_button_changed {
|
if changed_mouse_buttons.contains(&MouseButton::Left) {
|
||||||
// The object is pressed/released and may be removed immediately, we need to check
|
// The object is pressed/released and may be removed immediately, we need to check
|
||||||
// in the next frame if it still exists. If it doesn't, we'll update the cursor.
|
// in the next frame if it still exists. If it doesn't, we'll update the cursor.
|
||||||
mouse_cursor_needs_check = true;
|
mouse_cursor_needs_check = true;
|
||||||
|
@ -1429,7 +1460,7 @@ impl Player {
|
||||||
mouse_cursor_needs_check = false;
|
mouse_cursor_needs_check = false;
|
||||||
new_cursor = MouseCursor::Arrow;
|
new_cursor = MouseCursor::Arrow;
|
||||||
} else if !context.input.is_mouse_down(MouseButton::Left)
|
} else if !context.input.is_mouse_down(MouseButton::Left)
|
||||||
&& (is_mouse_moved || is_mouse_button_changed)
|
&& (is_mouse_moved || changed_mouse_buttons.contains(&MouseButton::Left))
|
||||||
{
|
{
|
||||||
// In every other case, the cursor remains until the user interacts with the mouse again.
|
// In every other case, the cursor remains until the user interacts with the mouse again.
|
||||||
new_cursor = MouseCursor::Arrow;
|
new_cursor = MouseCursor::Arrow;
|
||||||
|
@ -1501,7 +1532,7 @@ impl Player {
|
||||||
context.mouse_data.hovered = new_over_object;
|
context.mouse_data.hovered = new_over_object;
|
||||||
}
|
}
|
||||||
// Handle presses and releases.
|
// Handle presses and releases.
|
||||||
if is_mouse_button_changed {
|
if changed_mouse_buttons.contains(&MouseButton::Left) {
|
||||||
if context.input.is_mouse_down(MouseButton::Left) {
|
if context.input.is_mouse_down(MouseButton::Left) {
|
||||||
let index = context.input.last_click_index();
|
let index = context.input.last_click_index();
|
||||||
// Pressed on a hovered object.
|
// Pressed on a hovered object.
|
||||||
|
@ -2112,7 +2143,7 @@ impl Player {
|
||||||
self.mutate_with_update_context(|context| {
|
self.mutate_with_update_context(|context| {
|
||||||
Self::update_drag(context);
|
Self::update_drag(context);
|
||||||
});
|
});
|
||||||
self.update_mouse_state(false, false);
|
self.update_mouse_state(&HashSet::new(), false);
|
||||||
|
|
||||||
// GC
|
// GC
|
||||||
self.gc_arena.borrow_mut().collect_debt();
|
self.gc_arena.borrow_mut().collect_debt();
|
||||||
|
@ -2582,6 +2613,8 @@ impl PlayerBuilder {
|
||||||
mouse_data: MouseData {
|
mouse_data: MouseData {
|
||||||
hovered: None,
|
hovered: None,
|
||||||
pressed: None,
|
pressed: None,
|
||||||
|
right_pressed: None,
|
||||||
|
middle_pressed: None,
|
||||||
},
|
},
|
||||||
avm1_shared_objects: HashMap::new(),
|
avm1_shared_objects: HashMap::new(),
|
||||||
avm2_shared_objects: HashMap::new(),
|
avm2_shared_objects: HashMap::new(),
|
||||||
|
|
Loading…
Reference in New Issue