core: Empty movie clips can not be used as a mask

When a movie clip or button is used as a mask, the masking will be
disabled if that object has no children; the maskee will be
completely visible. An empty movie clip inside an empty movie clip
successfully masks.

An EditText can also not be used as a masker (although it can be
wrapped inside a movie clip, and then the text successfully masks).

Add a `TDisplayObject::allow_mask` trait method that will
return whether the object can be used as a mask.

This fixes characters not being visible in Dad 'n' Me.
This commit is contained in:
Mike Welsh 2020-02-01 00:38:44 -08:00
parent 6b7966f3fc
commit 2ff76775e0
4 changed files with 20 additions and 1 deletions

View File

@ -786,6 +786,13 @@ pub trait TDisplayObject<'gc>: 'gc + Collect + Debug {
fn instantiate(&self, gc_context: MutationContext<'gc, '_>) -> DisplayObject<'gc>;
fn as_ptr(&self) -> *const DisplayObjectPtr;
/// Whether this object can be used as a mask.
/// If this returns false and this object is used as a mask, the mask will not be applied.
/// This is used by movie clips to disable the mask when there are no children, for example.
fn allow_as_mask(&self) -> bool {
true
}
}
pub enum DisplayObjectPtr {}
@ -958,7 +965,7 @@ pub fn render_children<'gc>(
context.renderer.pop_mask();
clip_depth = clip_depth_stack.pop().unwrap();
}
if child.clip_depth() > 0 {
if child.clip_depth() > 0 && child.allow_as_mask() {
// Push and render the mask.
clip_depth_stack.push(clip_depth);
clip_depth = child.clip_depth();

View File

@ -203,6 +203,10 @@ impl<'gc> TDisplayObject<'gc> for Button<'gc> {
fn as_button(&self) -> Option<Self> {
Some(*self)
}
fn allow_as_mask(&self) -> bool {
!self.0.read().children.is_empty()
}
}
impl<'gc> ButtonData<'gc> {

View File

@ -169,6 +169,10 @@ impl<'gc> TDisplayObject<'gc> for EditText<'gc> {
}
context.transform_stack.pop();
}
fn allow_as_mask(&self) -> bool {
false
}
}
unsafe impl<'gc> gc_arena::Collect for EditTextData<'gc> {

View File

@ -387,6 +387,10 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
);
self.set_removed(context.gc_context, true);
}
fn allow_as_mask(&self) -> bool {
!self.0.read().children.is_empty()
}
}
unsafe impl<'gc> Collect for MovieClipData<'gc> {