From 14e0980226d522cdbe8a21ef3a13a838ac29310d Mon Sep 17 00:00:00 2001 From: Adrian Wielgosik Date: Sun, 28 Feb 2021 19:23:04 +0100 Subject: [PATCH] avm1: Implement getInstanceAtDepth --- core/src/avm1/globals/movie_clip.rs | 36 ++++++++++++++++++ core/tests/regression_tests.rs | 1 + .../output.txt | 28 ++++++++++++++ .../movieclip_get_instance_at_depth/test.fla | Bin 0 -> 24064 bytes .../movieclip_get_instance_at_depth/test.swf | Bin 0 -> 733 bytes 5 files changed, 65 insertions(+) create mode 100644 core/tests/swfs/avm1/movieclip_get_instance_at_depth/output.txt create mode 100644 core/tests/swfs/avm1/movieclip_get_instance_at_depth/test.fla create mode 100644 core/tests/swfs/avm1/movieclip_get_instance_at_depth/test.swf diff --git a/core/src/avm1/globals/movie_clip.rs b/core/src/avm1/globals/movie_clip.rs index 8b6ad0d6a..ef56bc285 100644 --- a/core/src/avm1/globals/movie_clip.rs +++ b/core/src/avm1/globals/movie_clip.rs @@ -176,6 +176,7 @@ pub fn create_proto<'gc>( "getBounds" => get_bounds, "getBytesLoaded" => get_bytes_loaded, "getBytesTotal" => get_bytes_total, + "getInstanceAtDepth" => get_instance_at_depth, "getNextHighestDepth" => get_next_highest_depth, "getRect" => get_rect, "getURL" => get_url, @@ -818,6 +819,41 @@ fn get_bytes_total<'gc>( .unwrap_or(Value::Undefined)) } +fn get_instance_at_depth<'gc>( + movie_clip: MovieClip<'gc>, + activation: &mut Activation<'_, 'gc, '_>, + args: &[Value<'gc>], +) -> Result, Error<'gc>> { + if activation.current_swf_version() >= 7 { + let depth = if let Some(depth) = args.get(0) { + depth + .coerce_to_i32(activation)? + .wrapping_add(AVM_DEPTH_BIAS) + } else { + avm_error!( + activation, + "MovieClip.get_instance_at_depth: Too few parameters" + ); + return Ok(Value::Undefined); + }; + match movie_clip.child_by_depth(depth) { + Some(child) => { + // If the child doesn't have a corresponding AVM object, return mc itself. + // NOTE: this behavior was guessed from observing behavior for Text and Graphic; + // I didn't test other variants like Bitmap, MorphSpahe, Video + // or objects that weren't fully initialized yet. + match child.object() { + Value::Undefined => Ok(movie_clip.object()), + obj => Ok(obj), + } + } + None => Ok(Value::Undefined), + } + } else { + Ok(Value::Undefined) + } +} + fn get_next_highest_depth<'gc>( movie_clip: MovieClip<'gc>, activation: &mut Activation<'_, 'gc, '_>, diff --git a/core/tests/regression_tests.rs b/core/tests/regression_tests.rs index 6c023246b..74cce7d09 100644 --- a/core/tests/regression_tests.rs +++ b/core/tests/regression_tests.rs @@ -163,6 +163,7 @@ swf_tests! { (lessthan2_swf7, "avm1/lessthan2_swf7", 1), (logical_ops_swf4, "avm1/logical_ops_swf4", 1), (logical_ops_swf8, "avm1/logical_ops_swf8", 1), + (movieclip_get_instance_at_depth, "avm1/movieclip_get_instance_at_depth", 1), (movieclip_depth_methods, "avm1/movieclip_depth_methods", 3), (get_variable_in_scope, "avm1/get_variable_in_scope", 1), (movieclip_init_object, "avm1/movieclip_init_object", 1), diff --git a/core/tests/swfs/avm1/movieclip_get_instance_at_depth/output.txt b/core/tests/swfs/avm1/movieclip_get_instance_at_depth/output.txt new file mode 100644 index 000000000..1998772ab --- /dev/null +++ b/core/tests/swfs/avm1/movieclip_get_instance_at_depth/output.txt @@ -0,0 +1,28 @@ +//_root.getInstanceAtDepth(-16384) +undefined +//_root.getInstanceAtDepth(-16384).getDepth() +undefined +//_root.getInstanceAtDepth(-16383) +_level0 +//_root.getInstanceAtDepth(-16383).getDepth() +-16384 +//_root.getInstanceAtDepth(-16382) +_level0.instance1 +//_root.getInstanceAtDepth(-16382).getDepth() +-16382 +//_root.getInstanceAtDepth(-16381) +undefined +//_root.getInstanceAtDepth(-16381).getDepth() +undefined +//_root.getInstanceAtDepth(-16380) +_level0 +//_root.getInstanceAtDepth(-16380).getDepth() +-16384 +//_root.getInstanceAtDepth(-16379) +_level0.instance2 +//_root.getInstanceAtDepth(-16379).getDepth() +-16379 +//this.getInstanceAtDepth(123) +_level0.fromscript +//_root.getInstanceAtDepth(123).getDepth() +123 diff --git a/core/tests/swfs/avm1/movieclip_get_instance_at_depth/test.fla b/core/tests/swfs/avm1/movieclip_get_instance_at_depth/test.fla new file mode 100644 index 0000000000000000000000000000000000000000..c0b92878f457824cf7e0521691cc677d852a8dc8 GIT binary patch literal 24064 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 V9*fycV4uGwP2lOfaB;KG^}k1VK=}Xw literal 0 HcmV?d00001 diff --git a/core/tests/swfs/avm1/movieclip_get_instance_at_depth/test.swf b/core/tests/swfs/avm1/movieclip_get_instance_at_depth/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..995d6c9173e52d440f4543b1af6d11c389e17bbf GIT binary patch literal 733 zcmV<30wVoGS5pUD1^@tfoRyJXNK;`L$Di}Dv&}YL&96*j5SU8lCsstLsihNVDAZM$ z&ZAqTXKjbjmMH|HhNBA|S`i9qbrWV$*iEAp66!(-6BSdlkaFOSVuhUE_o#T*4mr=o zdC&WQe$VgWyl)*S$^b%o05k;Tkb)p&Qk^tFOFbD1Nl9gPj^mG3vwT6VgDWGZoQEh$yy(R8-jWEs z>=P$A#Y5gMZcfnqPS~dYnE-Df2E_zeAm%BM6+nm$I{k$AX2KAfs7+7m%XOx$%2T-Q|zCsrv}@HD&~q=@COJ#u>}&6gQ!_R8 zVSRDb^)4w!tDUbrbU=U7YrnYKJTv@7AGL^ngNHg0NPKcMoKt<)SR#Q`yC{5gG_ee{ zasFUtpAFg=hDJnmcjW#{jq1awssL^^%DUe4s;S*T!7^?THZLg-fUUIhJX^=(Mg?M{ P?{!tp;=}z5V!pV^xj