playing an animation at a certain time from onUpdate

Hi,

I'm having trouble with using an animation on my Watch Face. Specifically, I've drawn a bunch of text and bitmaps through onUpdate, but at the start of a specific hour I would like the watch to only play a gif completely before showing everything else again. Based on the sample app example, as well as another I found, I had no issues with encoding and playing a gif on a real watch using the motion tool. However, the problem arises when I try to "transition" to an animation from a state where there are only bitmaps/text on the screen. As a simplified example, based on the sample app code I linked, this is what I'm doing:

// global vars

private var _aniDone = false;
var _aniInProg = false;

...

    function onUpdate(dc) {
    
    	View.onUpdate(dc);

    	hour = System.getClockTime().hour;
    	
    	//System.println(System.getClockTime().sec);
    	
    	// when the animation is done, kill it 
    	if (_aniDone == true && _aniInProg == true) // _aniInProg so we only run once
    	{
    		_aniDone = false;
    		System.println("Done");
    		_animationDelegate.handleOnHide(self);
    		WatchUi.requestUpdate();
    	}
    	
    	// play an animation at a particular time
    	if (hour == 0)
    	{
    		if (_aniInProg != true) // run once
    		{
				System.println("Animation starting");
	    		_animationDelegate.handleOnShow(self);
	        	_animationDelegate.play();
	        	WatchUi.requestUpdate();
	        	_aniInProg = true;
	        }
    	}

		// stuff drawn on screen
		dc.setColor(Graphics.COLOR_BLUE, Graphics.COLOR_TRANSPARENT);
		dc.drawText(100, 100, Graphics.FONT_NUMBER_MEDIUM, hour, Graphics.TEXT_JUSTIFY_CENTER);
        dc.clear();
    }

with_aniDone set to true in the WatchUi.ANIMATION_EVENT_COMPLETE event. The code works fine on the simulator (I set the time to 11:59:55 pm and just wait out a few seconds), but on a real watch, the watch face will not play the animation unless I leave and then reenter the view. I am unable to transition "directly" to the animation playback, even with the Ui.requestUpdate() call. I've tried changing the logic a bit (e.g., checking the hour and then putting everything inside that condition) but the results are the same.

How can I fix this? Is my approach correct? This seems like it should be a fairly simple thing to resolve, and I haven't found any previous threads on it.

I'm including the AnimationController and AnimationDelegate codes below for completeness.

using Toybox.WatchUi;

class DanceDanceAnimationController {
    private var _animation;
    private var _playing;

    function initialize() {
        _playing = false;
    }

    function handleOnShow(view) {
        if( view.getLayers() == null ) {
            // Initialize the Animation
            
            System.println("controller: initializing animation");
            
            _animation = new WatchUi.AnimationLayer(
                Rez.Drawables.dark_hour,
                {
                    :locX=>0,
                    :locY=>0,
                }
                );

            view.addLayer(_animation);
        }

    }

    function handleOnHide(view) {
    	System.println("controller: Clearing animation");
        view.clearLayers();
        _animation = null;
    }

    function play() {
        if(!_playing) {
        System.println("controller: animation playing");
            _animation.play({
                :delegate => new DanceDanceAnimationDelegate(self)
                });
            _playing = true;
        }
    }

    function stop() {
        if(_playing) {
        	System.println("controller: animation stopping");
            _animation.stop();
            _playing = false;
        }
    }

}

using Toybox.WatchUi;

// This class bridges communication between the app and the animation
// playback
class DanceDanceAnimationDelegate extends WatchUi.AnimationDelegate {
    var _controller;

	// Constructor
    function initialize(controller) {
        AnimationDelegate.initialize();
        _controller = controller;
    }

	// Animation event handler
    function onAnimationEvent(event, options) {
        switch(event) {
            case WatchUi.ANIMATION_EVENT_COMPLETE:
            	_aniDone = true;
            case WatchUi.ANIMATION_EVENT_CANCELED:
                _controller.stop();
                break;
        }
    }
}

Top Replies

All Replies

  • When you are testing in the sim, are you testing with low power checked?  When a WF is in low power (which will be most of the time) things are different.  onUpdate is only called once a minute, etc.

  • You're right. I see the same behavior in the simulator when that option is checked, even with the same Sys.println() calls I had in my log file. The overview of this page clarifies that. So much for making a small change and uploading it to the watch each time to test. :)

    ..so is there a way to manually turn on high-power mode, even if just for about 5-10 seconds, or "simulate" the high-power activation gesture via code? And if not, how else could I accomplish what I am trying to do?

  • ..so is there a way to manually turn on high-power mode, even if just for about 5-10 seconds, or "simulate" the high-power activation gesture via code? And if not, how else could I accomplish what I am trying to do?

    Nope, as it in code defeats the purpose of low power mode.  A gesture will drop out of low power for about 10 seconds.  If you notice the item in your first link, the animation is started in onExitSleep, which is when a WF drops out of low power mode.

    OnEnterSleep indicates it's back in low power.

  • Dang. Well that's the answer I was expecting, based on a few previous threads I recently looked at on the same topic. Seems a bit odd to provide a pretty powerful feature yet not trust developers to use them sparingly to minimize power consumption.

    I'll have to work around this somehow. Thanks for the info.

  • Understand that if only one WF misuses it and has a big battery impact, it gets reflected on all CIQ watch faces.  That's why a number of things are restricted in WFs.  The 30ms limit for onPartialUpdate(), the lack of access to Attention (tones/vibrate), timers can only be used when not in low power, etc.

    You could do what you want in a device/watch app, but doing so will also have a battery impact.

  • Maybe Garmin could put certain restrictions on whatever WFs gets uploaded to their app store. I'm creating a WF just for myself and this (and perhaps other as I learn more) restrictions seem somewhat unnecessary. But I also realize that I'm in the minority here and it's probably not worth their resources to handle these sort of issues.