AffineTransform symbol can not be found?

Hi all,

I am experiencing a run time error when calling `var transform = new Gfx.AffineTransform ()`.

I have gone through all the reference material for the `Toybox.Graphics.AffineTransform` at the link below. 
https://developer.garmin.com/connect-iq/api-docs/Toybox/Graphics/AffineTransform.html

For the life of me, I can't see what I am doing wrong.

Any ideas?

Here is the run time error.
```error
Error: Symbol Not Found Error
Details: Could not find symbol 'AffineTransform'
Stack:
- onUpdate() at X:\Projects\garmin\applications\Test1\source\PageTwo.mc:74 0x10000425

```


And for reference, here is the full class source file.
```mc
using Toybox.Application;

using Toybox.Timer;
using Toybox.WatchUi  as Ui;
using Toybox.Graphics as Gfx;
using Toybox.Lang     as Lang;
using Toybox.System   as Sys;


class PageTwo extends Ui.View
{
    var image;
    var angle = 0;
    var timer;

    // Constructor.

    function initialize ()
    {
        Ui.View.initialize ();

        // Load image resource.

        image = Ui.loadResource ( Rez.Drawables.ImageHela );

        // Initialise timer.

        timer = new Timer.Timer ();
        timer.start ( method ( :timerCallback ), 1000, true );        
    }

    // Called when the view is about to be displayed.

    function onShow ()
    {
        // Code to display the image.
    }

    // Timer callback to update rotation.

    function timerCallback () as Void
    {
        if ( Constant.CONSTANT_CONSOLE_ENABLED ) { System.println ( Constant.CONSTANT_CONSOLE_TIMER + "Angle update." ); }

        // Uopdate angle.

        angle += 1;

        // Request a redraw of the view.

        WatchUi.requestUpdate();
    }

    // Drawing the image on the screen.

    function onUpdate ( dc )
    {
        // Initialise geometry.

        var width       = dc.getWidth();
        var height      = dc.getHeight();
        var imageWidth  = image.getWidth();
        var imageHeight = image.getHeight();

        // Center image vertically and horizontaly.

        var x = ( width  - imageWidth  ) / 2;
        var y = ( height - imageHeight ) / 2;

        var xc = width / 2;
        var yc = height / 2;

        // Drawing the image.        

        var transform = new Gfx.AffineTransform ();
        transform.rotate ( angle );

        var parameters =
        {
            :bitmapX      => x,
            :bitmapY      => y,
            :bitmapWidth  => imageWidth,
            :bitmapHeight => imageHeight,
            //:tintColor    => null,
            //:filterMode   => null,
            :transform    => transform
        };

        dc.clear ();        
        dc.drawBitmap2 ( xc, yc, image, parameters );
    }

    // Handling the back button press to return to the main menu.

    function onKeyBack ()
    {
        // Switch back to the previous view (main menu).

        Ui.popView ( WatchUi.SLIDE_LEFT );

        // Indicates that the key event was handled.

        return true;
    }
}
```

 

  • What device are you trying to simulate?  This is not available on all devices. 

    What SDK are you using?

  • Hi Jim,

    Thanks for your response.

    • I am targeting a Descent G1 for this exercise. And I get the same error in the simulator and on the physical device. 
    • The SDK I'm using is Connect IQ 6.4.2.
    • And the Garmin Monkey C extension for VS code. 

    Interestingly, before I posted here, I asked ChatGPT, and while it was not able to fix the problem, it did also mention something about the AffineTransform not being available for all devices. I wrote it off as hallucination, because I didn't think that AffineTransform would be something specific to a particular device. 

    How do you check what devices a class or its methods are compatible with?

  • The Descent G1 only has CIQ 3.4

    DescentTm G1 / G1 Solar
    176 x 176 semi-octagon Transflective Liquid-Crystal (Single Color) 3.4.0

    And this call requires CIQ 4.2.0 or greater. It's not available on the Descent G1

    The API doc will say something like

    "Since API Level x.y.z"

    and you can see what devices have here:
    https://developer.garmin.com/connect-iq/compatible-devices/

  • I didn't think that AffineTransform would be something specific to a particular device. 

    I think AffineTransform requires a GPU, and only CIQ 4 devices have a GPU.

    Also, there are many old devices which are stuck on CIQ 1 or CIQ 2, and they won't be getting new features or bug fixes regardless of hardware requirements.

    How do you check what devices a class or its methods are compatible with?

    The API docs typically list the supported devices for a method, when applicable. Sometimes these lists have omissions (due to being out of date), but generally they're correct.

    Since AffineTransform doesn't have a supported devices list in the API docs, you'll have to go by the fact that it's available since CIQ API Level 4.2.0, as jim_m_58 mentioned.

    https://developer.garmin.com/connect-iq/api-docs/Toybox/Graphics/AffineTransform.html

  • Thanks ,

    Thanks for those insights.

    1. Then related to target CIQ level and target device. In terms of best practices, is the idea then to set the "Current SDK" in the CIQ SDK manager, to the level of the device you're targeting. CIQ 3.4 in my case for the Descent G1, rather than just using the latest CIQ release?
    2. I also notices that the CIQ SDK Manager doesn't actually have CIQ 3.4 in the list to select. Is the idea here, to maybe choose the highest available CIQ level at or under the documented CIQ level. So in the case where the documentation says CIQ 3.4, but the highest available CIQ level in the CIQ DSK Manager below 4.0, is CIQ 3.2.5. Then one chooses CIQ 3.2

  • The current production SDK (6.4.2) can be used.  You do not want to use a 3.x SDK.

  • No, as jim_m_58 implied, the latest non-beta CIQ SDK can always be used to build apps for all existing devices, even devices which have an "old" CIQ API level. Sometimes new devices will be released which require a newer SDK (which will be released at the same time.)

    There isn't much reason to use an old SDK, except maybe:

    - if the latest SDK is known to have a bug or performance/resource usage problems

    - if you're fixing a bug in an old app with that only supports old devices, and you want to change as little as possible from the previously released version

    - you want to recreate some issue that's happening with an app that was built with an older SDK and you want to change as little as possible