The stage alignment settings viewport_scale_factor should *not* be
applied to `Stage.transform.matrix`, which is only ever changed
as a result of explicit modification from ActionScript. Instead,
alignment and scaling are performed a separate step, which is
transparent to ActionScript.
I've implemented this through a new `viewport_matrix` field,
which is used during stage rendering and mouse coordinate
transformation.
This makes Stage3D instances properly scale - previously, they
would render unscaled. The linux standalone Flash Player doesn't
seem to use HiDPI mode, so I didn't realize that this was a bug
until now.
In the process of implementing this, I discovered and fixed a bug
with how we handle changing the viewport size under winit.
Calling `self.window.set_inner_size` does not immediately take
effect (at least on X11) - calling `self.window.inner_size()`
will report the old size until the next resize event.
Since build our Stage matrices from `self.window.inner_size()`
(and start running the SWF) immediately after `RuffleEvent::OnMetadata`,
we would run a few SWF frames with an incorrect viewport size. This
is visible to SWFs that have the scale mode set to "noScale", and
could break SWFs that expect the initial viewport size to be
the movie size. I've fixed this by delaying SWF execution until
we get a Resize event (if `self.window.inner_size()` does not
immediately report the size we set).
`build_output_stream` now takes in a `timeout` parameter - I've
passed in `None` to keep the current behavior.
cpal addded lots of new `SampleFormat` enum values. For now, I'm
just returning an error if we encounter any of them - a quick test
showed that desktop audio is still working on my Linux machine.
The desktop player now takes a `--spoof-url` argument, which overrides
the movie URL provided to ActionScript. This does not affect non-root
movies loaded through `Loader`.
We were incorrectly skipping the call to `task.set_ready`
if `self.waiting_for_poll` was set. The `waiting_for_poll` flag
should only be used to avoid redundant messages being sent into
the event loop.
This was causing us to ignore wakeups if more than one wakup
arrived in between calls to `poll_all`.
* avm2: Implement call stack
* avm2: Class traits should have a special prefix
* avm2: Stack tracebacks should also contain error message
* avm2: Move method naming to Executable
* avm2: Handle getter and setter methods in tracebacks
* chore: Formatting
* chore: Add comments
* avm2: Make full_name write to a string, instead of creating a new one
* core: Make GcArena publicly accessible
* core: Add Deref impl for Either type
* desktop: Add AVM2 call stack to panic message
* avm2: Prefix native methods with a `/`
* chore: Appease clippy
* avm2: Check if method actually contains bytecode instead of unwrapping
* web: Add AVM2 stack trace to panic message
* chore: Formatting
* chore: Clippy
* avm2: Fix stack traces for free standing functions
* core: Remove global data from context
* core: Rename GcGlobalData to GcCallstack
* core: Introduce StaticCallstack, make GcArena private again
Co-authored-by: Adrian Wielgosik <4729533+adrian17@users.noreply.github.com>
Previously, the viewport height and width were stored in
both `Stage` and the `RenderBackend`. Any changes to the viewport
dimensions (e.g. due to window resizing) needed to be updated in both
places to keep our handling of the viewport consistent.
This PR adds a new `ViewportDimensions` type, which holds the
width, height, and scale factor. It is stored inside the
`RenderBackend` impl, and is retrieved using the newly added
method `RenderBackend.get_viewport_dimensions`. After a `Player`
has been constructed, any code that needes access to the viewport
dimensions will ultimate go through this method.
Unfortunately, `Stage` needs to use the viewport dimensions
in `build_matrices`. Therefore, any code modifying the viewport
dimensions should go through `player.set_viewport_dimensions`,
which ensures that the stage matrices are rebuilt after the render
backend is updated.
Run (almost) all event handlers regardless of whether a movie is loaded
or not. This will be useful for rendering a blank screen before a
movie has been loaded.
The resolved URL only used by `NavigatorBackend::fetch`. So simply
inline `NavigatorBackend::resolve_relative_url` into `NavigatorBackend::fetch`,
per implementation.
`core` already depends on the `instant` crate which abstracts
`std::instant::Instant` and polyfills it on Web. Use it to replace
`NavigatorBackend::time_since_launch` in order to make `NavigatorBackend`
a little smaller and more simple.
Previously there were 3 implementations of `LocaleBackend`:
`DesktopLocaleBackend`, `WebLocaleBackend` and `NullLocaleBackend`.
While `DesktopLocaleBackend`, `WebLocaleBackend` were identical,
`NullLocaleBackend` always returned a fixed date/time for tests
determinism.
Unify them in a single file, and use `cfg!(test)` and a new dedicated
`deterministic` feature to decide whether to mock date/time or not.
This should not cause any behavioral changes.
This makes `DesktopUiBackend::is_key_down` a simple one-line check.
Also unify the handling code of `ElementState::Pressed` and `ElementState::Released`,
which had a lot of common code.
Pull out the audio mixing code from desktop and add it to core.
This will allow other backends to use it (such as the web audio
backend) to get consistent audio across all platforms.
It was initialized on a separate thread since 6178dd9ef1,
as a workaround for Windows.
But now thanks to https://github.com/RustAudio/cpal/pull/597, this
is no longer needed, and cpal can be initialized on the same thread
as before.
When reading an SWF, search for FileAttributes and
SetBackgroundColor and return this along with the header data
because it's useful (in particular, the AS3 flag).
Toss out any shared objects that contain ".." in the name
to avoid accessing files outside of the Ruffle data directory.
The DiskStorageBackend also will fail any requests with a ".."
component as an extra precaution.
Fixes#3961.
Also, prefix the shared object name with # if it contains a
slash, (e.g. `#mygame/foo`). This matches Flash's directory
structure and makes it easier to transfer saved data to Ruffle.
This adds two optional parameters, --width and --height, which
allow the user to specify a desired physical window width and
height to be used. If only one of the two parameters is present,
the other will be deduced from it and the movie's aspect ratio.
If neither are present, the window's size is set to the movie's
logical size, in accordance with the behaviour before this change.
* #[derive(Collect)] should be before #[collect]
* Replace redunant `&buf[..]` with `buf`
* Changes most cases of UPPERCase to UpperCase
* Allow upper_case_acronym on most SWF types, as they are from
SWF spec/more annoying to change.
It might not succeed.
This unwrap crashes the newgrounds Meat Boy flash on desktop.
Instead, use unwrap_or_default with an empty path. This will cause
the read to fail, but it's better than crashing the whole program.
The points in an SWF sound envelope are always in 44.1KHz. The
desktop audio backend would end up using this points in the sound's
sample rate, often causing the envelope to be delayed.
Now the envelope is applied after resampling, and the positions
are scaled based on the output sample rate.