swf: Convert ButtonActionCondition to bitflags
This commit is contained in:
parent
7f4845d777
commit
19662503ca
|
@ -11,6 +11,7 @@ use gc_arena::{Collect, GcCell, MutationContext};
|
|||
use std::collections::BTreeMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::sync::Arc;
|
||||
use swf::ButtonActionCondition;
|
||||
|
||||
#[derive(Clone, Debug, Collect, Copy)]
|
||||
#[collect(no_drop)]
|
||||
|
@ -42,15 +43,19 @@ impl<'gc> Button<'gc> {
|
|||
let action_data = source_movie
|
||||
.to_unbounded_subslice(action.action_data)
|
||||
.unwrap();
|
||||
for condition in &action.conditions {
|
||||
let button_action = ButtonAction {
|
||||
let bits = action.conditions.bits();
|
||||
let mut bit = 1u16;
|
||||
while bits & !(bit - 1) != 0 {
|
||||
if bits & bit != 0 {
|
||||
actions.push(ButtonAction {
|
||||
action_data: action_data.clone(),
|
||||
condition: *condition,
|
||||
condition: ButtonActionCondition::from_bits_truncate(bit),
|
||||
key_code: action
|
||||
.key_code
|
||||
.and_then(|k| ButtonKeyCode::try_from(k).ok()),
|
||||
};
|
||||
actions.push(button_action);
|
||||
});
|
||||
}
|
||||
bit <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,7 +411,7 @@ impl<'gc> TDisplayObject<'gc> for Button<'gc> {
|
|||
ClipEvent::KeyPress { key_code } => {
|
||||
handled = write.run_actions(
|
||||
context,
|
||||
swf::ButtonActionCondition::KeyPress,
|
||||
swf::ButtonActionCondition::KEY_PRESS,
|
||||
Some(key_code),
|
||||
);
|
||||
cur_state
|
||||
|
@ -416,22 +421,30 @@ impl<'gc> TDisplayObject<'gc> for Button<'gc> {
|
|||
|
||||
match (cur_state, new_state) {
|
||||
(ButtonState::Up, ButtonState::Over) => {
|
||||
write.run_actions(context, swf::ButtonActionCondition::IdleToOverUp, None);
|
||||
write.run_actions(context, swf::ButtonActionCondition::IDLE_TO_OVER_UP, None);
|
||||
write.play_sound(context, write.static_data.read().up_to_over_sound.as_ref());
|
||||
}
|
||||
(ButtonState::Over, ButtonState::Up) => {
|
||||
write.run_actions(context, swf::ButtonActionCondition::OverUpToIdle, None);
|
||||
write.run_actions(context, swf::ButtonActionCondition::OVER_UP_TO_IDLE, None);
|
||||
write.play_sound(context, write.static_data.read().over_to_up_sound.as_ref());
|
||||
}
|
||||
(ButtonState::Over, ButtonState::Down) => {
|
||||
write.run_actions(context, swf::ButtonActionCondition::OverUpToOverDown, None);
|
||||
write.run_actions(
|
||||
context,
|
||||
swf::ButtonActionCondition::OVER_UP_TO_OVER_DOWN,
|
||||
None,
|
||||
);
|
||||
write.play_sound(
|
||||
context,
|
||||
write.static_data.read().over_to_down_sound.as_ref(),
|
||||
);
|
||||
}
|
||||
(ButtonState::Down, ButtonState::Over) => {
|
||||
write.run_actions(context, swf::ButtonActionCondition::OverDownToOverUp, None);
|
||||
write.run_actions(
|
||||
context,
|
||||
swf::ButtonActionCondition::OVER_DOWN_TO_OVER_UP,
|
||||
None,
|
||||
);
|
||||
write.play_sound(
|
||||
context,
|
||||
write.static_data.read().down_to_over_sound.as_ref(),
|
||||
|
@ -512,7 +525,7 @@ impl<'gc> ButtonData<'gc> {
|
|||
if let Some(parent) = self.base.parent {
|
||||
for action in &self.static_data.read().actions {
|
||||
if action.condition == condition
|
||||
&& (action.condition != swf::ButtonActionCondition::KeyPress
|
||||
&& (action.condition != swf::ButtonActionCondition::KEY_PRESS
|
||||
|| action.key_code == key_code)
|
||||
{
|
||||
// Note that AVM1 buttons run actions relative to their parent, not themselves.
|
||||
|
|
|
@ -3108,10 +3108,10 @@ impl ClipAction {
|
|||
.unwrap();
|
||||
|
||||
let mut events = Vec::new();
|
||||
let flags = other.events.bits();
|
||||
let bits = other.events.bits();
|
||||
let mut bit = 1u32;
|
||||
while flags & !(bit - 1) != 0 {
|
||||
if (flags & bit) != 0 {
|
||||
while bits & !(bit - 1) != 0 {
|
||||
if bits & bit != 0 {
|
||||
events.push(ClipEventFlag::from_bits_truncate(bit));
|
||||
}
|
||||
bit <<= 1;
|
||||
|
|
|
@ -13,7 +13,6 @@ use crate::{
|
|||
};
|
||||
use bitstream_io::BitRead;
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
use std::collections::HashSet;
|
||||
use std::io::{self, Read};
|
||||
|
||||
/// Parse a decompressed SWF and return a `Vec` of tags.
|
||||
|
@ -802,9 +801,7 @@ impl<'a> Reader<'a> {
|
|||
is_track_as_menu: false,
|
||||
records,
|
||||
actions: vec![ButtonAction {
|
||||
conditions: vec![ButtonActionCondition::OverDownToOverUp]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
conditions: ButtonActionCondition::OVER_DOWN_TO_OVER_UP,
|
||||
key_code: None,
|
||||
action_data,
|
||||
}],
|
||||
|
@ -937,39 +934,9 @@ impl<'a> Reader<'a> {
|
|||
fn read_button_action(&mut self) -> Result<(ButtonAction<'a>, bool)> {
|
||||
let length = self.read_u16()?;
|
||||
let flags = self.read_u16()?;
|
||||
let mut conditions = HashSet::with_capacity(8);
|
||||
if (flags & 0b1) != 0 {
|
||||
conditions.insert(ButtonActionCondition::IdleToOverUp);
|
||||
}
|
||||
if (flags & 0b10) != 0 {
|
||||
conditions.insert(ButtonActionCondition::OverUpToIdle);
|
||||
}
|
||||
if (flags & 0b100) != 0 {
|
||||
conditions.insert(ButtonActionCondition::OverUpToOverDown);
|
||||
}
|
||||
if (flags & 0b1000) != 0 {
|
||||
conditions.insert(ButtonActionCondition::OverDownToOverUp);
|
||||
}
|
||||
if (flags & 0b1_0000) != 0 {
|
||||
conditions.insert(ButtonActionCondition::OverDownToOutDown);
|
||||
}
|
||||
if (flags & 0b10_0000) != 0 {
|
||||
conditions.insert(ButtonActionCondition::OutDownToOverDown);
|
||||
}
|
||||
if (flags & 0b100_0000) != 0 {
|
||||
conditions.insert(ButtonActionCondition::OutDownToIdle);
|
||||
}
|
||||
if (flags & 0b1000_0000) != 0 {
|
||||
conditions.insert(ButtonActionCondition::IdleToOverDown);
|
||||
}
|
||||
|
||||
if (flags & 0b1_0000_0000) != 0 {
|
||||
conditions.insert(ButtonActionCondition::OverDownToIdle);
|
||||
}
|
||||
let mut conditions = ButtonActionCondition::from_bits_truncate(flags);
|
||||
let key_code = (flags >> 9) as u8;
|
||||
if key_code != 0 {
|
||||
conditions.insert(ButtonActionCondition::KeyPress);
|
||||
}
|
||||
conditions.set(ButtonActionCondition::KEY_PRESS, key_code != 0);
|
||||
let action_data = if length >= 4 {
|
||||
self.read_slice(length as usize - 4)?
|
||||
} else if length == 0 {
|
||||
|
|
|
@ -201,9 +201,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
records: vec![
|
||||
ButtonRecord {
|
||||
id: 1,
|
||||
states: vec![ButtonState::Up, ButtonState::Over]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
states: ButtonState::UP | ButtonState::OVER,
|
||||
depth: 1,
|
||||
matrix: Matrix::identity(),
|
||||
color_transform: ColorTransform::new(),
|
||||
|
@ -212,9 +210,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
},
|
||||
ButtonRecord {
|
||||
id: 2,
|
||||
states: vec![ButtonState::Down, ButtonState::HitTest]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
states: ButtonState::DOWN | ButtonState::HIT_TEST,
|
||||
depth: 1,
|
||||
matrix: Matrix::identity(),
|
||||
color_transform: ColorTransform::new(),
|
||||
|
@ -223,9 +219,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
},
|
||||
],
|
||||
actions: vec![ButtonAction {
|
||||
conditions: vec![ButtonActionCondition::OverDownToOverUp]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
conditions: ButtonActionCondition::OVER_DOWN_TO_OVER_UP,
|
||||
key_code: None,
|
||||
action_data: &[0],
|
||||
}],
|
||||
|
@ -240,9 +234,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
records: vec![
|
||||
ButtonRecord {
|
||||
id: 2,
|
||||
states: vec![ButtonState::Up, ButtonState::Over]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
states: ButtonState::UP | ButtonState::OVER,
|
||||
depth: 1,
|
||||
matrix: Matrix::identity(),
|
||||
color_transform: ColorTransform {
|
||||
|
@ -264,9 +256,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
},
|
||||
ButtonRecord {
|
||||
id: 3,
|
||||
states: vec![ButtonState::Down, ButtonState::HitTest]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
states: ButtonState::DOWN | ButtonState::HIT_TEST,
|
||||
depth: 1,
|
||||
matrix: Matrix::identity(),
|
||||
color_transform: ColorTransform {
|
||||
|
@ -285,14 +275,12 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
],
|
||||
actions: vec![
|
||||
ButtonAction {
|
||||
conditions: vec![ButtonActionCondition::OverDownToOverUp]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
conditions: ButtonActionCondition::OVER_DOWN_TO_OVER_UP,
|
||||
key_code: None,
|
||||
action_data: &[150, 3, 0, 0, 65, 0, 38, 0], // trace("A");
|
||||
},
|
||||
ButtonAction {
|
||||
conditions: vec![ButtonActionCondition::KeyPress].into_iter().collect(),
|
||||
conditions: ButtonActionCondition::KEY_PRESS,
|
||||
key_code: Some(3), // Home
|
||||
action_data: &[150, 3, 0, 0, 66, 0, 38, 0], // trace("B");
|
||||
},
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
//! https://www.adobe.com/content/dam/acom/en/devnet/pdf/swf-file-format-spec.pdf
|
||||
use crate::string::SwfStr;
|
||||
use bitflags::bitflags;
|
||||
use std::collections::HashSet;
|
||||
|
||||
mod matrix;
|
||||
|
||||
|
@ -851,23 +850,24 @@ pub type ButtonSound = (CharacterId, SoundInfo);
|
|||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct ButtonAction<'a> {
|
||||
pub conditions: HashSet<ButtonActionCondition>,
|
||||
pub conditions: ButtonActionCondition,
|
||||
pub key_code: Option<u8>,
|
||||
pub action_data: &'a [u8],
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||
pub enum ButtonActionCondition {
|
||||
IdleToOverDown,
|
||||
OutDownToIdle,
|
||||
OutDownToOverDown,
|
||||
OverDownToOutDown,
|
||||
OverDownToOverUp,
|
||||
OverUpToOverDown,
|
||||
OverUpToIdle,
|
||||
IdleToOverUp,
|
||||
OverDownToIdle,
|
||||
KeyPress,
|
||||
bitflags! {
|
||||
pub struct ButtonActionCondition: u16 {
|
||||
const IDLE_TO_OVER_UP = 1 << 0;
|
||||
const OVER_UP_TO_IDLE = 1 << 1;
|
||||
const OVER_UP_TO_OVER_DOWN = 1 << 2;
|
||||
const OVER_DOWN_TO_OVER_UP = 1 << 3;
|
||||
const OVER_DOWN_TO_OUT_DOWN = 1 << 4;
|
||||
const OUT_DOWN_TO_OVER_DOWN = 1 << 5;
|
||||
const OUT_DOWN_TO_IDLE = 1 << 6;
|
||||
const IDLE_TO_OVER_DOWN = 1 << 7;
|
||||
const OVER_DOWN_TO_IDLE = 1 << 8;
|
||||
const KEY_PRESS = 1 << 9;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
|
|
@ -1064,79 +1064,13 @@ impl<W: Write> Writer<W> {
|
|||
} else {
|
||||
writer.write_u16(0)?;
|
||||
}
|
||||
writer.write_u8(
|
||||
if action
|
||||
.conditions
|
||||
.contains(&ButtonActionCondition::IdleToOverDown)
|
||||
{
|
||||
0b1000_0000
|
||||
} else {
|
||||
0
|
||||
} | if action
|
||||
.conditions
|
||||
.contains(&ButtonActionCondition::OutDownToIdle)
|
||||
{
|
||||
0b100_0000
|
||||
} else {
|
||||
0
|
||||
} | if action
|
||||
.conditions
|
||||
.contains(&ButtonActionCondition::OutDownToOverDown)
|
||||
{
|
||||
0b10_0000
|
||||
} else {
|
||||
0
|
||||
} | if action
|
||||
.conditions
|
||||
.contains(&ButtonActionCondition::OverDownToOutDown)
|
||||
{
|
||||
0b1_0000
|
||||
} else {
|
||||
0
|
||||
} | if action
|
||||
.conditions
|
||||
.contains(&ButtonActionCondition::OverDownToOverUp)
|
||||
{
|
||||
0b1000
|
||||
} else {
|
||||
0
|
||||
} | if action
|
||||
.conditions
|
||||
.contains(&ButtonActionCondition::OverUpToOverDown)
|
||||
{
|
||||
0b100
|
||||
} else {
|
||||
0
|
||||
} | if action
|
||||
.conditions
|
||||
.contains(&ButtonActionCondition::OverUpToIdle)
|
||||
{
|
||||
0b10
|
||||
} else {
|
||||
0
|
||||
} | if action
|
||||
.conditions
|
||||
.contains(&ButtonActionCondition::IdleToOverUp)
|
||||
{
|
||||
0b1
|
||||
} else {
|
||||
0
|
||||
},
|
||||
)?;
|
||||
let mut flags = if action
|
||||
.conditions
|
||||
.contains(&ButtonActionCondition::OverDownToIdle)
|
||||
{
|
||||
0b1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
if action.conditions.contains(&ButtonActionCondition::KeyPress) {
|
||||
let mut flags = action.conditions.bits();
|
||||
if action.conditions.contains(ButtonActionCondition::KEY_PRESS) {
|
||||
if let Some(key_code) = action.key_code {
|
||||
flags |= key_code << 1;
|
||||
flags |= (key_code as u16) << 9;
|
||||
}
|
||||
}
|
||||
writer.write_u8(flags)?;
|
||||
writer.write_u16(flags)?;
|
||||
writer.output.write_all(&action.action_data)?;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue