Conversation
|
So there's good news and bad news. 👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there. 😕 The bad news is that it appears that one or more commits were authored or co-authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that here in the pull request. Note to project maintainer: This is a terminal state, meaning the ℹ️ Googlers: Go here for more info. |
454cbbf to
f5559bf
Compare
| licensed under <a href="https://creativecommons.org/publicdomain/zero/1.0/">CC0</a> | ||
| (<a href="https://github.com/mrdoob/three.js/tree/dev/examples/models/gltf/RobotExpressive">source</a>) | ||
|
|
||
| ## small_hangar_01 |
There was a problem hiding this comment.
Horse.glb needs attribution
index.html
Outdated
| <p>Configures the model with custom text that will be used to describe the model to viewers who use a screen reader or otherwise depend on additional semantic context to understand what they are viewing.</p> | ||
| </li> | ||
| <li> | ||
| <h4>animated</h4> |
There was a problem hiding this comment.
I think animate might be a better attribute name than animated (present vs past tense), although can't think of good prior art (other than "checked", which is past tense, but seems like a different case?)
There was a problem hiding this comment.
Ugh, I forgot: I originally used animate, but it's a built-in method of HTMLElement (part of the Web Animations API).
There was a problem hiding this comment.
(and yah that's definitely not going to be confusing for folks at all)
😩
There was a problem hiding this comment.
This has been left as is, but if there is another name we like that doesn't overlap with a built-in API, I am open to changing it.
src/features/animation.ts
Outdated
| class AnimationModelViewerElement extends ModelViewerElement { | ||
| @property({type: Boolean}) animated: boolean = false; | ||
| @property({type: Boolean, attribute: 'pause-animation'}) | ||
| pauseAnimation: boolean = false; |
There was a problem hiding this comment.
pause-animation seems unused/undocumented (other than in the scenario where it's checked with !animated), is this necessary?
There was a problem hiding this comment.
Instead of pause-animation, there does seem like there would be a need to reset back to the default/T-Pose, so there is a difference between 'pausing' the animation (freezing in the middle of an animation) as opposed to 'removing' the animation -- of course, I don't think it necessary to solve this in this PR
There was a problem hiding this comment.
Yes, it is different from stopping the animation. Pause animation is documented, and will be necessary in order to implement @yuinchien 's mocks to spec in #425
There was a problem hiding this comment.
I think the effect you are describing is achieved when setting animate to false. Did you have something else in mind?
There was a problem hiding this comment.
pause-animation was not adequately documented, sorry. I added docs for it.
There was a problem hiding this comment.
@cdata yes, with pause-animation and !animate, both 'freeze' and 'reset' flows are supported
There was a problem hiding this comment.
After API refactor, to "pause" you must invoke pause() (there is no corresponding attribute/property). And, to "stop" you subsequently set .currentTime = 0.
src/features/animation.ts
Outdated
| * model. The promise rejects if the currently loaded model is | ||
| * changed to something new due to the src attribute changing. | ||
| */ | ||
| [$updateModelLoadsPromise]() { |
There was a problem hiding this comment.
Environments has a similar need/way of doing this -- wonder if there's a way to generalize this across all features?
There was a problem hiding this comment.
After offline discussion, I'm looking into whether this is necessary or not.
There was a problem hiding this comment.
I reduced the complexity of this implementation substantially, and I think it should be fine. Thanks for calling this out!
| // NOTE(cdata): If a property changes from values A -> B -> A in the space | ||
| // of a microtask, LitElement/UpdatingElement will notify of a change even | ||
| // though the value has effectively not changed, so we need to check to make | ||
| // sure that the value has actually changed before changing the loaded flag. |
There was a problem hiding this comment.
This seems like it'd be valuable for all properties, not just src
There was a problem hiding this comment.
Possibly, although the consequences of src change side-effects occurring unnecessarily seem particularly severe as they could affect all other features.
| get loaded() { | ||
| return super.loaded || this[$preloaded]; | ||
| return super.loaded || | ||
| (this.src && CachingGLTFLoader.hasFinishedLoading(this.src)); |
There was a problem hiding this comment.
This method, while probably valuable for tests at least, seems that it'd be more appropriate to live on this.src, our Model class (which could just wrap this); CachingGLTFLoader is an implementation detail that would benefit from continuing being hidden inside of Model, or at least out of features/*
There was a problem hiding this comment.
I don't know that I agree. CachingGLTFLoader was in fact the abstraction that enabled preloading to work in parallel with normal loading via setting src. Please offer a more concrete proposal for how you would change this!
There was a problem hiding this comment.
Keeping this as-is, but remain open to suggestions. I don't think it's the right answer to conflate preloading and the implementation in the Model class, because untangling that is what begot CachingGLTFLoader in the first place.
| .catch(() => {}); // Silently ignore exceptions here, they should be | ||
| // caught by the invoking function | ||
| cache.set(url, loadAttempt); | ||
| // window.loadAttempt = loadAttempt; |
src/features/loading.js
Outdated
| if (preloaded) { | ||
| this.dispatchEvent(new CustomEvent('preload', {detail})); | ||
| } else { | ||
| loader.preload(this.src) |
There was a problem hiding this comment.
I'll re-evaluate if this depends on asynchronous code flow
There was a problem hiding this comment.
I factored this out so that it's wrapped in an async function.
| .then(() => { | ||
| preloaded.set(url, true); | ||
| }) | ||
| .catch(() => {}); // Silently ignore exceptions here, they should be |
There was a problem hiding this comment.
Any reason using .then instead of await? This will swallow exceptions as indicated, but how would invoking function catch that if they're not thrown?
There was a problem hiding this comment.
When you invoke then or catch in a promise, it does not modify the state of a promise in place. The methods return new promise instances that are resolved differently depending on how you invoked them.
We don't cache the "caught" promise. So, try/catch blocks outside of this scope will still work as expected.
There was a problem hiding this comment.
And yeah, the reason for using then is that the asynchronous behavior is preferred.
There was a problem hiding this comment.
As mentioned in #421 (comment) I'll re-evaluate if this is necessary.
There was a problem hiding this comment.
Rewritten with await.
| const scene = await this.loader.load(url); | ||
| // If we have pending work due to a previous source change in progress, | ||
| // cancel it so that we do not incur a race condition: | ||
| if (this[$cancelPendingSourceChange] != null) { |
There was a problem hiding this comment.
Similar concept to other features ensuring that the changes are still valid; can that be abstracted so that model can handle it everywhere? No good ideas currently, but this seems like a potential growing source of race conditions throughout features
There was a problem hiding this comment.
I disagree, this problem is fairly unique to the consequences of changing the src. Let's discuss offline.
There was a problem hiding this comment.
After reviewing, I remain convinced that changing the src requires special considerations. I'm open to concrete suggestions for refactoring, though.
|
Tests ended in IE11 timeout, flagging for #433 |
|
What about |
|
Although conceptually, we would probably have to introduce an explicit API for pausing + resetting the animation. For example, to "stop" a video.pause();
video.currentTime = 0;WDYT? Should we go for something more like that? I'm also interested to hear what others think of |
|
I'm good with Chris and I chatted about Overall using |
|
This all SGTM. I'm going to change the current proposal so that the API tracks closely to
|
PTAL at your leisure! |
| // preloaded.set(url, true); | ||
| //}) | ||
| //.catch(() => {}); // Silently ignore exceptions here, they should be | ||
| //// caught by the invoking function |
smalls
left a comment
There was a problem hiding this comment.
Thanks, the API's looking great!
|
🎉🎉🎉 |
|
Is there a way to import the array from the gltf file and use it in the component? Because, for me only one of the multiple animations play. rest doesn't! Is this bug already being resolved or yet to ? Also, which is the recommended format for rendering animated 3D models - GLTF or GLB ?? @cdata |
Animations
This change proposes the addition of new API (and related bug fixes) to configure and present animated glTFs with
<model-viewer>. Morph, skeletal and keyframe should all be supported.New public API introduced by this change:
autoplayfalseanimatedchanges to false.animation-nameundefined<model-viewer>will look for an animation with this name when played. If an animation with that name is found, plays that animation. Otherwise, if an animation with that name is not found, falls back to the first animation (if any).animation-crossfade-duration300animation-name.availableAnimations[]pausedtrue<model-viewer>. A<model-viewer>displaying a model with no animations is always considered paused.currentTime0play()animation-name, or else falling back to the first animation) if it is available.pause()pause<model-viewer>is paused. The implicit default state of<model-viewer>is paused, and apauseevent will not be dispatched until the<model-viewer>has been played at least once.play<model-viewer>begins playing animations.poster-visibilityevent.detail.visiblepropertyAdditional highlights
srcattribute quickly<model-viewer>Examples
autoplayanimation-name="Run"animationNameon an intervalanimation-namewhile pausedFuture work
Fixes #404
Fixes #371