Commit Graph

246 Commits

Author SHA1 Message Date
David Wendt 318b018da8 core: `enter_frame` should be an event that all display objects get and can respond to 2022-08-25 19:24:56 -06:00
Aaron Hill 86e6983943 avm2: Partially implement Loader.load
This PR implements the `Loader.load` method, as well as
the associated `LoaderInfo` properties and events.

We can now load in an external AVM2 SWf: it will be added
as a child of `Loader` object, and will render properly
to the screen.

Limitations:
* The only supported `URLRequest` property is `url`
* `LoaderContext` is not supported at all - we always use the default
  behavior
* Only `Loader.load` is implemented - we do not yet support unloading.
* We fire a plain 'Event' for the 'progress' event, instead of using
  the (not yet implemented) 'ProgressEvent' class

The main changes in this PR are:
* The AVM2 `Loader` class now has an associated display object,
  `LoaderDisplay`. This is basically a stub, and just renders
  its single child (if it exists).
* `LoaderStream::Stage` is renamed to `LoaderStream::NotYetLoaded`.
  This is used for both the `Stage` and an 'uninitialized'
  `Loader.contentLoaderInfo`. In both cases, certain properties throw
  errors, while others return actual values.
* The rust `Loader` manager now handles both AVM1 and AVM2 movie loads.
2022-08-22 19:36:29 -07:00
Mike Welsh 89cb1212ad render: Disable most blend modes
Avoid blend modes except ADD and SUBTRACT until they can be
implemented properly.
2022-08-19 14:59:08 -07:00
Mike Welsh 2e83bb570d core: Warn when setting a blend mode 2022-08-18 16:38:17 -07:00
Mike Welsh 7aee05cf75 core: Apply blend mode from PlaceObject tags
* Set blend mode in `DisplayObject::apply_place_object`.
 * Change `DisplayObject::set_blend_mode` to take `&self`.
2022-08-18 16:38:17 -07:00
Aaron Hill f7205a02a9 render: Add BlendMode infrastructure and implement BlendMode.ADD
Each render backend keeps track of a stack of BlenModes,
which are pushed and popped by 'core' as we render objects
in the displaay tree. For now, I've just implemented BlendMode.ADD,
which maps directly onto blend mode supported by each backend.

All other blend modes (besides 'NORMAL') will produce a warning
when we try to render using them. This may produce a very large amount
of log output, but it's simpler than emitting each warning only once,
and will help to point developers in the right direction when they
get otherwise inexplicable rendering issues (due to a blend mode
not being implemented).

The wgpu implementation is by far the most complicated, as we need
to construct a `RenderPipeline` for each possible
`(BlendMode, MaskState)`. I haven't been able to find any documentation
about the maximum supported number of (simultaneous) WebGPU render
pipelines - if this becomes an issue, we may need to register them
on-demand when a particular blend mode is requested.
2022-08-18 16:38:17 -07:00
relrelb 4d8e4111e3 core: Remove `AvmType`
Simply use `is_action_script_3()` instead.
2022-08-16 13:04:02 +03:00
Aaron Hill 6f20e8882d avm2: Implement DisplayObject.transform and most of Transform
This PR implements the 'DisplayObject.transform' getters/setters,
and most of the getters/setters in the `Transform` class

From testing in FP, it appears that each call to the
'DisplayObject.transform' property produces a new
'Transform' instance, which is permanently tied to the
owner 'DisplayObject'. All of the getters/setters in
`Transform` operate directly on owner `DisplayObject`.
However, note that the `Matrix` and `ColorTransform`
valuse *produced* the getter are plain ActionScript objects,
and have no further tie to the `DisplayObject`.

Using the `DisplayObject.transform` setter results in
values being *copied* from the input `Transform` object.
The input object retains its original owner `DisplayObject`.

Not implemented:
* Transform.concatenatedColorTransform
* Transform.pixelBounds

When a DisplayObject is not a descendant of the stage,
the `concatenatedMatrix` property produces a bizarre matrix:
a scale matrix that the depends on the global state quality.
Any DisplayObject that *is* a descendant of the stage has
a `concatenatedMatrix` that does not depend on the stage quality.
I'm not sure why the behavior occurs - for now, I just manually
mimic the values prdduced by FP. However, these values may indicate
that we need to do some internal scaling based on stage quality values,
and then 'undo' this in certain circumstances when constructing
an ActionScript matrix.

Unfortunately, some of the computed 'concatenatedMatrix' values
are off by f32::EPSILON. This is likely due to us storing some
internal values in pixels rather than twips (the rounding introduced
by round-trip twips conversions could cause this slight difference0.
For now, I've opted to mark these tests as 'approximate'.

To support this, I've extended our test framework to support providing
a regex that matches floating-point values in the output. This allows
us to print out 'Matrix.toString()' and still perform approximate
comparisons between strings of the format
'(a=0, b=0, c=0, d=0, tx=0, ty=0)'
2022-08-14 19:12:25 -07:00
Nathan Adams 760da753fb render: Moved Transform from core to render 2022-08-14 18:38:14 -07:00
Adrian Wielgosik 5be7f425f0 avm2: Migrate all Events to AS, remove EventData. 2022-07-30 12:34:12 -07:00
Aaron Hill 49d1a985ca avm2: Store `LoaderInfo` object on `MovieClip` and `Stage`
Previously, we would create a fresh `LoaderInfo` object each
time the `loaderInfo` property was accessed. However, users can
add event handlers to a `LoaderInfo`, so we need to create and
store exactly one `LoaderInfo` object per movie (and stage).

To verify that we're correctly handling the storage of `LoaderInfo`,
I've implemented firing the "init" event. This required a new
`on_frame_exit` hook, so that we can properly fire the "init"
event after the "exitFrame" for the initial frame but before
the "enterFrame" of the next frame.
2022-07-27 22:38:49 -07:00
relrelb fc87a35572 core: Remove some dead `DisplayObject` methods 2022-07-23 22:22:20 +03:00
relrelb 8d30833d02 core: Don't use `saturating_sub` for `width` / `height`
Use regular subtraction, since it should never overflow.
Also remove `swf::Twips::saturating_sub`, which is now unused.
2022-07-23 10:33:12 -07:00
Aaron Hill dde21a2a60 chore: Fix latest Clippy warnings 2022-06-08 07:19:56 +03:00
Mike Welsh 82ed6fcba7 core: Cleanup PlaceObject comments 2022-05-06 11:33:52 -07:00
Mike Welsh 0833bd0d18 core: Clip events can only be set on initial placement 2022-05-06 11:33:52 -07:00
Mike Welsh 8bf0114fdf core: DisplayObject clip depth can only be set on initial placement 2022-05-06 11:33:52 -07:00
Mike Welsh 32252b2ed4 core: DisplayObject name can only be set on initial placement 2022-05-06 11:33:52 -07:00
Mike Welsh b46c07830e core: Stub DisplayObject::background_color 2022-05-06 11:33:52 -07:00
Mike Welsh f8698d1cc9 core: Stub DisplayObject::blend_mode 2022-05-06 11:33:52 -07:00
Mike Welsh 2cebd47ad2 core: Stub DisplayObject:is_bitmap_cached 2022-05-06 11:33:52 -07:00
Mike Welsh 3305ac69c4 web: Support wmode parameter 2022-04-17 08:33:51 -07:00
relrelb 5a1e417526 avm1: Simplify `TDisplayObject::avm1_root()`
Make it infailable.
2022-03-10 01:22:52 +02:00
David Wendt 6271d069d7 core: `Stage` should not include it's own transform in it's local/global matrix. 2022-01-22 19:58:32 -08:00
David Wendt 87a9a543ba chore: Fix clippy lint on nightly 2022-01-22 19:58:32 -08:00
David Wendt 353a5a78d6 core: Move `mouse_pick` and `mouse_cursor` to `InteractiveObject` as no non-interactive object implements them.
This also cascades into other places, ultimately resulting in more things being marked as `InteractiveObject`.
2022-01-22 19:58:32 -08:00
David Wendt f56782c5c7 core: Movie clips do not have a hand cursor unless they are also in button mode. 2022-01-22 19:58:32 -08:00
David Wendt 016cd6ccc0 avm2: Make event construction take an `EventData` parameter.
This also necessitated the introduction of a `FullScreenEvent` data type.
2022-01-22 19:58:32 -08:00
relrelb 164e1a38c0 core: Remove unnecessary parameter from `post_instantiation`
`display_object` was always equivalent to `self`, there's no need to
pass both.
2022-01-22 11:37:33 -08:00
Adrian Wielgosik 49d16dea8b avm2: Rip out `receiver` from get/set/call_property 2021-12-11 20:48:09 +01:00
Moulins 9701b817f5 core: Replace WStr<'_> and WStrMut<'_> by a single DST type WStr 2021-11-27 11:20:47 -07:00
Moulins ee326e31b7 core: Reduce allocations in AvmString::new_utf8
Also remove some useless back-and-forth conversions between
AvmString and String
2021-11-27 11:20:47 -07:00
Moulins fa30e1bc43 chore: rename AvmString::{new -> new_utf8, new_ucs2 -> new} 2021-11-27 11:20:47 -07:00
Moulins 8863b54db0 avm1: don't use &str for activation's path & variable logic 2021-11-27 11:20:47 -07:00
relrelb b32ec3cf6c audio: Calculate sound transform values using 30-bit integers
The fix in #5218 wasn't sufficient; 30-bit arithmetic should be used
along all the way when calculating an effective sound transform.

For example, a sound transform composited by volumes `-0x80000000` and
`25` should end up as effectively 0, whereas previously it would have
been calculated as `-0x80000000 * 25 / 100 = -0x20000000`, which is a
30-bit integer that hasn't been truncated.

Fixes #5655.
2021-11-27 12:09:33 +02:00
Tal Hayon 7ed38850fd core: implement displayState for Stage in avm1/2 2021-11-11 16:20:05 -07:00
David Wendt 51af0f708f core: Remove commented-out helper methods. 2021-11-09 16:48:29 -07:00
David Wendt c78e5e31fd core: Store `DisplayObjectBase` in `InteractiveObjectBase`.
This also necessitated removing the `impl_display_object` family of macros, as you cannot name a field of a field in a macro expression. I tried. So instead I've reverted to standard default method inheritance, in the same way we did with AVM2 objects.
2021-11-09 16:48:29 -07:00
David Wendt bb8ca8f136 core: Move `handle_clip_event` to `TInteractiveObject`, and split it into three pieces.
`handle_clip_event` is now a default trait method that calls three methods in order:

 * `filter_clip_event`, to determine which events that either this object or it's children may handle
 * `propagate_to_children`, to check if any children of this object want to handle an event. (This also includes AVM2 button states, which are not technically "children" in the usual sense...)
 * `event_dispatch`, which does the actual "object reacts to an event" bit if no child handles the object.

These roughly correspond to phases of existing event-handling objects pre-`InteractiveObject`.
2021-11-09 16:48:29 -07:00
David Wendt 618c32f859 core: Add `InteractiveObject` trait for objects that can receive input events 2021-11-09 16:48:29 -07:00
Chris Midgley c9e67d31dc core: move avm_type from display object to update context 2021-10-09 10:10:03 -07:00
Moulins 4ad6e1e698 avm1: Propagate AvmString<'gc>s to all methods on Object
Some frequently-used Object methods have an Into<impl AvmString<'gc>>
parameter to reduce the size of the changes.
2021-10-06 19:47:35 -06:00
David Wendt b07ad8070c avm2: Make `get_property`, `set_property`, `init_property`, and various other derivative methods take a `Multiname` and run the search inside `Object`.
This also introduces a `call_property` method.
2021-09-23 15:59:06 -06:00
Mike Welsh e3c05a021e core: De-duplicate enums between Avm1Button and Avm2Button
Needed to appease clippy.
2021-09-11 21:50:52 -07:00
David Wendt 10b98f72f5 core: Allow `Bitmap` to be reassociated with new `BitmapData` 2021-09-11 12:11:35 -07:00
David Wendt 5771d4c826 avm2: Deduplicate the sound transform conversion code 2021-09-03 16:47:02 -06:00
David Wendt 5018421eef avm2: Rename `SystemConstructors` to `SystemClasses` 2021-07-20 22:08:27 -04:00
David Wendt 7e3c017a63 avm2: `broadcast_event` should use constructors for it's type checks. 2021-07-20 22:02:02 -04:00
relrelb e3f1fe2004 chore: Prefer spelling "Graphic" 2021-06-24 14:36:45 +03:00
relrelb 0fd1c05fd5 chore: Use into() in more places 2021-06-22 11:49:41 -07:00