Source: prepare/PrepareQueue.ts

import { TextureSource } from '../rendering/renderers/shared/texture/sources/TextureSource';
import { Texture } from '../rendering/renderers/shared/texture/Texture';
import { Container } from '../scene/container/Container';
import { Graphics } from '../scene/graphics/shared/Graphics';
import { GraphicsContext } from '../scene/graphics/shared/GraphicsContext';
import { Mesh } from '../scene/mesh/shared/Mesh';
import { Sprite } from '../scene/sprite/Sprite';
import { AnimatedSprite } from '../scene/sprite-animated/AnimatedSprite';
import { TilingSprite } from '../scene/sprite-tiling/TilingSprite';
import { Text } from '../scene/text/Text';
import { PrepareBase } from './PrepareBase';

import type { FillInstruction, TextureInstruction } from '../scene/graphics/shared/GraphicsContext';
import type { FrameObject } from '../scene/sprite-animated/AnimatedSprite';
import type { PrepareQueueItem, PrepareSourceItem } from './PrepareBase';

/**
 * Part of the prepare system. Responsible for uploading all the items to the GPU.
 * This class extends the base functionality and resolves given resource items ready for the queue.
 * @memberof rendering
 */
export abstract class PrepareQueue extends PrepareBase
{
    /**
     * Resolve the given resource type and return an item for the queue
     * @param source
     * @param queue
     */
    protected resolveQueueItem(source: PrepareSourceItem, queue: PrepareQueueItem[]): void
    {
        if (source instanceof Container)
        {
            this.resolveContainerQueueItem(source, queue);
        }
        else if (source instanceof TextureSource || source instanceof Texture)
        {
            queue.push(source.source);
        }
        else if (source instanceof GraphicsContext)
        {
            queue.push(source);
        }

        // could not resolve the resource type
        return null;
    }

    /**
     * Resolve the given container and return an item for the queue
     * @param container
     * @param queue
     */
    protected resolveContainerQueueItem(container: Container, queue: PrepareQueueItem[]): void
    {
        // Note: we are just concerned with the given view.
        // Children are handled by the recursive call of the base class

        if (container instanceof Sprite || container instanceof TilingSprite || container instanceof Mesh)
        {
            queue.push(container.texture.source);
        }
        else if (container instanceof Text)
        {
            queue.push(container);
        }
        else if (container instanceof Graphics)
        {
            queue.push(container.context);
        }
        else if (container instanceof AnimatedSprite)
        {
            container.textures.forEach((textureOrFrame) =>
            {
                if ((textureOrFrame as Texture).source)
                {
                    queue.push((textureOrFrame as Texture).source);
                }
                else
                {
                    queue.push((textureOrFrame as FrameObject).texture.source);
                }
            });
        }
    }

    /**
     * Resolve the given graphics context and return an item for the queue
     * @param graphicsContext
     */
    protected resolveGraphicsContextQueueItem(graphicsContext: GraphicsContext): PrepareQueueItem | null
    {
        this.renderer.graphicsContext.getContextRenderData(graphicsContext);

        const { instructions } = graphicsContext;

        for (const instruction of instructions)
        {
            if (instruction.action === 'texture')
            {
                const { image } = (instruction as TextureInstruction).data;

                return image.source;
            }
            else if (instruction.action === 'fill')
            {
                const { texture } = (instruction as FillInstruction).data.style;

                return texture.source;
            }
        }

        return null;
    }
}