core: Fix setting certain DisplayObject properties to NaN
This doesn't perfectly match Flash's behavior - I haven't been able to reproduce the values produces when the DisplayObject starts out with certain 'Matrix' values (a non-zero 'b' or 'd'). Howver, when the 'b' and 'd' matrix values are both 0, setting 'dobj.rotation = NaN' has no effect on the matrix, while 'dobj.scaleX = NaN' and 'dobj.scaleY = NaN' both treat 'NaN' as 0 for the purposes of updating the matrix. This fixes the tack shooter in Bloons Tower Defense 3, which tries to set 'rotation = NaN' for spawned tacks.
This commit is contained in:
parent
2c1936db18
commit
c6c021f7f6
|
@ -262,6 +262,20 @@ impl<'gc> DisplayObjectBase<'gc> {
|
||||||
self.set_transformed_by_script(true);
|
self.set_transformed_by_script(true);
|
||||||
self.cache_scale_rotation();
|
self.cache_scale_rotation();
|
||||||
self.rotation = degrees;
|
self.rotation = degrees;
|
||||||
|
|
||||||
|
// FIXME - this isn't quite correct. In Flash player,
|
||||||
|
// trying to set rotation to NaN does nothing if the current
|
||||||
|
// matrix 'b' and 'd' terms are both zero. However, if one
|
||||||
|
// of those terms is non-zero, then the entire matrix gets
|
||||||
|
// modified in a way that depends on its starting values.
|
||||||
|
// I haven't been able to figure out how to reproduce those
|
||||||
|
// values, so for now, we never modify the matrix if the
|
||||||
|
// rotation is NaN. Hopefully, there are no SWFs depending
|
||||||
|
// on the weird behavior when b or d is non-zero.
|
||||||
|
if degrees.into_radians().is_nan() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let cos_x = f64::cos(degrees.into_radians());
|
let cos_x = f64::cos(degrees.into_radians());
|
||||||
let sin_x = f64::sin(degrees.into_radians());
|
let sin_x = f64::sin(degrees.into_radians());
|
||||||
let cos_y = f64::cos(degrees.into_radians() + self.skew);
|
let cos_y = f64::cos(degrees.into_radians() + self.skew);
|
||||||
|
@ -278,10 +292,18 @@ impl<'gc> DisplayObjectBase<'gc> {
|
||||||
self.scale_x
|
self.scale_x
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_scale_x(&mut self, value: Percent) {
|
fn set_scale_x(&mut self, mut value: Percent) {
|
||||||
self.set_transformed_by_script(true);
|
self.set_transformed_by_script(true);
|
||||||
self.cache_scale_rotation();
|
self.cache_scale_rotation();
|
||||||
self.scale_x = value;
|
self.scale_x = value;
|
||||||
|
|
||||||
|
// Note - in order to match Flash's behavior, the 'scale_x' field is set to NaN
|
||||||
|
// (which gets reported back to ActionScript), but we treat it as 0 for
|
||||||
|
// the purposes of updating the matrix
|
||||||
|
if value.percent().is_nan() {
|
||||||
|
value = 0.0.into();
|
||||||
|
}
|
||||||
|
|
||||||
let cos = f64::cos(self.rotation.into_radians());
|
let cos = f64::cos(self.rotation.into_radians());
|
||||||
let sin = f64::sin(self.rotation.into_radians());
|
let sin = f64::sin(self.rotation.into_radians());
|
||||||
let mut matrix = &mut self.transform.matrix;
|
let mut matrix = &mut self.transform.matrix;
|
||||||
|
@ -294,10 +316,18 @@ impl<'gc> DisplayObjectBase<'gc> {
|
||||||
self.scale_y
|
self.scale_y
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_scale_y(&mut self, value: Percent) {
|
fn set_scale_y(&mut self, mut value: Percent) {
|
||||||
self.set_transformed_by_script(true);
|
self.set_transformed_by_script(true);
|
||||||
self.cache_scale_rotation();
|
self.cache_scale_rotation();
|
||||||
self.scale_y = value;
|
self.scale_y = value;
|
||||||
|
|
||||||
|
// Note - in order to match Flash's behavior, the 'scale_y' field is set to NaN
|
||||||
|
// (which gets reported back to ActionScript), but we treat it as 0 for
|
||||||
|
// the purposes of updating the matrix
|
||||||
|
if value.percent().is_nan() {
|
||||||
|
value = 0.0.into();
|
||||||
|
}
|
||||||
|
|
||||||
let cos = f64::cos(self.rotation.into_radians() + self.skew);
|
let cos = f64::cos(self.rotation.into_radians() + self.skew);
|
||||||
let sin = f64::sin(self.rotation.into_radians() + self.skew);
|
let sin = f64::sin(self.rotation.into_radians() + self.skew);
|
||||||
let mut matrix = &mut self.transform.matrix;
|
let mut matrix = &mut self.transform.matrix;
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
|
||||||
|
package {
|
||||||
|
import flash.display.MovieClip;
|
||||||
|
import flash.geom.Matrix;
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
public function Test(main: MovieClip) {
|
||||||
|
|
||||||
|
var props = ["rotation", "x", "y", "scaleX", "scaleY"];
|
||||||
|
// FIXME - we should also be testing Infinity and -Infinity here,
|
||||||
|
// but those give very weird values back in the matrix,
|
||||||
|
// and I havne't yet figured out how to reproduce them. Hopefully,
|
||||||
|
// there are no SWFs relying on the behavior.
|
||||||
|
for each (var prop in props) {
|
||||||
|
var clip = new MovieClip();
|
||||||
|
clip.transform.matrix = new Matrix(2, 0, 4, 0, 5, 6);
|
||||||
|
trace("Setting initial matrix: " + clip.transform.matrix);
|
||||||
|
trace("Initial value: clip[" + prop + "] = " + clip[prop]);
|
||||||
|
tryValue(clip, prop, NaN);
|
||||||
|
|
||||||
|
clip = new MovieClip();
|
||||||
|
var newMat = new Matrix(2, 0, 4, 0, 5, 6);
|
||||||
|
clip.transform.matrix = newMat;
|
||||||
|
trace("Setting initial matrix: " + clip.transform.matrix);
|
||||||
|
trace("Initial value: clip[" + prop + "] = " + clip[prop]);
|
||||||
|
tryValue(clip, prop, NaN);
|
||||||
|
|
||||||
|
clip = new MovieClip();
|
||||||
|
var newMat = new Matrix(7, 0, 9, 0, 11, 12);
|
||||||
|
clip.transform.matrix = newMat;
|
||||||
|
trace("Setting initial matrix: " + clip.transform.matrix);
|
||||||
|
trace("Initial value: clip[" + prop + "] = " + clip[prop]);
|
||||||
|
tryValue(clip, prop, NaN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
import flash.display.MovieClip;
|
||||||
|
|
||||||
|
function tryValue(clip:MovieClip, prop:String, value:*) {
|
||||||
|
clip[prop] = value;
|
||||||
|
trace("Setting clip[" + prop + "] = " + value + " gave: " + clip[prop]);
|
||||||
|
trace("Matrix: " + clip.transform.matrix);
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
Setting initial matrix: (a=2, b=0, c=4, d=0, tx=5, ty=6)
|
||||||
|
Initial value: clip[rotation] = 0
|
||||||
|
Setting clip[rotation] = NaN gave: NaN
|
||||||
|
Matrix: (a=2, b=0, c=4, d=0, tx=5, ty=6)
|
||||||
|
Setting initial matrix: (a=2, b=0, c=4, d=0, tx=5, ty=6)
|
||||||
|
Initial value: clip[rotation] = 0
|
||||||
|
Setting clip[rotation] = NaN gave: NaN
|
||||||
|
Matrix: (a=2, b=0, c=4, d=0, tx=5, ty=6)
|
||||||
|
Setting initial matrix: (a=7, b=0, c=9, d=0, tx=11, ty=12)
|
||||||
|
Initial value: clip[rotation] = 0
|
||||||
|
Setting clip[rotation] = NaN gave: NaN
|
||||||
|
Matrix: (a=7, b=0, c=9, d=0, tx=11, ty=12)
|
||||||
|
Setting initial matrix: (a=2, b=0, c=4, d=0, tx=5, ty=6)
|
||||||
|
Initial value: clip[x] = 5
|
||||||
|
Setting clip[x] = NaN gave: 0
|
||||||
|
Matrix: (a=2, b=0, c=4, d=0, tx=0, ty=6)
|
||||||
|
Setting initial matrix: (a=2, b=0, c=4, d=0, tx=5, ty=6)
|
||||||
|
Initial value: clip[x] = 5
|
||||||
|
Setting clip[x] = NaN gave: 0
|
||||||
|
Matrix: (a=2, b=0, c=4, d=0, tx=0, ty=6)
|
||||||
|
Setting initial matrix: (a=7, b=0, c=9, d=0, tx=11, ty=12)
|
||||||
|
Initial value: clip[x] = 11
|
||||||
|
Setting clip[x] = NaN gave: 0
|
||||||
|
Matrix: (a=7, b=0, c=9, d=0, tx=0, ty=12)
|
||||||
|
Setting initial matrix: (a=2, b=0, c=4, d=0, tx=5, ty=6)
|
||||||
|
Initial value: clip[y] = 6
|
||||||
|
Setting clip[y] = NaN gave: 0
|
||||||
|
Matrix: (a=2, b=0, c=4, d=0, tx=5, ty=0)
|
||||||
|
Setting initial matrix: (a=2, b=0, c=4, d=0, tx=5, ty=6)
|
||||||
|
Initial value: clip[y] = 6
|
||||||
|
Setting clip[y] = NaN gave: 0
|
||||||
|
Matrix: (a=2, b=0, c=4, d=0, tx=5, ty=0)
|
||||||
|
Setting initial matrix: (a=7, b=0, c=9, d=0, tx=11, ty=12)
|
||||||
|
Initial value: clip[y] = 12
|
||||||
|
Setting clip[y] = NaN gave: 0
|
||||||
|
Matrix: (a=7, b=0, c=9, d=0, tx=11, ty=0)
|
||||||
|
Setting initial matrix: (a=2, b=0, c=4, d=0, tx=5, ty=6)
|
||||||
|
Initial value: clip[scaleX] = 2
|
||||||
|
Setting clip[scaleX] = NaN gave: NaN
|
||||||
|
Matrix: (a=0, b=0, c=4, d=0, tx=5, ty=6)
|
||||||
|
Setting initial matrix: (a=2, b=0, c=4, d=0, tx=5, ty=6)
|
||||||
|
Initial value: clip[scaleX] = 2
|
||||||
|
Setting clip[scaleX] = NaN gave: NaN
|
||||||
|
Matrix: (a=0, b=0, c=4, d=0, tx=5, ty=6)
|
||||||
|
Setting initial matrix: (a=7, b=0, c=9, d=0, tx=11, ty=12)
|
||||||
|
Initial value: clip[scaleX] = 7
|
||||||
|
Setting clip[scaleX] = NaN gave: NaN
|
||||||
|
Matrix: (a=0, b=0, c=9, d=0, tx=11, ty=12)
|
||||||
|
Setting initial matrix: (a=2, b=0, c=4, d=0, tx=5, ty=6)
|
||||||
|
Initial value: clip[scaleY] = 4
|
||||||
|
Setting clip[scaleY] = NaN gave: NaN
|
||||||
|
Matrix: (a=2, b=0, c=0, d=0, tx=5, ty=6)
|
||||||
|
Setting initial matrix: (a=2, b=0, c=4, d=0, tx=5, ty=6)
|
||||||
|
Initial value: clip[scaleY] = 4
|
||||||
|
Setting clip[scaleY] = NaN gave: NaN
|
||||||
|
Matrix: (a=2, b=0, c=0, d=0, tx=5, ty=6)
|
||||||
|
Setting initial matrix: (a=7, b=0, c=9, d=0, tx=11, ty=12)
|
||||||
|
Initial value: clip[scaleY] = 9
|
||||||
|
Setting clip[scaleY] = NaN gave: NaN
|
||||||
|
Matrix: (a=7, b=0, c=0, d=0, tx=11, ty=12)
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
num_frames = 1
|
Loading…
Reference in New Issue