avm1: Implement key.isToggled()

This commit is contained in:
michiel2005 2023-10-11 10:53:57 +02:00 committed by Daniel Jacobs
parent 180d275f13
commit 333009b79f
2 changed files with 42 additions and 1 deletions

View File

@ -27,6 +27,7 @@ const OBJECT_DECLS: &[Declaration] = declare_properties! {
"TAB" => int(KeyCode::Tab as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"UP" => int(KeyCode::Up as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"isDown" => method(is_down; DONT_ENUM | DONT_DELETE | READ_ONLY);
"isToggled" => method(is_toggled; DONT_ENUM | DONT_DELETE | READ_ONLY);
"getAscii" => method(get_ascii; DONT_ENUM | DONT_DELETE | READ_ONLY);
"getCode" => method(get_code; DONT_ENUM | DONT_DELETE | READ_ONLY);
};
@ -47,6 +48,25 @@ pub fn is_down<'gc>(
}
}
pub fn is_toggled<'gc>(
activation: &mut Activation<'_, 'gc>,
_this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
// This is not perfect: Flash Player could get the status of the Caps Lock, Num Lock,
// and Scroll Lock keys properly. We are just toggling them if the Ruffle window is
// in focus. This is the desired behavior for all keys, except these three.
if let Some(key) = KeyCode::from_u8(
args.get(0)
.unwrap_or(&Value::Undefined)
.coerce_to_i32(activation)? as u8,
) {
Ok(activation.context.input.is_key_toggled(key).into())
} else {
Ok(false.into())
}
}
pub fn get_ascii<'gc>(
activation: &mut Activation<'_, 'gc>,
_this: Object<'gc>,

View File

@ -78,6 +78,7 @@ pub enum MouseCursor {
pub struct InputManager {
keys_down: HashSet<KeyCode>,
keys_toggled: HashSet<KeyCode>,
last_key: KeyCode,
last_char: Option<char>,
last_text_control: Option<TextControlCode>,
@ -87,6 +88,7 @@ impl InputManager {
pub fn new() -> Self {
Self {
keys_down: HashSet::new(),
keys_toggled: HashSet::new(),
last_key: KeyCode::Unknown,
last_char: None,
last_text_control: None,
@ -100,6 +102,17 @@ impl InputManager {
}
}
fn toggle_key(&mut self, key_code: KeyCode) {
if key_code == KeyCode::Unknown || self.keys_down.contains(&key_code) {
return;
}
if self.keys_toggled.contains(&key_code) {
self.keys_toggled.remove(&key_code);
} else {
self.keys_toggled.insert(key_code);
}
}
fn remove_key(&mut self, key_code: KeyCode) {
self.last_key = key_code;
if key_code != KeyCode::Unknown {
@ -111,6 +124,7 @@ impl InputManager {
match *event {
PlayerEvent::KeyDown { key_code, key_char } => {
self.last_char = key_char;
self.toggle_key(key_code);
self.add_key(key_code);
}
PlayerEvent::KeyUp { key_code, key_char } => {
@ -121,7 +135,10 @@ impl InputManager {
PlayerEvent::TextControl { code } => {
self.last_text_control = Some(code);
}
PlayerEvent::MouseDown { button, .. } => self.add_key(button.into()),
PlayerEvent::MouseDown { button, .. } => {
self.toggle_key(button.into());
self.add_key(button.into())
}
PlayerEvent::MouseUp { button, .. } => self.remove_key(button.into()),
_ => {}
}
@ -131,6 +148,10 @@ impl InputManager {
self.keys_down.contains(&key)
}
pub fn is_key_toggled(&self, key: KeyCode) -> bool {
self.keys_toggled.contains(&key)
}
pub fn last_key_code(&self) -> KeyCode {
self.last_key
}