Skip to content

avm2: Store PerspectiveProjection to DisplayObject #19670

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

cookie-s
Copy link
Contributor

@cookie-s cookie-s commented Mar 1, 2025

Continued from #19532 .

DisplayObject stores Option<PerspectiveProjection> through Transform so we can remove HAS_PERSPECTIVE_PROJECTION_STUB flag from display objects.

The test from_shumway/avm2/flash/geom/perspectiveprojection passes now.

Limitation

PerspectiveProjection is stored in Transform, but it's not used in rendering at all. (Hence, we cannot remove stub_setters)

@cookie-s cookie-s force-pushed the perspective-projection-storage branch 7 times, most recently from 19168c2 to af96e50 Compare March 2, 2025 17:43
@cookie-s cookie-s marked this pull request as ready for review March 2, 2025 17:56
@Lord-McSweeney Lord-McSweeney added A-avm2 Area: AVM2 (ActionScript 3) T-fix Type: Bug fix (in something that's supposed to work already) waiting-on-review Waiting on review from a Ruffle team member labels Mar 3, 2025
@cookie-s cookie-s force-pushed the perspective-projection-storage branch from af96e50 to 970b60c Compare April 26, 2025 13:19
@cookie-s cookie-s marked this pull request as draft April 26, 2025 13:23
@cookie-s cookie-s force-pushed the perspective-projection-storage branch 3 times, most recently from e5874ce to da3e09a Compare April 26, 2025 14:17
Comment on lines +3 to +8
number_patterns = [
# Both FP 32,0,0,465 (for Linux) and FP 32 (for Windows) produced slightly different numbers in some environment. However, the original trace from mozilla/shumway is respected in the output file.
'focalLength: ([0-9.]+)'
]
max_relative = 0.0000001
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the output.txt is from https://github.com/mozilla/shumway/blob/master/test/swfs/avm2/flash/geom/perspectiveprojection/PerspectiveProjectionClass.swf.trace .
I couldn't reproduce exactly the same result from PerspectiveProjectionClass.as in the same directory (after recompilation with mxmlc) or even from the test.swf (without recompilation).

(Fun fact: I was able to pass this test without this approximation until #19748 was merged -- What does it mean? Anyway, I think the problem is that I cannot reproduce the output.txt from ActionScript or SWF.)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a small difference like this isn't a problem, we have similar issues with some of the AVM2 Number tests already.

@cookie-s cookie-s marked this pull request as ready for review April 26, 2025 14:31
.avm2()
.classes()
.perspectiveprojection
.construct(activation, &[])?;
.construct(activation, &[])?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, does this really return a new PerspectiveProjection each time the getter is called?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, to make it clear, I added a test case testEq() to geom_transform just now.
From the same Transform, every call to the getter creates a new PerspectiveProjection.

@@ -193,6 +194,7 @@ impl<'gc> Stage<'gc> {
},
));
stage.set_is_root(gc_context, true);
stage.set_perspective_projection(gc_context, None); // Set default PerspectiveProjection
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this line necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this line actually sets PerspectiveProjection::default() to DO's PerspectiveProjection.

if perspective_projection.is_none() {
// `stage` doesn't allow null PerspectiveProjection.
perspective_projection = Some(Default::default());

Technically it's fine to set PerspectiveProjection::default() directly at here, but for consistency with root.set_perspective_projection() in a different file I'm passing None here.

root.set_perspective_projection(self.gc(), None); // Set default PerspectiveProjection

The root actually has a different value used when None (null) is provided..
if perspective_projection.is_none() && self.is_root() {
// `root` doesn't allow null PerspectiveProjection.
perspective_projection = Some(PerspectiveProjection {
field_of_view: 55.0,
center: (
self.movie().width().to_pixels() / 2.0,
self.movie().height().to_pixels() / 2.0,
),
});
}

@cookie-s cookie-s force-pushed the perspective-projection-storage branch from da3e09a to aa6197e Compare May 2, 2025 00:42
Copy link
Contributor Author

@cookie-s cookie-s left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for review!

.avm2()
.classes()
.perspectiveprojection
.construct(activation, &[])?;
.construct(activation, &[])?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, to make it clear, I added a test case testEq() to geom_transform just now.
From the same Transform, every call to the getter creates a new PerspectiveProjection.

@@ -193,6 +194,7 @@ impl<'gc> Stage<'gc> {
},
));
stage.set_is_root(gc_context, true);
stage.set_perspective_projection(gc_context, None); // Set default PerspectiveProjection
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this line actually sets PerspectiveProjection::default() to DO's PerspectiveProjection.

if perspective_projection.is_none() {
// `stage` doesn't allow null PerspectiveProjection.
perspective_projection = Some(Default::default());

Technically it's fine to set PerspectiveProjection::default() directly at here, but for consistency with root.set_perspective_projection() in a different file I'm passing None here.

root.set_perspective_projection(self.gc(), None); // Set default PerspectiveProjection

The root actually has a different value used when None (null) is provided..
if perspective_projection.is_none() && self.is_root() {
// `root` doesn't allow null PerspectiveProjection.
perspective_projection = Some(PerspectiveProjection {
field_of_view: 55.0,
center: (
self.movie().width().to_pixels() / 2.0,
self.movie().height().to_pixels() / 2.0,
),
});
}

@cookie-s cookie-s force-pushed the perspective-projection-storage branch from aa6197e to 513015d Compare May 11, 2025 02:25
cookie-s added 4 commits May 27, 2025 03:17
Stage and root have their own initial PerspectiveProjection value, and
it's also used when attempting to set `null`.
* Remove FIXME for TestTranformUpdate()
* Add four more test cases
@cookie-s cookie-s force-pushed the perspective-projection-storage branch 2 times, most recently from fdba546 to 744856c Compare May 28, 2025 00:24
cookie-s added 4 commits May 28, 2025 00:24
Small number differences in focalLength are accepted as approximation
It's now unused because ruffle_render::Transform stores Option<PerspectiveProjection>.
It's very hard to verify this value with any test while
PerspectiveProjection rendering is not implemented. However, this change
makes the most sense.
It's not obvious whether each getter of one Transform object should return the same instance or newly created instance.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-avm2 Area: AVM2 (ActionScript 3) T-fix Type: Bug fix (in something that's supposed to work already) waiting-on-review Waiting on review from a Ruffle team member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants