Changeset 286066 in webkit


Ignore:
Timestamp:
Nov 19, 2021 10:21:57 AM (8 months ago)
Author:
graouts@webkit.org
Message:

[Model] add support for controlling looping animations
https://bugs.webkit.org/show_bug.cgi?id=233356
<rdar://problem/85428884>

Reviewed by Wenson Hsieh.

Source/WebCore:

We add two new promise-based methods to the HTMLModelElement IDL to control the looping state
of the animation built into the USDZ asset: isLoopingAnimation() and setIsLoopingAnimation().
All these methods are promise-based.

  • Modules/model-element/HTMLModelElement.cpp:

(WebCore::HTMLModelElement::isLoopingAnimation):
(WebCore::HTMLModelElement::setIsLoopingAnimation):

  • Modules/model-element/HTMLModelElement.h:
  • Modules/model-element/HTMLModelElement.idl:
  • Modules/model-element/ModelPlayer.h:
  • Modules/model-element/dummy/DummyModelPlayer.cpp:

(WebCore::DummyModelPlayer::isLoopingAnimation):
(WebCore::DummyModelPlayer::setIsLoopingAnimation):

  • Modules/model-element/dummy/DummyModelPlayer.h:
  • Modules/model-element/scenekit/SceneKitModelPlayer.h:
  • Modules/model-element/scenekit/SceneKitModelPlayer.mm:

(WebCore::SceneKitModelPlayer::isLoopingAnimation):
(WebCore::SceneKitModelPlayer::setIsLoopingAnimation):

Source/WebCore/PAL:

Add the new ARQL SPIs we are using to control animation looping.

  • pal/spi/ios/SystemPreviewSPI.h:
  • pal/spi/mac/SystemPreviewSPI.h:

Source/WebKit:

Expose new WebPageProxy messages to let the WebProcess message the UIProcess
to call into ASVInlinePreview methods to get and set the animation's looping
state.

  • UIProcess/Cocoa/ModelElementControllerCocoa.mm:

(WebKit::ModelElementController::isLoopingAnimationForModelElement):
(WebKit::ModelElementController::setIsLoopingAnimationForModelElement):

  • UIProcess/ModelElementController.h:
  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::modelElementIsLoopingAnimation):
(WebKit::WebPageProxy::modelElementSetIsLoopingAnimation):

  • UIProcess/WebPageProxy.h:
  • UIProcess/WebPageProxy.messages.in:
  • WebProcess/Model/ARKitInlinePreviewModelPlayer.h:
  • WebProcess/Model/ARKitInlinePreviewModelPlayer.mm:

(WebKit::ARKitInlinePreviewModelPlayer::isLoopingAnimation):
(WebKit::ARKitInlinePreviewModelPlayer::setIsLoopingAnimation):

Location:
trunk/Source
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r286065 r286066  
     12021-11-19  Antoine Quint  <graouts@webkit.org>
     2
     3        [Model] add support for controlling looping animations
     4        https://bugs.webkit.org/show_bug.cgi?id=233356
     5        <rdar://problem/85428884>
     6
     7        Reviewed by Wenson Hsieh.
     8
     9        We add two new promise-based methods to the HTMLModelElement IDL to control the looping state
     10        of the animation built into the USDZ asset: isLoopingAnimation() and setIsLoopingAnimation().
     11        All these methods are promise-based.
     12
     13        * Modules/model-element/HTMLModelElement.cpp:
     14        (WebCore::HTMLModelElement::isLoopingAnimation):
     15        (WebCore::HTMLModelElement::setIsLoopingAnimation):
     16        * Modules/model-element/HTMLModelElement.h:
     17        * Modules/model-element/HTMLModelElement.idl:
     18        * Modules/model-element/ModelPlayer.h:
     19        * Modules/model-element/dummy/DummyModelPlayer.cpp:
     20        (WebCore::DummyModelPlayer::isLoopingAnimation):
     21        (WebCore::DummyModelPlayer::setIsLoopingAnimation):
     22        * Modules/model-element/dummy/DummyModelPlayer.h:
     23        * Modules/model-element/scenekit/SceneKitModelPlayer.h:
     24        * Modules/model-element/scenekit/SceneKitModelPlayer.mm:
     25        (WebCore::SceneKitModelPlayer::isLoopingAnimation):
     26        (WebCore::SceneKitModelPlayer::setIsLoopingAnimation):
     27
    1282021-11-19  Antoine Quint  <graouts@webkit.org>
    229
  • trunk/Source/WebCore/Modules/model-element/HTMLModelElement.cpp

    r286065 r286066  
    438438}
    439439
     440void HTMLModelElement::isLoopingAnimation(IsLoopingAnimationPromise&& promise)
     441{
     442    if (!m_modelPlayer) {
     443        promise.reject();
     444        return;
     445    }
     446
     447    m_modelPlayer->isLoopingAnimation([promise = WTFMove(promise)] (std::optional<bool> isLooping) mutable {
     448        if (!isLooping)
     449            promise.reject();
     450        else
     451            promise.resolve(*isLooping);
     452    });
     453}
     454
     455void HTMLModelElement::setIsLoopingAnimation(bool isLooping, DOMPromiseDeferred<void>&& promise)
     456{
     457    if (!m_modelPlayer) {
     458        promise.reject();
     459        return;
     460    }
     461
     462    m_modelPlayer->setIsLoopingAnimation(isLooping, [promise = WTFMove(promise)] (bool success) mutable {
     463        if (success)
     464            promise.resolve();
     465        else
     466            promise.reject();
     467    });
     468}
     469
    440470// MARK: - Audio support.
    441471
  • trunk/Source/WebCore/Modules/model-element/HTMLModelElement.h

    r286065 r286066  
    8181    void pauseAnimation(DOMPromiseDeferred<void>&&);
    8282
     83    using IsLoopingAnimationPromise = DOMPromiseDeferred<IDLBoolean>;
     84    void isLoopingAnimation(IsLoopingAnimationPromise&&);
     85    void setIsLoopingAnimation(bool, DOMPromiseDeferred<void>&&);
     86
    8387    using HasAudioPromise = DOMPromiseDeferred<IDLBoolean>;
    8488    void hasAudio(HasAudioPromise&&);
  • trunk/Source/WebCore/Modules/model-element/HTMLModelElement.idl

    r286065 r286066  
    4242    Promise<undefined> pauseAnimation();
    4343
     44    Promise<boolean> isLoopingAnimation();
     45    Promise<undefined> setIsLoopingAnimation(boolean looping);
     46
    4447    Promise<boolean> hasAudio();
    4548    Promise<boolean> isMuted();
  • trunk/Source/WebCore/Modules/model-element/ModelPlayer.h

    r286065 r286066  
    5454    virtual void isPlayingAnimation(CompletionHandler<void(std::optional<bool>&&)>&&) = 0;
    5555    virtual void setAnimationIsPlaying(bool, CompletionHandler<void(bool success)>&&) = 0;
     56    virtual void isLoopingAnimation(CompletionHandler<void(std::optional<bool>&&)>&&) = 0;
     57    virtual void setIsLoopingAnimation(bool, CompletionHandler<void(bool success)>&&) = 0;
    5658    virtual void hasAudio(CompletionHandler<void(std::optional<bool>&&)>&&) = 0;
    5759    virtual void isMuted(CompletionHandler<void(std::optional<bool>&&)>&&) = 0;
  • trunk/Source/WebCore/Modules/model-element/dummy/DummyModelPlayer.cpp

    r286065 r286066  
    9191}
    9292
     93void DummyModelPlayer::isLoopingAnimation(CompletionHandler<void(std::optional<bool>&&)>&&)
     94{
     95}
     96
     97void DummyModelPlayer::setIsLoopingAnimation(bool, CompletionHandler<void(bool success)>&&)
     98{
     99}
     100
    93101void DummyModelPlayer::isMuted(CompletionHandler<void(std::optional<bool>&&)>&&)
    94102{
  • trunk/Source/WebCore/Modules/model-element/dummy/DummyModelPlayer.h

    r286065 r286066  
    5252    void isPlayingAnimation(CompletionHandler<void(std::optional<bool>&&)>&&) override;
    5353    void setAnimationIsPlaying(bool, CompletionHandler<void(bool success)>&&) override;
     54    void isLoopingAnimation(CompletionHandler<void(std::optional<bool>&&)>&&) override;
     55    void setIsLoopingAnimation(bool, CompletionHandler<void(bool success)>&&) override;
    5456    void hasAudio(CompletionHandler<void(std::optional<bool>&&)>&&) override;
    5557    void isMuted(CompletionHandler<void(std::optional<bool>&&)>&&) override;
  • trunk/Source/WebCore/Modules/model-element/scenekit/SceneKitModelPlayer.h

    r286065 r286066  
    6666    void isPlayingAnimation(CompletionHandler<void(std::optional<bool>&&)>&&) override;
    6767    void setAnimationIsPlaying(bool, CompletionHandler<void(bool success)>&&) override;
     68    void isLoopingAnimation(CompletionHandler<void(std::optional<bool>&&)>&&) override;
     69    void setIsLoopingAnimation(bool, CompletionHandler<void(bool success)>&&) override;
    6870    void hasAudio(CompletionHandler<void(std::optional<bool>&&)>&&) override;
    6971    void isMuted(CompletionHandler<void(std::optional<bool>&&)>&&) override;
  • trunk/Source/WebCore/Modules/model-element/scenekit/SceneKitModelPlayer.mm

    r286065 r286066  
    105105}
    106106
     107void SceneKitModelPlayer::isLoopingAnimation(CompletionHandler<void(std::optional<bool>&&)>&&)
     108{
     109}
     110
     111void SceneKitModelPlayer::setIsLoopingAnimation(bool, CompletionHandler<void(bool success)>&&)
     112{
     113}
     114
    107115void SceneKitModelPlayer::hasAudio(CompletionHandler<void(std::optional<bool>&&)>&&)
    108116{
  • trunk/Source/WebCore/PAL/ChangeLog

    r286065 r286066  
     12021-11-19  Antoine Quint  <graouts@webkit.org>
     2
     3        [Model] add support for controlling looping animations
     4        https://bugs.webkit.org/show_bug.cgi?id=233356
     5        <rdar://problem/85428884>
     6
     7        Reviewed by Wenson Hsieh.
     8
     9        Add the new ARQL SPIs we are using to control animation looping.
     10
     11        * pal/spi/ios/SystemPreviewSPI.h:
     12        * pal/spi/mac/SystemPreviewSPI.h:
     13
    1142021-11-19  Antoine Quint  <graouts@webkit.org>
    215
  • trunk/Source/WebCore/PAL/pal/spi/ios/SystemPreviewSPI.h

    r286065 r286066  
    109109- (void)setCameraTransform:(simd_float3)transform;
    110110
     111@property (nonatomic, readwrite) BOOL isLooping;
    111112@property (nonatomic, readonly) BOOL isPlaying;
    112113typedef void (^ASVSetIsPlayingReplyBlock) (BOOL isPlaying, NSError * _Nullable error);
  • trunk/Source/WebCore/PAL/pal/spi/mac/SystemPreviewSPI.h

    r286065 r286066  
    5959- (void)setCameraTransform:(simd_float3)transform;
    6060
     61@property (nonatomic, readwrite) BOOL isLooping;
    6162@property (nonatomic, readonly) BOOL isPlaying;
    6263typedef void (^ASVSetIsPlayingReplyBlock) (BOOL isPlaying, NSError * _Nullable error);
  • trunk/Source/WebKit/ChangeLog

    r286065 r286066  
     12021-11-19  Antoine Quint  <graouts@webkit.org>
     2
     3        [Model] add support for controlling looping animations
     4        https://bugs.webkit.org/show_bug.cgi?id=233356
     5        <rdar://problem/85428884>
     6
     7        Reviewed by Wenson Hsieh.
     8
     9        Expose new WebPageProxy messages to let the WebProcess message the UIProcess
     10        to call into ASVInlinePreview methods to get and set the animation's looping
     11        state.
     12
     13        * UIProcess/Cocoa/ModelElementControllerCocoa.mm:
     14        (WebKit::ModelElementController::isLoopingAnimationForModelElement):
     15        (WebKit::ModelElementController::setIsLoopingAnimationForModelElement):
     16        * UIProcess/ModelElementController.h:
     17        * UIProcess/WebPageProxy.cpp:
     18        (WebKit::WebPageProxy::modelElementIsLoopingAnimation):
     19        (WebKit::WebPageProxy::modelElementSetIsLoopingAnimation):
     20        * UIProcess/WebPageProxy.h:
     21        * UIProcess/WebPageProxy.messages.in:
     22        * WebProcess/Model/ARKitInlinePreviewModelPlayer.h:
     23        * WebProcess/Model/ARKitInlinePreviewModelPlayer.mm:
     24        (WebKit::ARKitInlinePreviewModelPlayer::isLoopingAnimation):
     25        (WebKit::ARKitInlinePreviewModelPlayer::setIsLoopingAnimation):
     26
    1272021-11-19  Antoine Quint  <graouts@webkit.org>
    228
  • trunk/Source/WebKit/UIProcess/Cocoa/ModelElementControllerCocoa.mm

    r286065 r286066  
    360360}
    361361
     362void ModelElementController::isLoopingAnimationForModelElement(ModelIdentifier modelIdentifier, CompletionHandler<void(Expected<bool, WebCore::ResourceError>)>&& completionHandler)
     363{
     364    auto* preview = previewForModelIdentifier(modelIdentifier);
     365    if (!previewHasAnimationSupport(preview)) {
     366        completionHandler(makeUnexpected(WebCore::ResourceError { WebCore::ResourceError::Type::General }));
     367        return;
     368    }
     369
     370#if ENABLE(ARKIT_INLINE_PREVIEW_ANIMATIONS_CONTROL)
     371    completionHandler([preview isLooping]);
     372#else
     373    ASSERT_NOT_REACHED();
     374#endif
     375}
     376
     377void ModelElementController::setIsLoopingAnimationForModelElement(ModelIdentifier modelIdentifier, bool isLooping, CompletionHandler<void(bool)>&& completionHandler)
     378{
     379    auto* preview = previewForModelIdentifier(modelIdentifier);
     380    if (!previewHasAnimationSupport(preview)) {
     381        completionHandler(false);
     382        return;
     383    }
     384
     385#if ENABLE(ARKIT_INLINE_PREVIEW_ANIMATIONS_CONTROL)
     386    preview.isLooping = isLooping;
     387    completionHandler(true);
     388#else
     389    ASSERT_NOT_REACHED();
     390#endif
     391}
     392
     393
    362394static bool previewHasAudioSupport(ASVInlinePreview *preview)
    363395{
  • trunk/Source/WebKit/UIProcess/ModelElementController.h

    r286065 r286066  
    5757    void isPlayingAnimationForModelElement(ModelIdentifier, CompletionHandler<void(Expected<bool, WebCore::ResourceError>)>&&);
    5858    void setAnimationIsPlayingForModelElement(ModelIdentifier, bool, CompletionHandler<void(bool)>&&);
     59    void isLoopingAnimationForModelElement(ModelIdentifier, CompletionHandler<void(Expected<bool, WebCore::ResourceError>)>&&);
     60    void setIsLoopingAnimationForModelElement(ModelIdentifier, bool, CompletionHandler<void(bool)>&&);
    5961    void hasAudioForModelElement(ModelIdentifier, CompletionHandler<void(Expected<bool, WebCore::ResourceError>)>&&);
    6062    void isMutedForModelElement(ModelIdentifier, CompletionHandler<void(Expected<bool, WebCore::ResourceError>)>&&);
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r286065 r286066  
    1085410854}
    1085510855
     10856void WebPageProxy::modelElementIsLoopingAnimation(ModelIdentifier modelIdentifier, CompletionHandler<void(Expected<bool, ResourceError>)>&& completionHandler)
     10857{
     10858    modelElementController()->isLoopingAnimationForModelElement(modelIdentifier, WTFMove(completionHandler));
     10859}
     10860
     10861void WebPageProxy::modelElementSetIsLoopingAnimation(ModelIdentifier modelIdentifier, bool isLooping, CompletionHandler<void(bool)>&& completionHandler)
     10862{
     10863    modelElementController()->setIsLoopingAnimationForModelElement(modelIdentifier, isLooping, WTFMove(completionHandler));
     10864}
     10865
    1085610866void WebPageProxy::modelElementHasAudio(ModelIdentifier modelIdentifier, CompletionHandler<void(Expected<bool, ResourceError>)>&& completionHandler)
    1085710867{
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r286065 r286066  
    593593    void modelElementIsPlayingAnimation(ModelIdentifier, CompletionHandler<void(Expected<bool, WebCore::ResourceError>)>&&);
    594594    void modelElementSetAnimationIsPlaying(ModelIdentifier, bool, CompletionHandler<void(bool)>&&);
     595    void modelElementIsLoopingAnimation(ModelIdentifier, CompletionHandler<void(Expected<bool, WebCore::ResourceError>)>&&);
     596    void modelElementSetIsLoopingAnimation(ModelIdentifier, bool, CompletionHandler<void(bool)>&&);
    595597    void modelElementHasAudio(ModelIdentifier, CompletionHandler<void(Expected<bool, WebCore::ResourceError>)>&&);
    596598    void modelElementIsMuted(ModelIdentifier, CompletionHandler<void(Expected<bool, WebCore::ResourceError>)>&&);
  • trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in

    r286065 r286066  
    600600    ModelElementIsPlayingAnimation(struct WebKit::ModelIdentifier modelIdentifier) -> (Expected<bool, WebCore::ResourceError> result) Async
    601601    ModelElementSetAnimationIsPlaying(struct WebKit::ModelIdentifier modelIdentifier, bool isPlaying) -> (bool success) Async
     602    ModelElementIsLoopingAnimation(struct WebKit::ModelIdentifier modelIdentifier) -> (Expected<bool, WebCore::ResourceError> result) Async
     603    ModelElementSetIsLoopingAnimation(struct WebKit::ModelIdentifier modelIdentifier, bool isLooping) -> (bool success) Async
    602604    ModelElementHasAudio(struct WebKit::ModelIdentifier modelIdentifier) -> (Expected<bool, WebCore::ResourceError> result) Async
    603605    ModelElementIsMuted(struct WebKit::ModelIdentifier modelIdentifier) -> (Expected<bool, WebCore::ResourceError> result) Async
  • trunk/Source/WebKit/WebProcess/Model/ARKitInlinePreviewModelPlayer.h

    r286065 r286066  
    5858    void isPlayingAnimation(CompletionHandler<void(std::optional<bool>&&)>&&) override;
    5959    void setAnimationIsPlaying(bool, CompletionHandler<void(bool success)>&&) override;
     60    void isLoopingAnimation(CompletionHandler<void(std::optional<bool>&&)>&&) override;
     61    void setIsLoopingAnimation(bool, CompletionHandler<void(bool success)>&&) override;
    6062    void hasAudio(CompletionHandler<void(std::optional<bool>&&)>&&) override;
    6163    void isMuted(CompletionHandler<void(std::optional<bool>&&)>&&) override;
  • trunk/Source/WebKit/WebProcess/Model/ARKitInlinePreviewModelPlayer.mm

    r286065 r286066  
    150150}
    151151
     152void ARKitInlinePreviewModelPlayer::isLoopingAnimation(CompletionHandler<void(std::optional<bool>&&)>&& completionHandler)
     153{
     154    auto modelIdentifier = this->modelIdentifier();
     155    if (!modelIdentifier) {
     156        completionHandler(std::nullopt);
     157        return;
     158    }
     159
     160    RefPtr strongPage = m_page.get();
     161    if (!strongPage) {
     162        completionHandler(std::nullopt);
     163        return;
     164    }
     165
     166    CompletionHandler<void(Expected<bool, WebCore::ResourceError>)> remoteCompletionHandler = [completionHandler = WTFMove(completionHandler)] (Expected<bool, WebCore::ResourceError> result) mutable {
     167        if (!result) {
     168            completionHandler(std::nullopt);
     169            return;
     170        }
     171
     172        completionHandler(*result);
     173    };
     174
     175    strongPage->sendWithAsyncReply(Messages::WebPageProxy::ModelElementIsLoopingAnimation(*modelIdentifier), WTFMove(remoteCompletionHandler));
     176}
     177
     178void ARKitInlinePreviewModelPlayer::setIsLoopingAnimation(bool isLooping, CompletionHandler<void(bool success)>&& completionHandler)
     179{
     180    auto modelIdentifier = this->modelIdentifier();
     181    if (!modelIdentifier) {
     182        completionHandler(false);
     183        return;
     184    }
     185
     186    RefPtr strongPage = m_page.get();
     187    if (!strongPage) {
     188        completionHandler(false);
     189        return;
     190    }
     191
     192    CompletionHandler<void(bool)> remoteCompletionHandler = [completionHandler = WTFMove(completionHandler)] (bool success) mutable {
     193        completionHandler(success);
     194    };
     195
     196    strongPage->sendWithAsyncReply(Messages::WebPageProxy::ModelElementSetIsLoopingAnimation(*modelIdentifier, isLooping), WTFMove(remoteCompletionHandler));
     197}
     198
    152199void ARKitInlinePreviewModelPlayer::hasAudio(CompletionHandler<void(std::optional<bool>&&)>&& completionHandler)
    153200{
Note: See TracChangeset for help on using the changeset viewer.