avm1: Implement TextField.removeTextField

This commit is contained in:
Mike Welsh 2020-11-21 19:13:53 -08:00
parent 03ab4e28d1
commit 7ac53be24f
6 changed files with 38 additions and 4 deletions

View File

@ -19,6 +19,10 @@ pub const AVM_DEPTH_BIAS: i32 = 16384;
/// What is the derivation of this number...?
pub const AVM_MAX_DEPTH: i32 = 2_130_706_428;
/// The maximum depth that the AVM will allow you to remove clips from.
/// What is the derivation of this number...?
pub const AVM_MAX_REMOVE_DEPTH: i32 = 2_130_706_416;
macro_rules! with_display_object {
( $gc_context: ident, $object:ident, $fn_proto: expr, $($name:expr => $fn:expr),* ) => {{
$(

View File

@ -3,7 +3,9 @@
use crate::avm1::activation::Activation;
use crate::avm1::error::Error;
use crate::avm1::function::{Executable, FunctionObject};
use crate::avm1::globals::display_object::{self, AVM_DEPTH_BIAS, AVM_MAX_DEPTH};
use crate::avm1::globals::display_object::{
self, AVM_DEPTH_BIAS, AVM_MAX_DEPTH, AVM_MAX_REMOVE_DEPTH,
};
use crate::avm1::globals::matrix::gradient_object_to_matrix;
use crate::avm1::property::Attribute::*;
use crate::avm1::{AvmString, Object, ScriptObject, TObject, Value};
@ -867,7 +869,7 @@ pub fn remove_movie_clip<'gc>(
// Generally this prevents you from removing non-dynamically created clips,
// although you can get around it with swapDepths.
// TODO: Figure out the derivation of this range.
if depth >= AVM_DEPTH_BIAS && depth < 2_130_706_416 {
if depth >= AVM_DEPTH_BIAS && depth < AVM_MAX_REMOVE_DEPTH {
// Need a parent to remove from.
let mut parent = if let Some(parent) = movie_clip.parent().and_then(|o| o.as_movie_clip()) {
parent

View File

@ -1,7 +1,7 @@
use crate::avm1::activation::Activation;
use crate::avm1::error::Error;
use crate::avm1::function::{Executable, FunctionObject};
use crate::avm1::globals::display_object;
use crate::avm1::globals::display_object::{self, AVM_DEPTH_BIAS, AVM_MAX_REMOVE_DEPTH};
use crate::avm1::property::Attribute::*;
use crate::avm1::{AvmString, Object, ScriptObject, TObject, Value};
use crate::avm_error;
@ -507,7 +507,8 @@ pub fn create_proto<'gc>(
"setNewTextFormat" => set_new_text_format,
"getTextFormat" => get_text_format,
"setTextFormat" => set_text_format,
"replaceText" => replace_text
"replaceText" => replace_text,
"removeTextField" => remove_text_field
);
with_text_field_props!(
@ -861,3 +862,24 @@ pub fn set_type<'gc>(
};
Ok(())
}
fn remove_text_field<'gc>(
text_field: EditText<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let depth = text_field.depth();
if depth >= AVM_DEPTH_BIAS && depth < AVM_MAX_REMOVE_DEPTH {
// Need a parent to remove from.
let mut parent = if let Some(parent) = text_field.parent().and_then(|o| o.as_movie_clip()) {
parent
} else {
return Ok(Value::Undefined);
};
parent.remove_child_from_avm(&mut activation.context, text_field.into());
}
Ok(Value::Undefined)
}

View File

@ -6,3 +6,9 @@ input
dynamic
// txt.type = 'invalid':
dynamic
// createTextField('txt2', 0, 0, 0, 100, 100)
_level0.txt2
// txt2.removeTextField()
undefined