-
Notifications
You must be signed in to change notification settings - Fork 876
Variants editor #2929
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
Variants editor #2929
Conversation
Display of material list based on variant working Fix issue where selecting a material occurs after dragging.
Adds variant tests.
import '@material/mwc-icon-button'; | ||
|
||
import {$gltfIndex, Material} from '@google/model-viewer/lib/features/scene-graph/material'; | ||
import {$primitivesList} from '@google/model-viewer/lib/features/scene-graph/model'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to consider our editor as built on top of model-viewer, meaning on its public API. If the feature we want in the editor can't be implemented with MV's public API, we should use that as feedback for changing its public API. Can we do this without accessing our private symbols?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is something that I keep wishing I had when working on other material features, I finally added it here because it makes the whole thing so much cleaner, but I agree in general, I do think this should have already been a thing which is why I felt ok adding it; we have this info just not in as useful a form.
</me-dropdown> | ||
<div slot="content"> | ||
${this.renderVariantsSelector()} | ||
<me-section-row label="Material"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This all seems to be nicely functional; let's tweak the CSS to make it a little nicer to look at. We can discuss at our next meeting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem, just keep in mind the 'create variant' functionality will be coming in next so that UI should be taken into account as well
getModelViewer().addEventListener('pointermove', () => drag = true); | ||
getModelViewer().addEventListener('pointerup', (event) => { | ||
if (!drag) { | ||
this.onClick(event); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks interesting; care to describe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This simply prevents selecting a material while dragging the object.
this.selectableMaterials = Array.from(selectableSet); | ||
this.selectableMaterials.sort((a, b) => { | ||
return a[$gltfIndex] - b[$gltfIndex]; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these not sorted to begin with? I thought we get things back in insertion order?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because the list is based on the order a material is encountered in the list primitives the materials will not be in order. Per our conversation isActive
is being added to Material
in order to provide the same information publicly without exposing primitive-node
Uses the new API in material_panel to implement variant selection, and to filter materials by active material.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking pretty close, just a few things.
return (this[$sourceObject] as DefaultedMaterial).emissiveFactor; | ||
} | ||
|
||
get gltfIndex(): number { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might just call this index
, since our materials
index is the same. Also looks like this wasn't added to the API?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good.
Added.
|
||
|
||
|
||
export interface VariantToMaterialMapping { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vestigial?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed.
} | ||
|
||
get selectedVariant(): string|null { | ||
if (!getModelViewer()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think for consistency you can remove this. In fact I think the getModelViewer()
return type doesn't even include null/undefined
now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
} | ||
|
||
updateSelectableMaterials() { | ||
if (getModelViewer() != null && getModelViewer()!.model != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Elsewhere we just assert these are not null. I think that's fine here since I believe the whole panel gets hidden if there's no model loaded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
getModelViewer().addEventListener('variant-applied', () => { | ||
onVariantApplied(); | ||
getModelViewer().removeEventListener( | ||
'variant-applied', onVariantApplied); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A simpler version of this is getModelViewer().addEventListener('variant-applied', onVariantApplied, { once: true });
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice
await panel.updateComplete; | ||
|
||
const selector = panel.shadowRoot?.getElementById('variant-selector'); | ||
expect(selector!.id).toEqual('variant-selector'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit tautological; maybe check that the selector is visible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
</me-section-row label> | ||
`; | ||
} | ||
return html``; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been trying to get away from this style we had a lot of where we would conditionally remove html. It makes a lot of things difficult (you never know if an element exists, etc). Let's instead change the visibility of the element when availableVariants changes; like set display: "none"
or add a class that does that. There should be plenty of examples around the code base to follow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting display: none
if you could verify that this code looks ok, everything works fine but...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost there, let's just fix the last of the CSS (since this will be public as soon as we click merge).
metallicFactorSlider!: SliderWithInputElement; | ||
@query('me-dropdown#material-selector') materialSelector!: Dropdown; | ||
@query('me-dropdown#variant-selector') variantSelector!: Dropdown; | ||
@query('me-dropdown#create-variant-selector') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vestigial?
<me-section-row | ||
label="Variant" | ||
style='display: ${ | ||
getModelViewer().availableVariants.length > 0 ? 'block' : 'none'}'> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine until you add create variant functionality. Then this length will change without updating any @property
, which means it won't cause render
to run. You can cross that bridge when you come to it. Generally I do CSS changes like this outside of the render function to avoid this, since it's cheaper than calling render more often.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, so you can just update CSS and it will respond without having to 're-render' the html?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah gonna leave this here until I have the button, which will provide the hooks to update the CSS display state
'Unnamed Material'}</paper-item>`)} | ||
</me-dropdown> | ||
<div slot="content"> | ||
<me-section-row> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can just remain unchanged from master, right? Are these divs and rows doing anything useful? Seems to be causing unwanted centering too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahhh yes
|
||
renderSelectMaterialTab() { | ||
return html` | ||
<me-expandable-tab tabName="Selected Material" .open=${true} .sticky=${ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you open enough tabs under this so it scrolls, you'll see that having a sticky one below a not sticky one is very weird. Let's go with neither is sticky. Hopefully that will make their styles match better too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Looks pretty good IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
Adds Variant selection to Material editor