Skip to content
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

Remove Material Asset on Material change #5109

Conversation

MushAsterion
Copy link
Collaborator

Fixes #3560

Set ImageElement#materialAsset to null on material change if new material does not match materialAsset to avoid overwrite from ImageElement#onEnable. Important to use setter instead of _materialAsset to remove listeners.

I confirm I have read the contributing guidelines and signed the Contributor License Agreement.

@MushAsterion MushAsterion marked this pull request as draft February 27, 2023 16:35
@MushAsterion MushAsterion marked this pull request as ready for review February 27, 2023 16:46
if (!asset) {
this.material = null;
this._materialAsset = _id;
Copy link
Contributor

Choose a reason for hiding this comment

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

this._materialAsset = _id; is in both branches of the if.

Can we replace only 1037 by this._materialAsset = _id || null;?

Copy link
Collaborator Author

@MushAsterion MushAsterion Mar 1, 2023

Choose a reason for hiding this comment

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

The point is that if this._materialAsset is not null when we set this.material to null, this.material setter will call this.materialAsset to null which we don't want. So I had to make sure it's null before assigning to the right value after processing with material reset.

It's also not possible to change this._material directly as it won't reset the displayed material.

So yeah a bit upside-down but I couldn't find any better way to do it...

The other solution could be to switch to:

this._materialAsset = null;
this.material = null;
this._materialAsset = _id

Copy link
Contributor

Choose a reason for hiding this comment

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

@querielo Any further comments here or is this particular conversation resolved?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I moved to the other solution

this._materialAsset = null;
this.material = null;

this._materialAsset = _id;

So it's more clear that the null assignment is only for material nulling and reduces the number of changed lines, as it's only to reduces call from material setter and avoid a loop between the two.

In fact the bug was coming from material setter not changing the _materialAsset and the enable callback using the _materialAsset if any, overriding any existing _material if it was from a different ID/no ID. So the main point is to remove _materialAsset inside material setter which was then making a loop with materialAsset setter if _materialAsset was non-null or different, why the null.

@MushAsterion MushAsterion added bug area: ui UI related issue labels Mar 26, 2023
@willeastcott
Copy link
Contributor

willeastcott commented Apr 13, 2023

@mvaligursky I think you should be the one to hit the merge button if you're satisfied. Over to you... 😄

Copy link
Member

@slimbuck slimbuck left a comment

Choose a reason for hiding this comment

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

Approving, sorry for the long wait @MushAsterion !!

@mvaligursky
Copy link
Contributor

It looks good, merging in, thanks all!

@mvaligursky mvaligursky merged commit e371052 into playcanvas:main Apr 28, 2023
@MushAsterion MushAsterion deleted the fix-imageelement-materialasset-notaffected branch April 29, 2023 11:28
if (this._materialAsset) {
const asset = this._system.app.assets.get(this._materialAsset);
if (!asset || asset.resource !== value) {
this.materialAsset = null;
Copy link
Contributor

@yaustar yaustar May 12, 2023

Choose a reason for hiding this comment

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

Should this line be this._materialAsset = null? as calling the setter for materialAsset also sets the _material to null as well? It's also a circular call where the setter for materialAsset calls this material setter.

Or does it still need to remove the listeners on the asset as well? In which case, we need to create separate function to remove the event listeners

@willeastcott
Copy link
Contributor

This PR seems to be causing a problem reported by a forum user:

https://forum.playcanvas.com/t/cannot-set-properties-of-alphatest-for-materials-even-on-playcanvas-examples/31387

They're cloning the material on an element and replacing the element's material with the clone. This internally sets materialAsset = null which in turn sets material to null. I'm wondering if we should back this out. Got any thoughts @MushAsterion?

@yaustar
Copy link
Contributor

yaustar commented May 20, 2023

The fix in #5327 has not been merged to a release yet @willeastcott

@mvaligursky
Copy link
Contributor

You're right! With so many patch releases, I was sure this was out already.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: ui UI related issue bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Material changes are lost when Image Element is disabled
6 participants