Microsoft MakeCode

How to have custom images in blocks

I have some code here which I will turn into an extension soon:

namespace SpriteKind {
    export const Notification = SpriteKind.create()
}
//% color="#6FFFFA"
namespace Notification {
    /**
     * Display some text with an optional icon at the top of the screen. 
     * @param rawText: A string of text to display.
     * @param icon: A 8x8 image as the icon. If the dimensdimensions do not fit, no icon will be displayed.
     */
    //% block="Notify with text $rawText || with icon $icon"
    //% rawText.defl="Notification!"
    //% expandableArgumentMode="toggle"
    export function notify(rawText: string, icon?: Image) {
        // Replace newlines with spaces
        const text = console.inspect(rawText).split("\n").join(" ");
        let font = image.getFontForText(text);
        let padding = 4;
        let holdTime = 1000; // ms
        let textTime = ((text.length * font.charWidth) / 40) * 1000;
        let textOffset = 0;
        let imageWidth = 156;
        let textLength = Math.max(text.length * font.charWidth, 24 * font.charWidth);
        let imageHeight = font.charHeight + padding;
        let bubble = image.create(imageWidth, imageHeight)
        let hasIcon = false;
        if (icon && icon.width == 8 && icon.height == 8) {
            hasIcon = true;
        }
        let notification = sprites.create(img`
            .
        `, SpriteKind.Notification);
        notification.setFlag(SpriteFlag.Ghost, true);
        function clearBubble() {
            bubble.fill(1);
        }
        function printToBubble(str: string, x: number) {
            if (hasIcon) {
                bubble.print(str, x+10, 2, 15, font);;
            } else {
                bubble.print(str, x, 2, 15, font);
            }
        }
        function padBubble() {
            // Left padding
            if (hasIcon) {
                bubble.fillRect(0, 0, padding+10, imageHeight, 1);
                spriteutils.drawTransparentImage(icon, bubble, padding-1, 2)
            } else {
                bubble.fillRect(0, 0, padding, imageHeight, 1);
            }
            // Right side padding
            bubble.fillRect(imageWidth - padding, 0, padding, font.charHeight + padding, 1);
        }
        function roundBubbleEdges() {
            bubble.setPixel(0, 0, 0);
            bubble.setPixel(imageWidth - 1, 0, 0);
            bubble.setPixel(0, font.charHeight + padding - 1, 0);
            bubble.setPixel(imageWidth - 1, font.charHeight + padding - 1, 0);
        }
        clearBubble();
        printToBubble(text, padding);
        padBubble();
        roundBubbleEdges();
        notification.setImage(bubble);
        notification.left = 2;
        notification.bottom = -2;
        notification.z = 100000000000;
        while (notification.top < 2) {
            notification.top += 1;
            pause(50);
        }
        let startTime = game.runtime();
        let displaying = true;
        let totalLength = 0;
        while (game.runtime() - startTime < holdTime + textTime) {
            if (hasIcon) {
                totalLength = Math.abs(text.length * font.charWidth) + (padding * 2) + textOffset + 10;
            } else {
                totalLength = Math.abs(text.length * font.charWidth) + (padding * 2) + textOffset;
            }
            if (game.runtime() - startTime > holdTime && text.length > 24 && totalLength > imageWidth) {
                clearBubble();
                printToBubble(text, padding + textOffset);
                padBubble();
                roundBubbleEdges();
                textOffset -= 1;
                pause(25);
            } else {
                pause(100);
            }
        }
        notification.top = 2;
        while (notification.bottom > -2) {
            notification.bottom -= 1;
            pause(50);
        }
        notification.destroy();
    }
}

It works well, but the image argument defaults to the built-in image selector and I can’t drag an image block onto it. I also want to force an image size of 8x8. Is there any way to make the block like the second block and force an image size of 8x8?

image

Well, adding this:

    //% icon.shadow=screen_image_picker

changed it! How can I enforce 8x8, like in the tile creator?
image

  //% block="Notify with text $rawText || with icon $icon=screen_image_picker"

Change it to that for the drawing editor.

1 Like