{
  "version": 3,
  "sources": ["../src/core/utils.js", "../src/core/commands.js", "../src/core/screen-manager.js", "../src/renderer/renderer.js", "../src/renderer/shaders/display.vert", "../src/renderer/shaders/display.frag", "../src/renderer/shaders.js", "../src/api/blends.js", "../src/renderer/shaders/point.vert", "../src/renderer/shaders/point.frag", "../src/renderer/shaders/image.vert", "../src/renderer/shaders/image.frag", "../src/renderer/shaders/geometry.vert", "../src/renderer/batches.js", "../src/renderer/draw/batch-helpers.js", "../src/renderer/draw/geometry.js", "../src/renderer/textures.js", "../src/renderer/readback.js", "../src/renderer/draw/sprites.js", "../src/renderer/draw/primitives.js", "../src/renderer/draw/arcs.js", "../src/renderer/draw/bezier.js", "../src/renderer/draw/lines.js", "../src/renderer/draw/rects.js", "../src/renderer/draw/circles.js", "../src/renderer/draw/ellipses.js", "../src/renderer/effects.js", "../src/api/graphics.js", "../src/api/colors.js", "../src/api/images.js", "../src/api/view.js", "../src/text/print.js", "../src/core/plugins.js", "../src/api/pixels.js", "../src/api/paint.js", "../src/api/draw.js", "../src/api/postfx.js", "../src/text/fonts.js", "../src/text/fonts/font-6x6.webp", "../src/text/fonts/font-6x8.js", "../src/text/fonts/font-8x8.webp", "../src/text/fonts/font-8x14.webp", "../src/text/fonts/font-8x16.webp", "../src/index.js", "../plugins/gamepad/index.js", "../plugins/keyboard/input.js", "../plugins/keyboard/index.js", "../plugins/sound/sound.js", "../plugins/sound/play.js", "../plugins/sound/index.js", "../plugins/pointer/shared-events.js", "../plugins/pointer/touch.js", "../plugins/pointer/press.js", "../plugins/pointer/mouse.js", "../plugins/pointer/index.js", "../src/index-full.js"],
  "sourceRoot": "../src/",
  "sourcesContent": ["/**\r\n * Pi.js - Utilities Module\r\n * \r\n * Common utility functions for math, colors, types, and data manipulation.\r\n * \r\n * @module core/utils\r\n */\r\n\r\n\"use strict\";\r\n\r\n\r\n/***************************************************************************************************\r\n * General Utility Functions\r\n **************************************************************************************************/\r\n\r\n\r\nexport const errFn = ( commandName ) => {\r\n\tconst error = new Error(\r\n\t\t`${commandName}: No screens available for command. You must first create a ` +\r\n\t\t`screen with $.screen command.`\r\n\t);\r\n\terror.code = \"NO_SCREEN\";\r\n\tthrow error;\r\n};\r\n\r\n/**\r\n * Parse options - normalizes input arguments into an object with named parameters.\r\n *\r\n * @param {Array<any>} args - Arguments passed to the command (from rest parameters like `...args`).\r\n * @param {Array<string>} parameterNames - Array of parameter names in expected order.\r\n * @returns {Object<string, any>} \tAn object where keys are `parameterNames` and values are the \r\n * \t\t\t\t\t\t\t\t\tparsed arguments. Missing values will be `null`.\r\n */\r\nexport function parseOptions( args, parameterNames ) {\r\n\tconst resultOptions = {};\r\n\r\n\t// Initialize all named parameters to null\r\n\tfor( const name of parameterNames ) {\r\n\t\tresultOptions[ name ] = null;\r\n\t}\r\n\r\n\tlet isNamedParameterFound = false;\r\n\r\n\t// Case 1: First argument is an object literal\r\n\tif( args.length > 0 && isObjectLiteral( args[ 0 ] ) ) {\r\n\t\tconst inputOptions = args[ 0 ];\r\n\r\n\t\tfor( const name of parameterNames ) {\r\n\t\t\tif( name in inputOptions ) {\r\n\t\t\t\tisNamedParameterFound = true;\r\n\t\t\t\tresultOptions[ name ] = inputOptions[ name ];\r\n\t\t\t}\r\n\t\t}\r\n\t} \r\n\t\r\n\t// If no named parameters found then treat as positional array\r\n\tif( !isNamedParameterFound ) {\r\n\r\n\t\t// Case 2: Arguments are passed positionally\r\n\t\t// Map the positional arguments to the named parameters\r\n\t\t// If args[ i ] is out of bounds, it remains null from initialization\r\n\t\tfor( let i = 0; i < parameterNames.length; i++ ) {\r\n\t\t\tif( i < args.length ) {\r\n\t\t\t\tresultOptions[ parameterNames[ i ] ] = args[ i ];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn resultOptions;\r\n}\r\n\r\n// Type checking utilities\r\nexport const isFunction = ( fn ) => typeof fn === \"function\";\r\nexport const isDomElement = ( el ) => el instanceof Element;\r\nexport const isObjectLiteral = ( obj ) => {\r\n\tif( typeof obj !== \"object\" || obj === null || Array.isArray( obj ) ) {\r\n\t\treturn false;\r\n\t}\r\n\tconst proto = Object.getPrototypeOf( obj );\r\n\treturn proto === null || proto === Object.prototype;\r\n};\r\n\r\n// Data conversion utilities\r\n\r\n/**\r\n * Convert hex string to 2D data array\r\n * \r\n * @param {string} hex - Hex string\r\n * @param {number} width - Width of data\r\n * @param {number} height - Height of data\r\n * @returns {Array<Array<number>>} 2D array of binary data\r\n */\r\nexport function hexToData( hex, width, height ) {\r\n\thex = hex.toUpperCase();\r\n\tconst data = [];\r\n\tlet i = 0;\r\n\tlet digits = \"\";\r\n\tlet digitIndex = 0;\r\n\r\n\tfor( let y = 0; y < height; y++ ) {\r\n\t\tdata.push( [] );\r\n\t\tfor( let x = 0; x < width; x++ ) {\r\n\t\t\tif( digitIndex >= digits.length ) {\r\n\t\t\t\tlet hexPart = parseInt( hex[ i ], 16 );\r\n\t\t\t\tif( isNaN( hexPart ) ) {\r\n\t\t\t\t\thexPart = 0;\r\n\t\t\t\t}\r\n\t\t\t\tdigits = padL( hexPart.toString( 2 ), 4, \"0\" );\r\n\t\t\t\ti += 1;\r\n\t\t\t\tdigitIndex = 0;\r\n\t\t\t}\r\n\t\t\tdata[ y ].push( parseInt( digits[ digitIndex ] ) );\r\n\t\t\tdigitIndex += 1;\r\n\t\t}\r\n\t}\r\n\treturn data;\r\n}\r\n\r\n// Math utilities\r\n\r\n/**\r\n * Clamp a number between min and max\r\n * \r\n * @param {number} num - Number to clamp\r\n * @param {number} min - Minimum value\r\n * @param {number} max - Maximum value\r\n * @returns {number} Clamped value\r\n */\r\nexport function clamp( num, min, max ) {\r\n\treturn Math.min( Math.max( num, min ), max );\r\n}\r\n\r\n/**\r\n * Check if a point is in a rectangle\r\n * \r\n * @param {Object} point - Point with x, y properties\r\n * @param {Object} hitBox - Rectangle with x, y, width, height properties\r\n * @returns {boolean} True if point is inside rectangle\r\n */\r\nexport function inRange( point, hitBox ) {\r\n\treturn point.x >= hitBox.x && point.x < hitBox.x + hitBox.width &&\r\n\t\tpoint.y >= hitBox.y && point.y < hitBox.y + hitBox.height;\r\n}\r\n\r\n/**\r\n * Check if coordinates are in a rectangle\r\n * \r\n * @param {number} x1 - Point x\r\n * @param {number} y1 - Point y\r\n * @param {number} x2 - Rectangle x\r\n * @param {number} y2 - Rectangle y\r\n * @param {number} width - Rectangle width\r\n * @param {number} height - Rectangle height\r\n * @returns {boolean} True if point is inside rectangle\r\n */\r\nexport function inRange2( x1, y1, x2, y2, width, height ) {\r\n\treturn x1 >= x2 && x1 < x2 + width &&\r\n\t\ty1 >= y2 && y1 < y2 + height;\r\n}\r\n\r\n/**\r\n * Generate random number in range\r\n * \r\n * @param {number} min - Minimum value\r\n * @param {number} max - Maximum value\r\n * @returns {number} Random number between min and max\r\n */\r\nexport function rndRange( min, max ) {\r\n\treturn Math.random() * ( max - min ) + min;\r\n}\r\n\r\n/**\r\n * Convert degrees to radians\r\n * \r\n * @param {number} deg - Degrees\r\n * @returns {number} Radians\r\n */\r\nexport function degreesToRadian( deg ) {\r\n\treturn deg * ( Math.PI / 180 );\r\n}\r\n\r\n/**\r\n * Convert radians to degrees\r\n * \r\n * @param {number} rad - Radians\r\n * @returns {number} Degrees\r\n */\r\nexport function radiansToDegrees( rad ) {\r\n\treturn rad * ( 180 / Math.PI );\r\n}\r\n\r\n// String utilities\r\n\r\n/**\r\n * Pad string on left\r\n * \r\n * @param {string} str - String to pad\r\n * @param {number} len - Target length\r\n * @param {string} c - Padding character\r\n * @returns {string} Padded string\r\n */\r\nexport function padL( str, len, c ) {\r\n\tif( typeof c !== \"string\" ) {\r\n\t\tc = \" \";\r\n\t}\r\n\tlet pad = \"\";\r\n\tstr = str + \"\";\r\n\tfor( let i = str.length; i < len; i++ ) {\r\n\t\tpad += c;\r\n\t}\r\n\treturn pad + str;\r\n}\r\n\r\n/**\r\n * Pad string on both sides\r\n * \r\n * @param {string} str - String to pad\r\n * @param {number} len - Target length\r\n * @param {string} c - Padding character\r\n * @returns {string} Padded string\r\n */\r\nexport function pad( str, len, c ) {\r\n\tif( typeof c !== \"string\" || c.length === 0 ) {\r\n\t\tc = \" \";\r\n\t}\r\n\tstr = str + \"\";\r\n\twhile( str.length < len ) {\r\n\t\tstr = c + str + c;\r\n\t}\r\n\tif( str.length > len ) {\r\n\t\tstr = str.substring( 0, len );\r\n\t}\r\n\treturn str;\r\n}\r\n\r\n/**\r\n * Parse integer with default value\r\n * \r\n * @param {*} val - Value to parse\r\n * @param {number} def - Default value if parsing fails\r\n * @returns {number} Parsed integer or default\r\n */\r\nexport function getInt( val, def ) {\r\n\tif( val === null || val === undefined ) {\r\n\t\treturn def;\r\n\t}\r\n\tconst parsed = Number( val );\r\n\tif( !Number.isFinite( parsed ) ) {\r\n\t\treturn def;\r\n\t}\r\n\r\n\treturn Math.round( parsed );\r\n}\r\n\r\n/**\r\n * Parse float with default value\r\n * \r\n * @param {*} val - Value to parse\r\n * @param {number} def - Default value if parsing fails\r\n * @returns {number} Parsed float or default\r\n */\r\nexport function getFloat( val, def ) {\r\n\tif( val === null || val === undefined ) {\r\n\t\treturn def;\r\n\t}\r\n\tconst parsed = Number( val );\r\n\tif( !Number.isFinite( parsed ) ) {\r\n\t\treturn def;\r\n\t}\r\n\r\n\treturn parsed;\r\n}\r\n\r\n// Queue microtask (built-in in modern browsers)\r\n// Wrap to preserve window context\r\nexport const queueMicrotask = ( callback ) => {\r\n\tif( window.queueMicrotask ) {\r\n\t\twindow.queueMicrotask( callback );\r\n\t} else {\r\n\t\tsetTimeout( callback, 0 );\r\n\t}\r\n};\r\n\r\n\r\n/***************************************************************************************************\r\n * Color Utility Functions\r\n **************************************************************************************************/\r\n\r\n\r\nconst m_colorCheckerContext = document.createElement( \"canvas\" ).getContext(\r\n\t\"2d\", { \"willReadFrequently\": true }\r\n);\r\nconst COLOR_PROTO = {\r\n\t\"key\": 0,\r\n\t\"r\": 0,\r\n\t\"g\": 0,\r\n\t\"b\": 0,\r\n\t\"a\": 0,\r\n\t\"array\": null\r\n};\r\n\r\n/**\r\n * Creates a color object based on a Uint8Array\r\n *\r\n * @param {Uint8Array} colorArray - Contains [ r, g, b, a ]\r\n * @returns {number} A 32-bit integer representing the color.\r\n */\r\nexport function createColor( colorArray ) {\r\n\tconst color = Object.create( COLOR_PROTO );\r\n\tcolor.array = colorArray;\r\n\tcolor.r = colorArray[ 0 ];\r\n\tcolor.g = colorArray[ 1 ];\r\n\tcolor.b = colorArray[ 2 ];\r\n\tcolor.a = colorArray[ 3 ];\r\n\tcolor.key = ( colorArray[ 0 ] << 24 ) |\r\n\t\t( colorArray[ 1 ] << 16 ) |\r\n\t\t( colorArray[ 2 ] << 8 ) |\r\n\t\tcolorArray[ 3 ];\r\n\treturn color;\r\n}\r\n\r\n/**\r\n * Generates a unique 32-bit integer key for an opaque RGB color.\r\n * Each color component (R, G, B) is assumed to be an 8-bit integer (0-255).\r\n * The components are packed in the order: Red | Green | Blue.\r\n *\r\n * @param {number} r - Red component (0-255)\r\n * @param {number} g - Green component (0-255)\r\n * @param {number} b - Blue component (0-255)\r\n * @param {number} a - Alpha component (0-255)\r\n * @returns {number} A 32-bit integer representing the color.\r\n */\r\nexport function generateColorKey( r, g, b, a ) {\r\n\treturn ( r << 24 ) | ( g << 16 ) | ( b << 8 ) | a;\r\n}\r\n\r\n/**\r\n * Convert RGB to color object\r\n * \r\n * @param {number} r - Red component (0-255)\r\n * @param {number} g - Green component (0-255)\r\n * @param {number} b - Blue component (0-255)\r\n * @param {number} a - Alpha component (0-255)\r\n * @returns {Object} Color object\r\n */\r\nexport function rgbToColor( r, g, b, a ) {\r\n\tconst colorArray = new Uint8Array( 4 );\r\n\tcolorArray.set( [ r, g, b, a ] );\r\n\treturn createColor( colorArray );\r\n}\r\n\r\n/**\r\n * Convert various color formats to color object\r\n * \r\n * @param {*} color - Color in various formats\r\n * @returns {Object|null} Color object or null if invalid\r\n */\r\nexport function convertToColor( color ) {\r\n\tif( color === undefined || color === null || color === \"\" ) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\t// Check if color is already a color prototype object\r\n\tif( Object.getPrototypeOf( color ) === COLOR_PROTO ) {\r\n\t\treturn color;\r\n\t} else if( Array.isArray( color ) ) {\r\n\r\n\t\t// Array must at least have red green and blue\r\n\t\tif( color.length < 3 ) {\r\n\t\t\treturn null;\r\n\t\t} else if( color.length === 3 ) {\r\n\t\t\tcolor.push( 255 );\r\n\t\t}\r\n\t} else if( typeof color === \"string\" ) {\r\n\r\n\t\t// Check if is hex format\r\n\t\tconst checkHexColor = /(^#[0-9A-F]{8}$)|(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i;\r\n\t\tif( checkHexColor.test( color ) ) {\r\n\t\t\treturn hexToColor( color );\r\n\t\t}\r\n\r\n\t\t// RGB/RGBA format\r\n\t\tif( color.indexOf( \"rgb\" ) === 0 ) {\r\n\t\t\tcolor = splitRgb( color );\r\n\t\t\tif( color.length < 3 ) {\r\n\t\t\t\treturn null;\r\n\t\t\t} else if( color.length === 3 ) {\r\n\t\t\t\tcolor.push( 255 );\r\n\t\t\t}\r\n\t\t} else {\r\n\r\n\t\t\t// Named color or other CSS color\r\n\t\t\treturn colorStringToColor( color );\r\n\t\t}\r\n\t} else if(\r\n\t\tcolor.r !== undefined &&\r\n\t\tcolor.g !== undefined &&\r\n\t\tcolor.b !== undefined &&\r\n\t\tcolor.a !== undefined\r\n\t) {\r\n\t\tcolor = [ color.r, color.g, color.b, color.a ];\r\n\t}\r\n\t\r\n\t// Parse rgb colors\r\n\tfor( let i = 0; i < 3; i += 1 ) {\r\n\t\tcolor[ i ] = getInt( color[ i ], 0 );\r\n\t}\r\n\r\n\t// Parse alpha\r\n\tcolor[ 3 ] = getFloat( color[ 3 ], 0 );\r\n\tif( color[ 3 ] <= 1 ) {\r\n\t\tcolor[ 3 ] = Math.round( color[ 3 ] * 255 );\r\n\t} else {\r\n\t\tcolor[ 3 ] = Math.round( color[ 3 ] );\r\n\t}\r\n\t\r\n\treturn rgbToColor( color[ 0 ], color[ 1 ], color[ 2 ], color[ 3 ] );\r\n}\r\n\r\nexport function calcColorDifference( c1, c2, w = [ 0.2, 0.68, 0.07, 0.05 ] ) {\r\n\tconst dr = c1.array[ 0 ] - c2.array[ 0 ];\r\n\tconst dg = c1.array[ 1 ] - c2.array[ 1 ];\r\n\tconst db = c1.array[ 2 ] - c2.array[ 2 ];\r\n\tconst da = c1.array[ 3 ] - c2.array[ 3 ];\r\n\r\n\treturn ( dr * dr * w[ 0 ] + dg * dg * w[ 1 ] + db * db * w[ 2 ] + da * da * w[ 3 ] );\r\n}\r\n\r\nexport function copyColor( colorSrc, colorDest ) {\r\n\tcolorDest.key = colorSrc.key;\r\n\tcolorDest.array[ 0 ] = colorSrc.array[ 0 ];\r\n\tcolorDest.array[ 1 ] = colorSrc.array[ 1 ];\r\n\tcolorDest.array[ 2 ] = colorSrc.array[ 2 ];\r\n\tcolorDest.array[ 3 ] = colorSrc.array[ 3 ];\r\n}\r\n\r\n/**\r\n * Convert hex color to color object\r\n * \r\n * @param {string} hex - Hex color string (#RGB, #RRGGBB, or #RRGGBBAA)\r\n * @returns {Object} Color object with r, g, b, a, s, s2 properties\r\n */\r\nfunction hexToColor( hex ) {\r\n\tlet r, g, b, a;\r\n\r\n\tif( hex.length === 4 ) {\r\n\t\tr = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 );\r\n\t\tg = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 );\r\n\t\tb = parseInt( hex.charAt( 3 ) + hex.charAt( 3 ), 16 );\r\n\t} else {\r\n\t\tr = parseInt( hex.substring( 1, 3 ), 16 );\r\n\t\tg = parseInt( hex.substring( 3, 5 ), 16 );\r\n\t\tb = parseInt( hex.substring( 5, 7 ), 16 );\r\n\t}\r\n\r\n\tif( hex.length === 9 ) {\r\n\t\ta = parseInt( hex.substring( 7, 9 ), 16 );\r\n\t} else {\r\n\t\ta = 255;\r\n\t}\r\n\r\n\treturn rgbToColor( r, g, b, a );\r\n}\r\n\r\n/**\r\n * Convert color component to hex\r\n * \r\n * @param {number} c - Color component (0-255)\r\n * @returns {string} Hex string\r\n */\r\nfunction cToHex( c ) {\r\n\tif( !Number.isInteger( c ) ) {\r\n\t\tc = Math.round( c );\r\n\t}\r\n\tc = clamp( c, 0, 255 );\r\n\tconst hex = Number( c ).toString( 16 );\r\n\treturn hex.length < 2 ? \"0\" + hex : hex.toUpperCase();\r\n}\r\n\r\n/**\r\n * Convert Color Object to hex string\r\n * \r\n * @param {Object} r - Red component (0-255)\r\n * @returns {string} Hex color string\r\n */\r\nexport function colorToHex( color ) {\r\n\treturn \"#\" + cToHex( color.r ) + cToHex( color.g ) + cToHex( color.b ) + cToHex( color.a );\r\n}\r\n\r\n/**\r\n * Split RGB/RGBA string into components\r\n * \r\n * @param {string} s - RGB or RGBA string\r\n * @returns {Array<number>} Array of color components\r\n */\r\nfunction splitRgb( s ) {\r\n\ts = s.slice( s.indexOf( \"(\" ) + 1, s.indexOf( \")\" ) );\r\n\tconst parts = s.split( \",\" );\r\n\tconst colors = [];\r\n\tfor( let i = 0; i < parts.length; i++ ) {\r\n\t\tlet val;\r\n\t\tif( i === 3 ) {\r\n\t\t\tval = parseFloat( parts[ i ].trim() );\r\n\t\t\tif( val <= 1 ) {\r\n\t\t\t\tval *= 255;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tval = parseInt( parts[ i ].trim() );\r\n\t\t}\r\n\t\tcolors.push( val );\r\n\t}\r\n\treturn colors;\r\n}\r\n\r\n/**\r\n * Convert color string to color object using canvas\r\n * \r\n * @param {string} colorStr - CSS color string\r\n * @returns {Object} Color object\r\n */\r\nfunction colorStringToColor( colorStr ) {\r\n\tm_colorCheckerContext.clearRect( 0, 0, 1, 1 );\r\n\tm_colorCheckerContext.fillStyle = colorStr;\r\n\tm_colorCheckerContext.fillRect( 0, 0, 1, 1 );\r\n\tconst data = m_colorCheckerContext.getImageData( 0, 0, 1, 1 ).data;\r\n\treturn rgbToColor( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ] );\r\n}\r\n", "/**\r\n * Pi.js - Command System Module\r\n * \r\n * Command registration and processing for Pi.js.\r\n * Handles ready command and set command.\r\n * \r\n * @module core/commands\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_utils from \"./utils.js\";\r\nimport * as g_screenManager from \"./screen-manager.js\";\r\n\r\nconst m_settings = {};\r\nconst m_commands = [];\r\nlet m_api = null;\r\nlet m_readyCallbacks = [];\r\nlet m_isDocumentReady = false;\r\nlet m_waitCount = 0;\r\nlet m_checkReadyTimeout = null;\r\n\r\n\r\n/**************************************************************************************************\r\n * Module Commands\r\n **************************************************************************************************/\r\n\r\n\r\nexport function init( api ) {\r\n\tm_api = api;\r\n\r\n\t// Set up document ready detection\r\n\tif( typeof document !== \"undefined\" ) {\r\n\t\tif( document.readyState === \"loading\" ) {\r\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", onDocumentReady );\r\n\t\t} else {\r\n\r\n\t\t\t// Document already ready\r\n\t\t\tm_isDocumentReady = true;\r\n\t\t}\r\n\t} else {\r\n\r\n\t\t// Not in browser environment, mark as ready immediately\r\n\t\tm_isDocumentReady = true;\r\n\t}\r\n\r\n\tregisterCommands();\r\n\tg_screenManager.addScreenInitFunction( processScreenCommands );\r\n}\r\n\r\nfunction registerCommands() {\r\n\r\n\t// Register non screen commands\r\n\taddCommand( \"ready\", ready, false, [ \"callback\" ] );\r\n\taddCommand( \"set\", set, true, [ \"options\" ], true );\r\n}\r\n\r\n\r\n/**************************************************************************************************\r\n * Command processing\r\n **************************************************************************************************/\r\n\r\n\r\nexport function addCommand( name, fn, isScreen, parameterNames, isScreenOptional ) {\r\n\tm_commands.push( { name, fn, isScreen, parameterNames, isScreenOptional } );\r\n\t\r\n\t// Auto-register set commands as settings\r\n\tif( name.startsWith( \"set\" ) && name !== \"set\" ) {\r\n\t\tconst settingName = name.substring( 3, 4 ).toLowerCase() + name.substring( 4 );\r\n\t\tm_settings[ settingName ] = {\r\n\t\t\tfn, isScreen, \"parameterNames\": parameterNames, isProcessed: false\r\n\t\t};\r\n\t}\r\n}\r\n\r\nexport function processCommands( api ) {\r\n\tfor( const command of m_commands ) {\r\n\t\tif( !command.isProcessed ) {\r\n\t\t\tprocessCommand( api, command );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfunction processCommand( api, command ) {\r\n\tconst { name, fn, isScreen, parameterNames, isScreenOptional } = command;\r\n\tif( isScreen ) {\r\n\t\tapi[ name ] = ( ...args ) => {\r\n\t\t\tconst options = g_utils.parseOptions( args, parameterNames );\r\n\t\t\tconst screenData = g_screenManager.getActiveScreen( name, isScreenOptional );\r\n\t\t\treturn fn( screenData, options );\r\n\t\t};\r\n\t} else {\r\n\t\tapi[ name ] = ( ...args ) => {\r\n\t\t\tconst options = g_utils.parseOptions( args, parameterNames );\r\n\t\t\treturn fn( options );\r\n\t\t};\r\n\t}\r\n}\r\n\r\nfunction processScreenCommands( screenData ) {\r\n\tfor( const command of m_commands ) {\r\n\t\tconst { name, fn, isScreen, parameterNames } = command;\r\n\t\tif( isScreen ) {\r\n\t\t\tscreenData.api[ name ] = ( ...args ) => {\r\n\t\t\t\tconst options = g_utils.parseOptions( args, parameterNames );\r\n\t\t\t\treturn fn( screenData, options );\r\n\t\t\t};\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/**************************************************************************************************\r\n * Resource Loader - Ready Command\r\n **************************************************************************************************/\r\n\r\n/**\r\n * ready command - waits for document ready and all pending resources\r\n * \r\n * Supports both callback and promise patterns:\r\n *   - $.ready( callback )        // Callback style\r\n *   - await $.ready()            // Promise style\r\n *   - $.ready().then( ... )      // Promise .then() style\r\n */\r\nfunction ready( options ) {\r\n\r\n\tconst callback = options.callback;\r\n\t\r\n\t// Validate callback if provided\r\n\tif( callback != null && !g_utils.isFunction( callback ) ) {\r\n\t\tconst error = new TypeError( \"ready: Parameter callback must be a function.\" );\r\n\t\terror.code = \"INVALID_CALLBACK\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Never execute immediately - always defer to next tick\r\n\treturn new Promise( ( resolve ) => {\r\n\t\tm_readyCallbacks.push( {\r\n\t\t\t\"callback\": callback,\r\n\t\t\t\"resolve\": resolve,\r\n\t\t\t\"triggered\": false\r\n\t\t} );\r\n\r\n\t\t// Schedule a check for next tick (allows more resources to be added in same thread)\r\n\t\tscheduleReadyCheck();\r\n\t} );\r\n}\r\n\r\nexport function wait() {\r\n\tm_waitCount++;\r\n}\r\n\r\nexport function done() {\r\n\tm_waitCount--;\r\n\tif( m_waitCount < 0 ) {\r\n\t\tm_waitCount = 0;\r\n\t}\r\n\r\n\t// Check if ready to trigger callbacks\r\n\tscheduleReadyCheck();\r\n}\r\n\r\nfunction onDocumentReady() {\r\n\tm_isDocumentReady = true;\r\n\tscheduleReadyCheck();\r\n}\r\n\r\nfunction scheduleReadyCheck() {\r\n\r\n\t// Clear any existing timeout\r\n\tif( m_checkReadyTimeout !== null ) {\r\n\t\tclearTimeout( m_checkReadyTimeout );\r\n\t}\r\n\r\n\t// Schedule check for next tick\r\n\tm_checkReadyTimeout = setTimeout( checkReady, 0 );\r\n}\r\n\r\nfunction checkReady() {\r\n\r\n\t// TODO-LATER: [Violation] 'setTimeout' handler took 381ms\r\n\t// Long running tasks in callback should be handled - maybe we should track callback times?\r\n\r\n\tm_checkReadyTimeout = null;\r\n\r\n\t// Don't check if document not ready\r\n\tif( !m_isDocumentReady ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Don't trigger if resources are still loading\r\n\tif( m_waitCount !== 0 ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Trigger all pending ready callbacks together\r\n\tconst callbacks = m_readyCallbacks.slice();\r\n\tm_readyCallbacks = [];\r\n\r\n\tfor( const item of callbacks ) {\r\n\r\n\t\t// Skip if already triggered\r\n\t\tif( item.triggered ) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// Mark as triggered\r\n\t\titem.triggered = true;\r\n\r\n\t\t// Execute callback and resolve promise\r\n\t\tif( item.callback ) {\r\n\t\t\titem.callback();\r\n\t\t}\r\n\t\titem.resolve();\r\n\t}\r\n}\r\n\r\n\r\n/**************************************************************************************************\r\n * Settings and set command\r\n **************************************************************************************************/\r\n\r\n/**\r\n * Global settings command\r\n * \r\n * This can get called from either the global api or directly from a screenData.api.\r\n * screenData can be null if no screen is available\r\n */\r\nexport function set( screenData, options ) {\r\n\r\n\t// Unpack options\r\n\toptions = options.options;\r\n\r\n\t// Loop through all the options\r\n\tfor( const optionName in options ) {\r\n\r\n\t\t// Skip blanks\r\n\t\tif( options[ optionName ] === null ) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// If the option is a valid setting\r\n\t\tif( m_settings[ optionName ] ) {\r\n\r\n\t\t\t// Get the setting data\r\n\t\t\tconst setting = m_settings[ optionName ];\r\n\t\t\tconst optionValues = options[ optionName ];\r\n\r\n\t\t\t// Parse the options from the setting\r\n\t\t\tconst argsArray = [ optionValues ];\r\n\t\t\tconst parsedOptions = g_utils.parseOptions( argsArray, setting.parameterNames );\r\n\r\n\t\t\t// Call the setting function\r\n\t\t\tif( setting.isScreen ) {\r\n\t\t\t\tsetting.fn( screenData, parsedOptions );\r\n\t\t\t} else {\r\n\t\t\t\tsetting.fn( parsedOptions );\r\n\t\t\t}\r\n\r\n\t\t\t// If we just set the screen then update the screenData to the new active screen\r\n\t\t\tif( optionName === \"screen\" ) {\r\n\t\t\t\tscreenData = g_screenManager.getActiveScreen();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nexport function addSetting( name, fn, isScreen ) {\r\n\tm_settings[ name ] = { fn, isScreen };\r\n}\r\n\r\n", "/**\r\n * Pi.js - Screen Manager Core Module\r\n * \r\n * Screen creation and management for Pi.js.\r\n * Creates canvas elements, manages multiple screens, handles aspect ratios.\r\n * WebGL2 only - no Canvas2D fallback.\r\n * \r\n * @module core/screen-manager\r\n */\r\n\r\n/**\r\n * IDEA:\r\n * \r\n * Simplify \"m\" multiple mode to use this formula:\r\n * scaleX = floor(canvas.width / FBO_WIDTH)\r\n * scaleY = floor(canvas.height / FBO_HEIGHT)\r\n * finalScale = min(scaleX, scaleY)\r\n *  \r\n * Even when I use \"m\" mode I still see artifacts, maybe handle the upscaling manually by setting\r\n * the canvas.width and canvas.height to match the CSS width and height and then when I copy the\r\n * FBO to the canvas it will apply gl.NEAREST when display to canvas is run, this is already \r\n * implemented I just need to set canvas.width and canvas.height to match.\r\n * \r\n * I did a test 640m480 and even it still has pixels that are uneven in size some pixels are 2x2,\r\n * other pixels are 1x2. Even with a css resolution of 1280x960 still resulted in uneven pixel\r\n * sizes.\r\n * \r\n * My main reason for letting CSS handle upscaling was I liked being able to copy and paste the\r\n * image and get the image with target resolution. But a work-around could be adding a copy\r\n * image that command that copies the canvas to clipboard.\r\n * \r\n * IDEA:\r\n * \r\n * Add a hardPalette flag to the screen command. When set it adds a hard requirement on palette\r\n * colors. This means that only colors from the palette can be used.\r\n * \r\n * Need to find an optimal solution to enforce the hardPalette flag and to update FBO when palette\r\n * changes. I can try adding a 1D array or texture with color lookups and try to do it in the\r\n * shader. If I have to I can do a CPU filter on the colors when palette changes, but this is not\r\n * optimal. I can also enforce the colors in the color lookups but that would require more\r\n * complex code in multiple places.  Need to really think about a good strategy for this.\r\n */\r\n\"use strict\";\r\n\r\nimport * as g_utils from \"./utils.js\";\r\nimport * as g_commands from \"./commands.js\";\r\nimport * as g_renderer from \"../renderer/renderer.js\";\r\nimport * as g_graphics from \"../api/graphics.js\";\r\nimport * as g_view from \"../api/view.js\";\r\n\r\nconst SCREEN_API_PROTO = { \"screen\": true, \"id\": 0 };\r\nconst m_screens = {};\r\nconst m_screenCanvasMap = new Map();\r\nconst m_screenDataItems = {};\r\nconst m_screenDataItemGetters = [];\nconst m_screenDataInitFunctions = [];\nconst m_screenDataPreCleanupFunctions = [];\nconst m_screenDataCleanupFunctions = [];\nconst MAX_CANVAS_DIMENSION = 8192;\r\nconst m_observedContainers = new Set();\r\n\r\nlet m_nextScreenId = 0;\r\nlet m_activeScreenData = null;\r\nlet m_resizeObserver = null;\r\nlet m_offscreenCanvas = null;\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Commands\r\n ***************************************************************************************************/\r\n\r\n\r\nexport { m_activeScreenData as activeScreenData };\r\nexport { m_screenCanvasMap as screenCanvasMap };\r\n\r\n/**\r\n * Initialize screen management.\r\n *\r\n * Creates the shared ResizeObserver, registers screen commands, and attaches\r\n * removeScreen on the global API and each new screen.\r\n *\r\n * @param {Object} api - Global Pi.js API object\r\n * @returns {void}\r\n */\r\nexport function init( api ) {\r\n\r\n\t// TODO-LATER: Add matchMedia to watch for DPR changes\r\n\r\n\t// Create a single ResizeObserver for all screen containers\r\n\tm_resizeObserver = new ResizeObserver( ( entries ) => {\r\n\t\tfor( const entry of entries ) {\r\n\t\t\tconst container = entry.target;\r\n\t\t\t\r\n\t\t\t// Find all canvas elements in this container\r\n\t\t\tconst canvases = container.querySelectorAll( \"canvas[data-screen-id]\" );\r\n\t\t\tif( canvases.length === 0 ) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Resize all screens in this container\r\n\t\t\tfor( const canvas of canvases ) {\r\n\t\t\t\tconst screenId = parseInt( canvas.dataset.screenId, 10 );\r\n\t\t\t\tconst screenData = m_screens[ screenId ];\r\n\t\t\t\t\r\n\t\t\t\tif( screenData ) {\r\n\t\t\t\t\tresizeScreen( screenData, false );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t} );\r\n\r\n\tregisterCommands();\r\n\r\n\t// Special command removeScreen\r\n\tapi.removeScreen = ( screenId ) => {\r\n\t\tif( Object.getPrototypeOf( screenId ) === SCREEN_API_PROTO ) {\r\n\t\t\tscreenId = screenId.id;\r\n\t\t}\r\n\t\tif( m_screens[ screenId ] ) {\r\n\t\t\treturn removeScreen( m_screens[ screenId ] );\r\n\t\t}\r\n\t};\r\n\r\n\t// Add screenObj remove screen command\r\n\taddScreenInitFunction( ( screenData ) => {\r\n\t\tscreenData.api.removeScreen = () => removeScreen( screenData );\r\n\t} );\r\n}\r\n\r\nfunction registerCommands() {\r\n\r\n\t// Global commands\r\n\tg_commands.addCommand(\r\n\t\t\"screen\", screen, false,\r\n\t\t[ \"aspect\", \"container\", \"isOffscreen\", \"resizeCallback\", \"parent\" ]\r\n\t);\r\n\tg_commands.addCommand( \"setScreen\", setScreen, false, [ \"screen\" ] );\r\n\tg_commands.addCommand( \"getScreen\", getScreen, false, [ \"screenId\" ] );\r\n\tg_commands.addCommand( \"getAllScreens\", getAllScreens, false, [] );\r\n\tg_commands.addCommand( \"removeAllScreens\", removeAllScreens, false, [] );\r\n\r\n\t// Screen-scoped info commands\r\n\tg_commands.addCommand( \"width\", widthCmd, true, [] );\r\n\tg_commands.addCommand( \"height\", heightCmd, true, [] );\r\n\tg_commands.addCommand( \"canvas\", canvasCmd, true, [] );\r\n}\r\n\r\n/**\r\n * Register a value cloned onto every new screenData object.\r\n *\r\n * Used by renderer and API modules at init for per-screen state.\r\n *\r\n * @param {string} name - Property name on screenData\r\n * @param {*} val - Default value to clone onto each new screen\r\n * @returns {void}\r\n */\r\nexport function addScreenDataItem( name, val ) {\r\n\tm_screenDataItems[ name ] = val;\r\n}\r\n\r\n/**\r\n * Register a getter that supplies a per-screen default.\r\n *\r\n * fn() is called for each new screen and the result is cloned onto\r\n * screenData. Used for per-screen defaults such as palette.\r\n *\r\n * @param {string} name - Property name on screenData\r\n * @param {Function} fn - Getter that returns the default value\r\n * @returns {void}\r\n */\r\nexport function addScreenDataItemGetter( name, fn ) {\r\n\tm_screenDataItemGetters.push( { name, fn } );\r\n}\r\n\r\n/**\r\n * Register a function to run after a screen is created.\r\n *\r\n * @param {Function} fn - Function called with the new screenData\r\n * @returns {void}\r\n */\r\nexport function addScreenInitFunction( fn ) {\n\tm_screenDataInitFunctions.push( fn );\n}\n\n/**\n * Register a function to run before screen module resources are cleaned up.\n *\n * @param {Function} fn - Function called with the screenData being removed\n * @returns {void}\n */\nexport function addScreenPreCleanupFunction( fn ) {\n\tm_screenDataPreCleanupFunctions.push( fn );\n}\n\n/**\n * Register a function to run before a screen is removed.\n *\r\n * @param {Function} fn - Function called with the screenData being removed\r\n * @returns {void}\r\n */\r\nexport function addScreenCleanupFunction( fn ) {\r\n\tm_screenDataCleanupFunctions.push( fn );\r\n}\r\n\r\n/**\r\n * Get the active screen data object.\r\n *\r\n * Throws NO_ACTIVE_SCREEN unless isScreenOptional is true.\r\n *\r\n * @param {string} fnName - Calling command name for the error message\r\n * @param {boolean} [isScreenOptional] - Allow null when no screen is active\r\n * @returns {Object|null} Active screen data, or null if optional and none\r\n */\r\nexport function getActiveScreen( fnName, isScreenOptional ) {\r\n\tif( m_activeScreenData === null && !isScreenOptional ) {\r\n\t\tconst error = new Error(\r\n\t\t\tfnName + \": You are attempting to call a method that requires a screen but there \" +\r\n\t\t\t\"there is currently no active screen. Call $.screen() before calling any graphics \" +\r\n\t\t\t\"commands.\"\r\n\t\t);\r\n\t\terror.code = \"NO_ACTIVE_SCREEN\";\r\n\t\tthrow error;\r\n\t}\r\n\treturn m_activeScreenData;\r\n}\r\n\r\n/**\r\n * Get screen data by screen id.\r\n *\r\n * Throws INVALID_SCREEN_ID if the id is not found.\r\n *\r\n * @param {string} fnName - Calling command name for the error message\r\n * @param {number} screenId - Screen id to look up\r\n * @returns {Object} Screen data object\r\n */\r\nexport function getScreenData( fnName, screenId ) {\r\n\tif( !m_screens[ screenId ] ) {\r\n\t\tconst error = new Error( `${fnName}: Invalid screen id.` );\r\n\t\terror.code = \"INVALID_SCREEN_ID\";\r\n\t\tthrow error;\r\n\t}\r\n\treturn m_screens[ screenId ];\r\n}\r\n\r\n/**\r\n * Get all active screens\r\n * \r\n * @returns {Array<Object>} Array of all screen data objects\r\n */\r\nexport function getAllScreensData() {\r\n\tconst screens = [];\r\n\tfor( const id in m_screens ) {\r\n\t\tscreens.push( m_screens[ id ] );\r\n\t}\r\n\treturn screens;\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Screen Command\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Create a WebGL2 screen and set it as the active screen.\r\n *\r\n * Aspect format is width + splitter + height:\r\n * - x: exact pixel size (e.g. \"320x200\")\r\n * - e: extend to fill the container\r\n * - m: scale by integer multiples of the target size\r\n *\r\n * Offscreen screens require exact pixel dimensions (x).\r\n *\r\n * @param {Object} options - Screen options\r\n * @param {string} options.aspect - Aspect string (WxH, WeH, or WmH)\r\n * @param {string|HTMLElement} [options.container] - Container element or id\r\n * @param {boolean} [options.isOffscreen] - Create an offscreen screen\r\n * @param {Function} [options.resizeCallback] - Called on container resize\r\n * @param {Object} [options.parent] - Screen whose WebGL context an offscreen screen uses\r\n * @returns {Object} Screen API object with id and graphics commands\r\n */\r\nfunction screen( options ) {\r\n\r\n\t// Validate resize callback\r\n\tif( options.resizeCallback != null && !g_utils.isFunction( options.resizeCallback ) ) {\r\n\t\tconst error = new TypeError( \"screen: Parameter resizeCallback must be a function.\" );\r\n\t\terror.code = \"INVALID_CALLBACK\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tlet parentData = null;\r\n\tlet parentScreenId = null;\r\n\tlet parentRenderContext = null;\r\n\tif( options.parent != null ) {\r\n\t\tif( !options.isOffscreen ) {\r\n\t\t\tconst error = new TypeError(\r\n\t\t\t\t\"screen: Parameter parent can only be used with an offscreen screen.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_SCREEN_PARENT\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\tif(\r\n\t\t\t( typeof options.parent === \"string\" || typeof options.parent === \"number\" ) &&\r\n\t\t\tm_screens[ options.parent ]\r\n\t\t) {\r\n\t\t\tparentData = m_screens[ options.parent ];\r\n\t\t} else if(\r\n\t\t\ttypeof options.parent !== \"object\" ||\r\n\t\t\tObject.getPrototypeOf( options.parent ) !== SCREEN_API_PROTO ||\r\n\t\t\t!m_screens[ options.parent.id ] ||\r\n\t\t\tm_screens[ options.parent.id ].api !== options.parent\r\n\t\t) {\r\n\t\t\tconst error = new TypeError(\r\n\t\t\t\t\"screen: Parameter parent must be an existing screen.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_SCREEN_PARENT\";\r\n\t\t\tthrow error;\r\n\t\t} else {\r\n\t\t\tparentData = m_screens[ options.parent.id ];\r\n\t\t}\r\n\t\tparentScreenId = parentData.id;\r\n\t\tparentRenderContext = parentData.gl;\r\n\t}\r\n\r\n\t// Validate aspect - \"Now Required\"\r\n\tif( typeof options.aspect !== \"string\" || options.aspect === \"\" ) {\r\n\t\tconst error = new Error( \"screen: Parameter aspect must be a non-empty string.\" );\r\n\t\terror.code = \"INVALID_ASPECT\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tconst screenData = {\r\n\t\t\"id\": m_nextScreenId,\r\n\t\t\"isOffscreen\": !!options.isOffscreen,\r\n\t\t\"resizeCallback\": options.resizeCallback,\r\n\t\t\"api\": Object.create( SCREEN_API_PROTO ),\r\n\t\t\"canvas\": null,\r\n\t\t\"width\": null,\r\n\t\t\"height\": null,\r\n\t\t\"container\": null,\r\n\t\t\"aspectData\": null,\r\n\t\t\"clientRect\": null,\r\n\t\t\"previousOffsetSize\": null,\r\n\t\t\"parentScreenId\": parentScreenId,\r\n\t\t\"parentRenderContext\": parentRenderContext\r\n\t};\r\n\r\n\tscreenData.api.id = screenData.id;\r\n\r\n\t// Append additional items onto the screendata\r\n\tObject.assign( screenData, structuredClone( m_screenDataItems ) );\r\n\r\n\t// Append dynamic screendata items (items with dynamic defaults)\r\n\tfor( const itemGetter of m_screenDataItemGetters ) {\r\n\t\tscreenData[ itemGetter.name ] = structuredClone( itemGetter.fn() );\r\n\t}\r\n\r\n\t// Increment to the next screen id\r\n\tm_nextScreenId += 1;\r\n\r\n\t// Parse aspect ratio\r\n\tscreenData.aspectData = parseAspect( options.aspect.toLowerCase() );\r\n\tif( !screenData.aspectData ) {\r\n\t\tconst error = new Error( \"screen: Parameter aspect is not valid.\" );\r\n\t\terror.code = \"INVALID_ASPECT\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// If it's not a ratio validate the dimensions\r\n\tvalidateDimensions( screenData.aspectData.width, screenData.aspectData.height );\r\n\r\n\t// Setup options for offscreen canvas\r\n\tif( screenData.isOffscreen ) {\r\n\r\n\t\t// Create a shared canvas for offscreen screens\r\n\t\tif( !m_offscreenCanvas ) {\r\n\t\t\tm_offscreenCanvas = document.createElement( \"canvas\" );\r\n\t\t}\r\n\r\n\t\t// Create a mock canvas for offscreen screen\r\n\t\tscreenData.canvas = {\r\n\t\t\t\"isMock\": true,\r\n\t\t\t\"canvas\": m_offscreenCanvas,\r\n\t\t\t\"dataset\": { \"screenId\": screenData.id },\r\n\t\t\t\"width\": screenData.aspectData.width,\r\n\t\t\t\"height\": screenData.aspectData.height,\r\n\t\t\t\"style\": {}\r\n\t\t};\r\n\r\n\t\tif( screenData.aspectData.splitter !== \"x\" ) {\r\n\t\t\tconst error = new Error(\r\n\t\t\t\t\"screen: You must use aspect ratio with e(x)act pixel dimensions for offscreen \" +\r\n\t\t\t\t\"screens. For example: 320x200 for width of 320 and height of 200 pixels.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_OFFSCREEN_ASPECT\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\tsetupOffscreenCanvasOptions( screenData );\r\n\t\tscreenData.width = screenData.aspectData.width;\r\n\t\tscreenData.height = screenData.aspectData.height;\r\n\t} else {\r\n\r\n\t\t// Create the canvas\r\n\t\tscreenData.canvas = document.createElement( \"canvas\" );\r\n\t\tscreenData.canvas.dataset.screenId = screenData.id;\r\n\r\n\t\t// Setup options for onscreen canvas\r\n\t\tscreenData.canvas.tabIndex = 0;\r\n\r\n\t\t// Get the container element from the dom if it's available\r\n\t\tif( typeof options.container === \"string\" ) {\r\n\t\t\tscreenData.container = document.getElementById( options.container );\r\n\t\t} else if( !options.container ) {\r\n\t\t\tscreenData.container = document.body;\r\n\t\t} else {\r\n\t\t\tscreenData.container = options.container;\r\n\t\t}\r\n\r\n\t\tif( !g_utils.isDomElement( screenData.container ) ) {\r\n\t\t\tconst error = new TypeError(\r\n\t\t\t\t\"screen: Invalid argument container. Container must be a DOM element or a string \" +\r\n\t\t\t\t\"id of a DOM element.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_CONTAINER\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Create a default canvas\r\n\t\tsetDefaultCanvasOptions( screenData );\r\n\r\n\t\t// Append the canvas to the container\r\n\t\tscreenData.container.appendChild( screenData.canvas );\r\n\r\n\t\t// Add container to the global resize observer (only if not already observed)\r\n\t\tif(\r\n\t\t\tm_resizeObserver && screenData.container &&\r\n\t\t\t!m_observedContainers.has( screenData.container )\r\n\t\t) {\r\n\t\t\tm_resizeObserver.observe( screenData.container );\r\n\t\t\tm_observedContainers.add( screenData.container );\r\n\t\t}\r\n\t}\r\n\r\n\t// Map the canvas to the screenData\r\n\tm_screenCanvasMap.set( screenData.canvas, screenData );\r\n\t\r\n\tif( !screenData.isOffscreen ) {\r\n\t\tresizeScreen( screenData, true );\r\n\t}\r\n\r\n\t// Assign screen to active screen\r\n\tm_activeScreenData = screenData;\r\n\tm_screens[ screenData.id ] = screenData;\r\n\r\n\t// Setup WebGL2 renderer\r\n\tg_renderer.createContext( screenData )\r\n\r\n\t// Call init functions for all modules that need initialization\r\n\tfor( const fn of m_screenDataInitFunctions ) {\r\n\t\tfn( screenData );\r\n\t}\r\n\r\n\treturn screenData.api;\r\n}\r\n\r\nfunction parseAspect( aspect ) {\r\n\tconst match = aspect.replaceAll( \" \", \"\" ).match( /^(\\d+)(x|e|m)(\\d+)$/ );\r\n\tif( !match ) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\tconst width = Number( match[ 1 ] );\r\n\tconst splitter = match[ 2 ];\r\n\tconst height = Number( match[ 3 ] );\r\n\r\n\tif( isNaN( width ) || width === 0 || isNaN( height ) || height === 0 ) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\treturn {\r\n\t\t\"width\": width,\r\n\t\t\"height\": height,\r\n\t\t\"splitter\": splitter,\r\n\t\t\"isFixedSize\": splitter !== \"e\"\r\n\t};\r\n}\r\n\r\nfunction setupOffscreenCanvasOptions( screenData ) {\r\n\tscreenData.canvas.width = screenData.aspectData.width;\r\n\tscreenData.canvas.height = screenData.aspectData.height;\r\n\tscreenData.container = null;\r\n\tscreenData.isOffscreen = true;\r\n\tscreenData.resizeCallback = null;\r\n\tscreenData.previousOffsetSize = null;\r\n}\r\n\r\nfunction setDefaultCanvasOptions( screenData ) {\r\n\tscreenData.canvas.style.outline = \"none\";\r\n\tscreenData.canvas.style.backgroundColor = \"black\";\r\n\tscreenData.canvas.style.position = \"absolute\";\r\n\tscreenData.canvas.style.imageRendering = \"pixelated\";\r\n\r\n\t// Check if the container is document.body\r\n\tif( screenData.container === document.body ) {\r\n\t\tdocument.documentElement.style.height = \"100%\";\r\n\t\tdocument.documentElement.style.margin = \"0\";\r\n\t\tdocument.documentElement.style.padding = \"0\";\r\n\t\tdocument.body.style.height = \"100%\";\r\n\t\tdocument.body.style.margin = \"0\";\r\n\t\tdocument.body.style.padding = \"0\";\r\n\t\tscreenData.canvas.style.left = \"0\";\r\n\t\tscreenData.canvas.style.top = \"0\";\r\n\t}\r\n\r\n\t// No scrolling within a container as canvases fit to size of container and are meant to \r\n\t// overlap. If scrolling is required use an outer container that scrolls.\r\n\tscreenData.container.style.overflow = \"hidden\";\r\n\r\n\t// Make sure container is not blank\r\n\tif( screenData.container.offsetHeight === 0 ) {\r\n\t\tscreenData.container.style.height = \"200px\";\r\n\t}\r\n}\r\n\r\nfunction validateDimensions( width, height ) {\r\n\tif( width <= 0 || height <= 0 ) {\r\n\t\tconst error = new Error( \"screen: Canvas dimensions must be positive.\" );\r\n\t\terror.code = \"INVALID_DIMENSIONS\";\r\n\t\tthrow error;\r\n\t}\r\n\tif( width > MAX_CANVAS_DIMENSION || height > MAX_CANVAS_DIMENSION ) {\r\n\t\tconst error = new Error(\r\n\t\t\t`screen: Canvas dimensions exceed maximum of ${MAX_CANVAS_DIMENSION}px.`\r\n\t\t);\r\n\t\terror.code = \"DIMENSION_TOO_LARGE\";\r\n\t\tthrow error;\r\n\t}\r\n}\r\n\r\n\r\n/**************************************************************************************************\r\n * Other External API Commands\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Remove every screen.\r\n *\r\n * @returns {void}\r\n */\r\nfunction removeAllScreens() {\r\n\tconst allScreenDatas = getAllScreensData();\r\n\tfor( const screenData of allScreenDatas ) {\r\n\t\tremoveScreen( screenData );\r\n\t}\r\n}\r\n\r\n/**\r\n * Tear down one screen and free its resources.\r\n *\r\n * Runs cleanup hooks, stubs API methods, unobserves the container when\r\n * unused, and clears screenData references.\r\n *\r\n * @param {Object} screenData - Screen data object to remove\r\n * @returns {void}\r\n */\r\nfunction removeScreen( screenData ) {\r\n\r\n\t// Get the id for reference\r\n\tconst screenId = screenData.id;\n\tflushScreenTextureUsers( screenData );\n\n\t// Invalidate references held by other screens before GPU resources are destroyed\n\tfor( const fn of m_screenDataPreCleanupFunctions ) {\n\t\tfn( screenData );\n\t}\n\n\t// Call cleanup functions for all modules that need cleanup\n\tfor( const fn of m_screenDataCleanupFunctions ) {\r\n\t\tfn( screenData );\r\n\t}\r\n\r\n\t// Replace all commands from screen object\r\n\tfor( const key in screenData.api ) {\r\n\t\tif( typeof screenData.api[ key ] === \"function\" ) {\r\n\r\n\t\t\t// Use string replacement to avoid capturing screenData in closure\r\n\t\t\tscreenData.api[ key ] = () => {\r\n\t\t\t\tconst error = new TypeError( \r\n\t\t\t\t\t`Cannot call ${key}() on removed screen (id: ${screenId}). ` +\r\n\t\t\t\t\t`The screen has been removed from the page.`\r\n\t\t\t\t);\r\n\t\t\t\terror.code = \"DELETED_METHOD\";\r\n\t\t\t\tthrow error;\r\n\t\t\t};\r\n\t\t}\r\n\t}\r\n\r\n\t// Remove from the screenCanvasMap\r\n\tm_screenCanvasMap.delete( screenData.canvas );\r\n\r\n\t// Remove the canvas from the page\r\n\tif( screenData.canvas && screenData.canvas.parentElement ) {\r\n\t\tscreenData.canvas.parentElement.removeChild( screenData.canvas );\r\n\t}\r\n\r\n\t// Unobserve the container from the global resize observer\r\n\tif( screenData.container && m_observedContainers.has( screenData.container ) ) {\r\n\t\t\r\n\t\t// Check if any other screens are using this container\r\n\t\tlet hasOtherScreens = false;\r\n\t\tfor( const id in m_screens ) {\r\n\t\t\tconst otherScreen = m_screens[ id ];\r\n\t\t\tif( otherScreen !== screenData && otherScreen.container === screenData.container ) {\r\n\t\t\t\thasOtherScreens = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// Only unobserve if no other screens are using this container\r\n\t\tif( !hasOtherScreens ) {\r\n\t\t\tm_resizeObserver.unobserve( screenData.container );\r\n\t\t\tm_observedContainers.delete( screenData.container );\r\n\t\t}\r\n\t}\r\n\r\n\t// Clean up all references to prevent memory leaks\r\n\tscreenData.canvas = null;\r\n\tscreenData.commands = null;\r\n\tscreenData.resizeCallback = null;\r\n\tscreenData.container = null;\r\n\tscreenData.aspectData = null;\r\n\tscreenData.clientRect = null;\r\n\tscreenData.previousOffsetSize = null;\r\n\tscreenData.parentScreenId = null;\r\n\tscreenData.parentRenderContext = null;\r\n\r\n\t// Remove additional screenData items\r\n\tfor( const i in m_screenDataItems ) {\r\n\t\tscreenData[ i ] = null;\r\n\t}\r\n\tfor( const getter of m_screenDataItemGetters ) {\r\n\t\tscreenData[ getter.name ] = null;\r\n\t}\r\n\r\n\t// If the current screen is the active screen then set to next screen available\r\n\tif( screenData === m_activeScreenData ) {\r\n\t\tm_activeScreenData = null;\r\n\t\tfor( const i in m_screens ) {\r\n\t\t\tif( m_screens[ i ] !== screenData ) {\r\n\t\t\t\tm_activeScreenData = m_screens[ i ];\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Delete the screen from the screens container\r\n\tdelete m_screens[ screenId ];\r\n}\r\n\r\n/**\r\n * Set the active screen from an id or screen API object.\r\n *\r\n * Rebuilds the screen API if the active screen changes.\r\n *\r\n * @param {Object} options - Command options\r\n * @param {number|Object} options.screen - Screen id or screen API object\r\n * @returns {void}\r\n */\r\nfunction setScreen( options ) {\r\n\tconst screenObj = options.screen;\r\n\tlet screenId;\r\n\r\n\tif( Number.isInteger( screenObj ) ) {\r\n\t\tscreenId = screenObj;\r\n\t} else if( screenObj && Number.isInteger( screenObj.id ) ) {\r\n\t\tscreenId = screenObj.id;\r\n\t}\r\n\tif( !m_screens[ screenId ] ) {\r\n\t\tconst error = new Error( \"screen: Invalid screen.\" );\r\n\t\terror.code = \"INVALID_SCREEN\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Note: there is no need to check if m_activeScreenData is null because it cannot be null\r\n\t// unless there are no screens in which case an error would already have been thrown.\r\n\tconst previousScreenId = m_activeScreenData.id;\r\n\tm_activeScreenData = m_screens[ screenId ];\r\n\r\n\tif( previousScreenId !== m_activeScreenData.id  ) {\r\n\t\tg_graphics.buildApi( m_activeScreenData );\r\n\t}\r\n}\r\n\r\n/**\r\n * Get a screen API object by screen id.\r\n *\r\n * @param {Object} options - Command options\r\n * @param {number} options.screenId - Screen id to retrieve\r\n * @returns {Object} Screen API object\r\n */\r\nfunction getScreen( options ) {\r\n\tconst screenId = g_utils.getInt( options.screenId, null );\r\n\tif( screenId === null || screenId < 0 ) {\r\n\t\tconst error = new Error( \"screen: Invalid screen id.\" );\r\n\t\terror.code = \"INVALID_SCREEN_ID\";\r\n\t\tthrow error;\r\n\t}\r\n\tconst screen = m_screens[ screenId ];\r\n\tif( !screen ) {\r\n\t\tconst error = new Error( `screen: Screen \"${screenId}\" not found.` );\r\n\t\terror.code = \"SCREEN_NOT_FOUND\";\r\n\t\tthrow error;\r\n\t}\r\n\treturn screen.api;\r\n}\r\n\r\n/**\r\n * Get all screen API objects.\r\n *\r\n * @returns {Array<Object>} Array of screen API objects\r\n */\r\nfunction getAllScreens() {\r\n\tconst screens = [];\r\n\tfor( const id in m_screens ) {\r\n\t\tscreens.push( m_screens[ id ].api );\r\n\t}\r\n\treturn screens;\r\n}\r\n\r\n/**\r\n * Get the logical framebuffer width of the screen.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @returns {number} Screen width in pixels\r\n */\r\nfunction widthCmd( screenData ) {\r\n\treturn screenData.view.width;\r\n}\r\n\r\n/**\r\n * Get the logical framebuffer height of the screen.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @returns {number} Screen height in pixels\r\n */\r\nfunction heightCmd( screenData ) {\r\n\treturn screenData.view.height;\r\n}\r\n\r\n/**\r\n * Get the HTML canvas for the screen.\r\n *\r\n * Offscreen screens share one canvas used to draw to textures. A warning\r\n * is logged because changes to that canvas can affect other screens.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @returns {HTMLCanvasElement} Canvas element for the screen\r\n */\r\nfunction canvasCmd( screenData ) {\r\n\tif( screenData.isOffscreen ) {\r\n\t\tconsole.warn(\r\n\t\t\t\"Offscreen screens use a shared canvas that draws to textures to simulate an \" +\r\n\t\t\t\"offscreen canvas. The canvas returned is that shared canvas. Proceed with caution \" +\r\n\t\t\t\"changes to this canvas could cause unexpected results.\" \r\n\t\t);\r\n\t\treturn screenData.canvas.canvas;\r\n\t}\r\n\treturn screenData.canvas;\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Resize Screen\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * True when the screen can use existing screen-manager sizing and presentation.\r\n *\r\n * Offscreen, hidden, and detached canvases are ineligible. forcePresent must\r\n * not bypass this check.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @returns {boolean} True if sizing and presentation may run\r\n */\r\nfunction canSizeAndPresent( screenData ) {\r\n\tif( screenData.isOffscreen ) {\r\n\t\treturn false;\r\n\t}\r\n\tif( !screenData.canvas || screenData.canvas.offsetParent === null ) {\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/**\r\n * Flush pending batches and present if the screen is currently eligible.\r\n *\r\n * Does not resize or rewrite canvas dimensions.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @returns {void}\r\n */\r\nexport function presentCurrentScreen( screenData ) {\r\n\tif( !canSizeAndPresent( screenData ) ) {\r\n\t\treturn;\r\n\t}\r\n\tg_renderer.flushBatches( screenData );\r\n\tg_renderer.displayToCanvas( screenData );\r\n}\r\n\r\n/**\r\n * Recalculate CSS, logical, and backing size. Resize FBOs and/or present.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {boolean} [forcePresent=false] - Present even if sizes did not change\r\n * @returns {void}\r\n */\r\nexport function refreshScreenSize( screenData, forcePresent ) {\r\n\tif( forcePresent == null ) {\r\n\t\tforcePresent = false;\r\n\t}\r\n\r\n\tif( !canSizeAndPresent( screenData ) ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst flags = applyScreenSizing( screenData );\r\n\tapplyResizeConsequences( screenData, flags, forcePresent );\r\n}\r\n\r\n/**\r\n * Resize an offscreen screen to exact logical pixel dimensions.\r\n *\r\n * This is exposed through the plugin API for container-style plugins. Onscreen screens continue\r\n * to be sized exclusively from their configured aspect and DOM container.\r\n *\r\n * @param {Object} screenData - Offscreen screen data object\r\n * @param {number} width - New logical width\r\n * @param {number} height - New logical height\r\n * @returns {void}\r\n */\r\nexport function resizeOffscreenScreen( screenData, width, height ) {\r\n\tif( !screenData || !screenData.isOffscreen ) {\r\n\t\tconst error = new TypeError( \"resizeOffscreenScreen: Screen must be offscreen.\" );\r\n\t\terror.code = \"INVALID_OFFSCREEN_SCREEN\";\r\n\t\tthrow error;\r\n\t}\r\n\tif( !Number.isInteger( width ) || !Number.isInteger( height ) ) {\r\n\t\tconst error = new TypeError(\r\n\t\t\t\"resizeOffscreenScreen: Width and height must be integers.\"\r\n\t\t);\r\n\t\terror.code = \"INVALID_SCREEN_DIMENSIONS\";\r\n\t\tthrow error;\r\n\t}\r\n\tvalidateDimensions( width, height );\r\n\tif( screenData.width === width && screenData.height === height ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tflushScreenTextureUsers( screenData );\r\n\tconst oldWidth = screenData.width;\r\n\tconst oldHeight = screenData.height;\r\n\tscreenData.width = width;\r\n\tscreenData.height = height;\r\n\tscreenData.canvas.width = width;\r\n\tscreenData.canvas.height = height;\r\n\tscreenData.aspectData.width = width;\r\n\tscreenData.aspectData.height = height;\r\n\tg_renderer.resizeScreen( screenData, oldWidth, oldHeight );\r\n\tg_view.onScreenResize( screenData );\r\n}\r\n\r\n/**\r\n * Finish queued same-context draws before a screen texture changes or is deleted.\r\n *\r\n * @param {Object} sourceData - Screen whose framebuffer texture is changing\r\n * @returns {void}\r\n */\r\nfunction flushScreenTextureUsers( sourceData ) {\r\n\tif( !sourceData.fboTexture ) {\r\n\t\treturn;\r\n\t}\r\n\tfor( const screenData of getAllScreensData() ) {\r\n\t\tif(\r\n\t\t\tscreenData !== sourceData && screenData.gl === sourceData.gl &&\r\n\t\t\tscreenData.batchInfo?.textureBatchSet.has( sourceData.fboTexture )\r\n\t\t) {\r\n\t\t\tg_renderer.flushBatches( screenData );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfunction resizeScreen( screenData, isInit ) {\r\n\tif( !canSizeAndPresent( screenData ) ) {\r\n\t\treturn;\r\n\t}\r\n\tconst flags = applyScreenSizing( screenData );\r\n\tif( !isInit ) {\r\n\t\tapplyResizeConsequences( screenData, flags, false );\r\n\t}\r\n}\r\n\r\n/**\r\n * Apply fit/aspect sizing and update CSS layout. Does not resize FBOs,\r\n * invoke resizeCallback, or present.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @returns {{ logicalChanged: boolean, backingChanged: boolean,\r\n * \toldWidth: number|null, oldHeight: number|null,\r\n * \tfromSize: Object|null, toSize: Object }} Sizing result\r\n */\r\nfunction applyScreenSizing( screenData ) {\r\n\tconst fromSize = screenData.previousOffsetSize;\r\n\tconst size = getSize( screenData.container );\r\n\tconst flags = setCanvasSize( screenData, size.width, size.height );\r\n\r\n\tscreenData.clientRect = screenData.canvas.getBoundingClientRect();\r\n\r\n\tconst toSize = {\r\n\t\t\"width\": screenData.canvas.offsetWidth,\r\n\t\t\"height\": screenData.canvas.offsetHeight\r\n\t};\r\n\r\n\tscreenData.previousOffsetSize = toSize;\r\n\treturn {\r\n\t\t\"logicalChanged\": flags.logicalChanged,\r\n\t\t\"backingChanged\": flags.backingChanged,\r\n\t\t\"oldWidth\": flags.oldWidth,\r\n\t\t\"oldHeight\": flags.oldHeight,\r\n\t\t\"fromSize\": fromSize,\r\n\t\t\"toSize\": toSize\r\n\t};\r\n}\r\n\r\n/**\r\n * Apply FBO resize, resize callback, optional flush, and a single present.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {{ logicalChanged: boolean, backingChanged: boolean,\r\n * \toldWidth: number|null, oldHeight: number|null,\r\n * \tfromSize: Object|null, toSize: Object }} flags - Sizing result\r\n * @param {boolean} forcePresent - Present even if sizes did not change\r\n * @returns {void}\r\n */\r\nfunction applyResizeConsequences( screenData, flags, forcePresent ) {\r\n\tif( flags.logicalChanged ) {\r\n\t\tg_renderer.resizeScreen( screenData, flags.oldWidth, flags.oldHeight );\r\n\t\tg_view.onScreenResize( screenData );\r\n\t}\r\n\r\n\tlet callbackRan = false;\r\n\tconst fromSize = flags.fromSize;\r\n\tconst toSize = flags.toSize;\r\n\tif(\r\n\t\tscreenData.resizeCallback &&\r\n\t\tfromSize !== null &&\r\n\t\t( fromSize.width !== toSize.width || fromSize.height !== toSize.height )\r\n\t) {\r\n\t\tscreenData.resizeCallback( screenData.api, fromSize, toSize );\r\n\t\tcallbackRan = true;\r\n\t}\r\n\r\n\tif( callbackRan ) {\r\n\t\tg_renderer.flushBatches( screenData );\r\n\t}\r\n\r\n\tif(\r\n\t\tflags.logicalChanged || flags.backingChanged || forcePresent || callbackRan\r\n\t) {\r\n\t\tg_renderer.displayToCanvas( screenData );\r\n\t}\r\n}\r\n\r\nfunction setCanvasSize( screenData, maxWidth, maxHeight ) {\r\n\tconst aspectData = screenData.aspectData;\r\n\tconst canvas = screenData.canvas;\r\n\tlet width = aspectData.width;\r\n\tlet height = aspectData.height;\r\n\tconst splitter = aspectData.splitter;\r\n\tlet newCssWidth, newCssHeight;\r\n\r\n\tconst oldWidth = screenData.width;\r\n\tconst oldHeight = screenData.height;\r\n\tconst oldBackingWidth = canvas.width;\r\n\tconst oldBackingHeight = canvas.height;\r\n\r\n\t// If set size to multiple or extend\r\n\tif( splitter === \"m\" || splitter === \"e\" ) {\r\n\t\tconst factorX = Math.floor( maxWidth / width );\r\n\t\tconst factorY = Math.floor( maxHeight / height );\r\n\t\tlet factor = factorX > factorY ? factorY : factorX;\r\n\t\tif( factor < 1 ) {\r\n\t\t\tfactor = 1;\r\n\t\t}\r\n\t\tnewCssWidth = width * factor;\r\n\t\tnewCssHeight = height * factor;\r\n\r\n\t\t// Extending the canvas to match container size\r\n\t\tif( splitter === \"e\" ) {\r\n\t\t\twidth = Math.floor( maxWidth / factor );\r\n\t\t\theight = Math.floor( maxHeight / factor );\r\n\t\t\tnewCssWidth = width * factor;\r\n\t\t\tnewCssHeight = height * factor;\r\n\t\t}\r\n\t} else {\r\n\r\n\t\t// Calculate the screen ratios\r\n\t\tconst ratio1 = height / width;\r\n\t\tconst ratio2 = width / height;\r\n\t\tnewCssWidth = maxHeight * ratio2;\r\n\t\tnewCssHeight = maxWidth * ratio1;\r\n\r\n\t\t// Calculate the best fit\r\n\t\tif( newCssWidth > maxWidth ) {\r\n\t\t\tnewCssWidth = maxWidth;\r\n\t\t\tnewCssHeight = newCssWidth * ratio1;\r\n\t\t} else {\r\n\t\t\tnewCssHeight = maxHeight;\r\n\t\t}\r\n\t}\r\n\r\n\tconst logicalChanged = oldWidth !== width || oldHeight !== height;\r\n\tscreenData.width = width;\r\n\tscreenData.height = height;\r\n\r\n\t// CSS presentation size (DOM layout only)\r\n\tcanvas.style.width = Math.floor( newCssWidth ) + \"px\";\r\n\tcanvas.style.height = Math.floor( newCssHeight ) + \"px\";\r\n\r\n\tcanvas.style.marginLeft = Math.floor( ( maxWidth - newCssWidth ) / 2 ) + \"px\";\r\n\tcanvas.style.marginTop = Math.floor( ( maxHeight - newCssHeight ) / 2 ) + \"px\";\r\n\r\n\tlet desiredBackingWidth;\r\n\tlet desiredBackingHeight;\r\n\tif( screenData.renderToDisplaySize ) {\r\n\t\tdesiredBackingWidth = Math.min(\r\n\t\t\tMath.floor( newCssWidth ), MAX_CANVAS_DIMENSION\r\n\t\t);\r\n\t\tdesiredBackingHeight = Math.min(\r\n\t\t\tMath.floor( newCssHeight ), MAX_CANVAS_DIMENSION\r\n\t\t);\r\n\t} else {\r\n\t\tdesiredBackingWidth = Math.min( width, MAX_CANVAS_DIMENSION );\r\n\t\tdesiredBackingHeight = Math.min( height, MAX_CANVAS_DIMENSION );\r\n\t}\r\n\r\n\tconst backingChanged = (\r\n\t\toldBackingWidth !== desiredBackingWidth ||\r\n\t\toldBackingHeight !== desiredBackingHeight\r\n\t);\r\n\r\n\tif( canvas.width !== desiredBackingWidth ) {\r\n\t\tcanvas.width = desiredBackingWidth;\r\n\t}\r\n\tif( canvas.height !== desiredBackingHeight ) {\r\n\t\tcanvas.height = desiredBackingHeight;\r\n\t}\r\n\r\n\treturn {\r\n\t\t\"logicalChanged\": logicalChanged,\r\n\t\t\"backingChanged\": backingChanged,\r\n\t\t\"oldWidth\": oldWidth,\r\n\t\t\"oldHeight\": oldHeight\r\n\t};\r\n}\r\n\r\nfunction getSize( element ) {\r\n\treturn {\r\n\t\t\"width\": element.offsetWidth || element.clientWidth || element.width,\r\n\t\t\"height\": element.offsetHeight || element.clientHeight || element.height\r\n\t};\r\n}\r\n", "/**\r\n * Pi.js - Renderer Module\r\n * \r\n * WebGL2 context creation, module orchestration, and public API exports.\r\n * Main orchestrator for all renderer modules.\r\n * \r\n * @module renderer/renderer\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_screenManager from \"../core/screen-manager.js\";\r\nimport * as g_utils from \"../core/utils.js\";\r\n\r\n// Import renderer modules\r\nimport * as g_shaders from \"./shaders.js\";\r\nimport * as g_batches from \"./batches.js\";\r\n\r\n// Import shapes module for geometry drawing\r\nimport * as g_geometry from \"./draw/geometry.js\";\r\nimport * as g_textures from \"./textures.js\";\r\nimport * as g_readback from \"./readback.js\";\r\n\r\n\r\n/***************************************************************************************************\r\n * Public API Exports\r\n ***************************************************************************************************/\r\n\r\n\r\n// Re-export batch constants\r\nexport {\r\n\tPOINTS_BATCH, IMAGE_BATCH, GEOMETRY_BATCH, POINTS_REPLACE_BATCH, IMAGE_REPLACE_BATCH, SHADER_BATCH\r\n} from \"./batches.js\";\r\n\r\n// Re-export drawing functions\r\nexport { drawImage, drawSprite } from \"./draw/sprites.js\";\r\nexport { drawPixel, drawPixelUnsafe } from \"./draw/primitives.js\";\r\nexport { drawArc } from \"./draw/arcs.js\";\r\nexport { drawBezier } from \"./draw/bezier.js\";\r\nexport { drawLine } from \"./draw/lines.js\";\r\nexport { drawCachedGeometry } from \"./draw/geometry.js\";\r\nexport { drawRect, drawRectFilled } from \"./draw/rects.js\";\r\nexport { drawCircle, drawCircleFilled } from \"./draw/circles.js\";\r\nexport { drawEllipse } from \"./draw/ellipses.js\";\r\nexport { shiftImageUp, cls } from \"./effects.js\";\r\n\r\n// Re-export batch management\r\nexport {\n\tprepareBatch, flushBatches, displayToCanvas, prepareShaderBatch, countQueuedShaderPasses\n} from \"./batches.js\";\n\n// Re-export custom shader validation and uniform normalization\nexport {\n\tvalidateCustomShaderProgram, normalizeCustomUniforms, getCustomShaderDiagnostics,\n\tdeleteCustomShaderProgram\n} from \"./shaders.js\";\n\r\n// Re-export texture management\r\nexport {\r\n\tgetWebGL2Texture, deleteWebGL2Texture, updateWebGL2TextureImage, updateWebGL2TextureSubImage\r\n} from \"./textures.js\";\r\n\r\n// Re-export readback functions\r\nexport {\r\n\treadPixel, readPixelAsync, readPixels, readPixelsAsync, readPixelsRaw\r\n} from \"./readback.js\";\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Initialization\r\n ***************************************************************************************************/\r\n\r\nconst m_isDebug = window.location.search.includes( \"webgl-debug\" );\r\nlet m_offscreenContext = null;\r\n\r\n/**\r\n * Initialize all renderer modules\r\n * \r\n * @param {Object} api - The main Pi.js API object\r\n * @returns {void}\r\n */\r\nexport function init( api ) {\r\n\r\n\t// Add screenData items\r\n\tg_screenManager.addScreenDataItem( \"contextLost\", false );\r\n\tg_screenManager.addScreenDataItem( \"isRenderScheduled\", false );\r\n\tg_screenManager.addScreenDataItem( \"isFirstRender\", true );\r\n\tg_screenManager.addScreenDataItem( \"gl\", null );\r\n\tg_screenManager.addScreenDataItem( \"fboTexture\", null );\r\n\tg_screenManager.addScreenDataItem( \"FBO\", null );\r\n\tg_screenManager.addScreenDataItem( \"bufferFboTexture\", null );\r\n\tg_screenManager.addScreenDataItem( \"bufferFBO\", null );\r\n\tg_screenManager.addScreenDataItem( \"customShaders\", {} );\r\n\tg_screenManager.addScreenDataItem( \"frameCount\", 0 );\r\n\r\n\t// Register renderer cleanup function\r\n\tg_screenManager.addScreenCleanupFunction( cleanup );\r\n\r\n\t// Initialize renderer modules in order\r\n\tg_shaders.init();\r\n\tg_batches.init();\r\n\tg_textures.init();\r\n\tg_readback.init();\r\n\tg_geometry.init();\r\n}\r\n\r\n/**\r\n * Create WebGL2 context for screen\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @returns {boolean} True if context created successfully\r\n */\r\nexport function createContext( screenData ) {\r\n\r\n\tlet canvas = screenData.canvas;\r\n\tconst width = screenData.width;\r\n\tconst height = screenData.height;\r\n\t\r\n\tif( screenData.parentRenderContext ) {\r\n\t\tcanvas = screenData.canvas.canvas;\r\n\t\tscreenData.gl = screenData.parentRenderContext;\r\n\t} else if( screenData.isOffscreen ) {\r\n\t\tcanvas = screenData.canvas.canvas;\r\n\t\tif( !m_offscreenContext ) {\r\n\t\t\tm_offscreenContext = canvas.getContext( \"webgl2\", { \r\n\t\t\t\t\"alpha\": true, \r\n\t\t\t\t\"premultipliedAlpha\": false,\r\n\t\t\t\t\"antialias\": false,\r\n\t\t\t\t\"preserveDrawingBuffer\": true,\r\n\t\t\t\t\"desynchronized\": false,\r\n\t\t\t\t\"colorType\": \"unorm8\"\r\n\t\t\t} );\r\n\t\t}\r\n\t\tscreenData.gl = m_offscreenContext;\r\n\t} else {\r\n\t\tscreenData.gl = canvas.getContext( \"webgl2\", { \r\n\t\t\t\"alpha\": true, \r\n\t\t\t\"premultipliedAlpha\": false,\r\n\t\t\t\"antialias\": false,\r\n\t\t\t\"preserveDrawingBuffer\": true,\r\n\t\t\t\"desynchronized\": false,\r\n\t\t\t\"colorType\": \"unorm8\"\r\n\t\t} );\r\n\t}\r\n\t\r\n\t// WebGL2 not available\r\n\tif( !screenData.gl ) {\r\n\t\tconst error = new Error( \"screen: Failed to create WebGL2 context. WebGL2 is required.\" );\r\n\t\terror.code = \"WEBGL_ERROR\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Setup viewport\r\n\tscreenData.gl.viewport( 0, 0, width, height );\r\n\t\r\n\t// Create texture and FBO\r\n\tconst fboAndTexture = createTextureAndFBO( screenData );\r\n\tscreenData.fboTexture = fboAndTexture.fboTexture;\r\n\tscreenData.FBO = fboAndTexture.FBO;\r\n\t\r\n\t// Create a buffer texture and FBO\r\n\tconst bufferFboAndTexture = createTextureAndFBO( screenData );\r\n\tscreenData.bufferFboTexture = bufferFboAndTexture.fboTexture;\r\n\tscreenData.bufferFBO = bufferFboAndTexture.FBO;\r\n\r\n\t// Create all the batches\r\n\tg_batches.createBatches( screenData );\r\n\r\n\t// Setup display shader\r\n\tg_shaders.setupDisplayShader( screenData );\r\n\r\n\t// Enable WebGL debugging extensions\r\n\tif( m_isDebug) {\r\n\t\tconst debugExt = screenData.gl.getExtension( \"WEBGL_debug_renderer_info\" );\r\n\t\tif( debugExt ) {\r\n\t\t\tconsole.log( \"GPU:\", screenData.gl.getParameter( debugExt.UNMASKED_RENDERER_WEBGL ) );\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Track if webglcontext gets lost\r\n\tcanvas.addEventListener( \"webglcontextlost\", ( e ) => {\r\n\t\te.preventDefault();\r\n\t\tconsole.warn( \"WebGL context lost\" );\r\n\t\tscreenData.contextLost = true;\r\n\t} );\r\n\t\r\n\t// Reinit canvas when webglcontext gets restored\r\n\tcanvas.addEventListener( \"webglcontextrestored\", () => {\r\n\t\tconsole.log( \"WebGL context restored\" );\r\n\r\n\t\t// TODO-LATER: Reinitialize WebGL resources\r\n\t\t// initWebGL( screenData );\r\n\t\tscreenData.contextLost = false;\r\n\r\n\t\t// TODO-LATER: Reset blend mode\r\n\t\t// blendModeChanged( screenData );\r\n\t} );\r\n}\r\n\r\n/**\r\n * Create FBO and texture for screen\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @returns {boolean} True if FBO created successfully\r\n */\r\nfunction createTextureAndFBO( screenData ) {\r\n\r\n\tconst gl = screenData.gl;\r\n\tconst width = screenData.width;\r\n\tconst height = screenData.height;\r\n\t\r\n\t// Create texture\r\n\tconst fboTexture = gl.createTexture();\r\n\tif( !fboTexture ) {\r\n\t\tconst error = new Error( \"screen: Failed to create WebGL2 texture.\" );\r\n\t\terror.code = \"WEBGL_ERROR\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tgl.bindTexture( gl.TEXTURE_2D, fboTexture );\r\n\tgl.texImage2D( \r\n\t\tgl.TEXTURE_2D, 0, gl.RGBA8, \r\n\t\twidth, height, 0, \r\n\t\tgl.RGBA, gl.UNSIGNED_BYTE, null \r\n\t);\r\n\t\r\n\t// Set texture parameters for pixel-perfect rendering\r\n\tgl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );\r\n\tgl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );\r\n\tgl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );\r\n\tgl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );\r\n\t\r\n\t// Create FBO\r\n\tconst FBO = gl.createFramebuffer();\r\n\tgl.bindFramebuffer( gl.FRAMEBUFFER, FBO );\r\n\t\r\n\t// Attach texture to FBO\r\n\tgl.framebufferTexture2D(\r\n\t\tgl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, \r\n\t\tgl.TEXTURE_2D, fboTexture, 0 \r\n\t);\r\n\r\n\t// Make sure that framebuffer is complete\r\n\tconst status = gl.checkFramebufferStatus( gl.FRAMEBUFFER );\r\n\tif( status !== gl.FRAMEBUFFER_COMPLETE ) {\r\n\t\tconst error = new Error( `screen: WebGL2 Framebuffer incomplete. ${status}` );\r\n\t\terror.code = \"WEBGL_ERROR\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Unbind\r\n\tgl.bindFramebuffer( gl.FRAMEBUFFER, null );\r\n\tgl.bindTexture( gl.TEXTURE_2D, null );\r\n\r\n\treturn { fboTexture, FBO };\r\n}\r\n\r\n/**\r\n * Cleanup renderer resources for screen\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @returns {void}\r\n */\r\nexport function cleanup( screenData ) {\r\n\tconst gl = screenData.gl;\r\n\r\n\t// Make sure no render gets executed in the microtask\r\n\tscreenData.isRenderScheduled = false;\r\n\t\r\n\t// Cleanup batches\r\n\tg_batches.cleanup( screenData );\r\n\r\n\t// Cleanup display shader\r\n\tif( screenData.displayProgram ) {\r\n\t\tgl.deleteProgram( screenData.displayProgram );\r\n\t\tgl.deleteBuffer( screenData.displayPositionBuffer );\r\n\t\tgl.deleteVertexArray( screenData.displayQuadVao );\r\n\t}\r\n\r\n\t// Cleanup custom shader programs (FBO / display)\r\n\tif( screenData.customShaders ) {\r\n\t\tfor( const id of Object.keys( screenData.customShaders ) ) {\r\n\t\t\tconst cache = screenData.customShaders[ id ];\r\n\t\t\tif( cache && cache.program ) {\r\n\t\t\t\tgl.deleteProgram( cache.program );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Cleanup textures\r\n\tg_textures.cleanup( screenData );\r\n\r\n\t// Cleanup FBO\r\n\tif( screenData.FBO ) {\r\n\t\tgl.deleteFramebuffer( screenData.FBO );\r\n\t\tgl.deleteTexture( screenData.fboTexture );\r\n\t}\r\n\r\n\t// Cleanup Buffe FBO\r\n\tif( screenData.bufferFBO ) {\r\n\t\tgl.deleteFramebuffer( screenData.bufferFBO );\r\n\t\tgl.deleteTexture( screenData.bufferFboTexture );\r\n\t}\r\n}\r\n\r\n/**\r\n * Sets the image dirty / Queue automatic render\r\n * @param {Object} screenData - Screen data object\r\n * @returns {void}\r\n */\r\nexport function setImageDirty( screenData ) {\r\n\t// Parent-affiliated offscreen screens never present to a canvas. Their FBO is flushed lazily\r\n\t// when another screen composites it or a readback operation needs its pixels.\r\n\tif( screenData.isOffscreen && screenData.parentRenderContext ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif( !screenData.isRenderScheduled ) {\r\n\t\tscreenData.isRenderScheduled = true;\r\n\t\tg_utils.queueMicrotask( () => {\n\t\t\t\n\t\t\t// Make sure render hasn't been cancelled\n\t\t\tif( !screenData.isRenderScheduled ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tg_batches.flushBatches( screenData );\n\t\t\t\tg_batches.displayToCanvas( screenData );\n\t\t\t} finally {\n\t\t\t\tscreenData.isRenderScheduled = false;\n\t\t\t}\n\t\t} );\n\t}\n}\n\r\n/**\r\n * Called when blend mode changes, flush current batch with old blend mode\r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} previousBlends - Blends data including blend mode, noise, seed or null default\r\n * @returns {void}\r\n */\r\nexport function blendModeChanged( screenData, previousBlends ) {\r\n\r\n\t// Flush existing batch with old blend mode\r\n\tg_batches.flushBatches( screenData, previousBlends );\r\n\tg_batches.displayToCanvas( screenData );\r\n}\r\n\r\nexport function resizeScreen( screenData, oldWidth, oldHeight ) {\r\n\r\n\t// Finish rendering to the FBO before resizing\r\n\tg_batches.flushBatches( screenData );\r\n\r\n\tconst gl = screenData.gl;\r\n\tconst newWidth = screenData.width;\r\n\tconst newHeight = screenData.height;\r\n\r\n\t// Preserve the current contents in the buffer FBO before reallocating\r\n\tgl.bindFramebuffer( gl.READ_FRAMEBUFFER, screenData.FBO );\r\n\tgl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, screenData.bufferFBO );\r\n\tgl.clearColor( 0, 0, 0, 0 );\r\n\tgl.clear( gl.COLOR_BUFFER_BIT );\r\n\tgl.blitFramebuffer(\r\n\t\t0, 0, oldWidth, oldHeight,\r\n\t\t0, 0, oldWidth, oldHeight,\r\n\t\tgl.COLOR_BUFFER_BIT, gl.NEAREST\r\n\t);\r\n\r\n\t// Resize the primary FBO texture\r\n\tgl.bindTexture( gl.TEXTURE_2D, screenData.fboTexture );\r\n\tgl.texImage2D( \r\n\t\tgl.TEXTURE_2D, 0, gl.RGBA8, \r\n\t\tnewWidth, newHeight, 0,\r\n\t\tgl.RGBA, gl.UNSIGNED_BYTE, null \r\n\t);\r\n\tgl.bindTexture( gl.TEXTURE_2D, null );\r\n\r\n\t// Copy the preserved pixels back into the resized primary FBO\r\n\tconst copyWidth = Math.min( oldWidth, newWidth );\r\n\tconst copyHeight = Math.min( oldHeight, newHeight );\r\n\tgl.bindFramebuffer( gl.READ_FRAMEBUFFER, screenData.bufferFBO );\r\n\tgl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, screenData.FBO );\r\n\r\n\t// WebGL blits use a bottom-left origin. Offset both rectangles so the logical top-left region\r\n\t// remains anchored when growing as well as when shrinking.\r\n\tconst srcY = oldHeight - copyHeight;\r\n\tconst destinationY = newHeight - copyHeight;\r\n\tgl.blitFramebuffer(\r\n\t\t0, srcY, copyWidth, srcY + copyHeight,\r\n\t\t0, destinationY, copyWidth, destinationY + copyHeight,\r\n\t\tgl.COLOR_BUFFER_BIT, gl.NEAREST\r\n\t);\r\n\r\n\t// Resize the buffer FBO texture to match the new dimensions\r\n\tgl.bindTexture( gl.TEXTURE_2D, screenData.bufferFboTexture );\r\n\tgl.texImage2D( \r\n\t\tgl.TEXTURE_2D, 0, gl.RGBA8, \r\n\t\tnewWidth, newHeight, 0,\r\n\t\tgl.RGBA, gl.UNSIGNED_BYTE, null \r\n\t);\r\n\tgl.bindTexture( gl.TEXTURE_2D, null );\r\n\r\n\tgl.bindFramebuffer( gl.READ_FRAMEBUFFER, null );\r\n\tgl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, null );\r\n}\r\n", "#version 300 es\r\nin vec2 a_position;\r\nout vec2 v_texCoord;\r\n\r\nvoid main() {\r\n\tgl_Position = vec4(a_position, 0.0, 1.0);\r\n\r\n\t// Flip Y coordinate when sampling texture\r\n\tv_texCoord = (a_position + 1.0) * 0.5;\r\n}\r\n\r\n", "#version 300 es\r\nprecision mediump float;\r\nin vec2 v_texCoord;\r\nuniform sampler2D u_texture;\r\nout vec4 fragColor;\r\n\r\nvoid main() {\r\n\tvec4 texColor = texture(u_texture, v_texCoord);\r\n\t\r\n\t// The FBO already contains STRAIGHT ALPHA, so just output it directly.\r\n\tfragColor = texColor;\r\n}\r\n\r\n", "/**\r\n * Pi.js - Shaders Module\r\n * \r\n * Shader compilation, program creation, and display shader setup.\r\n * \r\n * @module renderer/shaders\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_screenManager from \"../core/screen-manager.js\";\r\n\r\n// Shaders are imported from external files via esbuild text loader\r\nimport m_displayVertSrc from \"./shaders/display.vert\";\r\nimport m_displayFragSrc from \"./shaders/display.frag\";\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Initialization\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Initialize shaders module\r\n * \r\n * @returns {void}\r\n */\r\nexport function init() {\r\n\r\n\tg_screenManager.addScreenDataItem( \"displayProgram\", null );\r\n\tg_screenManager.addScreenDataItem( \"displayPositionBuffer\", null );\r\n\tg_screenManager.addScreenDataItem( \"displayLocations\", null );\r\n}\r\n\r\n/**\r\n * Compile a single shader\r\n * \r\n * @param {WebGL2RenderingContext} gl - WebGL2 context\r\n * @param {number} type - Shader type (VERTEX_SHADER or FRAGMENT_SHADER)\r\n * @param {string} source - Shader source code\r\n * @returns {WebGLShader|null} Compiled shader or null on error\r\n */\r\nexport function compileShader( gl, type, source ) {\r\n\tconst shader = gl.createShader( type );\r\n\tgl.shaderSource( shader, source );\r\n\tgl.compileShader( shader );\r\n\t\r\n\tif( !gl.getShaderParameter( shader, gl.COMPILE_STATUS ) ) {\r\n\t\tconsole.error( \"Shader compile error:\", gl.getShaderInfoLog( shader ) );\r\n\t\tgl.deleteShader( shader );\r\n\t\treturn null;\r\n\t}\r\n\t\r\n\treturn shader;\r\n}\r\n\r\n/**\r\n * Create a linked shader program\r\n * \r\n * @param {WebGL2RenderingContext} gl - WebGL2 context\r\n * @param {string} vertexSrc - Vertex shader source\r\n * @param {string} fragSrc - Fragment shader source\n * @param {string} [cmdName=\"screen\"] - Command name for error messages\n * @returns {WebGLProgram|null} Linked program or null on error\n */\nexport function createShaderProgram( gl, vertexSrc, fragSrc, cmdName = \"screen\" ) {\n\tlet vertexShader = null;\n\tlet fragmentShader = null;\n\tlet program = null;\n\tlet isProgramLinked = false;\n\n\ttry {\n\t\tvertexShader = compileShader( gl, gl.VERTEX_SHADER, vertexSrc );\n\t\tfragmentShader = compileShader( gl, gl.FRAGMENT_SHADER, fragSrc );\n\n\t\tif( !vertexShader || !fragmentShader ) {\n\t\t\tconst error = new Error( `${cmdName}: Unable to compile shaders.` );\n\t\t\terror.code = \"INVALID_SHADERS\";\n\t\t\tthrow error;\n\t\t}\n\n\t\tprogram = gl.createProgram();\n\t\tgl.attachShader( program, vertexShader );\n\t\tgl.attachShader( program, fragmentShader );\n\t\tgl.linkProgram( program );\n\n\t\tif( !gl.getProgramParameter( program, gl.LINK_STATUS ) ) {\n\t\t\tconst errLog = gl.getProgramInfoLog( program );\n\t\t\tconst error = new Error( `${cmdName}: Shader program error: ${errLog}.` );\n\t\t\terror.code = \"SHADER_PROGRAM_ERROR\";\n\t\t\tthrow error;\n\t\t}\n\n\t\tisProgramLinked = true;\n\t\treturn program;\n\t} finally {\n\t\tif( vertexShader ) {\n\t\t\tgl.deleteShader( vertexShader );\n\t\t}\n\t\tif( fragmentShader ) {\n\t\t\tgl.deleteShader( fragmentShader );\n\t\t}\n\t\tif( program && !isProgramLinked ) {\n\t\t\tgl.deleteProgram( program );\n\t\t}\n\t}\n}\n\r\n/**\r\n * Setup display shader for rendering FBO to screen\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @returns {void}\r\n */\r\nexport function setupDisplayShader( screenData ) {\r\n\tconst gl = screenData.gl;\r\n\t\r\n\t// Create shader program\r\n\tconst program = createShaderProgram( gl, m_displayVertSrc, m_displayFragSrc );\r\n\t\r\n\t// Create fullscreen quad vertices (NDC: -1 to 1)\r\n\tconst positions = new Float32Array( [\r\n\t\t-1, -1, // Bottom left\r\n\t\t 1, -1, // Bottom right\r\n\t\t-1,  1, // Top left\r\n\t\t-1,  1, // Top left\r\n\t\t 1, -1, // Bottom right\r\n\t\t 1,  1  // Top right\r\n\t] );\r\n\t\r\n\t// Create vertex buffer\r\n\tconst positionBuffer = gl.createBuffer();\r\n\tgl.bindBuffer( gl.ARRAY_BUFFER, positionBuffer );\r\n\tgl.bufferData( gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW );\r\n\t\r\n\t// Get attribute/uniform locations\r\n\tconst positionLoc = gl.getAttribLocation( program, \"a_position\" );\r\n\tconst textureLoc = gl.getUniformLocation( program, \"u_texture\" );\r\n\r\n\t// VAO for fullscreen quad (shared by display pass and FBO shader pass)\r\n\tconst quadVao = gl.createVertexArray();\r\n\tgl.bindVertexArray( quadVao );\r\n\tgl.bindBuffer( gl.ARRAY_BUFFER, positionBuffer );\r\n\tgl.enableVertexAttribArray( positionLoc );\r\n\tgl.vertexAttribPointer( positionLoc, 2, gl.FLOAT, false, 0, 0 );\r\n\tgl.bindVertexArray( null );\r\n\t\r\n\t// Store in screen data\r\n\tscreenData.displayProgram = program;\r\n\tscreenData.displayPositionBuffer = positionBuffer;\r\n\tscreenData.displayQuadVao = quadVao;\r\n\tscreenData.displayLocations = {\r\n\t\t\"position\": positionLoc,\r\n\t\t\"texture\": textureLoc\r\n\t};\r\n}\r\n\r\n/**\r\n * Get or create a custom shader program for a handle (lazy compile per screen).\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {{ id: number, fragmentSource: string, uniforms: Object }} handle - Shader handle\r\n * @param {string} [cmdName=\"screen\"] - Command name for compilation errors\n * @returns {{ program: WebGLProgram, locations: Object }} Program and cached locations\n */\nexport function getOrCreateCustomShaderProgram( screenData, handle, cmdName = \"screen\" ) {\n\tconst gl = screenData.gl;\r\n\tlet cache = screenData.customShaders[ handle.id ];\r\n\tif( cache ) {\r\n\t\treturn cache;\r\n\t}\r\n\tconst program = createShaderProgram( gl, m_displayVertSrc, handle.fragmentSource, cmdName );\n\tconst positionLoc = gl.getAttribLocation( program, \"a_position\" );\r\n\tconst textureLoc = gl.getUniformLocation( program, \"u_texture\" );\r\n\tconst sourceSizeLoc = gl.getUniformLocation( program, \"u_sourceSize\" );\r\n\tconst outputSizeLoc = gl.getUniformLocation( program, \"u_outputSize\" );\r\n\tconst timeLoc = gl.getUniformLocation( program, \"u_time\" );\r\n\tconst frameLoc = gl.getUniformLocation( program, \"u_frame\" );\n\tconst customUniforms = reflectCustomUniforms( gl, program );\n\tcache = {\n\t\tprogram,\n\t\tcustomUniforms,\n\t\tlocations: {\n\t\t\tposition: positionLoc,\r\n\t\t\ttexture: textureLoc,\r\n\t\t\tsourceSize: sourceSizeLoc,\r\n\t\t\toutputSize: outputSizeLoc,\r\n\t\t\ttime: timeLoc,\r\n\t\t\tframe: frameLoc\r\n\t\t}\r\n\t};\r\n\tscreenData.customShaders[ handle.id ] = cache;\r\n\treturn cache;\n}\n\nconst m_reservedUniforms = new Set( [\n\t\"u_texture\", \"u_sourceSize\", \"u_outputSize\", \"u_time\", \"u_frame\"\n] );\n\n/**\n * Convert a reflected WebGL uniform type to its GLSL ES name.\n *\n * @param {WebGL2RenderingContext} gl - WebGL2 context\n * @param {number} type - WebGL uniform type enum\n * @returns {string} GLSL type name, or \"unknown\"\n */\nfunction getUniformTypeName( gl, type ) {\n\tconst types = new Map( [\n\t\t[ gl.FLOAT, \"float\" ],\n\t\t[ gl.FLOAT_VEC2, \"vec2\" ],\n\t\t[ gl.FLOAT_VEC3, \"vec3\" ],\n\t\t[ gl.FLOAT_VEC4, \"vec4\" ],\n\t\t[ gl.INT, \"int\" ],\n\t\t[ gl.INT_VEC2, \"ivec2\" ],\n\t\t[ gl.INT_VEC3, \"ivec3\" ],\n\t\t[ gl.INT_VEC4, \"ivec4\" ],\n\t\t[ gl.UNSIGNED_INT, \"uint\" ],\n\t\t[ gl.UNSIGNED_INT_VEC2, \"uvec2\" ],\n\t\t[ gl.UNSIGNED_INT_VEC3, \"uvec3\" ],\n\t\t[ gl.UNSIGNED_INT_VEC4, \"uvec4\" ],\n\t\t[ gl.BOOL, \"bool\" ],\n\t\t[ gl.BOOL_VEC2, \"bvec2\" ],\n\t\t[ gl.BOOL_VEC3, \"bvec3\" ],\n\t\t[ gl.BOOL_VEC4, \"bvec4\" ],\n\t\t[ gl.FLOAT_MAT2, \"mat2\" ],\n\t\t[ gl.FLOAT_MAT3, \"mat3\" ],\n\t\t[ gl.FLOAT_MAT4, \"mat4\" ],\n\t\t[ gl.FLOAT_MAT2x3, \"mat2x3\" ],\n\t\t[ gl.FLOAT_MAT2x4, \"mat2x4\" ],\n\t\t[ gl.FLOAT_MAT3x2, \"mat3x2\" ],\n\t\t[ gl.FLOAT_MAT3x4, \"mat3x4\" ],\n\t\t[ gl.FLOAT_MAT4x2, \"mat4x2\" ],\n\t\t[ gl.FLOAT_MAT4x3, \"mat4x3\" ],\n\t\t[ gl.SAMPLER_2D, \"sampler2D\" ]\n\t] );\n\treturn types.get( type ) ?? \"unknown\";\n}\n\n/**\n * Inspect a cached custom shader without compiling it.\n *\n * @param {Object} screenData - Screen data object\n * @param {number} shaderId - Custom shader id\n * @returns {{ compiled: boolean, uniforms: Array<Object> }} Per-screen diagnostics\n */\nexport function getCustomShaderDiagnostics( screenData, shaderId ) {\n\tconst cache = screenData.customShaders[ shaderId ];\n\tif( !cache ) {\n\t\treturn { \"compiled\": false, \"uniforms\": [] };\n\t}\n\tconst uniforms = [];\n\tfor( const uniform of Object.values( cache.customUniforms ) ) {\n\t\tuniforms.push( {\n\t\t\t\"name\": uniform.name,\n\t\t\t\"type\": getUniformTypeName( screenData.gl, uniform.type ),\n\t\t\t\"size\": uniform.size,\n\t\t\t\"reserved\": m_reservedUniforms.has( uniform.name )\n\t\t} );\n\t}\n\treturn { \"compiled\": true, \"uniforms\": uniforms };\n}\n\n/**\n * Delete one cached custom shader program from a screen.\n *\n * @param {Object} screenData - Screen data object\n * @param {number} shaderId - Custom shader id\n * @returns {void}\n */\nexport function deleteCustomShaderProgram( screenData, shaderId ) {\n\tconst cache = screenData.customShaders[ shaderId ];\n\tif( !cache ) {\n\t\treturn;\n\t}\n\tif( cache.program ) {\n\t\tscreenData.gl.deleteProgram( cache.program );\n\t}\n\tdelete screenData.customShaders[ shaderId ];\n}\n\n/**\n * Reflect active uniforms so JavaScript values can be dispatched by their GLSL types.\n *\n * @param {WebGL2RenderingContext} gl - WebGL2 context\n * @param {WebGLProgram} program - Linked shader program\n * @returns {Object} Uniform metadata keyed by base uniform name\n */\nfunction reflectCustomUniforms( gl, program ) {\n\tconst uniforms = {};\n\tconst count = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );\n\tfor( let i = 0; i < count; i++ ) {\n\t\tconst active = gl.getActiveUniform( program, i );\n\t\tif( !active ) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst name = active.name.endsWith( \"[0]\" ) ? active.name.slice( 0, -3 ) : active.name;\n\t\tuniforms[ name ] = {\n\t\t\t\"location\": gl.getUniformLocation( program, active.name ),\n\t\t\t\"name\": name,\n\t\t\t\"size\": active.size,\n\t\t\t\"type\": active.type\n\t\t};\n\t}\n\treturn uniforms;\n}\n\n/**\n * Compile and validate a custom shader before it changes rendering state.\n *\n * Programs are cached per screen after successful compilation. Custom post-processing shaders\n * must sample the current framebuffer through u_texture.\n *\n * @param {Object} screenData - Screen data object\n * @param {{ id: number, fragmentSource: string, uniforms: Object }} handle - Shader handle\n * @param {string} cmdName - Public command applying the shader\n * @returns {{ program: WebGLProgram, locations: Object }} Validated program cache\n */\nexport function validateCustomShaderProgram( screenData, handle, cmdName ) {\n\tconst cache = getOrCreateCustomShaderProgram( screenData, handle, cmdName );\n\tif( cache.locations.texture === null ) {\n\t\tconst error = new Error(\n\t\t\t`${cmdName}: Missing required uniform u_texture in shader.`\n\t\t);\n\t\terror.code = \"MISSING_U_TEXTURE\";\n\t\tthrow error;\n\t}\n\treturn cache;\n}\n\r\nconst m_isDebug = typeof window !== \"undefined\" && window.location.search.includes( \"webgl-debug\" );\n\nfunction uniformError( cmdName, code, message ) {\n\tconst error = new TypeError( `${cmdName}: ${message}` );\n\terror.code = code;\n\treturn error;\n}\n\nfunction getUniformTypeInfo( gl, type ) {\n\tconst types = new Map( [\n\t\t[ gl.FLOAT, [ \"float\", 1, \"float\" ] ],\n\t\t[ gl.FLOAT_VEC2, [ \"float\", 2, \"float\" ] ],\n\t\t[ gl.FLOAT_VEC3, [ \"float\", 3, \"float\" ] ],\n\t\t[ gl.FLOAT_VEC4, [ \"float\", 4, \"float\" ] ],\n\t\t[ gl.INT, [ \"int\", 1, \"int\" ] ],\n\t\t[ gl.INT_VEC2, [ \"int\", 2, \"int\" ] ],\n\t\t[ gl.INT_VEC3, [ \"int\", 3, \"int\" ] ],\n\t\t[ gl.INT_VEC4, [ \"int\", 4, \"int\" ] ],\n\t\t[ gl.UNSIGNED_INT, [ \"uint\", 1, \"uint\" ] ],\n\t\t[ gl.UNSIGNED_INT_VEC2, [ \"uint\", 2, \"uint\" ] ],\n\t\t[ gl.UNSIGNED_INT_VEC3, [ \"uint\", 3, \"uint\" ] ],\n\t\t[ gl.UNSIGNED_INT_VEC4, [ \"uint\", 4, \"uint\" ] ],\n\t\t[ gl.BOOL, [ \"bool\", 1, \"int\" ] ],\n\t\t[ gl.BOOL_VEC2, [ \"bool\", 2, \"int\" ] ],\n\t\t[ gl.BOOL_VEC3, [ \"bool\", 3, \"int\" ] ],\n\t\t[ gl.BOOL_VEC4, [ \"bool\", 4, \"int\" ] ],\n\t\t[ gl.FLOAT_MAT2, [ \"matrix2fv\", 4, \"float\" ] ],\n\t\t[ gl.FLOAT_MAT3, [ \"matrix3fv\", 9, \"float\" ] ],\n\t\t[ gl.FLOAT_MAT4, [ \"matrix4fv\", 16, \"float\" ] ],\n\t\t[ gl.FLOAT_MAT2x3, [ \"matrix2x3fv\", 6, \"float\" ] ],\n\t\t[ gl.FLOAT_MAT2x4, [ \"matrix2x4fv\", 8, \"float\" ] ],\n\t\t[ gl.FLOAT_MAT3x2, [ \"matrix3x2fv\", 6, \"float\" ] ],\n\t\t[ gl.FLOAT_MAT3x4, [ \"matrix3x4fv\", 12, \"float\" ] ],\n\t\t[ gl.FLOAT_MAT4x2, [ \"matrix4x2fv\", 8, \"float\" ] ],\n\t\t[ gl.FLOAT_MAT4x3, [ \"matrix4x3fv\", 12, \"float\" ] ]\n\t] );\n\tif( type === gl.SAMPLER_2D ) {\n\t\treturn { \"components\": 1, \"family\": \"sampler\", \"setter\": \"sampler\" };\n\t}\n\tconst info = types.get( type );\n\tif( !info ) {\n\t\treturn null;\n\t}\n\treturn { \"components\": info[ 1 ], \"family\": info[ 2 ], \"setter\": info[ 0 ] };\n}\n\nfunction isNumericArray( value ) {\n\treturn Array.isArray( value ) || value instanceof Float32Array ||\n\t\tvalue instanceof Int32Array || value instanceof Uint32Array;\n}\n\nfunction normalizeNumericUniform( info, value, cmdName ) {\n\tconst expectedLength = info.components * info.uniform.size;\n\tlet values;\n\tif( expectedLength === 1 && !isNumericArray( value ) ) {\n\t\tvalues = [ value ];\n\t} else if( isNumericArray( value ) ) {\n\t\tvalues = Array.from( value );\n\t} else {\n\t\tthrow uniformError(\n\t\t\tcmdName, \"INVALID_UNIFORM_VALUE\",\n\t\t\t`Uniform \"${info.uniform.name}\" requires ${expectedLength} values.`\n\t\t);\n\t}\n\tif( values.length !== expectedLength ) {\n\t\tthrow uniformError(\n\t\t\tcmdName, \"INVALID_UNIFORM_VALUE\",\n\t\t\t`Uniform \"${info.uniform.name}\" requires ${expectedLength} values.`\n\t\t);\n\t}\n\tfor( const item of values ) {\n\t\tlet isValid = typeof item === \"number\" && Number.isFinite( item );\n\t\tif( info.setter === \"bool\" ) {\n\t\t\tisValid = typeof item === \"boolean\";\n\t\t} else if( info.family === \"int\" || info.family === \"uint\" ) {\n\t\t\tisValid = isValid && Number.isInteger( item );\n\t\t\tif( info.family === \"uint\" ) {\n\t\t\t\tisValid = isValid && item >= 0 && item <= 4294967295;\n\t\t\t} else {\n\t\t\t\tisValid = isValid && item >= -2147483648 && item <= 2147483647;\n\t\t\t}\n\t\t}\n\t\tif( !isValid ) {\n\t\t\tthrow uniformError(\n\t\t\t\tcmdName, \"INVALID_UNIFORM_VALUE\",\n\t\t\t\t`Uniform \"${info.uniform.name}\" contains an invalid value.`\n\t\t\t);\n\t\t}\n\t}\n\tif( info.setter === \"bool\" ) {\n\t\tvalues = values.map( ( item ) => {\n\t\t\tif( item ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\treturn 0;\n\t\t} );\n\t}\n\tif( info.family === \"float\" ) {\n\t\treturn new Float32Array( values );\n\t}\n\tif( info.family === \"uint\" ) {\n\t\treturn new Uint32Array( values );\n\t}\n\treturn new Int32Array( values );\n}\n\n/**\n * Validate and snapshot custom uniform values without changing WebGL state.\n *\n * @param {WebGL2RenderingContext} gl - WebGL2 context\n * @param {Object} cache - Custom shader program cache\n * @param {Object} uniforms - Merged custom uniform values\n * @param {string} cmdName - Public command name\n * @param {Function} resolveSampler - Converts a public image input to an image source\n * @returns {Object} Normalized uniform bindings\n */\nexport function normalizeCustomUniforms( gl, cache, uniforms, cmdName, resolveSampler ) {\n\tconst normalized = {};\n\tconst samplerInfos = Object.values( cache.customUniforms ).filter( ( uniform ) => {\n\t\tif( m_reservedUniforms.has( uniform.name ) ) {\n\t\t\treturn false;\n\t\t}\n\t\tconst typeInfo = getUniformTypeInfo( gl, uniform.type );\n\t\treturn typeInfo && typeInfo.family === \"sampler\";\n\t} );\n\tconst samplerCount = samplerInfos.reduce( ( total, uniform ) => total + uniform.size, 0 );\n\tif( samplerCount + 1 > gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS ) ) {\n\t\tthrow uniformError(\n\t\t\tcmdName, \"TOO_MANY_TEXTURE_UNIFORMS\",\n\t\t\t\"Shader requires more fragment texture units than this WebGL context supports.\"\n\t\t);\n\t}\n\n\tfor( const name of Object.keys( uniforms ?? {} ) ) {\n\t\tif( m_reservedUniforms.has( name ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst uniform = cache.customUniforms[ name ];\n\t\tif( !uniform ) {\n\t\t\tif( m_isDebug ) {\n\t\t\t\tconsole.warn( `${cmdName}: Unknown uniform \"${name}\" ignored.` );\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tconst typeInfo = getUniformTypeInfo( gl, uniform.type );\n\t\tif( !typeInfo ) {\n\t\t\tthrow uniformError(\n\t\t\t\tcmdName, \"UNSUPPORTED_UNIFORM_TYPE\",\n\t\t\t\t`Uniform \"${name}\" uses an unsupported GLSL type.`\n\t\t\t);\n\t\t}\n\t\tconst info = {\n\t\t\t\"components\": typeInfo.components,\n\t\t\t\"family\": typeInfo.family,\n\t\t\t\"setter\": typeInfo.setter,\n\t\t\t\"uniform\": uniform\n\t\t};\n\t\tif( info.family === \"sampler\" ) {\n\t\t\tconst inputs = uniform.size === 1 ? [ uniforms[ name ] ] : uniforms[ name ];\n\t\t\tif( !Array.isArray( inputs ) || inputs.length !== uniform.size ) {\n\t\t\t\tthrow uniformError(\n\t\t\t\t\tcmdName, \"INVALID_UNIFORM_VALUE\",\n\t\t\t\t\t`Uniform \"${name}\" requires ${uniform.size} image inputs.`\n\t\t\t\t);\n\t\t\t}\n\t\t\tnormalized[ name ] = {\n\t\t\t\t\"info\": info,\n\t\t\t\t\"sources\": inputs.map( ( input ) => resolveSampler( input ) )\n\t\t\t};\n\t\t} else {\n\t\t\tnormalized[ name ] = {\n\t\t\t\t\"info\": info,\n\t\t\t\t\"value\": normalizeNumericUniform( info, uniforms[ name ], cmdName )\n\t\t\t};\n\t\t}\n\t}\n\n\tfor( const uniform of samplerInfos ) {\n\t\tif( !normalized[ uniform.name ] ) {\n\t\t\tthrow uniformError(\n\t\t\t\tcmdName, \"INVALID_UNIFORM_VALUE\",\n\t\t\t\t`Sampler uniform \"${uniform.name}\" requires an image input.`\n\t\t\t);\n\t\t}\n\t}\n\treturn normalized;\n}\n\r\n/**\r\n * Set normalized custom uniforms on a program.\n *\r\n * @param {WebGL2RenderingContext} gl - WebGL2 context\r\n * @param {Object} uniforms - Normalized uniform bindings\n * @param {Function} getTexture - Gets a WebGL texture for a sampler source\n * @returns {void}\r\n */\r\nexport function setCustomUniforms( gl, uniforms, getTexture ) {\n\tlet textureUnit = 1;\n\tfor( const binding of Object.values( uniforms ?? {} ) ) {\n\t\tconst { info, value, sources } = binding;\n\t\tconst loc = info.uniform.location;\n\t\tif( info.family === \"sampler\" ) {\n\t\t\tconst units = [];\n\t\t\tfor( const source of sources ) {\n\t\t\t\tgl.activeTexture( gl.TEXTURE0 + textureUnit );\n\t\t\t\tgl.bindTexture( gl.TEXTURE_2D, getTexture( source ) );\n\t\t\t\tunits.push( textureUnit++ );\n\t\t\t}\n\t\t\tif( units.length === 1 ) {\n\t\t\t\tgl.uniform1i( loc, units[ 0 ] );\n\t\t\t} else {\n\t\t\t\tgl.uniform1iv( loc, new Int32Array( units ) );\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif( info.setter.startsWith( \"matrix\" ) ) {\n\t\t\tgl[ `uniformMatrix${info.setter.slice( 6 )}` ]( loc, false, value );\n\t\t} else if( info.components === 1 && info.uniform.size === 1 ) {\n\t\t\tlet method = \"uniform1i\";\n\t\t\tif( info.family === \"float\" ) {\n\t\t\t\tmethod = \"uniform1f\";\n\t\t\t} else if( info.family === \"uint\" ) {\n\t\t\t\tmethod = \"uniform1ui\";\n\t\t\t}\n\t\t\tgl[ method ]( loc, value[ 0 ] );\n\t\t} else {\n\t\t\tlet suffix = \"iv\";\n\t\t\tif( info.family === \"float\" ) {\n\t\t\t\tsuffix = \"fv\";\n\t\t\t} else if( info.family === \"uint\" ) {\n\t\t\t\tsuffix = \"uiv\";\n\t\t\t}\n\t\t\tgl[ `uniform${info.components}${suffix}` ]( loc, value );\n\t\t}\n\t}\n\tgl.activeTexture( gl.TEXTURE0 );\n}\n", "/**\r\n * Pi.js - Blends Module\r\n * \r\n * Manages the api for blending in WebGL2.\r\n * \r\n * @module api/blends\r\n */\r\n\r\n\"use strict\";\r\n\r\n// Import modules directly\r\nimport * as g_screenManager from \"../core/screen-manager.js\";\r\nimport * as g_commands from \"../core/commands.js\";\r\nimport * as g_utils from \"../core/utils.js\";\r\nimport * as g_renderer from \"../renderer/renderer.js\";\r\n\r\n// Blends\r\nexport const BLEND_REPLACE = \"replace\";\r\nexport const BLEND_ALPHA = \"alpha\";\r\nexport const BLENDS = new Set( [ BLEND_REPLACE, BLEND_ALPHA ] );\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Commands\r\n ***************************************************************************************************/\r\n\r\n\r\n// Initialize the blends\r\nexport function init( api ) {\r\n\t\r\n\t// Add Render Screen Data - Store pen and blend configuration only\r\n\tg_screenManager.addScreenDataItem( \"blends\", {\r\n\t\t\"blend\": BLEND_REPLACE, \"noise\": null, \"noiseSeed\": null, \"noiseData\": []\r\n\t} );\r\n\r\n\tregisterCommands();\r\n}\r\n\r\n\r\nfunction registerCommands() {\r\n\tg_commands.addCommand( \"setBlend\", setBlend, true, [ \"blend\" ] );\r\n\tg_commands.addCommand( \"setNoise\", setNoise, true, [ \"noise\", \"seed\" ] );\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * External API Commands\r\n ***************************************************************************************************/\r\n\r\n\r\n// Set Blend Command\r\nfunction setBlend( screenData, options ) {\r\n\tlet blend = options.blend ?? screenData.blends.blend;\r\n\r\n\tif( !BLENDS.has( blend ) ) {\r\n\t\tconst error = new TypeError(\r\n\t\t\t`setBlend: Parameter blend is not a valid blend. Valid blends are (` +\r\n\t\t\t`${Array.from( BLENDS ).join( \", \" )}).`\r\n\t\t);\r\n\t\terror.code = \"INVALID_BLEND_MODE\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Set blend data on screen\r\n\tconst previousBlend = screenData.blends.blend;\r\n\tconst previousBlends = structuredClone( screenData.blends );\r\n\tscreenData.blends.blend = blend;\r\n\r\n\t// Notify renderer that blend mode has changed\r\n\tif( previousBlend !== blend ) {\r\n\t\tg_renderer.blendModeChanged( screenData, previousBlends );\r\n\t}\r\n}\r\n\r\n\r\n// Set Noise Command\r\nfunction setNoise( screenData, options ) {\r\n\tlet noise = options.noise;\r\n\tlet seed = options.seed;\r\n\r\n\tconst noiseErrorMsg = \"setNoise: Parameter noise must either be a number ie: 32, a 1d array \" +\r\n\t\t\"with numbers ie: [23, 13, 15, 0], or a 2d array where the inner array is two arrays \" +\r\n\t\t\"first array is min values second array is max values for each ie: \" +\r\n\t\t\"[[23, 15, 18, 0], [32,18, 12, 0]]. The order of items in the inner array is \" +\r\n\t\t\"[red, green, blue, alpha].\";\r\n\r\n\tlet noiseResult = null;\r\n\r\n\t// Only process noise if it's provided\r\n\tif( noise !== null ) {\r\n\r\n\t\t// Validate the noise option\r\n\t\tconst validateNoiseValFn = ( noiseVal ) => {\r\n\t\t\tif( noiseVal === null ) {\r\n\t\t\t\tconst error = new TypeError( noiseErrorMsg );\r\n\t\t\t\terror.code = \"INVALID_NOISE_VALUE\";\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\t// First validate noise if it's an array\r\n\t\tif( Array.isArray( noise ) ) {\r\n\r\n\t\t\t// Create a blank noise result\r\n\t\t\tnoiseResult = [\r\n\t\t\t\tnew Float32Array( [ 0, 0, 0, 0 ] ), new Float32Array( [ 0, 0, 0, 0 ] )\r\n\t\t\t];\r\n\r\n\t\t\t// Loop through the array max of 4 items\r\n\t\t\tfor( let i = 0; i < noise.length && i < 4; i += 1 ) {\r\n\r\n\t\t\t\tconst noiseRow = noise[ i ];\r\n\t\t\r\n\t\t\t\t// Validate if 2d array\r\n\t\t\t\tif( Array.isArray( noiseRow ) ) {\r\n\r\n\t\t\t\t\t// If 2d array ignore any result after 2nd item\r\n\t\t\t\t\tif( i >= 2 ) {\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Loop through inner array max of 4 items\r\n\t\t\t\t\tfor( let j = 0; j < noiseRow.length && j < 4; j += 1 ) {\r\n\t\t\t\t\t\tconst noiseVal = g_utils.getInt( noiseRow[ j ], null );\r\n\t\t\t\t\t\tvalidateNoiseValFn( noiseVal );\r\n\t\t\t\t\t\tnoiseResult[ i ][ j ] = noiseVal / 255;\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tconst noiseVal = g_utils.getInt( noiseRow, null );\r\n\t\t\t\t\tvalidateNoiseValFn( noiseVal );\r\n\r\n\t\t\t\t\t// Update min and max values based on parallel values\r\n\t\t\t\t\tnoiseResult[ 0 ][ i ] = -noiseVal / 255;\r\n\t\t\t\t\tnoiseResult[ 1 ][ i ] = noiseVal / 255;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\r\n\t\t\t// Validate if noise is an integer\r\n\t\t\tconst noiseVal = g_utils.getInt( noise, null );\r\n\r\n\t\t\t// If noise is an integer it will not be null\r\n\t\t\tif( noiseVal !== null ) {\r\n\t\t\t\tconst val = noiseVal / 255;\r\n\t\t\t\tnoiseResult = [\r\n\t\t\t\t\tnew Float32Array( [ -val, -val, -val, -val ] ),\r\n\t\t\t\t\tnew Float32Array( [  val,  val,  val,  val ] ),\r\n\t\t\t\t];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Set seed - if null, use time\r\n\tlet noiseSeed = g_utils.getFloat( seed, null );\r\n\r\n\t// Set noise data on screen\r\n\tconst previousNoise = screenData.blends.noise;\r\n\tconst previousSeed = screenData.blends.noiseSeed;\r\n\tconst previousBlends = structuredClone( screenData.blends );\r\n\r\n\tscreenData.blends.noise = noiseResult;\r\n\tscreenData.blends.noiseSeed = noiseSeed;\r\n\r\n\t// Check if noise has changed\r\n\tlet isNoiseChanged = false;\r\n\tif( previousNoise === null && noiseResult === null ) {\r\n\t\tisNoiseChanged = false;\r\n\t} else if(\r\n\t\tpreviousNoise === null && noiseResult !== null ||\r\n\t\tpreviousNoise !== null && noiseResult === null\r\n\t) {\r\n\t\tisNoiseChanged = true;\r\n\t} else {\r\n\t\tisNoiseChanged = JSON.stringify( previousNoise ) !== JSON.stringify( noiseResult );\r\n\t}\r\n\r\n\t// Check if seed has changed\r\n\tconst isSeedChanged = previousSeed !== noiseSeed;\r\n\r\n\t// Notify renderer that noise or seed has changed\r\n\tif( isNoiseChanged || isSeedChanged ) {\r\n\t\tg_renderer.blendModeChanged( screenData, previousBlends );\r\n\t}\r\n}\r\n", "#version 300 es\r\nin vec2 a_position;\r\nin vec4 a_color;\r\nuniform vec2 u_resolution;\r\nout vec4 v_color;\r\n\r\nvoid main() {\r\n\r\n\t// Convert screen coords to NDC with pixel center adjustment\r\n\t// Add 0.5 to center the pixel, then convert to NDC\r\n\tvec2 pixelCenter = a_position + 0.5;\r\n\tvec2 ndc = ((pixelCenter / u_resolution) * 2.0 - 1.0) * vec2(1.0, -1.0);\r\n\tgl_Position = vec4(ndc, 0.0, 1.0);\r\n\tgl_PointSize = 1.0;\r\n\tv_color = a_color;\r\n}\r\n\r\n", "#version 300 es\r\nprecision mediump float;\r\nin vec4 v_color;\r\nuniform vec4 u_noiseMin;\r\nuniform vec4 u_noiseMax;\r\nuniform float u_time;\r\nout vec4 fragColor;\r\n\r\n// A hash function that works with integer coordinates\r\n// This tends to be very effective at breaking coherence.\r\nfloat hash(vec2 p) {\r\n\tp = fract(p * vec2(5.3983, 5.4439));\r\n\tp += dot(p, p.yx + 2.153); // Add a small value to break symmetry\r\n\treturn fract(p.x * p.y * 954.3121);\r\n}\r\n\r\n// Map value from [0,1] range to [min,max] range\r\nfloat mapRange(float value, float min, float max) {\r\n\treturn min + value * (max - min);\r\n}\r\n\r\nvoid main() {\r\n\r\n\tvec4 baseColor = v_color;\r\n\tvec4 pixelNoise = vec4(0.0);\r\n\r\n\tfloat noiseRange = abs(u_noiseMax.r - u_noiseMin.r) +\r\n\t                   abs(u_noiseMax.g - u_noiseMin.g) +\r\n\t                   abs(u_noiseMax.b - u_noiseMin.b) +\r\n\t                   abs(u_noiseMax.a - u_noiseMin.a);\r\n\r\n\tif (noiseRange > 0.0001) {\r\n\r\n\t\t// Use integer coordinates for the hash function\r\n\t\t// This is critical for noise that looks truly random at pixel level\r\n\t\tvec2 iFragCoord = floor(gl_FragCoord.xy);\r\n\r\n\t\t// Combine iFragCoord with u_time and different offsets for each channel\r\n\t\t// The offsets here can be smaller because the hash itself is strong.\r\n\t\tfloat noiseR = hash(iFragCoord + vec2(u_time * 0.01, u_time * 0.02) + vec2(10.0, 20.0));\r\n\t\tfloat noiseG = hash(iFragCoord + vec2(u_time * 0.03, u_time * 0.04) + vec2(30.0, 40.0));\r\n\t\tfloat noiseB = hash(iFragCoord + vec2(u_time * 0.05, u_time * 0.06) + vec2(50.0, 60.0));\r\n\t\tfloat noiseA = hash(iFragCoord + vec2(u_time * 0.07, u_time * 0.08) + vec2(70.0, 80.0));\r\n\r\n\t\tpixelNoise.r = mapRange(noiseR, u_noiseMin.r, u_noiseMax.r);\r\n\t\tpixelNoise.g = mapRange(noiseG, u_noiseMin.g, u_noiseMax.g);\r\n\t\tpixelNoise.b = mapRange(noiseB, u_noiseMin.b, u_noiseMax.b);\r\n\t\tpixelNoise.a = mapRange(noiseA, u_noiseMin.a, u_noiseMax.a);\r\n\t}\r\n\r\n\tvec4 finalColor = baseColor + pixelNoise;\r\n\tfragColor = clamp(finalColor, 0.0, 1.0);\r\n}", "#version 300 es\r\nin vec4 a_position;\r\nin vec4 a_color;\r\nin vec2 a_texCoord;\r\n\r\nuniform vec2 u_resolution;\r\n\r\nout vec4 v_color;\r\nout vec2 v_texCoord;\r\n\r\nvoid main() {\r\n\t\r\n\t// Convert from pixel space (0 to u_resolution) to clip space (-1 to 1)\r\n\tvec2 zeroToOne = a_position.xy / u_resolution;\r\n\tvec2 zeroToTwo = zeroToOne * 2.0;\r\n\tvec2 clipSpace = zeroToTwo - 1.0;\r\n\r\n\t// Flip the Y-coordinate to match standard 2D graphics (top-left origin)\r\n\t// In WebGL, +Y is typically up, but for 2D, we want +Y down.\r\n\tgl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);\r\n\r\n\tv_color = a_color;\r\n\tv_texCoord = a_texCoord;\r\n}\r\n\r\n", "#version 300 es\r\nprecision highp float;\r\n\r\nin vec4 v_color;\r\nin vec2 v_texCoord;\r\n\r\nuniform sampler2D u_texture;\r\n\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n\r\n\t// Sample the color from the texture at the given texture coordinates\r\n\tvec4 texColor = texture(u_texture, v_texCoord);\r\n\r\n\t// Multiply the texture color by the vertex color (which can be used for tinting/alpha)\r\n\t// If v_color is white (1,1,1,1), it will just use the texColor.\r\n\toutColor = texColor * v_color;\r\n}\r\n\r\n", "#version 300 es\r\nin vec2 a_position;\r\nin vec4 a_color;\r\nuniform vec2 u_resolution;\r\nout vec4 v_color;\r\n\r\nvoid main() {\r\n\t\r\n\t// For TRIANGLES/LINES, a_position directly represents the desired vertex\r\n\t// position (e.g., top-left of a pixel boundary).\r\n\t// No 0.5 offset needed for precise geometry rasterization.\r\n\tvec2 ndc = ((a_position / u_resolution) * 2.0 - 1.0) * vec2(1.0, -1.0);\r\n\tgl_Position = vec4(ndc, 0.0, 1.0);\r\n\tv_color = a_color;\r\n}", "/**\r\n * Pi.js - Batches and Rendering Module\r\n * \r\n * Batch system for rendering points and images efficiently.\r\n * Combines batch management and rendering operations.\r\n * \r\n * @module api/renderer/batches\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_shaders from \"./shaders.js\";\r\nimport * as g_screenManager from \"../core/screen-manager.js\";\r\n\r\n// Import blend mode constants\r\nimport * as g_blends from \"../api/blends.js\";\r\n\r\n// Shaders are imported from external files via esbuild text loader\r\nimport m_pointVertSrc from \"./shaders/point.vert\";\r\nimport m_pointFragSrc from \"./shaders/point.frag\";\r\nimport m_imageVertSrc from \"./shaders/image.vert\";\r\nimport m_imageFragSrc from \"./shaders/image.frag\";\r\nimport m_gemoetryVertSrc from \"./shaders/geometry.vert\";\r\n\r\n\r\n/**************************************************************************************************\r\n * Constants\r\n **************************************************************************************************/\r\n\r\n\r\nexport const POINTS_BATCH = 0;\r\nexport const IMAGE_BATCH = 1;\r\nexport const GEOMETRY_BATCH = 2;\r\nexport const POINTS_REPLACE_BATCH = 3;\r\nexport const IMAGE_REPLACE_BATCH = 4;\r\nexport const SHADER_BATCH = 5;\r\n\r\n// Resize by doubling up to 8 times\r\nconst MAX_SIZE_MULTIPLIER = Math.pow( 2, 8 );\r\n\r\n// Set point batch size to 7500 defautl up to 1_920_000\r\nconst DEFAULT_POINT_BATCH_SIZE = 7500;\r\nconst MAX_POINT_BATCH_SIZE = DEFAULT_POINT_BATCH_SIZE * MAX_SIZE_MULTIPLIER;\r\n\r\n// Set image batch size to 700 defautl up to 179_200\r\nconst DEFAULT_IMAGE_BATCH_SIZE = 700;\r\nconst MAX_IMAGE_BATCH_SIZE = DEFAULT_IMAGE_BATCH_SIZE * MAX_SIZE_MULTIPLIER;\r\n\r\n// Set geometry batch size to 800 default up to 204_800\r\nconst DEFAULT_GEOMETRY_BATCH_SIZE = 800;\r\nconst MAX_GEOMETRY_BATCH_SIZE = DEFAULT_GEOMETRY_BATCH_SIZE * MAX_SIZE_MULTIPLIER;\r\n\r\n// Batch will automatically shrink by 1/2 every 5 seconds if capacity is not used\r\nconst BATCH_CAPACITY_SHRINK_INTERVAL = 5000;\r\n\r\n// String constants to identify batch system names\r\nconst BATCH_TYPES = [ \"POINTS\", \"IMAGE\", \"GEOMETRY\", \"POINTS_REPLACE\", \"IMAGE_REPLACE\", \"SHADER\" ];\r\n\r\n// Batch prototype\r\nconst m_batchProto = {\r\n\t\r\n\t// Type of batch POINTS_BATCH, IMAGE_BATCH, etc...\r\n\t\"type\": null,\r\n\t\"overrideGlobalBlend\": null,   // Tri-state: null = use default, true = alpha, false = replace\r\n\r\n\t\"program\": null,\r\n\t\"vertices\": null,\r\n\t\"colors\": null,\r\n\t\"count\": 0,\r\n\r\n\t// View origin applied to local vertices\r\n\t\"originX\": 0,\r\n\t\"originY\": 0,\r\n\r\n\t// Capacity\r\n\t\"minCapacity\": 0,\r\n\t\"capacity\": 0,\r\n\t\"maxCapacity\": 0,\r\n\t\"capacityChanged\": true,\r\n\t\"capacityLocalMax\": 0,\r\n\t\"capacityShrinkCheckTime\": 0,\r\n\r\n\t// Components\r\n\t\"vertexComps\": 2,\r\n\t\"colorComps\": 4,\r\n\t\"texCoordComps\": 2,\r\n\r\n\t// WebGL resources\r\n\t\"vertexVBO\": null,\r\n\t\"colorVBO\": null,\r\n\t\"texCoordVBO\": null,\r\n\t\"vao\": null,\r\n\r\n\t// Image Specific items\r\n\t\"useTexture\": false,\r\n\t\"texture\": null,\r\n\r\n\t// Drawing mode, e.g., gl.POINTS or gl.TRIANGLES\r\n\t\"mode\": null,\r\n\r\n\t// Cached shader locations\r\n\t\"locations\": null\r\n};\r\n\r\nconst m_isDebug = window.location.search.includes( \"webgl-debug\" );\r\n\r\n\r\n/**************************************************************************************************\r\n * Module Initialization\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Initialize batch and rendering module\r\n * \r\n * @returns {void}\r\n */\r\nexport function init() {\r\n\r\n\t// Initialize screenData items owned by the batch system\r\n\tg_screenManager.addScreenDataItem( \"batches\", {} );\r\n\tg_screenManager.addScreenDataItem( \"batchInfo\", {\r\n\t\t\"currentBatch\": null,\r\n\t\t\"drawOrder\": [],\r\n\t\t\"textureBatchSet\": new Set()\r\n\t} );\r\n}\r\n\r\n/**\r\n * Creates all the batches\r\n * \r\n * @returns {void}\r\n */\r\nexport function createBatches( screenData ) {\r\n\r\n\t// Create the point batch\r\n\tscreenData.batches[ POINTS_BATCH ] = createBatch( screenData, POINTS_BATCH );\r\n\tscreenData.batches[ IMAGE_BATCH ] = createBatch( screenData, IMAGE_BATCH );\r\n\tscreenData.batches[ GEOMETRY_BATCH ] = createBatch( screenData, GEOMETRY_BATCH );\r\n\tscreenData.batches[ POINTS_REPLACE_BATCH ] = createBatch( screenData, POINTS_REPLACE_BATCH );\r\n\tscreenData.batches[ IMAGE_REPLACE_BATCH ] = createBatch( screenData, IMAGE_REPLACE_BATCH );\r\n\r\n\t// Shader batch: no geometry, programs created lazily per handle in customShaders\r\n\tconst shaderBatch = Object.create( m_batchProto );\r\n\tshaderBatch.type = SHADER_BATCH;\r\n\tshaderBatch.overrideGlobalBlend = null;\r\n\tshaderBatch.count = 0;\r\n\tscreenData.batches[ SHADER_BATCH ] = shaderBatch;\r\n}\r\n\r\n/**\r\n * Create batch system for points or images\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {number} type - Batch type (POINTS_BATCH or IMAGE_BATCH, etc..)\r\n * @returns {Object|null} Batch object or null on error\r\n */\r\nexport function createBatch( screenData, type ) {\r\n\r\n\tconst gl = screenData.gl;\r\n\tconst batch = Object.create( m_batchProto );\r\n\r\n\t// Get shader sources based on batch type\r\n\tlet vertSrc, fragSrc;\r\n\tif( type === POINTS_BATCH ) {\r\n\t\tvertSrc = m_pointVertSrc;\r\n\t\tfragSrc = m_pointFragSrc;\r\n\t\tbatch.capacity = DEFAULT_POINT_BATCH_SIZE;\r\n\t\tbatch.minCapacity = DEFAULT_POINT_BATCH_SIZE;\r\n\t\tbatch.maxCapacity = MAX_POINT_BATCH_SIZE;\r\n\t\tbatch.mode = gl.POINTS;\r\n\t} else if( type === IMAGE_BATCH || type === IMAGE_REPLACE_BATCH ) {\r\n\t\tvertSrc = m_imageVertSrc;\r\n\t\tfragSrc = m_imageFragSrc;\r\n\t\tbatch.capacity = DEFAULT_IMAGE_BATCH_SIZE;\r\n\t\tbatch.minCapacity = DEFAULT_IMAGE_BATCH_SIZE;\r\n\t\tbatch.maxCapacity = MAX_IMAGE_BATCH_SIZE;\r\n\t\tbatch.mode = gl.TRIANGLES;\r\n\t\tbatch.useTexture = true;\r\n\t\tif( type === IMAGE_BATCH ) {\r\n\t\t\tbatch.overrideGlobalBlend = true;\r\n\t\t}\r\n\t} else if( type === GEOMETRY_BATCH ) {\r\n\t\tvertSrc = m_gemoetryVertSrc;\r\n\t\tfragSrc = m_pointFragSrc;\r\n\t\tbatch.capacity = DEFAULT_GEOMETRY_BATCH_SIZE;\r\n\t\tbatch.minCapacity = DEFAULT_GEOMETRY_BATCH_SIZE;\r\n\t\tbatch.maxCapacity = MAX_GEOMETRY_BATCH_SIZE;\r\n\t\tbatch.mode = gl.TRIANGLES;\r\n\t} else if( type === POINTS_REPLACE_BATCH ) {\r\n\t\tvertSrc = m_pointVertSrc;\r\n\t\tfragSrc = m_pointFragSrc;\r\n\t\tbatch.capacity = DEFAULT_POINT_BATCH_SIZE;\r\n\t\tbatch.minCapacity = DEFAULT_POINT_BATCH_SIZE;\r\n\t\tbatch.maxCapacity = MAX_POINT_BATCH_SIZE;\r\n\t\tbatch.mode = gl.POINTS;\r\n\t\tbatch.overrideGlobalBlend = false;\r\n\t} else {\r\n\t\tconst error = new Error( `createBatch: Unknown batch type ${type}` );\r\n\t\terror.code = \"INVALID_BATCH_TYPE\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Create the batch shader program\r\n\tbatch.program = g_shaders.createShaderProgram( gl, vertSrc, fragSrc );\r\n\r\n\t// Cache shader locations for efficiency\r\n\tbatch.locations = {\r\n\t\t\"position\": gl.getAttribLocation( batch.program, \"a_position\" ),\r\n\t\t\"color\": gl.getAttribLocation( batch.program, \"a_color\" ),\r\n\t\t\"resolution\": gl.getUniformLocation( batch.program, \"u_resolution\" )\r\n\t};\r\n\r\n\t// Add noise uniform locations for batches that use point shaders\r\n\tif(\r\n\t\ttype === POINTS_BATCH || type === POINTS_REPLACE_BATCH || type === GEOMETRY_BATCH\r\n\t) {\r\n\t\tbatch.locations.noiseMin = gl.getUniformLocation( batch.program, \"u_noiseMin\" );\r\n\t\tbatch.locations.noiseMax = gl.getUniformLocation( batch.program, \"u_noiseMax\" );\r\n\t\tbatch.locations.time = gl.getUniformLocation( batch.program, \"u_time\" );\r\n\t}\r\n\r\n\t// Setup batch type and capacity\r\n\tbatch.type = type;\r\n\r\n\t// Setup image specific webgl variables\r\n\tif( batch.useTexture === true ) {\r\n\r\n\t\t// Image-specific shader locations\r\n\t\tbatch.locations.texCoord = gl.getAttribLocation( batch.program, \"a_texCoord\" );\r\n\t\tbatch.locations.texture = gl.getUniformLocation( batch.program, \"u_texture\" );\r\n\r\n\t\t// Image-specific data array\r\n\t\tbatch.texCoords = new Float32Array( batch.capacity * batch.texCoordComps );\r\n\r\n\t\t// Image-specific VBO\r\n\t\tbatch.texCoordVBO = gl.createBuffer();\r\n\t}\r\n\r\n\t// These are created for all batches\r\n\tbatch.vertices = new Float32Array( batch.capacity * batch.vertexComps );\r\n\tbatch.colors = new Uint8Array( batch.capacity * batch.colorComps );\r\n\tbatch.vertexVBO = gl.createBuffer();\r\n\tbatch.colorVBO = gl.createBuffer();\r\n\r\n\t// Create VAO (WebGL2 only)\r\n\tbatch.vao = gl.createVertexArray();\r\n\tgl.bindVertexArray( batch.vao );\r\n\r\n\t// Setup position attribute\r\n\tgl.bindBuffer( gl.ARRAY_BUFFER, batch.vertexVBO );\r\n\tgl.enableVertexAttribArray( batch.locations.position );\r\n\tgl.vertexAttribPointer(\r\n\t\tbatch.locations.position, batch.vertexComps, gl.FLOAT, false, 0, 0\r\n\t);\r\n\r\n\t// Setup color attribute\r\n\tgl.bindBuffer( gl.ARRAY_BUFFER, batch.colorVBO );\r\n\tgl.enableVertexAttribArray( batch.locations.color );\r\n\tgl.vertexAttribPointer(\r\n\t\tbatch.locations.color, batch.colorComps, gl.UNSIGNED_BYTE, true, 0, 0\r\n\t);\r\n\r\n\t// Setup texCoord attribute for image batches\r\n\tif( batch.useTexture === true ) {\r\n\t\tgl.bindBuffer( gl.ARRAY_BUFFER, batch.texCoordVBO );\r\n\t\tgl.enableVertexAttribArray( batch.locations.texCoord );\r\n\t\tgl.vertexAttribPointer(\r\n\t\t\tbatch.locations.texCoord, batch.texCoordComps, gl.FLOAT, false, 0, 0\r\n\t\t);\r\n\t}\r\n\r\n\tgl.bindVertexArray( null );\r\n\r\n\t// Set the next shrink check time\r\n\tbatch.capacityShrinkCheckTime = Date.now() + BATCH_CAPACITY_SHRINK_INTERVAL;\r\n\r\n\treturn batch;\r\n}\r\n\r\n/**\r\n * Resize batch to new capacity\r\n * \r\n * @param {Object} batch - Batch object\r\n * @param {number} newCapacity - New capacity\r\n * @returns {void}\r\n */\r\nfunction resizeBatch( batch, newCapacity ) {\r\n\r\n\t// Resize arrays\r\n\tconst newVertices = new Float32Array( newCapacity * batch.vertexComps );\r\n\tconst newColors = new Uint8Array( newCapacity * batch.colorComps );\r\n\t\r\n\t// Copy existing data only if there is data to copy\r\n\t// When shrinking after flush, count is 0 so no copy is needed\r\n\tif( batch.count > 0 ) {\r\n\t\tnewVertices.set( batch.vertices.subarray( 0, batch.count * batch.vertexComps ) );\r\n\t\tnewColors.set( batch.colors.subarray( 0, batch.count * batch.colorComps ) );\r\n\t}\r\n\t\r\n\tbatch.vertices = newVertices;\r\n\tbatch.colors = newColors;\r\n\t\r\n\tif( batch.useTexture === true ) {\r\n\t\tconst newTexCoords = new Float32Array( newCapacity * batch.texCoordComps );\r\n\t\t\r\n\t\t// Copy existing texture coordinates only if there is data to copy\r\n\t\tif( batch.count > 0 ) {\r\n\t\t\tnewTexCoords.set( batch.texCoords.subarray( 0, batch.count * batch.texCoordComps ) );\r\n\t\t}\r\n\t\t\r\n\t\tbatch.texCoords = newTexCoords;\r\n\t}\r\n\r\n\tif( m_isDebug ) {\r\n\t\tconsole.log(\r\n\t\t\t`Batch ${BATCH_TYPES[ batch.type ]} resized from ${batch.capacity} to ${newCapacity}`\r\n\t\t);\r\n\t}\r\n\r\n\t// Update batch\r\n\tbatch.capacity = newCapacity;\r\n\tbatch.capacityChanged = true;\r\n\r\n\t// Set the time capacity last changed\r\n\tbatch.capacityShrinkCheckTime = Date.now() + BATCH_CAPACITY_SHRINK_INTERVAL;\r\n}\r\n\r\n/**\r\n * Ensure batch has capacity for items\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {number} batchType - Batch type\r\n * @param {number} itemCount - Number of items needed\r\n * @param {WebGLTexture} [texture] - Texture for images\r\n * @returns {void}\r\n */\r\nexport function prepareBatch( screenData, batchType, itemCount, texture ) {\r\n\r\n\t// Get the batch\r\n\tconst batch = screenData.batches[ batchType ];\r\n\tif( screenData.view ) {\r\n\t\tbatch.originX = screenData.view.originX;\r\n\t\tbatch.originY = screenData.view.originY;\r\n\t} else {\r\n\t\tbatch.originX = 0;\r\n\t\tbatch.originY = 0;\r\n\t}\r\n\r\n\t// Track if the batch type is changing or texture is changing (for image batches)\r\n\tconst batchInfo = screenData.batchInfo;\r\n\tconst batchTypeChanging = batchInfo.currentBatch !== batch;\r\n\tconst textureChanging = batch.useTexture === true &&\r\n\t\tbatchInfo.currentBatch === batch && batch.texture !== texture;\r\n\r\n\tif( batchTypeChanging || textureChanging ) {\r\n\t\t\r\n\t\t// Set the end index for the last drawOrderItem to it's current count\r\n\t\tif( batchInfo.drawOrder.length > 0 ) {\r\n\t\t\tconst lastDrawOrderItem = batchInfo.drawOrder[ batchInfo.drawOrder.length - 1 ];\r\n\t\t\tlastDrawOrderItem.endIndex = lastDrawOrderItem.batch.count;\r\n\t\t}\r\n\r\n\t\t// Create a new draw order item\r\n\t\tconst drawOrderItem = {\r\n\t\t\t\"batch\": batch,\r\n\t\t\t\"startIndex\": batch.count,\r\n\t\t\t\"endIndex\": null,\r\n\t\t\t\"overrideGlobalBlend\": batch.overrideGlobalBlend\r\n\t\t};\r\n\t\t\r\n\t\t// For image batches, track the current image/texture for this segment\r\n\t\tif( batch.useTexture === true ) {\r\n\t\t\tbatch.texture = texture;\r\n\t\t\tdrawOrderItem.texture = texture;\r\n\t\t\tbatchInfo.textureBatchSet.add( texture );\r\n\t\t}\r\n\r\n\t\t// Add the draw order item\r\n\t\tbatchInfo.drawOrder.push( drawOrderItem );\r\n\t\tbatchInfo.currentBatch = batch;\r\n\t}\r\n\r\n\t// Check if need to increase capacity\r\n\tconst requiredCount = batch.count + itemCount;\r\n\tif( requiredCount >= batch.capacity ) {\r\n\r\n\t\t// Make sure we don't exceed max batch size\r\n\t\tif( requiredCount > batch.maxCapacity ) {\r\n\t\t\tif( m_isDebug ) {\r\n\t\t\t\tconsole.log(\r\n\t\t\t\t\t`Batch ${BATCH_TYPES[ batch.type ]} exceeded maxCapacity ` +\r\n\t\t\t\t\t`${batch.maxCapacity}, requested ${requiredCount}.  Flushing batch to reset` +\r\n\t\t\t\t\t` count to 0.`\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t\r\n\t\t\tflushBatches( screenData );\r\n\t\t\treturn prepareBatch( screenData, batchType, itemCount, texture );\r\n\t\t}\r\n\r\n\t\t// Resize to new capacity by doubling current capacity up to maxCapacity\r\n\t\tconst newCapacity = Math.max(\r\n\t\t\trequiredCount, Math.min( batch.capacity * 2, batch.maxCapacity )\r\n\t\t);\r\n\t\tresizeBatch( batch, newCapacity );\r\n\t}\r\n}\r\n\r\n/**\r\n * Queue a shader item at the current point in draw order (batch-break, does not flush).\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {{ id: number, fragmentSource: string, uniforms: Object }} handle - Shader handle\r\n * @param {Object} uniforms - Normalized uniform bindings\n * @param {Map} samplerTextures - Sampler source to queued WebGL texture\n * @returns {void}\r\n */\r\nexport function prepareShaderBatch( screenData, handle, uniforms, samplerTextures = new Map() ) {\n\tconst batchInfo = screenData.batchInfo;\r\n\tconst batch = screenData.batches[ SHADER_BATCH ];\r\n\r\n\t// Batch-break: close current batch before adding shader item (same as prepareBatch)\r\n\tif( batchInfo.drawOrder.length > 0 ) {\r\n\t\tconst lastDrawOrderItem = batchInfo.drawOrder[ batchInfo.drawOrder.length - 1 ];\r\n\t\tlastDrawOrderItem.endIndex = lastDrawOrderItem.batch.count;\r\n\t}\r\n\r\n\tconst drawOrderItem = {\r\n\t\t\"batch\": batch,\r\n\t\t\"startIndex\": 0,\r\n\t\t\"endIndex\": 0,\r\n\t\t\"overrideGlobalBlend\": batch.overrideGlobalBlend,\n\t\t\"shaderHandle\": handle,\n\t\t\"uniforms\": uniforms ?? {},\n\t\t\"samplerTextures\": samplerTextures\n\t};\n\tfor( const texture of samplerTextures.values() ) {\n\t\tbatchInfo.textureBatchSet.add( texture );\n\t}\n\tbatchInfo.drawOrder.push( drawOrderItem );\r\n\tbatchInfo.currentBatch = batch;\n}\n\n/**\n * Count queued passes that reference a custom shader.\n *\n * @param {Object} screenData - Screen data object\n * @param {number} shaderId - Custom shader id\n * @returns {number} Number of queued shader passes\n */\nexport function countQueuedShaderPasses( screenData, shaderId ) {\n\tlet count = 0;\n\tfor( const item of screenData.batchInfo.drawOrder ) {\n\t\tif( item.shaderHandle && item.shaderHandle.id === shaderId ) {\n\t\t\tcount += 1;\n\t\t}\n\t}\n\treturn count;\n}\n\r\n/**\r\n * Run one FBO shader pass: render FBO to bufferFBO with shader, then blit back to FBO.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {{ batch: Object, shaderHandle: Object, uniforms: Object }} drawOrderItem\r\n * @returns {void}\r\n */\r\nfunction runShaderPass( screenData, drawOrderItem ) {\r\n\tconst gl = screenData.gl;\r\n\tconst handle = drawOrderItem.shaderHandle;\n\tconst uniforms = drawOrderItem.uniforms;\n\tconst samplerTextures = drawOrderItem.samplerTextures;\n\r\n\tconst { program, locations } = g_shaders.getOrCreateCustomShaderProgram( screenData, handle );\r\n\tif( locations.texture === null ) {\r\n\t\tconst error = new Error( \"applyShader: Missing required uniform u_texture in shader.\" );\r\n\t\terror.code = \"MISSING_U_TEXTURE\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tconst w = screenData.width;\r\n\tconst h = screenData.height;\r\n\r\n\t// 1. Bind bufferFBO as draw target, render fullscreen quad with FBO texture as input\r\n\tgl.bindFramebuffer( gl.FRAMEBUFFER, screenData.bufferFBO );\r\n\tgl.viewport( 0, 0, w, h );\r\n\tgl.disable( gl.BLEND );\r\n\tgl.disable( gl.SCISSOR_TEST );\r\n\r\n\tgl.useProgram( program );\r\n\tgl.bindVertexArray( screenData.displayQuadVao );\r\n\r\n\tgl.activeTexture( gl.TEXTURE0 );\r\n\tgl.bindTexture( gl.TEXTURE_2D, screenData.fboTexture );\r\n\tgl.uniform1i( locations.texture, 0 );\r\n\r\n\tif( locations.sourceSize !== null ) {\r\n\t\tgl.uniform2f( locations.sourceSize, w, h );\r\n\t}\r\n\tif( locations.outputSize !== null ) {\r\n\t\tgl.uniform2f( locations.outputSize, w, h );\r\n\t}\r\n\tif( locations.time !== null ) {\r\n\t\tgl.uniform1f( locations.time, performance.now() / 1000 );\r\n\t}\r\n\tif( locations.frame !== null ) {\r\n\t\tgl.uniform1i( locations.frame, screenData.frameCount ?? 0 );\r\n\t}\r\n\r\n\tg_shaders.setCustomUniforms( gl, uniforms, ( source ) => samplerTextures.get( source ) );\n\r\n\tgl.drawArrays( gl.TRIANGLES, 0, 6 );\r\n\r\n\tgl.bindVertexArray( null );\r\n\r\n\t// 2. Blit bufferFBO (READ) \u2192 FBO (DRAW)\r\n\tgl.bindFramebuffer( gl.READ_FRAMEBUFFER, screenData.bufferFBO );\r\n\tgl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, screenData.FBO );\r\n\tgl.blitFramebuffer( 0, 0, w, h, 0, 0, w, h, gl.COLOR_BUFFER_BIT, gl.NEAREST );\r\n\r\n\t// 3. Restore FBO as current for remaining draw order items\r\n\tgl.bindFramebuffer( gl.READ_FRAMEBUFFER, null );\r\n\tgl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, screenData.FBO );\r\n}\r\n\r\n/**\r\n * Flush all batches to FBO\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Object|null} blends - Blends data including blend mode, noise, seed or null for default\r\n * @param {Array<Float32Array>|null} noise - Noise values\r\n * @returns {void}\r\n */\r\nexport function flushBatches( screenData, blends = null ) {\r\n\t// Avoid rebinding framebuffers and restoring GL state when a screen has no queued work.\r\n\t// The first flush still initializes a newly created framebuffer.\r\n\tif( !screenData.isFirstRender && screenData.batchInfo.drawOrder.length === 0 ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif( blends === null ) {\r\n\t\tblends = screenData.blends;\r\n\t}\r\n\t\r\n\tconst gl = screenData.gl;\r\n\r\n\tif( screenData.contextLost ) {\r\n\r\n\t\t// TODO-LATER: Maybe add warning here?\r\n\t\t// console.warn( \"WebGL context lost unable to render screen.\" );\r\n\t\treturn;\r\n\t}\r\n\r\n\tscreenData.frameCount = ( screenData.frameCount ?? 0 ) + 1;\r\n\r\n\t// Bind FBO\r\n\tgl.bindFramebuffer( gl.FRAMEBUFFER, screenData.FBO );\r\n\t\r\n\t// Set viewport\r\n\tgl.viewport( 0, 0, screenData.width, screenData.height );\r\n\t\r\n\t// Clear FBO on first render only\r\n\tif( screenData.isFirstRender ) {\r\n\t\tgl.clearColor( 0, 0, 0, 0 );\r\n\t\tgl.clear( gl.COLOR_BUFFER_BIT );\r\n\t\tscreenData.isFirstRender = false;\r\n\t}\r\n\r\n\t// Upload batch buffers\r\n\tfor( const batchType in screenData.batches ) {\r\n\t\tconst batch = screenData.batches[ batchType ];\r\n\t\tif( batch.count > 0 ) {\r\n\t\t\tuploadBatch( gl, batch, screenData.width, screenData.height );\r\n\t\t}\r\n\t}\r\n\r\n\t// Apply the current view scissor for geometry; shader passes disable it\r\n\tapplyViewScissor( gl, screenData );\r\n\r\n\t// Draw items\r\n\tfor( const drawOrderItem of screenData.batchInfo.drawOrder ) {\r\n\t\tif( drawOrderItem.endIndex === null ) {\r\n\t\t\tdrawOrderItem.endIndex = drawOrderItem.batch.count;\r\n\t\t}\r\n\r\n\t\tif( drawOrderItem.batch.type === SHADER_BATCH ) {\r\n\t\t\trunShaderPass( screenData, drawOrderItem );\r\n\t\t\tapplyViewScissor( gl, screenData );\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// Only draw the batch if there is something to draw\r\n\t\tif( drawOrderItem.endIndex - drawOrderItem.startIndex > 0 ) {\r\n\r\n\t\t\t// Set blend mode for this item\r\n\t\t\tif( drawOrderItem.overrideGlobalBlend === null ) {\r\n\r\n\t\t\t\t// Other batches use global blend mode\r\n\t\t\t\tif( blends.blend === g_blends.BLEND_REPLACE ) {\r\n\t\t\t\t\tgl.disable( gl.BLEND );\r\n\t\t\t\t} else {\r\n\t\t\t\t\tgl.enable( gl.BLEND );\r\n\t\t\t\t\tgl.blendFuncSeparate(\r\n\t\t\t\t\t\tgl.SRC_ALPHA,           // srcRGBFactor\r\n\t\t\t\t\t\tgl.ONE_MINUS_SRC_ALPHA, // dstRGBFactor\r\n\t\t\t\t\t\tgl.ONE,                 // srcAlphaFactor - src alpha factor 1.0 (no scale)\r\n\t\t\t\t\t\tgl.ONE_MINUS_SRC_ALPHA  // dstAlphaFactor - dst alpha factor (1-src.a)\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if( drawOrderItem.overrideGlobalBlend === true ) {\r\n\r\n\t\t\t\t// IMAGE_BATCH always uses alpha blending\r\n\t\t\t\tgl.enable( gl.BLEND );\r\n\t\t\t\tgl.blendFuncSeparate(\r\n\t\t\t\t\tgl.SRC_ALPHA,           // srcRGBFactor\r\n\t\t\t\t\tgl.ONE_MINUS_SRC_ALPHA, // dstRGBFactor\r\n\t\t\t\t\tgl.ONE,                 // srcAlphaFactor - src alpha factor 1.0 (no scale)\r\n\t\t\t\t\tgl.ONE_MINUS_SRC_ALPHA  // dstAlphaFactor - dst alpha factor (1-src.a)\r\n\t\t\t\t);\r\n\t\t\t} else {\r\n\t\t\t\tgl.disable( gl.BLEND );\r\n\t\t\t}\r\n\r\n\t\t\tlet texture = null;\r\n\t\t\tif( drawOrderItem.batch.useTexture === true ) {\r\n\t\t\t\ttexture = drawOrderItem.texture;\r\n\t\t\t}\r\n\t\t\tdrawBatch(\r\n\t\t\t\tgl, screenData, drawOrderItem.batch,\r\n\t\t\t\tdrawOrderItem.startIndex, drawOrderItem.endIndex, texture, blends\r\n\t\t\t);\r\n\t\t}\r\n\t}\r\n\r\n\t// Reset Batches\r\n\tfor( const batchType in screenData.batches ) {\r\n\t\tconst batch = screenData.batches[ batchType ];\r\n\t\tresetBatch( batch );\r\n\t}\r\n\r\n\t// Reset drawOrder object\r\n\tscreenData.batchInfo.drawOrder = [];\r\n\tscreenData.batchInfo.currentBatch = null;\r\n\tscreenData.batchInfo.textureBatchSet.clear();\r\n\r\n\t// Unbind VAO\r\n\tgl.bindVertexArray( null );\r\n\r\n\tgl.disable( gl.SCISSOR_TEST );\r\n\r\n\t// Unbind FBO\r\n\tgl.bindFramebuffer( gl.FRAMEBUFFER, null );\r\n}\r\n\r\n/**\r\n * Enable scissor for the current view clip, or disable if the clip is full-screen.\r\n *\r\n * @param {WebGL2RenderingContext} gl - WebGL2 context\r\n * @param {Object} screenData - Screen data object\r\n * @returns {void}\r\n */\r\nfunction applyViewScissor( gl, screenData ) {\r\n\tconst view = screenData.view;\r\n\tif( !view || view.clipWidth <= 0 || view.clipHeight <= 0 ) {\r\n\t\tgl.enable( gl.SCISSOR_TEST );\r\n\t\tgl.scissor( 0, 0, 0, 0 );\r\n\t\treturn;\r\n\t}\r\n\r\n\tif(\r\n\t\tview.clipX === 0 && view.clipY === 0 &&\r\n\t\tview.clipWidth === screenData.width &&\r\n\t\tview.clipHeight === screenData.height\r\n\t) {\r\n\t\tgl.disable( gl.SCISSOR_TEST );\r\n\t\treturn;\r\n\t}\r\n\r\n\tgl.enable( gl.SCISSOR_TEST );\r\n\tconst scissorY = screenData.height - ( view.clipY + view.clipHeight );\r\n\tgl.scissor( view.clipX, scissorY, view.clipWidth, view.clipHeight );\r\n}\r\n\r\n/**\r\n * Upload batch data to GPU\r\n * \r\n * @param {WebGL2RenderingContext} gl - WebGL2 context\r\n * @param {Object} batch - Batch object\r\n * @param {number} width - Screen width\r\n * @param {number} height - Screen height\r\n * @returns {void}\r\n */\r\nfunction uploadBatch( gl, batch, width, height ) {\r\n\tgl.useProgram( batch.program );\r\n\tgl.uniform2f( batch.locations.resolution, width, height );\r\n\tgl.bindVertexArray( batch.vao );\r\n\t\r\n\t// Allocate or resize buffers on capacity change\r\n\tif( batch.capacityChanged ) {\r\n\t\tgl.bindBuffer( gl.ARRAY_BUFFER, batch.vertexVBO );\r\n\t\tgl.bufferData( gl.ARRAY_BUFFER, batch.vertices.byteLength, gl.STREAM_DRAW );\r\n\t\tgl.bindBuffer( gl.ARRAY_BUFFER, batch.colorVBO );\r\n\t\tgl.bufferData( gl.ARRAY_BUFFER, batch.colors.byteLength, gl.STREAM_DRAW );\r\n\r\n\t\tif( batch.useTexture === true ) {\r\n\t\t\tgl.bindBuffer( gl.ARRAY_BUFFER, batch.texCoordVBO );\r\n\t\t\tgl.bufferData( gl.ARRAY_BUFFER, batch.texCoords.byteLength, gl.STREAM_DRAW );\r\n\t\t}\r\n\r\n\t\tbatch.capacityChanged = false;\r\n\t}\r\n\r\n\t// Upload positions\r\n\tgl.bindBuffer( gl.ARRAY_BUFFER, batch.vertexVBO );\r\n\tgl.bufferSubData( \r\n\t\tgl.ARRAY_BUFFER, 0, batch.vertices.subarray( 0, batch.count * batch.vertexComps )\r\n\t);\r\n\t\r\n\t// Upload colors\r\n\tgl.bindBuffer( gl.ARRAY_BUFFER, batch.colorVBO );\r\n\tgl.bufferSubData(\r\n\t\tgl.ARRAY_BUFFER, 0, batch.colors.subarray( 0, batch.count * batch.colorComps )\r\n\t);\r\n\r\n\t// Upload texture coordinates\r\n\tif( batch.useTexture === true ) {\r\n\t\tgl.bindBuffer( gl.ARRAY_BUFFER, batch.texCoordVBO );\r\n\t\tgl.bufferSubData(\r\n\t\t\tgl.ARRAY_BUFFER, 0, batch.texCoords.subarray( 0, batch.count * batch.texCoordComps )\r\n\t\t);\r\n\t}\r\n}\r\n\r\n/**\r\n * Draw batch to FBO\r\n * \r\n * @param {WebGL2RenderingContext} gl - WebGL2 context\r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} batch - Batch object\r\n * @param {number} startIndex - Start index in batch\r\n * @param {number} endIndex - End index in batch\r\n * @param {WebGLTexture|null} texture - Texture for image batches or null\r\n * @param {Object} blends - Blends data including blend mode, noise, seed or null default\r\n * @returns {void}\r\n */\r\nfunction drawBatch( gl, screenData, batch, startIndex, endIndex, texture = null, blends = null ) {\r\n\r\n\tgl.useProgram( batch.program );\r\n\tgl.bindVertexArray( batch.vao );\r\n\r\n\t// For image batches, bind the texture and set uniform\r\n\tif( batch.useTexture === true && texture ) {\r\n\t\tgl.activeTexture( gl.TEXTURE0 );\r\n\t\tgl.bindTexture( gl.TEXTURE_2D, texture );\r\n\t\tgl.uniform1i( batch.locations.texture, 0 );\r\n\t}\r\n\r\n\t// Set noise uniforms for batches that use point shaders\r\n\tif( batch.locations.noiseMin !== undefined ) {\r\n\t\tif( blends === null ) {\r\n\t\t\tblends = screenData.blends;\r\n\t\t}\r\n\t\tconst noise = blends.noise;\r\n\t\tconst noiseSeed = blends.noiseSeed;\r\n\t\t\r\n\t\t// Calculate noise min and max ranges\r\n\t\tlet noiseMin, noiseMax;\r\n\t\tif( noise === null ) {\r\n\r\n\t\t\t// No noise - set both to zero\r\n\t\t\tnoiseMin = new Float32Array( [ 0.0, 0.0, 0.0, 0.0 ] );\r\n\t\t\tnoiseMax = new Float32Array( [ 0.0, 0.0, 0.0, 0.0 ] );\r\n\t\t} else {\r\n\r\n\t\t\tnoiseMin = noise[ 0 ];\r\n\t\t\tnoiseMax = noise[ 1 ];\r\n\t\t}\r\n\t\t\r\n\t\tgl.uniform4fv( batch.locations.noiseMin, noiseMin );\r\n\t\tgl.uniform4fv( batch.locations.noiseMax, noiseMax );\r\n\t\t\r\n\t\t// Set time for animated noise\r\n\t\t// Use seed if available, otherwise use current time\r\n\t\tlet timeValue;\r\n\t\tif( noiseSeed !== null ) {\r\n\t\t\ttimeValue = noiseSeed / 1000.0;\r\n\t\t} else {\r\n\t\t\ttimeValue = performance.now() / 1000.0;\r\n\t\t}\r\n\t\tgl.uniform1f( batch.locations.time, timeValue );\r\n\t}\r\n\r\n\t// Draw based on batch mode\r\n\tgl.drawArrays( batch.mode, startIndex, endIndex - startIndex );\r\n}\r\n\r\n\r\n/**\r\n * Reset batches and draw order items\r\n * \r\n * @param {Object} batch - Batch object\r\n * @returns {void}\r\n */\r\nexport function resetBatches( screenData ) {\r\n\r\n\t// Reset Batches\r\n\tfor( const batchType in screenData.batches ) {\r\n\t\tconst batch = screenData.batches[ batchType ];\r\n\t\tresetBatch( batch );\r\n\t}\r\n\r\n\t// Reset drawOrder object\r\n\tscreenData.batchInfo.drawOrder = [];\r\n\tscreenData.batchInfo.currentBatch = null;\r\n\tscreenData.batchInfo.textureBatchSet.clear();\r\n}\r\n\r\n/**\r\n * Reset batch after flush\r\n * \r\n * @param {Object} batch - Batch object\r\n * @returns {void}\r\n */\r\nfunction resetBatch( batch ) {\r\n\r\n\tif( batch.type === SHADER_BATCH ) {\r\n\t\tbatch.count = 0;\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Update the batch local max\r\n\tbatch.capacityLocalMax = Math.max( batch.count, batch.capacityLocalMax );\r\n\r\n\t// Reset batch count\r\n\tbatch.count = 0;\r\n\r\n\tif( batch.useTexture === true ) {\r\n\t\tbatch.texture = null;\r\n\t\tbatch.image = null;\r\n\t}\r\n\r\n\t// Check if should shrink capacity\r\n\tif( Date.now() > batch.capacityShrinkCheckTime ) {\r\n\r\n\t\t// This will resize the batch slowly over time - cutting in half every 5 seconds\r\n\t\tif( batch.capacity > batch.minCapacity && batch.capacityLocalMax < batch.capacity * 0.5 ) {\r\n\r\n\t\t\t// Resize the batch\r\n\t\t\tresizeBatch( batch, Math.max( batch.capacity * 0.5, batch.minCapacity ) );\r\n\t\t}\r\n\r\n\t\tbatch.capacityShrinkCheckTime = Date.now() + BATCH_CAPACITY_SHRINK_INTERVAL;\r\n\t\tbatch.capacityLocalMax = 0;\r\n\t}\r\n}\r\n\r\n/**\r\n * Display FBO texture to canvas\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @returns {void}\r\n */\r\nexport function displayToCanvas( screenData ) {\r\n\t// Parent-affiliated offscreen screens share the visible screen's context but remain FBO-only.\r\n\tif( screenData.isOffscreen && screenData.parentRenderContext ) {\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tconst gl = screenData.gl;\r\n\tconst useCustom = !screenData.isOffscreen && !!screenData.displayShaderHandle;\r\n\r\n\tlet program;\r\n\tlet locations;\r\n\tlet customUniforms = null;\r\n\r\n\tif( useCustom ) {\r\n\t\tconst handle = screenData.displayShaderHandle;\r\n\t\tconst cache = g_shaders.getOrCreateCustomShaderProgram( screenData, handle );\r\n\t\tif( cache.locations.texture === null ) {\r\n\t\t\tconst error = new Error(\r\n\t\t\t\t\"setDisplayShader: Missing required uniform u_texture in shader.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"MISSING_U_TEXTURE\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\tprogram = cache.program;\r\n\t\tlocations = cache.locations;\r\n\t\tcustomUniforms = screenData.displayShaderUniformBindings ?? {};\n\t} else {\n\t\tprogram = screenData.displayProgram;\n\t\tlocations = screenData.displayLocations;\n\t}\n\tconst samplerTextures = new Map();\n\tif( useCustom ) {\n\t\tfor( const binding of Object.values( customUniforms ) ) {\n\t\t\tif( binding.info.family !== \"sampler\" ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfor( const source of binding.sources ) {\n\t\t\t\tif( !samplerTextures.has( source ) ) {\n\t\t\t\t\tsamplerTextures.set(\n\t\t\t\t\t\tsource, screenData.displayShaderTextureResolver( source )\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\r\n\t// Bind default framebuffer (screen)\r\n\tgl.bindFramebuffer( gl.FRAMEBUFFER, null );\r\n\r\n\t// Viewport always matches the actual canvas backing store\r\n\tgl.viewport( 0, 0, screenData.canvas.width, screenData.canvas.height );\r\n\r\n\t// Clear the canvas before drawing the FBO texture\r\n\tgl.clearColor( 0, 0, 0, 0 );\r\n\tgl.clear( gl.COLOR_BUFFER_BIT );\r\n\r\n\tgl.disable( gl.BLEND );\r\n\tgl.disable( gl.SCISSOR_TEST );\r\n\r\n\tgl.useProgram( program );\r\n\tgl.bindVertexArray( screenData.displayQuadVao );\r\n\r\n\tgl.activeTexture( gl.TEXTURE0 );\r\n\tgl.bindTexture( gl.TEXTURE_2D, screenData.fboTexture );\r\n\tgl.uniform1i( locations.texture, 0 );\r\n\r\n\tif( useCustom ) {\r\n\t\tif( locations.sourceSize !== null ) {\r\n\t\t\tgl.uniform2f( locations.sourceSize, screenData.width, screenData.height );\r\n\t\t}\r\n\t\tif( locations.outputSize !== null ) {\r\n\t\t\tgl.uniform2f(\r\n\t\t\t\tlocations.outputSize, screenData.canvas.width, screenData.canvas.height\r\n\t\t\t);\r\n\t\t}\r\n\t\tif( locations.time !== null ) {\r\n\t\t\tgl.uniform1f( locations.time, performance.now() / 1000 );\r\n\t\t}\r\n\t\tif( locations.frame !== null ) {\r\n\t\t\tgl.uniform1i( locations.frame, screenData.frameCount ?? 0 );\r\n\t\t}\r\n\t\tg_shaders.setCustomUniforms(\n\t\t\tgl, customUniforms, ( source ) => samplerTextures.get( source )\n\t\t);\n\t}\r\n\r\n\tgl.drawArrays( gl.TRIANGLES, 0, 6 );\r\n\r\n\tgl.bindVertexArray( null );\r\n}\r\n\r\n/**\r\n * Cleanup batch resources for screen\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @returns {void}\r\n */\r\nexport function cleanup( screenData ) {\r\n\tconst gl = screenData.gl;\r\n\r\n\t// Cleanup batches\r\n\tfor( const batchType in screenData.batches ) {\r\n\r\n\t\t// Get the batch\r\n\t\tconst batch = screenData.batches[ batchType ];\r\n\r\n\t\tif( batch.type === SHADER_BATCH ) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// Delete texCoord items\r\n\t\tif( batch.texCoordVBO ) {\r\n\t\t\tgl.deleteBuffer( batch.texCoordVBO );\r\n\t\t}\r\n\r\n\t\tgl.deleteBuffer( batch.vertexVBO );\r\n\t\tgl.deleteBuffer( batch.colorVBO );\r\n\t\tgl.deleteVertexArray( batch.vao );\r\n\t\tgl.deleteProgram( batch.program );\r\n\r\n\t\tif( batch.useTexture === true ) {\r\n\t\t\tbatch.texture = null;\r\n\t\t\tbatch.image = null;\r\n\t\t}\r\n\t}\r\n\r\n\t// Clear references for GC and signal uninitialized state\r\n\tscreenData.batches = null;\r\n\tscreenData.batchInfo = null;\r\n}\r\n", "/**\r\n * Pi.js - Batch Drawing Helpers Module\r\n * \r\n * Shared helper functions for adding geometry to batches.\r\n * Provides common operations like adding vertices, quads, and triangles.\r\n * \r\n * @module renderer/draw/batch-helpers\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_batches from \"../batches.js\";\r\n\r\n\r\n/***************************************************************************************************\r\n * Vertex Helpers\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Add a single vertex to a geometry or points batch\r\n * \r\n * @param {Object} batch - Batch object (GEOMETRY_BATCH or POINTS_BATCH)\r\n * @param {number} x - X coordinate\r\n * @param {number} y - Y coordinate\r\n * @param {Object} color - Color Object with array [ r, g, b, a ] values (0-255)\r\n * @returns {void}\r\n */\r\nexport function addVertexToBatch( batch, x, y, color ) {\r\n\tconst idx = batch.count * batch.vertexComps;\r\n\tconst cidx = batch.count * batch.colorComps;\r\n\tconst originX = batch.originX || 0;\r\n\tconst originY = batch.originY || 0;\r\n\tbatch.vertices[ idx     ] = x + originX;\r\n\tbatch.vertices[ idx + 1 ] = y + originY;\r\n\tbatch.colors[ cidx     ] = color.r;\r\n\tbatch.colors[ cidx + 1 ] = color.g;\r\n\tbatch.colors[ cidx + 2 ] = color.b;\r\n\tbatch.colors[ cidx + 3 ] = color.a;\r\n\r\n\tbatch.count++;\r\n}\r\n\r\n/**\r\n * Add a triangle (3 vertices) to a geometry batch\r\n * \r\n * @param {Object} batch - Geometry batch object\r\n * @param {number} x1 - First vertex X coordinate\r\n * @param {number} y1 - First vertex Y coordinate\r\n * @param {number} x2 - Second vertex X coordinate\r\n * @param {number} y2 - Second vertex Y coordinate\r\n * @param {number} x3 - Third vertex X coordinate\r\n * @param {number} y3 - Third vertex Y coordinate\r\n * @param {Object} color - Color object with [ r, g, b, a ] values (0-255)\r\n * @returns {void}\r\n */\r\nexport function addTriangleToBatch( batch, x1, y1, x2, y2, x3, y3, color ) {\r\n\taddVertexToBatch( batch, x1, y1, color );\r\n\taddVertexToBatch( batch, x2, y2, color );\r\n\taddVertexToBatch( batch, x3, y3, color );\r\n}\r\n\r\n/**\r\n * Add a quad (rectangle as two triangles) to a geometry batch\r\n * The quad is defined by two corner points (x1,y1) and (x2,y2) forming a rectangle\r\n * \r\n * TODO-LATER: Improve efficiency, this should work more similiarly to addTexturedQuadToBatch\r\n * \r\n * @param {Object} batch - Geometry batch object\r\n * @param {number} x1 - Left/bottom-left X coordinate\r\n * @param {number} y1 - Left/bottom-left Y coordinate\r\n * @param {number} x2 - Right/top-right X coordinate\r\n * @param {number} y2 - Right/top-right Y coordinate\r\n * @param {Object} color - Color object with [ r, g, b, a ] values (0-255)\r\n * @returns {void}\r\n */\r\nexport function addQuadToBatch( batch, x1, y1, x2, y2, color ) {\r\n\r\n\t// Truncate coordinates for pixel-perfect rendering\r\n\tconst vx1 = x1 | 0;\r\n\tconst vy1 = y1 | 0;\r\n\tconst vx2 = x2 | 0;\r\n\tconst vy2 = y2 | 0;\r\n\r\n\t// First triangle: (x1,y1), (x2,y1), (x1,y2)\r\n\taddVertexToBatch( batch, vx1, vy1, color );\r\n\taddVertexToBatch( batch, vx2, vy1, color );\r\n\taddVertexToBatch( batch, vx1, vy2, color );\r\n\r\n\t// Second triangle: (x2,y1), (x2,y2), (x1,y2)\r\n\taddVertexToBatch( batch, vx2, vy1, color );\r\n\taddVertexToBatch( batch, vx2, vy2, color );\r\n\taddVertexToBatch( batch, vx1, vy2, color );\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Curves Helpers - TODO-LATER Get out of here\r\n ***************************************************************************************************/\r\n\r\n/**\r\n * Tessellate a cubic Bezier curve into a polyline using an adaptive flatness criterion.\r\n * Returns an array of points [x0, y0, x1, y1, ..., xn, yn] including endpoints.\r\n * \r\n * TODO-LATER: Move this function to bezier module\r\n * \r\n * @param {number} x0\r\n * @param {number} y0\r\n * @param {number} x1\r\n * @param {number} y1\r\n * @param {number} x2\r\n * @param {number} y2\r\n * @param {number} x3\r\n * @param {number} y3\r\n * @param {number} maxError - Max perpendicular error in pixels\r\n * @returns {number[]}\r\n */\r\nexport function tessellateCubicBezier( x0, y0, x1, y1, x2, y2, x3, y3, maxError ) {\r\n\r\n\tconst out = [];\r\n\r\n\t// Distance from point to line segment (squared)\r\n\tfunction pointLineDistanceSq( px, py, ax, ay, bx, by ) {\r\n\t\tconst abx = bx - ax;\r\n\t\tconst aby = by - ay;\r\n\t\tconst apx = px - ax;\r\n\t\tconst apy = py - ay;\r\n\t\tconst abLenSq = abx * abx + aby * aby;\r\n\t\tif( abLenSq === 0 ) return apx * apx + apy * apy;\r\n\t\tlet t = ( apx * abx + apy * aby ) / abLenSq;\r\n\t\tif( t < 0 ) t = 0; else if( t > 1 ) t = 1;\r\n\t\tconst cx = ax + t * abx;\r\n\t\tconst cy = ay + t * aby;\r\n\t\tconst dx = px - cx;\r\n\t\tconst dy = py - cy;\r\n\t\treturn dx * dx + dy * dy;\r\n\t}\r\n\r\n\tconst maxErrorSq = maxError * maxError;\r\n\tconst maxDepth = 12;\r\n\r\n\tfunction subdivide( ax, ay, bx, by, cx, cy, dx, dy, depth ) {\r\n\r\n\t\t// Flatness test: max distance of control points to chord (a-d)\r\n\t\tconst d1 = pointLineDistanceSq( bx, by, ax, ay, dx, dy );\r\n\t\tconst d2 = pointLineDistanceSq( cx, cy, ax, ay, dx, dy );\r\n\t\tif( depth >= maxDepth || ( d1 <= maxErrorSq && d2 <= maxErrorSq ) ) {\r\n\t\t\t// Accept segment\r\n\t\t\tif( out.length === 0 ) {\r\n\t\t\t\tout.push( ax, ay );\r\n\t\t\t}\r\n\t\t\tout.push( dx, dy );\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// De Casteljau subdivision at t=0.5\r\n\t\tconst abx = ( ax + bx ) * 0.5; const aby = ( ay + by ) * 0.5;\r\n\t\tconst bcx = ( bx + cx ) * 0.5; const bcy = ( by + cy ) * 0.5;\r\n\t\tconst cdx = ( cx + dx ) * 0.5; const cdy = ( cy + dy ) * 0.5;\r\n\r\n\t\tconst abbcx = ( abx + bcx ) * 0.5; const abbcy = ( aby + bcy ) * 0.5;\r\n\t\tconst bccdx = ( bcx + cdx ) * 0.5; const bccdy = ( bcy + cdy ) * 0.5;\r\n\r\n\t\tconst midx = ( abbcx + bccdx ) * 0.5; const midy = ( abbcy + bccdy ) * 0.5;\r\n\r\n\t\tsubdivide( ax, ay, abx, aby, abbcx, abbcy, midx, midy, depth + 1 );\r\n\t\tsubdivide( midx, midy, bccdx, bccdy, cdx, cdy, dx, dy, depth + 1 );\r\n\t}\r\n\r\n\tsubdivide( x0, y0, x1, y1, x2, y2, x3, y3, 0 );\r\n\treturn out;\r\n}\r\n\r\n", "/**\r\n * Pi.js - Geometry Cache Module\r\n * \r\n * Cached geometry for commonly used shapes.\r\n * Stores pre-computed vertex data for efficient rendering.\r\n * \r\n * @module renderer/draw/geometry\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_batches from \"../batches.js\";\r\nimport * as g_batchHelpers from \"./batch-helpers.js\";\r\n\r\nexport const FILLED_CIRCLE = 0;\r\nexport const FILLED_ELLIPSE = 1;\r\n\r\n/***************************************************************************************************\r\n * Geometry Cache\r\n ***************************************************************************************************/\r\n\r\n\r\n// Cache key format: \"type:radius\"\r\n// Example: \"circle:32\" for a circle of radius 32\r\nconst m_geometryCache = new Map();\r\n\r\n// Cached vertex data structure:\r\n// {\r\n//   \"vertexCount\": number,\r\n//   \"vertices\": Float32Array,  // Raw x,y positions\r\n// }\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Initialization\r\n ***************************************************************************************************/\r\n\r\nexport { m_geometryCache as geometryCache };\r\n\r\n/**\r\n * Initialize geometry module\r\n * \r\n * @returns {void}\r\n */\r\nexport function init() {\r\n\r\n\t// Pre-populate cache with a couple circles\r\n\tprepopulateCache();\r\n}\r\n\r\n/**\r\n * Pre-populate cache with commonly used geometry\r\n * \r\n * @returns {void}\r\n */\r\nfunction prepopulateCache() {\r\n\r\n\t// Special geometries for small circle radius\r\n\t// radius 1: single pixel as 1x1 quad centered at origin covering [0,0]-[1,1]\r\n\tconst circle1 = generateSinglePixelGeometry();\r\n\tm_geometryCache.set( `${FILLED_CIRCLE}:1`, circle1 );\r\n\r\n\t// Pre-generate circles for sizes 1-10\r\n\tfor( let radius = 1; radius <= 10; radius++ ) {\r\n\t\tconst cacheKey = `${FILLED_CIRCLE}:${radius}`;\r\n\t\t\r\n\t\t// Use Alpha 2's radius threshold: (half - 0.5)^2\r\n\t\tconst geometry = generateCircleGeometry( radius );\r\n\t\tm_geometryCache.set( cacheKey, geometry );\r\n\t}\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Geometry Building Helpers\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Add a single vertex to a geometry vertices array\r\n * \r\n * @param {Float32Array} vertices - Vertices array\r\n * @param {number} vIdx - Current index into vertices array (will be modified)\r\n * @param {number} x - X coordinate\r\n * @param {number} y - Y coordinate\r\n * @returns {number} New index after adding vertex\r\n */\r\nfunction addVertex( vertices, vIdx, x, y ) {\r\n\r\n\tvertices[ vIdx++ ] = x;\r\n\tvertices[ vIdx++ ] = y;\r\n\treturn vIdx;\r\n}\r\n\r\n/**\r\n * Add a triangle (3 vertices) to a geometry vertices array\r\n * \r\n * @param {Float32Array} vertices - Vertices array\r\n * @param {number} vIdx - Current index into vertices array (will be modified)\r\n * @param {number} x1 - First vertex X coordinate\r\n * @param {number} y1 - First vertex Y coordinate\r\n * @param {number} x2 - Second vertex X coordinate\r\n * @param {number} y2 - Second vertex Y coordinate\r\n * @param {number} x3 - Third vertex X coordinate\r\n * @param {number} y3 - Third vertex Y coordinate\r\n * @returns {number} New index after adding triangle\r\n */\r\nfunction addTriangle( vertices, vIdx, x1, y1, x2, y2, x3, y3 ) {\r\n\r\n\tvIdx = addVertex( vertices, vIdx, x1, y1 );\r\n\tvIdx = addVertex( vertices, vIdx, x2, y2 );\r\n\tvIdx = addVertex( vertices, vIdx, x3, y3 );\r\n\treturn vIdx;\r\n}\r\n\r\n/**\r\n * Add a quad (rectangle as two triangles) to a geometry vertices array\r\n * The quad is defined by two corner points (x1,y1) and (x2,y2) forming a rectangle\r\n * \r\n * @param {Float32Array} vertices - Vertices array\r\n * @param {number} vIdx - Current index into vertices array (will be modified)\r\n * @param {number} x1 - Left/bottom-left X coordinate\r\n * @param {number} y1 - Left/bottom-left Y coordinate\r\n * @param {number} x2 - Right/top-right X coordinate\r\n * @param {number} y2 - Right/top-right Y coordinate\r\n * @returns {number} New index after adding quad\r\n */\r\nfunction addQuad( vertices, vIdx, x1, y1, x2, y2 ) {\r\n\r\n\t// First triangle: (x1,y1), (x2,y1), (x1,y2)\r\n\tvIdx = addTriangle( vertices, vIdx, x1, y1, x2, y1, x1, y2 );\r\n\r\n\t// Second triangle: (x2,y1), (x2,y2), (x1,y2)\r\n\tvIdx = addTriangle( vertices, vIdx, x2, y1, x2, y2, x1, y2 );\r\n\treturn vIdx;\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Geometry Generation\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Fill points in an array first, then generate scanlines for pixel-perfect results\r\n * \r\n * @param {number} radius - Radius of the circle\r\n * @returns {Object} Geometry data with vertexCount and vertices array\r\n */\r\nfunction generateCircleGeometry( radius ) {\r\n\r\n\tif( radius <= 0 ) {\r\n\t\treturn { \"vertexCount\": 0, \"vertices\": null };\r\n\t}\r\n\t\r\n\t// Store min/max X for each Y scanline as we discover them during MCA\r\n\tconst scanlineMinMax = new Map(); // Map<y, {min: x, max: x}>\r\n\r\n\t// --- Midpoint Circle Algorithm to find outline pixels ---\r\n\tlet x = radius - 1;  // Radius adjustment - due to integer rounding it looks better this way\r\n\tlet y = 0;\r\n\tlet err = 1 - x;\r\n\r\n\t// Helper to update min/max X for a specific Y scanline\r\n\tconst updateScanline = ( px, py ) => {\r\n\r\n\t\tconst pixelY = py | 0; // Fast Math.floor\r\n\t\tconst pixelX = px | 0;\r\n\r\n\t\tif( !scanlineMinMax.has( pixelY ) ) {\r\n\t\t\tif( pixelX < 0 ) {\r\n\t\t\t\tscanlineMinMax.set( pixelY, { \"left\": pixelX, \"right\": Infinity } );\r\n\t\t\t} else if( pixelX > 0 ) {\r\n\t\t\t\tscanlineMinMax.set( pixelY, { \"left\": -Infinity, \"right\": pixelX } );\t\r\n\t\t\t} else {\r\n\t\t\t\tscanlineMinMax.set( pixelY, { \"left\": pixelX, \"right\": pixelX } );\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tconst limits = scanlineMinMax.get( pixelY );\r\n\r\n\t\t\t// We want to find interior pixels only not border pixels so we are looking for the\r\n\t\t\t// closest interior pixel. We need to account for two horizontal border pixels in a row.\r\n\r\n\t\t\tif( pixelX < 0 && pixelX > limits.left ) {\r\n\t\t\t\tlimits.left = pixelX;\r\n\t\t\t}\r\n\t\t\tif( pixelX > 0 && pixelX < limits.right ) {\r\n\t\t\t\tlimits.right = pixelX;\r\n\t\t\t}\r\n\t\t}\r\n\t};\r\n\r\n\twhile( x >= y ) {\r\n\r\n\t\t// Apply 8-way symmetry to update scanlines\r\n\t\tupdateScanline(  x,  y ); // Quadrant 1\r\n\t\tupdateScanline(  y,  x ); // Quadrant 2\r\n\t\tupdateScanline( -y,  x ); // Quadrant 3\r\n\t\tupdateScanline( -x,  y ); // Quadrant 4\r\n\t\tupdateScanline( -x, -y ); // Quadrant 5\r\n\t\tupdateScanline( -y, -x ); // Quadrant 6\r\n\t\tupdateScanline(  y, -x ); // Quadrant 7\r\n\t\tupdateScanline(  x, -y ); // Quadrant 8\r\n\r\n\t\ty++;\r\n\t\tif( err < 0 ) {\r\n\t\t\terr += 2 * y + 1;\r\n\t\t} else {\r\n\t\t\tx--;\r\n\t\t\terr += 2 * ( y - x ) + 1;\r\n\t\t}\r\n\t}\r\n\r\n\t// Count valid scanlines for batch preparation\r\n\tlet vertexCount = 0;\r\n\tconst sortedYCoords = [];\r\n\tfor( const [ currentY, mm ] of scanlineMinMax.entries() ) {\r\n\t\tvertexCount += 6;\r\n\t\tsortedYCoords.push( currentY );\r\n\t}\r\n\r\n\tsortedYCoords.sort( ( a, b ) => a - b );\r\n\r\n\tconst vertices = new Float32Array( vertexCount * 2 );\r\n\tlet vIdx = 0;\r\n\r\n\t// Generate quads for each scanline -- skip the top row as it's border\r\n\tfor(let row = 1; row < sortedYCoords.length - 1; row += 1 ) {\r\n\t\tconst currentY = sortedYCoords[ row ];\r\n\t\tconst limits = scanlineMinMax.get( currentY );\r\n\r\n\t\t// Get the interior starts by moving over 1 pixel from border\r\n\t\tconst xStart = limits.left + 1;\r\n\t\tconst xEnd = limits.right - 1;\r\n\r\n\t\t// Quad from (xStart, currentY) to (xEnd+1, currentY+1)\r\n\t\tvIdx = addQuad( vertices, vIdx, xStart, currentY, xEnd + 1, currentY + 1 );\r\n\t}\r\n\r\n\treturn { \"vertexCount\": vertexCount, \"vertices\": vertices };\r\n}\r\n\r\n\r\n/**\r\n * Generate geometry for a single pixel 1x1 quad at origin.\r\n * @returns {Object}\r\n */\r\nfunction generateSinglePixelGeometry() {\r\n\r\n\t// Two triangles forming a 1x1 quad with corners (0,0)-(1,1)\r\n\tconst vertexCount = 6;\r\n\tconst vertices = new Float32Array( vertexCount * 2 );\r\n\tlet vIdx = 0;\r\n\r\n\t// Quad from (0,0) to (1,1)\r\n\tvIdx = addQuad( vertices, vIdx, 0, 0, 1, 1 );\r\n\r\n\treturn { \"vertexCount\": vertexCount, \"vertices\": vertices };\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Cache Management\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Get cached geometry or generate and cache it\r\n * \r\n * @param {string} cacheKey - Geometry cache key (e.g., \"circle:32\")\r\n * @returns {Object} Geometry data with vertexCount and vertices array\r\n */\r\nfunction getCachedGeometry( cacheType, unit ) {\r\n\r\n\tconst cacheKey = `${cacheType}:${unit}`;\r\n\tif( m_geometryCache.has( cacheKey ) ) {\r\n\t\treturn m_geometryCache.get( cacheKey );\r\n\t}\r\n\r\n\t// Parse cache key to determine what to generate\r\n\tlet geometry;\r\n\r\n\tif( cacheType === FILLED_CIRCLE ) {\r\n\t\tgeometry = generateCircleGeometry( unit );\r\n\t} else {\r\n\t\tthrow new Error( `Unknown geometry cache type: ${cacheType}` );\r\n\t}\r\n\r\n\t// Cache the geometry\r\n\tm_geometryCache.set( cacheKey, geometry );\r\n\r\n\treturn geometry;\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Drawing Functions\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Draw cached geometry with specified color\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {string} cacheKey - Geometry cache key (e.g., \"circle:32\")\r\n * @param {number} x - X coordinate\r\n * @param {number} y - Y coordinate\r\n * @param {Object} color - Color object with [ r, g, b, a ] values (0-255)\r\n * @returns {void}\r\n */\r\nexport function drawCachedGeometry( screenData, cacheType, unit, x, y, color ) {\r\n\r\n\t// Get cached geometry\r\n\tconst geometry = getCachedGeometry( cacheType, unit );\r\n\tconst batch = screenData.batches[ g_batches.GEOMETRY_BATCH ];\r\n\r\n\t// Prepare batch for vertices\r\n\tg_batches.prepareBatch( screenData, g_batches.GEOMETRY_BATCH, geometry.vertexCount );\r\n\r\n\t// Copy vertices to batch with offset and generate colors\r\n\tconst vertices = geometry.vertices;\r\n\tlet vIdx = 0;\r\n\r\n\tfor( let i = 0; i < geometry.vertexCount; i++ ) {\r\n\r\n\t\tconst vx = vertices[ vIdx++ ] + x;\r\n\t\tconst vy = vertices[ vIdx++ ] + y;\r\n\t\tg_batchHelpers.addVertexToBatch( batch, vx, vy, color );\r\n\t}\r\n}\r\n\r\n", "/**\r\n * Pi.js - Textures Module\r\n * \r\n * Texture cache management and WebGL2 texture operations.\r\n * \r\n * @module renderer/textures\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_screenManager from \"../core/screen-manager.js\";\r\nimport * as g_batches from \"./batches.js\";\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Initialization\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Initialize textures module\r\n * \r\n * @returns {void}\r\n */\r\nexport function init() {\r\n\r\n\t// Nested Map for WebGL2 texture storage\r\n\t// Outer Map: Image element -> Inner Map: GL context -> WebGL texture\r\n\t// This allows efficient lookup by image and cleanup when image is removed\r\n\tg_screenManager.addScreenDataItem( \"imageContextMap\", new Map() );\r\n\tg_screenManager.addScreenDataItem( \"textureCopyFBO\", null );\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Texture Cache Management\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Copy image data to currently bound texture, handling mock canvases by copying from FBO\r\n * Handles cross-context copying when mock canvas uses a different WebGL context\r\n * \r\n * @param {Object} screenData - Destination screen data\r\n * @param {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas} img - Image or Canvas element\r\n * @param {WebGLTexture} texture - Currently bound destination texture\r\n * @returns {void}\r\n */\r\nfunction copyImageToTexture( screenData, img, texture ) {\r\n\tconst gl = screenData.gl;\r\n\t\r\n\t// If img is a mock canvas, copy from the FBO instead of the mock canvas\r\n\tif( img.isMock ) {\r\n\t\tconst imgScreenData = g_screenManager.screenCanvasMap.get( img );\r\n\t\tif( imgScreenData ) {\r\n\r\n\t\t\t// Make sure the other screen is up to date\r\n\t\t\tg_batches.flushBatches( imgScreenData );\r\n\t\t\t\r\n\t\t\t// Check if contexts are different (cross-context copy needed)\r\n\t\t\tif( imgScreenData.gl !== gl ) {\r\n\t\t\t\t\r\n\t\t\t\t// Cross-context copy: read pixels from source FBO, upload to destination texture\r\n\t\t\t\tconst srcGl = imgScreenData.gl;\r\n\t\t\t\tconst width = imgScreenData.width;\r\n\t\t\t\tconst height = imgScreenData.height;\r\n\t\t\t\t\r\n\t\t\t\t// Allocate buffer for pixel data\r\n\t\t\t\tconst pixelData = new Uint8Array( width * height * 4 );\r\n\t\t\t\t\r\n\t\t\t\t// Read pixels from source FBO in source context\r\n\t\t\t\tsrcGl.bindFramebuffer( srcGl.FRAMEBUFFER, imgScreenData.FBO );\r\n\t\t\t\tsrcGl.readPixels( 0, 0, width, height, srcGl.RGBA, srcGl.UNSIGNED_BYTE, pixelData );\r\n\t\t\t\tsrcGl.bindFramebuffer( srcGl.FRAMEBUFFER, null );\r\n\t\t\t\t\r\n\t\t\t\t// Flip Y-axis (WebGL reads bottom-to-top, but texImage2D expects top-to-bottom)\r\n\t\t\t\t// Flip rows in place\r\n\t\t\t\tconst rowSize = width * 4;\r\n\t\t\t\tconst tempRow = new Uint8Array( rowSize );\r\n\t\t\t\tfor( let y = 0; y < Math.floor( height / 2 ); y++ ) {\r\n\t\t\t\t\tconst topRow = y * rowSize;\r\n\t\t\t\t\tconst bottomRow = ( height - 1 - y ) * rowSize;\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Swap rows\r\n\t\t\t\t\ttempRow.set( pixelData.subarray( topRow, topRow + rowSize ) );\r\n\t\t\t\t\tpixelData.set( pixelData.subarray( bottomRow, bottomRow + rowSize ), topRow );\r\n\t\t\t\t\tpixelData.set( tempRow, bottomRow );\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// Upload pixel data to destination texture in destination context\r\n\t\t\t\tgl.texImage2D(\r\n\t\t\t\t\tgl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE,\r\n\t\t\t\t\tpixelData\r\n\t\t\t\t);\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// Allocate the destination texture before attaching it to the copy framebuffer\r\n\t\t\t\tgl.texImage2D(\r\n\t\t\t\t\tgl.TEXTURE_2D, 0, gl.RGBA8, imgScreenData.width, imgScreenData.height, 0,\r\n\t\t\t\t\tgl.RGBA, gl.UNSIGNED_BYTE, null\r\n\t\t\t\t);\r\n\r\n\t\t\t\t// Reuse a framebuffer to keep same-context copies entirely on the GPU\r\n\t\t\t\tif( !screenData.textureCopyFBO ) {\r\n\t\t\t\t\tscreenData.textureCopyFBO = gl.createFramebuffer();\r\n\t\t\t\t\tif( !screenData.textureCopyFBO ) {\r\n\t\t\t\t\t\tconst error = new Error( \"Failed to create texture copy framebuffer.\" );\r\n\t\t\t\t\t\terror.code = \"WEBGL2_ERROR\";\r\n\t\t\t\t\t\tthrow error;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgl.bindFramebuffer( gl.READ_FRAMEBUFFER, imgScreenData.FBO );\r\n\t\t\t\tgl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, screenData.textureCopyFBO );\r\n\t\t\t\tgl.framebufferTexture2D(\r\n\t\t\t\t\tgl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0\r\n\t\t\t\t);\r\n\r\n\t\t\t\t// Reverse destination Y so the texture uses top-left image coordinates\r\n\t\t\t\tgl.blitFramebuffer(\r\n\t\t\t\t\t0, 0, imgScreenData.width, imgScreenData.height,\r\n\t\t\t\t\t0, imgScreenData.height, imgScreenData.width, 0,\r\n\t\t\t\t\tgl.COLOR_BUFFER_BIT, gl.NEAREST\r\n\t\t\t\t);\r\n\t\t\t\tgl.bindFramebuffer( gl.READ_FRAMEBUFFER, null );\r\n\t\t\t\tgl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, null );\r\n\t\t\t}\r\n\t\t} else {\r\n\r\n\t\t\t// Fallback to regular canvas copy if screenData not found\r\n\t\t\tgl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img );\r\n\t\t}\r\n\t} else {\r\n\t\tgl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img );\r\n\t}\r\n}\r\n\r\n/**\r\n * Get or create WebGL2 texture for image\r\n * Creates and caches texture if it doesn't exist for this GL context.\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas} img - Image or Canvas element\r\n * @returns {WebGLTexture|null} WebGL texture or null on error\r\n */\r\nexport function getWebGL2Texture( screenData, img ) {\r\n\r\n\t// imageContextMap is a map (image -> context) containing a map (context -> texture)\r\n\t// Get or create inner Map for this image\r\n\tlet contextTextureMap = screenData.imageContextMap.get( img );\r\n\tif( !contextTextureMap ) {\r\n\t\tcontextTextureMap = new Map();\r\n\t\tscreenData.imageContextMap.set( img, contextTextureMap );\r\n\t}\r\n\r\n\t// Check if texture is another screen\r\n\tconst otherScreenData = g_screenManager.screenCanvasMap.get( img );\r\n\tif( otherScreenData ) {\r\n\r\n\t\t// Make sure the other screen is up to date\r\n\t\tg_batches.flushBatches( otherScreenData );\r\n\t\tg_batches.displayToCanvas( otherScreenData );\r\n\t}\r\n\r\n\t// Check if texture already exists for this screen's context\r\n\tconst gl = screenData.gl;\r\n\tlet texture = contextTextureMap.get( gl );\r\n\tif( texture ) {\r\n\r\n\t\t// If image is a canvas, update the texture so that it has the latest data\r\n\t\tif(\r\n\t\t\timg instanceof HTMLCanvasElement ||\r\n\t\t\t( typeof OffscreenCanvas !== \"undefined\" && img instanceof OffscreenCanvas ) ||\r\n\t\t\timg.isMock\r\n\t\t) {\r\n\r\n\t\t\t// If the img.isDirty is not defined then assume it's dirty, otherwise only if it's\r\n\t\t\t// explicitly set to false then we don't perform the copy, this makes it so that the \r\n\t\t\t// default behavior is to copy the texture.\r\n\t\t\tif( img.isDirty !== undefined && img.isDirty === false ) {\r\n\t\t\t\treturn texture;\r\n\t\t\t}\r\n\r\n\t\t\t// If a texture is currently scheduled to be drawn we need to flush the batch so that\r\n\t\t\t// the texture will appear as it was when the draw command was issued\r\n\t\t\tif( screenData.batchInfo.textureBatchSet.has( texture ) ) {\r\n\t\t\t\tg_batches.flushBatches( screenData );\r\n\t\t\t}\r\n\r\n\t\t\t// Copy the content of the source canvas to the texture\r\n\t\t\tgl.bindTexture( gl.TEXTURE_2D, texture );\r\n\t\t\tcopyImageToTexture( screenData, img, texture );\r\n\t\t\tgl.bindTexture( gl.TEXTURE_2D, null );\r\n\t\t}\r\n\t\treturn texture;\r\n\t}\r\n\r\n\t// Create the texture\r\n\ttexture = gl.createTexture();\r\n\tif( !texture ) {\r\n\t\tconst error = new Error( \"Failed to create WebGL2 texture for image.\" );\r\n\t\terror.code = \"WEBGL2_ERROR\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Upload image data to texture\r\n\tgl.bindTexture( gl.TEXTURE_2D, texture );\r\n\tcopyImageToTexture( screenData, img, texture );\r\n\r\n\t// Set texture parameters for pixel-perfect rendering\r\n\tgl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );\r\n\tgl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );\r\n\tgl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );\r\n\tgl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );\r\n\r\n\t// Unbind the texture\r\n\tgl.bindTexture( gl.TEXTURE_2D, null );\r\n\r\n\t// Store texture in nested Map\r\n\tcontextTextureMap.set( gl, texture );\r\n\r\n\treturn texture;\r\n}\r\n\r\n/**\r\n * Resolve a texture and coordinate orientation for an image draw.\r\n *\r\n * @param {Object} screenData - Destination screen data\r\n * @param {Image|Canvas|WebGLTexture} img - Image source\r\n * @returns {{texture: WebGLTexture, invertedY: boolean}} Texture draw information\r\n */\r\nexport function getTextureDrawInfo( screenData, img ) {\r\n\tconst sourceData = g_screenManager.screenCanvasMap.get( img );\r\n\tif( !sourceData || sourceData.gl !== screenData.gl ) {\r\n\t\treturn { \"texture\": getWebGL2Texture( screenData, img ), \"invertedY\": false };\r\n\t}\r\n\tif( sourceData.FBO === screenData.FBO ) {\r\n\t\tconst error = new Error( \"drawImage: A screen cannot draw its own framebuffer.\" );\r\n\t\terror.code = \"FRAMEBUFFER_FEEDBACK_LOOP\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Preserve an earlier queued draw before the source framebuffer can be changed.\r\n\tif( screenData.batchInfo.textureBatchSet.has( sourceData.fboTexture ) ) {\r\n\t\tg_batches.flushBatches( screenData );\r\n\t}\r\n\tg_batches.flushBatches( sourceData );\r\n\treturn { \"texture\": sourceData.fboTexture, \"invertedY\": true };\r\n}\r\n\r\n/**\n * Delete the WebGL2 texture for an image on one screen.\n * Must be called explicitly to free GPU memory - textures are not automatically\n * garbage collected by the browser.\n *\n * @param {Object} screenData - Screen data object\n * @param {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas} img - Image or Canvas element\n * @returns {void}\n */\nexport function deleteWebGL2Texture( screenData, img ) {\n\r\n\t// Get the context Map for this image\r\n\tconst contextMap = screenData.imageContextMap.get( img );\r\n\tif( !contextMap ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Delete the texture from gl\r\n\tconst gl = screenData.gl;\n\tconst texture = contextMap.get( gl );\n\tif( texture ) {\n\t\tif( screenData.batchInfo.textureBatchSet.has( texture ) ) {\n\t\t\tg_batches.flushBatches( screenData );\n\t\t}\n\t\tgl.deleteTexture( texture );\n\t\tcontextMap.delete( gl );\n\t}\n\r\n\t// Remove the context Map if empty\r\n\tif( contextMap.size === 0 ) {\r\n\t\tscreenData.imageContextMap.delete( img );\r\n\t}\r\n}\r\n\r\n/**\r\n * Update a sub-rectangle of an existing WebGL2 texture using pixel data.\r\n * Creates the texture on-demand if it doesn't yet exist for this context.\r\n * If imgKey is null, uses screenData.fboTexture directly (for FBO updates).\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas|null} imgKey - Image cache key\r\n * @param {Uint8ClampedArray|Uint8Array} pixelData - RGBA pixel data array\r\n * @param {number} width - Width of the pixel data\r\n * @param {number} height - Height of the pixel data\r\n * @param {number} dstX - Destination X in the texture\r\n * @param {number} dstY - Destination Y in the texture\r\n * @returns {WebGLTexture|null} Updated WebGL texture or null on error\r\n */\r\nexport function updateWebGL2TextureSubImage(\r\n\tscreenData, imgKey, pixelData, width, height, dstX, dstY\r\n) {\r\n\r\n\tif( !screenData.gl ) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\tconst gl = screenData.gl;\r\n\tlet texture;\r\n\r\n\t// If imgKey is null, use FBO texture directly\r\n\tif( imgKey === null ) {\r\n\t\ttexture = screenData.fboTexture;\r\n\t\tif( !texture ) {\r\n\t\t\treturn null;\r\n\t\t}\r\n\t} else {\r\n\t\t\r\n\t\t// Ensure texture exists for the image key\r\n\t\ttexture = getWebGL2Texture( screenData, imgKey );\r\n\t}\r\n\r\n\t// If a texture is currently scheduled to be drawn we need to flush the batch so that\r\n\t// the texture will appear as it was when the draw command was issued\r\n\tif( screenData.batchInfo.textureBatchSet.has( texture ) ) {\r\n\t\tg_batches.flushBatches( screenData );\r\n\t}\r\n\r\n\tgl.bindTexture( gl.TEXTURE_2D, texture );\r\n\r\n\t// Upload only the updated region using pixel data\r\n\tgl.texSubImage2D( \r\n\t\tgl.TEXTURE_2D, 0, dstX, dstY,\r\n\t\twidth, height,\r\n\t\tgl.RGBA, gl.UNSIGNED_BYTE, pixelData \r\n\t);\r\n\r\n\t// Keep texture parameters consistent\r\n\tgl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );\r\n\tgl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );\r\n\tgl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );\r\n\tgl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );\r\n\r\n\tgl.bindTexture( gl.TEXTURE_2D, null );\r\n\r\n\treturn texture;\r\n}\r\n\r\n/**\r\n * Update an entire WebGL2 texture using pixel data.\r\n * Creates the texture on-demand if it doesn't yet exist for this context.\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas} imgKey - Image cache key\r\n * @param {Uint8ClampedArray} pixelData - RGBA pixel data array\r\n * @param {number} width - Width of the pixel data\r\n * @param {number} height - Height of the pixel data\r\n * @returns {WebGLTexture|null} Updated WebGL texture or null on error\r\n */\r\nexport function updateWebGL2TextureImage( screenData, imgKey, pixelData, width, height ) {\r\n\r\n\t// Get the texture\r\n\tlet texture = getWebGL2Texture( screenData, imgKey );\r\n\r\n\t// If a texture is currently scheduled to be drawn we need to flush the batch so that\r\n\t// the texture will appear as it was when the draw command was issued\r\n\tif( screenData.batchInfo.textureBatchSet.has( texture ) ) {\r\n\t\tg_batches.flushBatches( screenData );\r\n\t}\r\n\t\r\n\tconst gl = screenData.gl;\r\n\tgl.bindTexture( gl.TEXTURE_2D, texture );\r\n\r\n\t// Upload the entire texture using pixel data\r\n\tgl.texImage2D( \r\n\t\tgl.TEXTURE_2D, 0, gl.RGBA,\r\n\t\twidth, height, 0,\r\n\t\tgl.RGBA, gl.UNSIGNED_BYTE, pixelData \r\n\t);\r\n\r\n\t// Keep texture parameters consistent\r\n\t// gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );\r\n\t// gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );\r\n\t// gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );\r\n\t// gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );\r\n\r\n\tgl.bindTexture( gl.TEXTURE_2D, null );\r\n\r\n\treturn texture;\r\n}\r\n\r\nexport function cleanup( screenData ) {\r\n\tconst gl = screenData.gl;\r\n\r\n\tif( screenData.textureCopyFBO ) {\r\n\t\tgl.deleteFramebuffer( screenData.textureCopyFBO );\r\n\t\tscreenData.textureCopyFBO = null;\r\n\t}\r\n\r\n\t// Delete all textures in the imageContextMap for this screen but keep the image \r\n\tfor( const img of screenData.imageContextMap.keys() ) {\r\n\t\tconst screenMap = screenData.imageContextMap.get( img );\r\n\t\tconst texture = screenMap.get( gl );\r\n\t\tif( texture ) {\r\n\t\t\tgl.deleteTexture( texture );\r\n\t\t}\r\n\t}\r\n\r\n\t// Clear references for GC and signal uninitialized state\r\n\tscreenData.imageContextMap = null;\r\n}\r\n", "/**\r\n * Pi.js - Pixel Readback Module\r\n * \r\n * Pixel readback operations: single pixel and rectangular regions.\r\n * \r\n * @module renderer/readback\r\n */\r\n\r\n\"use strict\";\r\n\r\n// Import required modules\r\nimport * as g_batches from \"./batches.js\";\r\nimport * as g_utils from \"../core/utils.js\";\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Initialization\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Initialize readback module\r\n * \r\n * @returns {void}\r\n */\r\nexport function init() {\r\n\t// No initialization needed\r\n}\r\n\r\n/**\r\n * Read single pixel (synchronous)\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {number} x - X coordinate\r\n * @param {number} y - Y coordinate\r\n * @returns {Object|null} Color object with r, g, b, a or null on error\r\n */\r\nexport function readPixel( screenData, x, y ) {\r\n\r\n\t// Ensure latest contents are in the FBO\r\n\tg_batches.flushBatches( screenData );\r\n\r\n\tconst gl = screenData.gl;\r\n\tconst screenHeight = screenData.height;\r\n\r\n\t// WebGL uses bottom-left origin; flip Y\r\n\tconst glY = ( screenHeight - 1 ) - y;\r\n\tconst buf = new Uint8Array( 4 );\r\n\r\n\tgl.bindFramebuffer( gl.FRAMEBUFFER, screenData.FBO );\r\n\tgl.readPixels( x, glY, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf );\r\n\tgl.bindFramebuffer( gl.FRAMEBUFFER, null );\r\n\r\n\treturn g_utils.rgbToColor( buf[ 0 ], buf[ 1 ], buf[ 2 ], buf[ 3 ] );\r\n}\r\n\r\n/**\r\n * Read single pixel (asynchronous)\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {number} x - X coordinate\r\n * @param {number} y - Y coordinate\r\n * @returns {Promise<Object|null>} Promise resolving to color object or null\r\n */\r\nexport function readPixelAsync( screenData, x, y ) {\r\n\r\n\t// TODO-LATER: Instead of queueing a microtask make this a part of the batch system, that way \r\n\t// the user will get a result that reflects the state of the FBO when they make the call rather\r\n\t// than the state at the end of the frame.\r\n\t// If I make this change I should rename the API functions to something like getPixelQueued\r\n\t// instead of getPixelAsync.\r\n\treturn new Promise( ( resolve ) => {\r\n\t\tg_utils.queueMicrotask( () => {\r\n\t\t\tresolve( readPixel( screenData, x, y ) );\r\n\t\t} );\r\n\t} );\r\n}\r\n\r\n/**\r\n * Read pixel rectangle (synchronous)\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {number} x - X coordinate\r\n * @param {number} y - Y coordinate\r\n * @param {number} width - Rectangle width\r\n * @param {number} height - Rectangle height\r\n * @returns {Array<Array<Object>>} 2D array of color objects [height][width]\r\n */\r\nexport function readPixels( screenData, x, y, width, height ) {\r\n\tconst gl = screenData.gl;\r\n\tconst screenWidth = screenData.width;\r\n\tconst screenHeight = screenData.height;\r\n\r\n\t// Clamp to screen bounds for robustness if not fully clipped by pixels.js\r\n\tconst clampedX = Math.max( 0, x );\r\n\tconst clampedY = Math.max( 0, y );\r\n\tconst clampedWidth = Math.min( width, screenWidth - clampedX );\r\n\tconst clampedHeight = Math.min( height, screenHeight - clampedY );\r\n\r\n\t// If after clamping, nothing left to read\r\n\tif( clampedWidth <= 0 || clampedHeight <= 0 ) {\r\n\t\treturn [];\r\n\t}\r\n\r\n\t// Flush batches before reading\r\n\tg_batches.flushBatches( screenData );\r\n\r\n\t// Allocate buffer for the exact rectangle to read\r\n\tconst buf = new Uint8Array( clampedWidth * clampedHeight * 4 );\r\n\r\n\t// WebGL origin is bottom-left; convert to top-left for `gl.readPixels`\r\n\t// The Y coordinate for `gl.readPixels` is the bottom edge of the rectangle.\r\n\t// Bottom-left corner Y of the rectangle\r\n\tconst glReadY = ( screenHeight - ( clampedY + clampedHeight ) );\r\n\r\n\tgl.bindFramebuffer( gl.FRAMEBUFFER, screenData.FBO );\r\n\tgl.readPixels( clampedX, glReadY, clampedWidth, clampedHeight, gl.RGBA, gl.UNSIGNED_BYTE, buf );\r\n\tgl.bindFramebuffer( gl.FRAMEBUFFER, null );\r\n\r\n\t// Map back to output structure expected by api/pixels.js\r\n\t// This function will return a flat array of color objects\r\n\tconst resultColors = new Array( clampedHeight );\r\n\tfor( let row = 0; row < clampedHeight; row++ ) {\r\n\r\n\t\tconst resultsRow = new Array( clampedWidth );\r\n\t\tfor( let col = 0; col < clampedWidth; col++ ) {\r\n\r\n\t\t\t// Convert gl.readPixels' bottom-origin Y to top-origin Y for the buffer index\r\n\t\t\t// `buf` itself is ordered from glReadY up to glReadY + clampedHeight - 1\r\n\t\t\t// Flip row index\r\n\t\t\tconst bufRow = ( clampedHeight - 1 ) - row;\r\n\t\t\tconst i = ( ( clampedWidth * bufRow ) + col ) * 4;\r\n\t\t\tresultsRow[ col ] = g_utils.rgbToColor(\r\n\t\t\t\tbuf[ i ], buf[ i + 1 ], buf[ i + 2 ], buf[ i + 3 ]\r\n\t\t\t);\r\n\t\t}\r\n\t\tresultColors[ row ] = resultsRow;\r\n\t}\r\n\r\n\treturn resultColors;\r\n}\r\n\r\n/**\r\n * Read pixel rectangle (asynchronous)\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {number} x - X coordinate\r\n * @param {number} y - Y coordinate\r\n * @param {number} width - Rectangle width\r\n * @param {number} height - Rectangle height\r\n * @returns {Promise<Array<Array<Object>>>} Promise resolving to 2D array of color objects\r\n */\r\nexport function readPixelsAsync( screenData, x, y, width, height ) {\r\n\treturn new Promise( ( resolve ) => {\r\n\t\tg_utils.queueMicrotask( () => {\r\n\t\t\tresolve( readPixels( screenData, x, y, width, height ) );\r\n\t\t} );\r\n\t} );\r\n}\r\n\r\n/**\r\n * Read pixel rectangle as raw Uint8Array (synchronous)\r\n * Returns RGBA data in a Uint8Array with WebGL bottom-left origin ordering.\r\n * Format: [r0, g0, b0, a0, r1, g1, b1, a1, ...] where pixels are ordered\r\n * row by row from bottom to top, left to right (WebGL native format).\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {number} x - X coordinate\r\n * @param {number} y - Y coordinate\r\n * @param {number} width - Rectangle width\r\n * @param {number} height - Rectangle height\r\n * @returns {Uint8Array|null} Raw RGBA pixel data (width * height * 4 bytes) or null if invalid\r\n */\r\nexport function readPixelsRaw( screenData, x, y, width, height ) {\r\n\tconst gl = screenData.gl;\r\n\tconst screenWidth = screenData.width;\r\n\tconst screenHeight = screenData.height;\r\n\r\n\t// Clamp to screen bounds for robustness\r\n\tconst clampedX = Math.max( 0, x );\r\n\tconst clampedY = Math.max( 0, y );\r\n\tconst clampedWidth = Math.min( width, screenWidth - clampedX );\r\n\tconst clampedHeight = Math.min( height, screenHeight - clampedY );\r\n\r\n\t// If after clamping, nothing left to read\r\n\tif( clampedWidth <= 0 || clampedHeight <= 0 ) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\t// Flush batches before reading\r\n\tg_batches.flushBatches( screenData );\r\n\r\n\t// Allocate buffer for the exact rectangle to read\r\n\tconst buf = new Uint8Array( clampedWidth * clampedHeight * 4 );\r\n\r\n\t// WebGL origin is bottom-left; convert to top-left for `gl.readPixels`\r\n\t// The Y coordinate for `gl.readPixels` is the bottom edge of the rectangle.\r\n\t// Bottom-left corner Y of the rectangle\r\n\tconst glReadY = ( screenHeight - ( clampedY + clampedHeight ) );\r\n\r\n\tgl.bindFramebuffer( gl.FRAMEBUFFER, screenData.FBO );\r\n\tgl.readPixels( clampedX, glReadY, clampedWidth, clampedHeight, gl.RGBA, gl.UNSIGNED_BYTE, buf );\r\n\tgl.bindFramebuffer( gl.FRAMEBUFFER, null );\r\n\r\n\t// Return raw WebGL data (bottom-left origin) - flipping will be done in applyFilter\r\n\treturn buf;\r\n}\r\n\r\n", "/**\r\n * Pi.js - Images Drawing Module\r\n * \r\n * Low-level drawing operations: image drawing.\r\n * \r\n * @module renderer/draw/images\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_batches from \"../batches.js\";\r\nimport * as g_textures from \"../textures.js\";\r\n\r\n// Color array map to speed up copying of colors to vertices\r\nconst MAX_QUAD_COLOR_MAP_SIZE = 1000;\r\nconst m_quadColorMap = new Map();\r\n\r\n/**\r\n * Calculate transformed corner positions for a quad\r\n * \r\n * @param {number} width - Quad width\r\n * @param {number} height - Quad height\r\n * @param {number} anchorX - Anchor point X (0-1)\r\n * @param {number} anchorY - Anchor point Y (0-1)\r\n * @param {number} scaleX - Scale X factor\r\n * @param {number} scaleY - Scale Y factor\r\n * @param {number} angleRad - Rotation angle in radians\r\n * @param {number} x - Translation X\r\n * @param {number} y - Translation Y\r\n * @returns {Array<Object>} Array of 4 corner objects with x, y properties\r\n */\r\nfunction calculateTransformedCorners(\r\n\twidth, height, anchorX, anchorY, scaleX, scaleY, angleRad, x, y\r\n) {\r\n\r\n\t// Calculate scaled dimensions first\r\n\tconst scaledWidth = width * scaleX;\r\n\tconst scaledHeight = height * scaleY;\r\n\r\n\t// Calculate anchor position in pixels from scaled dimensions\r\n\tconst anchorXPx = Math.round( scaledWidth * anchorX );\r\n\tconst anchorYPx = Math.round( scaledHeight * anchorY );\r\n\r\n\t// Calculate corner positions relative to anchor point\r\n\tconst corners = [\r\n\t\t{ \"x\": -anchorXPx, \"y\": -anchorYPx },\t\t\t\t\t\t\t\t// Top-left\r\n\t\t{ \"x\": scaledWidth - anchorXPx, \"y\": -anchorYPx },\t\t\t\t\t// Top-right\r\n\t\t{ \"x\": -anchorXPx, \"y\": scaledHeight - anchorYPx },\t\t\t\t\t// Bottom-left\r\n\t\t{ \"x\": scaledWidth - anchorXPx, \"y\": scaledHeight - anchorYPx }\t\t// Bottom-right\r\n\t];\r\n\r\n\t// Rotate corners around (0,0) then translate to (x,y)\r\n\tif( angleRad !== 0 ) {\r\n\t\tconst cos = Math.cos( angleRad );\r\n\t\tconst sin = Math.sin( angleRad );\r\n\t\tfor( let i = 0; i < corners.length; i++ ) {\r\n\t\t\tconst corner = corners[ i ];\r\n\t\t\tconst rx = corner.x * cos - corner.y * sin;\r\n\t\t\tconst ry = corner.x * sin + corner.y * cos;\r\n\t\t\tcorner.x = rx + x;\r\n\t\t\tcorner.y = ry + y;\r\n\t\t}\r\n\t} else {\r\n\t\t\r\n\t\t// No rotation, just translate\r\n\t\tfor( let i = 0; i < corners.length; i++ ) {\r\n\t\t\tcorners[ i ].x += x;\r\n\t\t\tcorners[ i ].y += y;\r\n\t\t}\r\n\t}\r\n\r\n\treturn corners;\r\n}\r\n\r\n/**\r\n * Add a textured quad (2 triangles, 6 vertices) to IMAGE_BATCH\r\n * \r\n * TODO-LATER: Move to batch helpers and call addQuadToBatch\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {WebGLTexture} texture - WebGL texture\r\n * @param {Array<Object>} corners - Array of 4 corner objects with x, y properties\r\n * @param {Array<number>} texCoords - Array of 12 texture coordinates (2 per vertex for 6 vertices)\r\n * @param {Uint8Array} colorQuadArray - Color array with 6 sets of 4 color values (24 values)\r\n * @returns {void}\r\n */\r\nfunction addTexturedQuadToBatch(\r\n\tscreenData, texture, corners, texCoords, colorQuadArray, batchType\r\n) {\r\n\r\n\t// Prepare batch for 6 vertices (2 triangles)\r\n\tconst batch = screenData.batches[ batchType ];\r\n\tg_batches.prepareBatch( screenData, batchType, 6, texture );\r\n\r\n\tconst batchVertices = batch.vertices;\r\n\tconst batchTexCoords = batch.texCoords;\r\n\tconst batchColors = batch.colors;\r\n\tconst originX = batch.originX || 0;\r\n\tconst originY = batch.originY || 0;\r\n\r\n\t// Add two triangles (6 vertices)\r\n\tconst baseIdx = batch.count;\r\n\tconst vertexBase = baseIdx * batch.vertexComps;\r\n\tconst texBase = baseIdx * batch.texCoordComps;\r\n\tconst colorBase = baseIdx * batch.colorComps;\r\n\r\n\t// Triangle 1: Top-left, Top-right, Bottom-left\r\n\tlet vIdx = vertexBase;\r\n\tlet tIdx = texBase;\r\n\r\n\t// Vertex 0: Top-left\r\n\tbatchVertices[ vIdx++ ] = corners[ 0 ].x + originX;\r\n\tbatchVertices[ vIdx++ ] = corners[ 0 ].y + originY;\r\n\tbatchTexCoords[ tIdx++ ] = texCoords[ 0 ];\r\n\tbatchTexCoords[ tIdx++ ] = texCoords[ 1 ];\r\n\r\n\t// Vertex 1: Top-right\r\n\tbatchVertices[ vIdx++ ] = corners[ 1 ].x + originX;\r\n\tbatchVertices[ vIdx++ ] = corners[ 1 ].y + originY;\r\n\tbatchTexCoords[ tIdx++ ] = texCoords[ 2 ];\r\n\tbatchTexCoords[ tIdx++ ] = texCoords[ 3 ];\r\n\r\n\t// Vertex 2: Bottom-left\r\n\tbatchVertices[ vIdx++ ] = corners[ 2 ].x + originX;\r\n\tbatchVertices[ vIdx++ ] = corners[ 2 ].y + originY;\r\n\tbatchTexCoords[ tIdx++ ] = texCoords[ 4 ];\r\n\tbatchTexCoords[ tIdx++ ] = texCoords[ 5 ];\r\n\r\n\t// Triangle 2: Top-right, Bottom-right, Bottom-left\r\n\t// Vertex 3: Top-right\r\n\tbatchVertices[ vIdx++ ] = corners[ 1 ].x + originX;\r\n\tbatchVertices[ vIdx++ ] = corners[ 1 ].y + originY;\r\n\tbatchTexCoords[ tIdx++ ] = texCoords[ 6 ];\r\n\tbatchTexCoords[ tIdx++ ] = texCoords[ 7 ];\r\n\r\n\t// Vertex 4: Bottom-right\r\n\tbatchVertices[ vIdx++ ] = corners[ 3 ].x + originX;\r\n\tbatchVertices[ vIdx++ ] = corners[ 3 ].y + originY;\r\n\tbatchTexCoords[ tIdx++ ] = texCoords[ 8 ];\r\n\tbatchTexCoords[ tIdx++ ] = texCoords[ 9 ];\r\n\r\n\t// Vertex 5: Bottom-left\r\n\tbatchVertices[ vIdx++ ] = corners[ 2 ].x + originX;\r\n\tbatchVertices[ vIdx++ ] = corners[ 2 ].y + originY;\r\n\tbatchTexCoords[ tIdx++ ] = texCoords[ 10 ];\r\n\tbatchTexCoords[ tIdx++ ] = texCoords[ 11 ];\r\n\r\n\tbatchColors.set( colorQuadArray, colorBase );\r\n\r\n\t// Update batch count\r\n\tbatch.count += 6;\r\n}\r\n\r\nfunction getQuadColorArray( color ) {\r\n\tlet quadColorArray = m_quadColorMap.get( color.key );\r\n\r\n\tif( quadColorArray === undefined ) {\r\n\r\n\t\t// Simple approach: Clear the entire map. Aggressive but easy.\r\n\t\tif( m_quadColorMap.size >= MAX_QUAD_COLOR_MAP_SIZE ) {\r\n\t\t\tm_quadColorMap.clear();\r\n\t\t}\r\n\t\t\r\n\t\tconst r = color.r;\r\n\t\tconst g = color.g;\r\n\t\tconst b = color.b;\r\n\t\tconst a = color.a;\r\n\r\n\t\t// Create the quad color array\r\n\t\tquadColorArray = new Uint8Array( 24 );\r\n\t\tquadColorArray[ 0 ] = r;\r\n\t\tquadColorArray[ 1 ] = g;\r\n\t\tquadColorArray[ 2 ] = b;\r\n\t\tquadColorArray[ 3 ] = a;\r\n\t\tquadColorArray[ 4 ] = r;\r\n\t\tquadColorArray[ 5 ] = g;\r\n\t\tquadColorArray[ 6 ] = b;\r\n\t\tquadColorArray[ 7 ] = a;\r\n\t\tquadColorArray[ 8 ] = r;\r\n\t\tquadColorArray[ 9 ] = g;\r\n\t\tquadColorArray[ 10 ] = b;\r\n\t\tquadColorArray[ 11 ] = a;\r\n\t\tquadColorArray[ 12 ] = r;\r\n\t\tquadColorArray[ 13 ] = g;\r\n\t\tquadColorArray[ 14 ] = b;\r\n\t\tquadColorArray[ 15 ] = a;\r\n\t\tquadColorArray[ 16 ] = r;\r\n\t\tquadColorArray[ 17 ] = g;\r\n\t\tquadColorArray[ 18 ] = b;\r\n\t\tquadColorArray[ 19 ] = a;\r\n\t\tquadColorArray[ 20 ] = r;\r\n\t\tquadColorArray[ 21 ] = g;\r\n\t\tquadColorArray[ 22 ] = b;\r\n\t\tquadColorArray[ 23 ] = a;\r\n\r\n\t\t// Add the key to map\r\n\t\tm_quadColorMap.set( color.key, quadColorArray );\r\n\t}\r\n\treturn quadColorArray;\r\n}\r\n\r\n/**\r\n * Draw image as textured quad with optional transform\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Image|Canvas|WebGLTexture} img - Image, Canvas, or Texture\r\n * @param {number} x - X position\r\n * @param {number} y - Y position\r\n * @param {number} anchorX - Anchor point X (0-1)\r\n * @param {number} anchorY - Anchor point Y (0-1)\r\n * @param {Object} color - Color value object with rgba and key for map lookups\r\n * @param {number} scaleX - Scale X factor\r\n * @param {number} scaleY - Scale Y factor\r\n * @param {number} angleRad - Rotation angle in radians\r\n * @returns {void}\r\n */\r\nexport function drawImage( \r\n\tscreenData, img, x, y, color, anchorX, anchorY, scaleX, scaleY, angleRad,\r\n\tbatchType = g_batches.IMAGE_BATCH\r\n) {\r\n\r\n\t// Get or create texture\r\n\tconst textureInfo = g_textures.getTextureDrawInfo( screenData, img );\r\n\tconst texture = textureInfo.texture;\r\n\r\n\t// Calculate image dimensions\r\n\tconst imgWidth = img.width;\r\n\tconst imgHeight = img.height;\r\n\r\n\t// Calculate transformed corners\r\n\tconst corners = calculateTransformedCorners(\r\n\t\timgWidth, imgHeight, anchorX, anchorY, scaleX, scaleY, angleRad, x, y\r\n\t);\r\n\r\n\t// Texture coordinates (full image)\r\n\tlet texCoords;\r\n\tif( textureInfo.invertedY ) {\r\n\t\ttexCoords = [\r\n\t\t\t0, 1,  // Top-left\r\n\t\t\t1, 1,  // Top-right\r\n\t\t\t0, 0,  // Bottom-left\r\n\t\t\t1, 1,  // Top-right (repeat for second triangle)\r\n\t\t\t1, 0,  // Bottom-right\r\n\t\t\t0, 0   // Bottom-left (repeat for second triangle)\r\n\t\t];\r\n\t} else {\r\n\t\ttexCoords = [\r\n\t\t\t0, 0,  // Top-left\r\n\t\t\t1, 0,  // Top-right\r\n\t\t\t0, 1,  // Bottom-left\r\n\t\t\t1, 0,  // Top-right (repeat for second triangle)\r\n\t\t\t1, 1,  // Bottom-right\r\n\t\t\t0, 1   // Bottom-left (repeat for second triangle)\r\n\t\t];\r\n\t}\r\n\r\n\t// Add textured quad to batch\r\n\taddTexturedQuadToBatch(\r\n\t\tscreenData, texture, corners, texCoords, getQuadColorArray( color ), batchType\r\n\t);\r\n}\r\n\r\n/**\r\n * Draw sprite (sub-region) from texture atlas\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Image|Canvas|WebGLTexture} img - Image, Canvas, or Texture\r\n * @param {number} sx - Source X in texture\r\n * @param {number} sy - Source Y in texture\r\n * @param {number} sw - Source width\r\n * @param {number} sh - Source height\r\n * @param {number} x - Destination X position\r\n * @param {number} y - Destination Y position\r\n * @param {number} width - Destination width\r\n * @param {number} height - Destination height\r\n * @param {Object} color - Color object with rgba and key for map lookups\r\n * @param {number} [anchorX=0] - Anchor point X (0-1)\r\n * @param {number} [anchorY=0] - Anchor point Y (0-1)\r\n * @param {number} [scaleX=1] - Scale X factor\r\n * @param {number} [scaleY=1] - Scale Y factor\r\n * @param {number} [angleRad=0] - Rotation angle in radians\r\n * @returns {void}\r\n */\r\nexport function drawSprite(\r\n\tscreenData, img, sx, sy, sw, sh, x, y, width, height, color,\r\n\tanchorX = 0, anchorY = 0, scaleX = 1, scaleY = 1, angleRad = 0,\r\n\tbatchType = g_batches.IMAGE_BATCH\r\n) {\r\n\r\n\t// Get or create texture\r\n\tconst textureInfo = g_textures.getTextureDrawInfo( screenData, img );\r\n\tconst texture = textureInfo.texture;\r\n\r\n\t// Get texture dimensions for coordinate conversion\r\n\tconst texWidth = img.width;\r\n\tconst texHeight = img.height;\r\n\r\n\t// Convert pixel coordinates to normalized texture coordinates (0-1)\r\n\tconst u0 = sx / texWidth;\r\n\tlet v0 = sy / texHeight;\r\n\tconst u1 = ( sx + sw ) / texWidth;\r\n\tlet v1 = ( sy + sh ) / texHeight;\r\n\tif( textureInfo.invertedY ) {\r\n\t\tv0 = 1 - v0;\r\n\t\tv1 = 1 - v1;\r\n\t}\r\n\r\n\t// Calculate transformed corners\r\n\tconst corners = calculateTransformedCorners(\r\n\t\twidth, height, anchorX, anchorY, scaleX, scaleY, angleRad, x, y\r\n\t);\r\n\r\n\t// Texture coordinates for sub-region\r\n\tconst texCoords = [\r\n\t\tu0, v0,  // Top-left\r\n\t\tu1, v0,  // Top-right\r\n\t\tu0, v1,  // Bottom-left\r\n\t\tu1, v0,  // Top-right (repeat for second triangle)\r\n\t\tu1, v1,  // Bottom-right\r\n\t\tu0, v1   // Bottom-left (repeat for second triangle)\r\n\t];\r\n\r\n\t// Add textured quad to batch\r\n\taddTexturedQuadToBatch(\r\n\t\tscreenData, texture, corners, texCoords, getQuadColorArray( color ), batchType\r\n\t);\r\n}\r\n", "/**\r\n * Pi.js - Low-Level Drawing Module\r\n * \r\n * Low-level drawing operations: pixel writes\r\n * \r\n * @module renderer/draw/primitives\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_batchHelpers from \"./batch-helpers.js\";\r\nimport * as g_batches from \"../batches.js\";\r\n\r\n\r\n/**\r\n * Fast path for single pixel write (safe - prepares batch)\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {number} x - X coordinate\r\n * @param {number} y - Y coordinate\r\n * @returns {void}\r\n */\r\nexport function drawPixel( screenData, x, y, batchType ) {\r\n\r\n\t// Prep for 1 pixel\r\n\tg_batches.prepareBatch( screenData, batchType, 1, null, null );\r\n\r\n\t// Add directly to point batch\r\n\tconst batch = screenData.batches[ batchType ];\r\n\tg_batchHelpers.addVertexToBatch( batch, x, y, screenData.color );\r\n}\r\n\r\n/**\r\n * Fast path for single pixel write (unsafe - does not prepare batch)\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {number} x - X coordinate\r\n * @param {number} y - Y coordinate\r\n * @param {Object} color - Color color with [ r, g, b, a ] values (0-255)\r\n * @returns {void}\r\n */\r\nexport function drawPixelUnsafe( screenData, x, y, color, batchType ) {\r\n\r\n\t// Add directly to point batch\r\n\tconst batch = screenData.batches[ batchType ];\r\n\tg_batchHelpers.addVertexToBatch( batch, x, y, color );\r\n}\r\n", "/**\r\n * Pi.js - Arcs Drawing Module\r\n * \r\n * Low-level drawing operations: arcs drawing.\r\n * \r\n * drawArc, drawArcSquare, drawArcCircle\r\n * \r\n * @module renderer/draw/arcs\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_batches from \"../batches.js\";\r\nimport * as g_batchHelpers from \"./batch-helpers.js\";\r\n\r\nconst TWO_PI = 2 * Math.PI;\r\nconst FULL_CIRCLE_EPSILON = 0.0001;\r\n\r\n/**\r\n * Draw arc outline using midpoint circle algorithm\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {number} cx - Center X coordinate\r\n * @param {number} cy - Center Y coordinate\r\n * @param {number} radius - Arc radius\r\n * @param {number} angle1 - Start angle in radians\r\n * @param {number} angle2 - End angle in radians\r\n * @returns {void}\r\n */\r\nexport function drawArc( screenData, cx, cy, radius, angle1, angle2 ) {\r\n\tconst color = screenData.color;\r\n\r\n\t// Normalize angles to [0, 2\u03C0)\r\n\tlet a1 = normalizeAngle( angle1 );\r\n\tlet a2 = normalizeAngle( angle2 );\r\n\r\n\t// CCW span from a1 to a2 in [0, 2\u03C0)\r\n\tlet span = a2 - a1;\r\n\tif( span < 0 ) {\r\n\t\tspan += TWO_PI;\r\n\t}\r\n\r\n\tconst isFullCircle = span >= TWO_PI - FULL_CIRCLE_EPSILON;\r\n\tconst isLargeArc = !isFullCircle && span > Math.PI;\r\n\r\n\t// Estimate pixel count based on span\r\n\tconst estimatedPixels = Math.max(\r\n\t\t4,\r\n\t\tMath.ceil( radius * ( isFullCircle ? TWO_PI : span ) )\r\n\t);\r\n\r\n\t// Prepare batch\r\n\tconst batchIndex = g_batches.POINTS_BATCH;\r\n\tg_batches.prepareBatch( screenData, batchIndex, estimatedPixels );\r\n\tconst batch = screenData.batches[ batchIndex ];\r\n\r\n\t// Precompute start/end direction vectors for angle tests\r\n\tlet startX = 0;\r\n\tlet startY = 0;\r\n\tlet endX = 0;\r\n\tlet endY = 0;\r\n\r\n\tif( !isFullCircle ) {\r\n\t\tstartX = Math.cos( a1 );\r\n\t\tstartY = Math.sin( a1 );\r\n\t\tendX = Math.cos( a2 );\r\n\t\tendY = Math.sin( a2 );\r\n\t}\r\n\r\n\t// Per-pixel plot helper with arc angle filtering (no atan2)\r\n\tlet setPixel;\r\n\r\n\tif( isFullCircle ) {\r\n\t\tsetPixel = function( px, py ) {\r\n\t\t\tg_batchHelpers.addVertexToBatch( batch, px, py, color );\r\n\t\t};\r\n\t} else if( !isLargeArc ) {\r\n\r\n\t\t// Small arc: span <= \u03C0\r\n\t\t// Inside if: cross( startDir, w ) >= 0 && cross( endDir, w ) <= 0\r\n\t\tsetPixel = function( px, py ) {\r\n\t\t\tconst dx = px - cx;\r\n\t\t\tconst dy = py - cy;\r\n\r\n\t\t\tif( dx === 0 && dy === 0 ) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tconst cuw = startX * dy - startY * dx;\r\n\t\t\tconst cvw = endX * dy - endY * dx;\r\n\r\n\t\t\tif( cuw >= 0 && cvw <= 0 ) {\r\n\t\t\t\tg_batchHelpers.addVertexToBatch( batch, px, py, color );\r\n\t\t\t}\r\n\t\t};\r\n\t} else {\r\n\r\n\t\t// Large arc: span > \u03C0\r\n\t\t// The gap is the small arc from endDir to startDir.\r\n\t\t// w is inside arc if it is NOT in the gap:\r\n\t\t// gap if: cross( endDir, w ) >= 0 && cross( startDir, w ) <= 0\r\n\t\tsetPixel = function( px, py ) {\r\n\t\t\tconst dx = px - cx;\r\n\t\t\tconst dy = py - cy;\r\n\r\n\t\t\tif( dx === 0 && dy === 0 ) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tconst cuw = startX * dy - startY * dx;\r\n\t\t\tconst cvw = endX * dy - endY * dx;\r\n\r\n\t\t\tif( !( cvw >= 0 && cuw <= 0 ) ) {\r\n\t\t\t\tg_batchHelpers.addVertexToBatch( batch, px, py, color );\r\n\t\t\t}\r\n\t\t};\r\n\t}\r\n\r\n\t// Adjust radius (consistent with filled circle implementation)\r\n\tconst finalRadius = radius - 1;\r\n\r\n\t// Handle special cases\r\n\tif( finalRadius < 1 ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif( finalRadius === 1 ) {\r\n\r\n\t\t// Draw 4 cardinal points\r\n\t\tsetPixel( cx + 1, cy );\r\n\t\tsetPixel( cx - 1, cy );\r\n\t\tsetPixel( cx, cy + 1 );\r\n\t\tsetPixel( cx, cy - 1 );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Midpoint circle algorithm\r\n\tlet x = finalRadius;\r\n\tlet y = 0;\r\n\tlet err = 1 - x;\r\n\r\n\t// Initial symmetrical points (no duplicates here)\r\n\tsetPixel( cx + x, cy + y );\r\n\tsetPixel( cx - x, cy + y );\r\n\tsetPixel( cx + y, cy + x );\r\n\tsetPixel( cx + y, cy - x );\r\n\r\n\twhile( x >= y ) {\r\n\t\ty++;\r\n\r\n\t\tif( err < 0 ) {\r\n\t\t\terr += 2 * y + 1;\r\n\t\t} else {\r\n\t\t\tx--;\r\n\t\t\terr += 2 * ( y - x ) + 1;\r\n\t\t}\r\n\r\n\t\tif( x === y ) {\r\n\r\n\t\t\t// Diagonal: 8-way symmetry collapses to 4 unique pixels\r\n\t\t\tsetPixel( cx + x, cy + y );\r\n\t\t\tsetPixel( cx - x, cy + y );\r\n\t\t\tsetPixel( cx - x, cy - y );\r\n\t\t\tsetPixel( cx + x, cy - y );\r\n\t\t} else {\r\n\r\n\t\t\t// 8-way symmetry, all distinct when x !== y\r\n\t\t\tsetPixel( cx + x, cy + y );\r\n\t\t\tsetPixel( cx + y, cy + x );\r\n\t\t\tsetPixel( cx - y, cy + x );\r\n\t\t\tsetPixel( cx - x, cy + y );\r\n\t\t\tsetPixel( cx - x, cy - y );\r\n\t\t\tsetPixel( cx - y, cy - x );\r\n\t\t\tsetPixel( cx + y, cy - x );\r\n\t\t\tsetPixel( cx + x, cy - y );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfunction normalizeAngle( angle ) {\r\n\tlet normalized = angle % TWO_PI;\r\n\tif( normalized < 0 ) {\r\n\t\tnormalized += TWO_PI;\r\n\t}\r\n\treturn normalized;\r\n}\r\n", "/**\r\n * Pi.js - Bezier Drawing Module\r\n * \r\n * Low-level drawing operations: bezier drawing.\r\n * \r\n * drawBezier, drawBezierSquare, drawBezierCircle\r\n * \r\n * @module renderer/draw/bezier\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_batches from \"../batches.js\";\r\nimport * as g_batchHelpers from \"./batch-helpers.js\";\r\n\r\n/**\r\n * Draw cubic Bezier with pixel pen by tessellating into short line segments.\r\n * Uses adaptive subdivision for smoothness and deduplicates pixels at junctions.\r\n * \r\n * @param {Object} screenData\r\n * @param {number} p0x\r\n * @param {number} p0y\r\n * @param {number} p1x\r\n * @param {number} p1y\r\n * @param {number} p2x\r\n * @param {number} p2y\r\n * @param {number} p3x\r\n * @param {number} p3y\r\n * @param {Object} color\r\n * @returns {void}\r\n */\r\nexport function drawBezier( screenData, p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y ) {\r\n\tconst color = screenData.color;\r\n\r\n\t// Tessellate curve into points with ~0.75px max error\r\n\tconst maxError = 0.75;\r\n\tconst pts = g_batchHelpers.tessellateCubicBezier(\r\n\t\tp0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y, maxError\r\n\t);\r\n\r\n\tif( pts.length < 4 ) {\r\n\t\t\r\n\t\t// Degenerate: plot a single pixel\r\n\t\tconst batch = screenData.batches[ g_batches.POINTS_BATCH ];\r\n\t\tg_batches.prepareBatch( screenData, g_batches.POINTS_BATCH, 1 );\r\n\t\tg_batchHelpers.addVertexToBatch( batch, p0x | 0, p0y | 0, color );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Track drawn pixels to avoid duplicates at segment junctions\r\n\tconst drawn = new Set();\r\n\tconst batch = screenData.batches[ g_batches.POINTS_BATCH ];\r\n\r\n\t// Draw consecutive segments, skipping duplicate pixels\r\n\tfor( let i = 0; i + 3 < pts.length; i += 2 ) {\r\n\t\tconst x1 = pts[ i ] | 0;\r\n\t\tconst y1 = pts[ i + 1 ] | 0;\r\n\t\tconst x2 = pts[ i + 2 ] | 0;\r\n\t\tconst y2 = pts[ i + 3 ] | 0;\r\n\t\tif( x1 === x2 && y1 === y2 ) continue;\r\n\r\n\t\tconst dx = Math.abs( x2 - x1 );\r\n\t\tconst dy = Math.abs( y2 - y1 );\r\n\t\tconst pointCount = Math.max( dx, dy ) + 1;\r\n\t\tg_batches.prepareBatch( screenData, g_batches.POINTS_BATCH, pointCount );\r\n\r\n\t\tconst sx = x1 < x2 ? 1 : -1;\r\n\t\tconst sy = y1 < y2 ? 1 : -1;\r\n\t\tlet err = dx - dy;\r\n\t\tlet x = x1;\r\n\t\tlet y = y1;\r\n\r\n\t\twhile( true ) {\r\n\t\t\tconst key = x + \",\" + y;\r\n\t\t\tif( !drawn.has( key ) ) {\r\n\t\t\t\tdrawn.add( key );\r\n\t\t\t\tg_batchHelpers.addVertexToBatch( batch, x, y, color );\r\n\t\t\t}\r\n\r\n\t\t\tif( x === x2 && y === y2 ) {\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tconst e2 = err * 2;\r\n\t\t\tif( e2 > -dy ) {\r\n\t\t\t\terr -= dy;\r\n\t\t\t\tx += sx;\r\n\t\t\t}\r\n\t\t\tif( e2 < dx ) {\r\n\t\t\t\terr += dx;\r\n\t\t\t\ty += sy;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n", "/**\r\n * Pi.js - Lines Drawing Module\r\n * \r\n * High-level primitive drawing operations: lines\r\n * \r\n * drawLine, drawLineSquare, drawLineCircle\r\n * \r\n * @module renderer/draw/lines\r\n */\r\n\r\n\"use strict\";\r\n\r\n// Import required modules\r\nimport * as g_batches from \"../batches.js\";\r\nimport * as g_batchHelpers from \"./batch-helpers.js\";\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Initialization\r\n ***************************************************************************************************/\r\n\r\n/**\r\n * Draw line using WebGL2 LINES or geometry based on pen size\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {number} x1 - Start X coordinate\r\n * @param {number} y1 - Start Y coordinate\r\n * @param {number} x2 - End X coordinate\r\n * @param {number} y2 - End Y coordinate\r\n * @returns {void}\r\n */\r\nexport function drawLine( screenData, x1, y1, x2, y2 ) {\r\n\tconst color = screenData.color;\r\n\r\n\t// Estimate number of points needed (Manhattan distance)\r\n\tconst dx = Math.abs( x2 - x1 );\r\n\tconst dy = Math.abs( y2 - y1 );\r\n\tconst pointCount = Math.max( dx, dy ) + 1;\r\n\r\n\t// Prepare batch for points\r\n\tconst batch = screenData.batches[ g_batches.POINTS_BATCH ];\r\n\tg_batches.prepareBatch( screenData, g_batches.POINTS_BATCH, pointCount );\r\n\r\n\t// Add a line using Bresenham's algorithm (as individual points)\r\n\tconst sx = x1 < x2 ? 1 : -1;\r\n\tconst sy = y1 < y2 ? 1 : -1;\r\n\tlet err = dx - dy;\r\n\r\n\tlet x = x1;\r\n\tlet y = y1;\r\n\r\n\twhile( true ) {\r\n\r\n\t\t// Add current point\r\n\t\tg_batchHelpers.addVertexToBatch( batch, x, y, color );\r\n\r\n\t\t// Check if we've reached the end\r\n\t\tif( x === x2 && y === y2 ) {\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// Bresenham error calculation\r\n\t\tconst e2 = err * 2;\r\n\t\tif( e2 > -dy ) {\r\n\t\t\terr -= dy;\r\n\t\t\tx += sx;\r\n\t\t}\r\n\t\tif( e2 < dx ) {\r\n\t\t\terr += dx;\r\n\t\t\ty += sy;\r\n\t\t}\r\n\t}\r\n}\r\n", "/**\r\n * Pi.js - Rects Drawing Module\r\n * \r\n * High-level primitive drawing operations: rects\r\n * \r\n * drawRectPenPixel, drawRectSquare, drawRectCircle\r\n * \r\n * @module renderer/draw/rects\r\n */\r\n\r\n\"use strict\";\r\n\r\n// Import required modules\r\nimport { drawLine } from \"./lines.js\";\r\nimport { GEOMETRY_BATCH  } from \"../renderer.js\";\r\nimport * as g_batches from \"../batches.js\";\r\nimport * as g_batchHelpers from \"./batch-helpers.js\";\r\n\r\n/***************************************************************************************************\r\n * Public API\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Draw a rectangle (outline and optional fill) using the pixel pen.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {number} x - Left coordinate\r\n * @param {number} y - Top coordinate\r\n * @param {number} width - Rectangle width (pixels)\r\n * @param {number} height - Rectangle height (pixels)\r\n * @returns {void}\r\n */\r\nexport function drawRect( screenData, x, y, width, height ) {\r\n\tconst x2 = x + width - 1;\r\n\tconst y2 = y + height - 1;\r\n\tconst color = screenData.color;\r\n\t\r\n\t// Outline only for pixel pen rectangles\r\n\r\n\t// Top edge\r\n\tdrawRectFilled( screenData, x, y, width, 1, color );\r\n\r\n\t// Bottom edge\r\n\tif( height > 1 ) {\r\n\t\tdrawRectFilled( screenData, x, y + height - 1, width, 1, color );\r\n\t}\r\n\r\n\t// Left edge\r\n\tif( width > 1 && height > 2 ) {\r\n\t\tdrawRectFilled( screenData, x + width - 1, y + 1, 1, height - 2, color );\r\n\t}\r\n\t\r\n\t// Right edge\r\n\tif( height > 2 ) {\r\n\t\tdrawRectFilled( screenData, x, y + 1, 1, height - 2, color );\r\n\t}\r\n}\r\n\r\n\r\n/**\r\n * Draw filled rectangle (unsafe - no bounds checking, GPU clipping)\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {number} x - X coordinate\r\n * @param {number} y - Y coordinate\r\n * @param {number} width - Rectangle width\r\n * @param {number} height - Rectangle height\r\n * @param {Object} color - Color object with r/g/b/a components (0-255)\r\n * @returns {void}\r\n */\r\nexport function drawRectFilled( screenData, x, y, width, height, color ) {\r\n\r\n\t// Get geometry batch\r\n\tconst batch = screenData.batches[ GEOMETRY_BATCH ];\r\n\r\n\t// Prepare batch for 6 vertices (2 triangles)\r\n\tg_batches.prepareBatch( screenData, GEOMETRY_BATCH, 6 );\r\n\r\n\tconst x1 = x;\r\n\tconst y1 = y;\r\n\tconst x2 = x + width;\r\n\tconst y2 = y + height;\r\n\r\n\t// First triangle: (x,y), (x+width,y), (x,y+height)\r\n\tg_batchHelpers.addTriangleToBatch( batch, x1, y1, x2, y1, x1, y2, color );\r\n\r\n\t// Second triangle: (x+width,y), (x+width,y+height), (x,y+height)\r\n\tg_batchHelpers.addTriangleToBatch( batch, x2, y1, x2, y2, x1, y2, color );\r\n}\r\n", "/**\r\n * Pi.js - Circles Drawing Module\r\n * \r\n * Low-level drawing operations: circle drawing.\r\n * \r\n * drawCircle, drawCirclePenSquare, drawCircleCircle\r\n * \r\n * @module renderer/draw/circles\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_batches from \"../batches.js\";\r\nimport * as g_geometry from \"./geometry.js\";\r\nimport { drawPixelUnsafe } from \"./primitives.js\";\r\n\r\n\r\n/**\r\n * Draw circle outline using pixel drawing (no bounds checking, GPU clipping)\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {number} cx - Center X coordinate\r\n * @param {number} cy - Center Y coordinate\r\n * @param {number} radius - Circle radius\r\n * @returns {void}\r\n */\r\nexport function drawCircle( screenData, cx, cy, radius ) {\r\n\tconst color = screenData.color;\r\n\r\n\t// Nothing to draw\r\n\tif( radius <= 0 ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif( radius === 1 ) {\r\n\t\tg_batches.prepareBatch( screenData, g_batches.POINTS_BATCH, 1 );\r\n\t\tdrawPixelUnsafe( screenData, cx + 1, cy, color, g_batches.POINTS_BATCH );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Radius adjustment\r\n\tradius -= 1;\r\n\r\n\t// Single point\r\n\tif( radius === 1 ) {\r\n\t\tg_batches.prepareBatch( screenData, g_batches.POINTS_BATCH, 4 );\r\n\t\tdrawPixelUnsafe( screenData, cx + 1, cy, color, g_batches.POINTS_BATCH );\r\n\t\tdrawPixelUnsafe( screenData, cx - 1, cy, color, g_batches.POINTS_BATCH );\r\n\t\tdrawPixelUnsafe( screenData, cx, cy + 1, color, g_batches.POINTS_BATCH );\r\n\t\tdrawPixelUnsafe( screenData, cx, cy - 1, color, g_batches.POINTS_BATCH );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Estimate batch size based on circumference\r\n\tconst perimeterPixels = Math.round( 2 * Math.PI * radius );\r\n\tg_batches.prepareBatch( screenData, g_batches.POINTS_BATCH, perimeterPixels );\r\n\r\n\t// Midpoint circle algorithm (8-way symmetry)\r\n\tlet x = radius;\r\n\tlet y = 0;\r\n\tlet err = 1 - x;\r\n\r\n\t// Initial symmetrical points (no duplicates here)\r\n\tdrawPixelUnsafe( screenData, cx + x, cy + y, color, g_batches.POINTS_BATCH );\r\n\tdrawPixelUnsafe( screenData, cx - x, cy + y, color, g_batches.POINTS_BATCH );\r\n\tdrawPixelUnsafe( screenData, cx + y, cy + x, color, g_batches.POINTS_BATCH );\r\n\tdrawPixelUnsafe( screenData, cx + y, cy - x, color, g_batches.POINTS_BATCH );\r\n\r\n\twhile( x >= y ) {\r\n\t\ty++;\r\n\t\tif( err < 0 ) {\r\n\t\t\terr += 2 * y + 1;\r\n\t\t} else {\r\n\t\t\tx--;\r\n\t\t\terr += 2 * ( y - x ) + 1;\r\n\t\t}\r\n\r\n\t\tif( x === y ) {\r\n\r\n\t\t\t// On the diagonal, 8-way symmetry collapses to 4 distinct pixels.\r\n\t\t\t// Emit each unique coordinate only once so there are no overlaps.\r\n\t\t\tdrawPixelUnsafe( screenData, cx + x, cy + y, color, g_batches.POINTS_BATCH );\r\n\t\t\tdrawPixelUnsafe( screenData, cx - x, cy + y, color, g_batches.POINTS_BATCH );\r\n\t\t\tdrawPixelUnsafe( screenData, cx - x, cy - y, color, g_batches.POINTS_BATCH );\r\n\t\t\tdrawPixelUnsafe( screenData, cx + x, cy - y, color, g_batches.POINTS_BATCH );\r\n\t\t} else {\r\n\r\n\t\t\t// 8-way symmetry, all distinct when x !== y\r\n\t\t\tdrawPixelUnsafe( screenData, cx + x, cy + y, color, g_batches.POINTS_BATCH );\r\n\t\t\tdrawPixelUnsafe( screenData, cx + y, cy + x, color, g_batches.POINTS_BATCH );\r\n\t\t\tdrawPixelUnsafe( screenData, cx - y, cy + x, color, g_batches.POINTS_BATCH );\r\n\t\t\tdrawPixelUnsafe( screenData, cx - x, cy + y, color, g_batches.POINTS_BATCH );\r\n\t\t\tdrawPixelUnsafe( screenData, cx - x, cy - y, color, g_batches.POINTS_BATCH );\r\n\t\t\tdrawPixelUnsafe( screenData, cx - y, cy - x, color, g_batches.POINTS_BATCH );\r\n\t\t\tdrawPixelUnsafe( screenData, cx + y, cy - x, color, g_batches.POINTS_BATCH );\r\n\t\t\tdrawPixelUnsafe( screenData, cx + x, cy - y, color, g_batches.POINTS_BATCH );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/**\r\n * Draw filled circle (no bounds checking, GPU clipping)\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {number} cx - Center X coordinate\r\n * @param {number} cy - Center Y coordinate\r\n * @param {number} radius - Circle radius\r\n * @param {Object} color - Color object with r/g/b/a components (0-255)\r\n * @returns {void}\r\n */\r\nexport function drawCircleFilled( screenData, cx, cy, radius, color ) {\r\n\r\n\t// Apply input adjustments for MCA consistency\r\n\treturn g_geometry.drawCachedGeometry(\r\n\t\tscreenData, g_geometry.FILLED_CIRCLE, radius, cx, cy, color\r\n\t);\r\n}\r\n", "/**\r\n * Pi.js - Ellipses Drawing Module\r\n * \r\n * Low-level drawing operations: ellipse drawing.\r\n * \r\n * drawEllipse, drawEllipseSquare, drawEllipseCircle\r\n * \r\n * @module renderer/draw/ellipses\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_batches from \"../batches.js\";\r\nimport * as g_batchHelpers from \"./batch-helpers.js\";\r\n\r\n/**\r\n * Draw ellipse outline or filled\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {number} cx - Center X coordinate\r\n * @param {number} cy - Center Y coordinate\r\n * @param {number} rx - Radius X\r\n * @param {number} ry - Radius Y\r\n * @param {Object} fillColor - Fill color object (or null for outline only)\r\n * @returns {void}\r\n */\r\nexport function drawEllipse( screenData, cx, cy, rx, ry, fillColor ) {\r\n\tconst color = screenData.color;\r\n\r\n\t// Validate radii\r\n\tif( rx < 0 || ry < 0 ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Handle trivial cases\r\n\tif( rx === 0 && ry === 0 ) {\r\n\t\tg_batches.prepareBatch( screenData, g_batches.POINTS_BATCH, 1 );\r\n\t\tconst singleBatch = screenData.batches[ g_batches.POINTS_BATCH ];\r\n\t\tg_batchHelpers.addVertexToBatch( singleBatch, cx, cy, color );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Estimate pixel count using Ramanujan perimeter approximation\r\n\t// P \u2248 \u03C0[ 3(a+b) \u2212 sqrt{ (3a+b)(a+3b) } ] where a=rx, b=ry\r\n\tconst a = rx;\r\n\tconst b = ry;\r\n\tconst perimeter = Math.PI * ( 3 * ( a + b ) - Math.sqrt( ( 3 * a + b ) * ( a + 3 * b ) ) );\r\n\tconst estimatedPixels = Math.max( 8, Math.ceil( perimeter ) );\r\n\r\n\t// Prepare outline batch\r\n\tconst pointsBatchIndex = g_batches.POINTS_BATCH;\r\n\tg_batches.prepareBatch( screenData, pointsBatchIndex, estimatedPixels );\r\n\tconst pointsBatch = screenData.batches[ pointsBatchIndex ];\r\n\r\n\tconst plotPoint = function( px, py ) {\r\n\t\tconst ix = px | 0;\r\n\t\tconst iy = py | 0;\r\n\t\tg_batchHelpers.addVertexToBatch( pointsBatch, ix, iy, color );\r\n\t};\r\n\r\n\t// Symmetric plotting for the four quadrants (no duplicate pixels)\r\n\tconst plotSymmetric = function( x, y ) {\r\n\t\t\r\n\t\t// x, y are integers from the midpoint algorithm\r\n\t\tif( x === 0 ) {\r\n\r\n\t\t\t// Vertical axis: top and bottom only\r\n\t\t\tplotPoint( cx, cy + y );\r\n\t\t\tif( y !== 0 ) {\r\n\t\t\t\tplotPoint( cx, cy - y );\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif( y === 0 ) {\r\n\r\n\t\t\t// Horizontal axis: left and right only\r\n\t\t\tplotPoint( cx + x, cy );\r\n\t\t\tplotPoint( cx - x, cy );\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// General case: four distinct points\r\n\t\tplotPoint( cx + x, cy + y );\r\n\t\tplotPoint( cx - x, cy + y );\r\n\t\tplotPoint( cx - x, cy - y );\r\n\t\tplotPoint( cx + x, cy - y );\r\n\t};\r\n\r\n\t// Midpoint ellipse algorithm\r\n\tlet x = 0;\r\n\tlet y = ry;\r\n\r\n\tconst rx2 = rx * rx;\r\n\tconst ry2 = ry * ry;\r\n\tlet dx = 2 * ry2 * x;\r\n\tlet dy = 2 * rx2 * y;\r\n\r\n\t// Decision parameter for region 1\r\n\tlet d1 = ry2 - rx2 * ry + 0.25 * rx2;\r\n\tplotSymmetric( x, y );\r\n\r\n\t// Optional: collect scanlines for fill (no caching)\r\n\tconst doFill = fillColor !== null && rx >= 1 && ry >= 1;\r\n\tlet scanlineMinMax = null;\r\n\tlet updateScanlineSym = null;\r\n\r\n\tif( doFill ) {\r\n\r\n\t\t// Map<y, {left: x, right: x}>\r\n\t\tscanlineMinMax = new Map();\r\n\r\n\t\tconst updateScanline = function( px, py ) {\r\n\t\t\tconst pixelY = py | 0;\r\n\t\t\tconst pixelX = px | 0;\r\n\r\n\t\t\tif( !scanlineMinMax.has( pixelY ) ) {\r\n\t\t\t\tif( pixelX < 0 ) {\r\n\t\t\t\t\tscanlineMinMax.set( pixelY, { \"left\": pixelX, \"right\": Infinity } );\r\n\t\t\t\t} else if( pixelX > 0 ) {\r\n\t\t\t\t\tscanlineMinMax.set( pixelY, { \"left\": -Infinity, \"right\": pixelX } );\r\n\t\t\t\t} else {\r\n\t\t\t\t\tscanlineMinMax.set( pixelY, { \"left\": pixelX, \"right\": pixelX } );\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tconst limits = scanlineMinMax.get( pixelY );\r\n\r\n\t\t\t\t// Find innermost border pixels (closest to center)\r\n\t\t\t\tif( pixelX < 0 && pixelX > limits.left ) {\r\n\t\t\t\t\tlimits.left = pixelX;\r\n\t\t\t\t}\r\n\t\t\t\tif( pixelX > 0 && pixelX < limits.right ) {\r\n\t\t\t\t\tlimits.right = pixelX;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\t// Seed\r\n\t\tupdateScanline(  x,  y );\r\n\t\tupdateScanline( -x,  y );\r\n\t\tupdateScanline( -x, -y );\r\n\t\tupdateScanline(  x, -y );\r\n\r\n\t\t// Symmetric updater for scanlines (can accept any x,y pair)\r\n\t\tupdateScanlineSym = function( sx, sy ) {\r\n\t\t\tupdateScanline(  sx,  sy );\r\n\t\t\tupdateScanline( -sx,  sy );\r\n\t\t\tupdateScanline( -sx, -sy );\r\n\t\t\tupdateScanline(  sx, -sy );\r\n\t\t};\r\n\t}\r\n\r\n\t// Region 1\r\n\twhile( dx < dy ) {\r\n\t\tif( d1 < 0 ) {\r\n\t\t\tx += 1;\r\n\t\t\tdx = dx + 2 * ry2;\r\n\t\t\td1 = d1 + dx + ry2;\r\n\t\t} else {\r\n\t\t\tx += 1;\r\n\t\t\ty -= 1;\r\n\t\t\tdx = dx + 2 * ry2;\r\n\t\t\tdy = dy - 2 * rx2;\r\n\t\t\td1 = d1 + dx - dy + ry2;\r\n\t\t}\r\n\r\n\t\tplotSymmetric( x, y );\r\n\r\n\t\t// Update fill scanlines\r\n\t\tif( doFill ) {\r\n\t\t\tupdateScanlineSym( x, y );\r\n\t\t}\r\n\t}\r\n\r\n\t// Decision parameter for region 2\r\n\tlet d2 = ry2 * ( x + 0.5 ) * ( x + 0.5 ) + rx2 * ( y - 1 ) * ( y - 1 ) - rx2 * ry2;\r\n\r\n\t// Region 2\r\n\twhile( y >= 0 ) {\r\n\t\tif( d2 > 0 ) {\r\n\t\t\ty -= 1;\r\n\t\t\tdy = dy - 2 * rx2;\r\n\t\t\td2 = d2 + rx2 - dy;\r\n\t\t} else {\r\n\t\t\ty -= 1;\r\n\t\t\tx += 1;\r\n\t\t\tdx = dx + 2 * ry2;\r\n\t\t\tdy = dy - 2 * rx2;\r\n\t\t\td2 = d2 + dx - dy + rx2;\r\n\t\t}\r\n\r\n\t\tplotSymmetric( x, y );\r\n\r\n\t\t// Update fill scanlines\r\n\t\tif( doFill ) {\r\n\t\t\tupdateScanlineSym( x, y );\r\n\t\t}\r\n\t}\r\n\r\n\t// Emit fill geometry if requested\r\n\tif( doFill ) {\r\n\t\tconst sortedYCoords = [];\r\n\t\tfor( const [ currentY ] of scanlineMinMax.entries() ) {\r\n\t\t\tsortedYCoords.push( currentY );\r\n\t\t}\r\n\t\tsortedYCoords.sort( function( a, b ) { return a - b; } );\r\n\r\n\t\tif( sortedYCoords.length >= 3 ) {\r\n\t\t\tconst interiorRowCount = sortedYCoords.length - 2;\r\n\t\t\tconst vertexCount = interiorRowCount * 6;\r\n\t\t\tg_batches.prepareBatch( screenData, g_batches.GEOMETRY_BATCH, vertexCount );\r\n\t\t\tconst geoBatch = screenData.batches[ g_batches.GEOMETRY_BATCH ];\r\n\r\n\t\t\tfor( let row = 1; row < sortedYCoords.length - 1; row++ ) {\r\n\t\t\t\tconst currentY = sortedYCoords[ row ];\r\n\t\t\t\tconst limits = scanlineMinMax.get( currentY );\r\n\r\n\t\t\t\t// Skip if we don't have valid limits (safety)\r\n\t\t\t\tif( limits.left === -Infinity || limits.right === Infinity ) {\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Get the interior span by moving 1 pixel inward from innermost border pixels\r\n\t\t\t\tconst xStart = limits.left + 1;\r\n\t\t\t\tconst xEnd = limits.right - 1;\r\n\t\t\t\tif( xEnd < xStart ) {\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Adjust Y to align fill with outline\r\n\t\t\t\tconst yWorld = cy + currentY;\r\n\t\t\t\tconst x1 = cx + xStart;\r\n\t\t\t\tconst x2 = cx + xEnd + 1;\r\n\r\n\t\t\t\tg_batchHelpers.addVertexToBatch( geoBatch, x1, yWorld, fillColor );\r\n\t\t\t\tg_batchHelpers.addVertexToBatch( geoBatch, x2, yWorld, fillColor );\r\n\t\t\t\tg_batchHelpers.addVertexToBatch( geoBatch, x1, yWorld + 1, fillColor );\r\n\t\t\t\tg_batchHelpers.addVertexToBatch( geoBatch, x2, yWorld, fillColor );\r\n\t\t\t\tg_batchHelpers.addVertexToBatch( geoBatch, x2, yWorld + 1, fillColor );\r\n\t\t\t\tg_batchHelpers.addVertexToBatch( geoBatch, x1, yWorld + 1, fillColor );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n", "/**\r\n * Pi.js - Render Effects Module\r\n * \r\n * Screen-space post operations that manipulate the off-screen render target (FBO),\r\n * such as scrolling and simple blits.\r\n * \r\n * @module renderer/draw/effects\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_batches from \"./batches.js\";\r\n\r\n/**\r\n * Shift a rectangular region of the screen image up by yOffset pixels.\r\n *\r\n * Coordinates are physical/FBO top-left. Defaults to the full framebuffer.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {number} yOffset - Number of pixels to shift up\r\n * @param {number} [x] - Region left\r\n * @param {number} [y] - Region top\r\n * @param {number} [width] - Region width\r\n * @param {number} [height] - Region height\r\n * @returns {void}\r\n */\r\nexport function shiftImageUp( screenData, yOffset, x, y, width, height ) {\r\n\r\n\tif( yOffset <= 0 ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst screenWidth = screenData.width;\r\n\tconst screenHeight = screenData.height;\r\n\tlet regionX = 0;\r\n\tlet regionY = 0;\r\n\tlet regionW = screenWidth;\r\n\tlet regionH = screenHeight;\r\n\r\n\tif( x !== undefined && x !== null ) {\r\n\t\tregionX = x;\r\n\t\tregionY = y;\r\n\t\tregionW = width;\r\n\t\tregionH = height;\r\n\t}\r\n\r\n\tif( regionW <= 0 || regionH <= 0 ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst gl = screenData.gl;\r\n\r\n\t// Ensure the latest content is in screenData.fboTexture\r\n\tg_batches.flushBatches( screenData );\r\n\r\n\tconst remainH = regionH - yOffset;\r\n\r\n\t// GL clip rectangle (bottom-left origin)\r\n\tconst glX0 = regionX;\r\n\tconst glY0 = screenHeight - ( regionY + regionH );\r\n\tconst glX1 = regionX + regionW;\r\n\tconst glY1 = screenHeight - regionY;\r\n\r\n\tif( remainH <= 0 ) {\r\n\t\tgl.bindFramebuffer( gl.FRAMEBUFFER, screenData.FBO );\r\n\t\tgl.enable( gl.SCISSOR_TEST );\r\n\t\tgl.scissor( glX0, glY0, regionW, regionH );\r\n\t\tgl.clearColor( 0, 0, 0, 0 );\r\n\t\tgl.clear( gl.COLOR_BUFFER_BIT );\r\n\t\tgl.disable( gl.SCISSOR_TEST );\r\n\t\tgl.bindFramebuffer( gl.FRAMEBUFFER, null );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// NOTE ABOUT COORDINATES:\r\n\t// WebGL framebuffer coordinates are bottom-left origin. When we say\r\n\t// \"shift image up\" in the on-screen sense, we mean the visible content moves\r\n\t// toward the top of the window, leaving a newly blank area at the bottom.\r\n\r\n\tconst srcY0 = screenHeight - ( regionY + regionH );\r\n\tconst srcY1 = screenHeight - ( regionY + yOffset );\r\n\tconst dstY0 = screenHeight - ( regionY + remainH );\r\n\tconst dstY1 = screenHeight - regionY;\r\n\r\n\t// Pass 1: Copy the remaining strip into the shifted destination\r\n\tgl.bindFramebuffer( gl.READ_FRAMEBUFFER, screenData.FBO );\r\n\tgl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, screenData.bufferFBO );\r\n\tgl.clearColor( 0, 0, 0, 0 );\r\n\tgl.clear( gl.COLOR_BUFFER_BIT );\r\n\tgl.blitFramebuffer(\r\n\t\tglX0, srcY0, glX1, srcY1,\r\n\t\tglX0, dstY0, glX1, dstY1,\r\n\t\tgl.COLOR_BUFFER_BIT, gl.NEAREST\r\n\t);\r\n\r\n\t// Pass 2: Copy only the region back so pixels outside the clip stay\r\n\tgl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, screenData.FBO );\r\n\tgl.bindFramebuffer( gl.READ_FRAMEBUFFER, screenData.bufferFBO );\r\n\tgl.blitFramebuffer(\r\n\t\tglX0, glY0, glX1, glY1,\r\n\t\tglX0, glY0, glX1, glY1,\r\n\t\tgl.COLOR_BUFFER_BIT, gl.NEAREST\r\n\t);\r\n\r\n\t// Unbind framebuffers\r\n\tgl.bindFramebuffer( gl.READ_FRAMEBUFFER, null );\r\n\tgl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, null );\r\n}\r\n\r\n\r\n/**\r\n * Clear a region of the screen framebuffer\r\n *\r\n * Coordinates are physical/FBO top-left.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {number} x - Left coordinate\r\n * @param {number} y - Top coordinate\r\n * @param {number} width - Region width\r\n * @param {number} height - Region height\r\n * @returns {void}\r\n */\r\nexport function cls( screenData, x, y, width, height ) {\r\n\r\n\tif( width <= 0 || height <= 0 ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// If clearing entire screen remove all batches, if not flush before clearing area\r\n\tif( x === 0 && y === 0 && width === screenData.width && height === screenData.height ) {\r\n\t\tg_batches.resetBatches( screenData );\r\n\t} else {\r\n\t\tg_batches.flushBatches( screenData );\r\n\t}\r\n\r\n\tconst gl = screenData.gl;\r\n\r\n\tgl.bindFramebuffer( gl.FRAMEBUFFER, screenData.FBO );\r\n\tgl.viewport( 0, 0, screenData.width, screenData.height );\r\n\r\n\tif(\r\n\t\tx === 0 &&\r\n\t\ty === 0 &&\r\n\t\twidth === screenData.width &&\r\n\t\theight === screenData.height\r\n\t) {\r\n\t\tgl.clearColor( 0, 0, 0, 0 );\r\n\t\tgl.clear( gl.COLOR_BUFFER_BIT );\r\n\t} else {\r\n\t\tgl.enable( gl.SCISSOR_TEST );\r\n\t\tconst scissorY = screenData.height - ( y + height );\r\n\t\tgl.scissor( x, scissorY, width, height );\r\n\t\tgl.clearColor( 0, 0, 0, 0 );\r\n\t\tgl.clear( gl.COLOR_BUFFER_BIT );\r\n\t\tgl.disable( gl.SCISSOR_TEST );\r\n\t}\r\n\r\n\tgl.bindFramebuffer( gl.FRAMEBUFFER, null );\r\n}\r\n", "/**\r\n * Pi.js - Graphics API Module\r\n * \r\n * Thin wrapper layer for graphics commands.\r\n * Handles input parsing, validation, and builds optimized drawing functions.\r\n * \r\n * @module api/graphics\r\n */\r\n\r\n\"use strict\";\r\n\r\n// Import modules\r\nimport * as g_commands from \"../core/commands.js\";\r\nimport * as g_screenManager from \"../core/screen-manager.js\";\r\nimport * as g_utils from \"../core/utils.js\";\r\nimport * as g_renderer from \"../renderer/renderer.js\";\r\nimport * as g_colors from \"./colors.js\";\r\nimport * as g_images from \"./images.js\";\r\nimport * as g_view from \"./view.js\";\r\n\r\nconst DEFAULT_BLIT_COLOR = g_utils.rgbToColor( 255, 255, 255, 255 );\r\nlet m_api = null;\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Commands\r\n ***************************************************************************************************/\r\n\r\n\r\n// Initialize graphics module - only gets called on script load\r\nexport function init( api ) {\r\n\tm_api = api;\r\n\r\n\t// Build the null graphics commands - basically will throw an error since no screen is available\r\n\tbuildApi( null );\r\n\r\n\t// CLS doesn't need to be a hot-path item so just use addCommand\r\n\tg_commands.addCommand( \"cls\", cls, true, [ \"x\", \"y\", \"width\", \"height\" ] );\r\n\r\n\t// Register screen init function to rebuild API when screen is created\r\n\tg_screenManager.addScreenInitFunction( ( screenData ) => buildApi( screenData ) );\r\n}\r\n\r\n// Function to build the external API drawing commands (e.g., pset, line, etc...) for the current\r\n// active screen. This creates specialized API wrappers that handle input parsing/validation, then\r\n// call optimized internal drawing routines. By closing over specific, already-optimized functions\r\n// and screen configuration, it provides highly performant, monomorphic call sites in hot loops.\r\nexport function buildApi( s_screenData ) {\r\n\r\n\t// Set error functions for when no screen is available\r\n\tif( s_screenData === null ) {\r\n\t\tm_api.arc = () => g_utils.errFn( \"arc\" );\r\n\t\tm_api.bezier = () => g_utils.errFn( \"bezier\" );\r\n\t\tm_api.circle = () => g_utils.errFn( \"circle\" );\r\n\t\tm_api.ellipse = () => g_utils.errFn( \"ellipse\" );\r\n\t\tm_api.line = () => g_utils.errFn( \"line\" );\r\n\t\tm_api.pset = () => g_utils.errFn( \"pset\" );\r\n\t\tm_api.rect = () => g_utils.errFn( \"rect\" );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Draw commands\r\n\tconst s_drawArc = g_renderer.drawArc;\r\n\tconst s_drawBezier = g_renderer.drawBezier;\r\n\tconst s_drawCircle = g_renderer.drawCircle;\r\n\tconst s_drawCircleFilled = g_renderer.drawCircleFilled;\r\n\tconst s_drawEllipse = g_renderer.drawEllipse;\r\n\tconst s_drawLine = g_renderer.drawLine;\r\n\tconst s_drawPixel = g_renderer.drawPixel;\r\n\tconst s_drawRect = g_renderer.drawRect;\r\n\tconst s_drawRectFilled = g_renderer.drawRectFilled;\r\n\tconst s_drawImage = g_renderer.drawImage;\r\n\tconst s_drawSprite = g_renderer.drawSprite;\r\n\t\r\n\t// Other API Commands\r\n\tconst s_getImageFromRawInput = g_images.getImageFromRawInput;\r\n\tconst s_getStoredImage = g_images.getStoredImage;\r\n\r\n\t// Utility commands\r\n\tconst s_isObjectLiteral = g_utils.isObjectLiteral;\r\n\tconst s_setImageDirty = g_renderer.setImageDirty;\r\n\tconst s_getInt = g_utils.getInt;\r\n\tconst s_getFloat = g_utils.getFloat;\r\n\tconst s_degreesToRadian = g_utils.degreesToRadian;\r\n\tconst s_getColorValueByRawInput = g_colors.getColorValueByRawInput;\r\n\r\n\t// Constants\r\n\tconst s_pointsBatch = g_renderer.POINTS_BATCH;\r\n\tconst s_imageReplaceBatch = g_renderer.IMAGE_REPLACE_BATCH;\r\n\r\n\t/**********************************************************************************************\r\n\t * ARC Command\r\n\t **********************************************************************************************/\r\n\r\n\tconst arcFn = ( x, y, radius, angle1, angle2 ) => {\r\n\t\tconst pX = s_getInt( x, null );\r\n\t\tconst pY = s_getInt( y, null );\r\n\t\tconst pRadius = s_getInt( radius, null );\r\n\r\n\t\t// Validate integer parameters\r\n\t\tif( pX === null || pY === null || pRadius === null ) {\r\n\t\t\tconst error = new TypeError( \"arc: Parameters x, y, and radius must be integers.\" );\r\n\t\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Validate angle parameters (numbers in radians)\r\n\t\tif(\r\n\t\t\ttypeof angle1 !== \"number\" || isNaN( angle1 ) ||\r\n\t\t\ttypeof angle2 !== \"number\" || isNaN( angle2 )\r\n\t\t) {\r\n\t\t\tconst error = new TypeError(\r\n\t\t\t\t\"arc: Parameters angle1 and angle2 must be numbers (in radians).\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Draw Arc\r\n\t\ts_drawArc(\r\n\t\t\ts_screenData, pX, pY, pRadius, s_degreesToRadian( angle1 ),\r\n\t\t\ts_degreesToRadian( angle2 )\r\n\t\t);\r\n\t\ts_setImageDirty( s_screenData );\r\n\t};\r\n\tconst arcFnWrapper = ( x, y, radius, angle1, angle2 ) => {\r\n\t\tif( s_isObjectLiteral( x ) ) {\r\n\t\t\tarcFn( x.x, x.y, x.radius, x.angle1, x.angle2 );\r\n\t\t} else {\r\n\t\t\tarcFn( x, y, radius, angle1, angle2 );\r\n\t\t}\r\n\t};\r\n\tm_api.arc = arcFnWrapper;\r\n\ts_screenData.api.arc = arcFnWrapper;\r\n\t\r\n\t/**********************************************************************************************\r\n\t * BEZIER Command\r\n\t **********************************************************************************************/\r\n\r\n\tconst bezierFn = ( x1, y1, x2, y2, x3, y3, x4, y4 ) => {\r\n\t\tconst pX1 = s_getInt( x1, null );\r\n\t\tconst pY1 = s_getInt( y1, null );\r\n\t\tconst pX2 = s_getInt( x2, null );\r\n\t\tconst pY2 = s_getInt( y2, null );\r\n\t\tconst pX3 = s_getInt( x3, null );\r\n\t\tconst pY3 = s_getInt( y3, null );\r\n\t\tconst pX4 = s_getInt( x4, null );\r\n\t\tconst pY4 = s_getInt( y4, null );\r\n\r\n\t\tif(\r\n\t\t\tpX1 === null || pY1 === null || pX2 === null || pY2 === null ||\r\n\t\t\tpX3 === null || pY3 === null || pX4 === null || pY4 === null\r\n\t\t) {\r\n\t\t\tconst error = new TypeError(\r\n\t\t\t\t\"bezier: All control point coordinates must be integers.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Draw Bezier\r\n\t\ts_drawBezier( s_screenData, pX1, pY1, pX2, pY2, pX3, pY3, pX4, pY4 );\r\n\t\ts_setImageDirty( s_screenData );\r\n\t};\r\n\tconst bezierFnWrapper = ( x1, y1, x2, y2, x3, y3, x4, y4 ) => {\r\n\t\tif( s_isObjectLiteral( x1 ) ) {\r\n\t\t\tbezierFn( x1.x1, x1.y1, x1.x2, x1.y2, x1.x3, x1.y3, x1.x4, x1.y4 );\r\n\t\t} else {\r\n\t\t\tbezierFn( x1, y1, x2, y2, x3, y3, x4, y4 );\r\n\t\t}\r\n\t};\r\n\tm_api.bezier = bezierFnWrapper;\r\n\ts_screenData.api.bezier = bezierFnWrapper;\r\n\r\n\t/**********************************************************************************************\r\n\t * Circle Command\r\n\t **********************************************************************************************/\r\n\r\n\tconst circleFn = ( x, y, radius, fillColor ) => {\r\n\t\tconst pX = s_getInt( x, null );\r\n\t\tconst pY = s_getInt( y, null );\r\n\t\tconst pRadius = s_getInt( radius, null );\r\n\r\n\t\tif( pX === null || pY === null || pRadius === null ) {\r\n\t\t\tconst error = new TypeError(\r\n\t\t\t\t\"circle: Parameters x, y, and radius must be integers.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Parse and validate fillColor here (single source of truth)\r\n\t\tlet fillColorValue = null;\r\n\t\tif( fillColor != null ) {\r\n\t\t\tfillColorValue = s_getColorValueByRawInput( s_screenData, fillColor );\r\n\t\t\tif( fillColorValue === null ) {\r\n\t\t\t\tconst error = new TypeError(\r\n\t\t\t\t\t\"circle: Parameter 'fillColor' must be a valid color.\"\r\n\t\t\t\t);\r\n\t\t\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\r\n\t\t\t// Fill in the circle\r\n\t\t\tif( pRadius > 0 ) {\r\n\t\t\t\ts_drawCircleFilled( s_screenData, pX, pY, pRadius, fillColorValue );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Draw the circle border\r\n\t\ts_drawCircle( s_screenData, pX, pY, pRadius );\r\n\t\ts_setImageDirty( s_screenData );\r\n\t};\r\n\tconst circleFnWrapper = ( x, y, radius, fillColor ) => {\r\n\t\tif( s_isObjectLiteral( x ) ) {\r\n\t\t\tcircleFn( x.x, x.y, x.radius, x.fillColor );\r\n\t\t} else {\r\n\t\t\tcircleFn( x, y, radius, fillColor);\r\n\t\t}\r\n\t};\r\n\r\n\tm_api.circle = circleFnWrapper;\r\n\ts_screenData.api.circle = circleFnWrapper;\r\n\r\n\t/**********************************************************************************************\r\n\t * Ellipse Command\r\n\t **********************************************************************************************/\r\n\r\n\tconst ellipseFn = ( x, y, radiusX, radiusY, fillColor ) => {\r\n\t\tconst pX = s_getInt( x, null );\r\n\t\tconst pY = s_getInt( y, null );\r\n\t\tconst pRx = s_getInt( radiusX, null );\r\n\t\tconst pRy = s_getInt( radiusY, null );\r\n\r\n\t\tif( pX === null || pY === null || pRx === null || pRy === null ) {\r\n\t\t\tconst error = new TypeError( \"ellipse: Parameters x, y, rx, and ry must be integers.\" );\r\n\t\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Parse and validate fillColor here (single source of truth)\r\n\t\tlet fillColorValue = null;\r\n\t\tif( fillColor != null ) {\r\n\t\t\tfillColorValue = s_getColorValueByRawInput( s_screenData, fillColor );\r\n\t\t\tif( fillColorValue === null ) {\r\n\t\t\t\tconst error = new TypeError(\r\n\t\t\t\t\t\"ellipse: Parameter 'fillColor' must be a valid color.\"\r\n\t\t\t\t);\r\n\t\t\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\r\n\t\t\t// Filled handled inside drawEllipse\r\n\t\t}\r\n\r\n\t\t// Draw the ellipse border\r\n\t\ts_drawEllipse( s_screenData, pX, pY, pRx, pRy, fillColorValue );\r\n\t\ts_setImageDirty( s_screenData );\r\n\t};\r\n\tconst ellipseFnWrapper = ( x, y, radiusX, radiusY, fillColor ) => {\r\n\t\tif( s_isObjectLiteral( x ) ) {\r\n\t\t\tellipseFn( x.x, x.y, x.radiusX, x.radiusY, x.fillColor );\r\n\t\t} else {\r\n\t\t\tellipseFn( x, y, radiusX, radiusY, fillColor);\r\n\t\t}\r\n\t};\r\n\r\n\tm_api.ellipse = ellipseFnWrapper;\r\n\ts_screenData.api.ellipse = ellipseFnWrapper;\r\n\r\n\t/**********************************************************************************************\r\n\t * LINE Command\r\n\t **********************************************************************************************/\r\n\r\n\tconst lineFn = ( x1, y1, x2, y2 ) => {\r\n\t\tconst pX1 = s_getInt( x1, null );\r\n\t\tconst pY1 = s_getInt( y1, null );\r\n\t\tconst pX2 = s_getInt( x2, null );\r\n\t\tconst pY2 = s_getInt( y2, null );\r\n\r\n\t\t// Make sure x1, y1, x2, y2 are integers\r\n\t\tif( pX1 === null || pY1 === null || pX2 === null || pY2 === null ) {\r\n\t\t\tconst error = new TypeError( \"line: Parameters x1, y1, x2, y2 must be integers.\" );\r\n\t\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Draw Line\r\n\t\ts_drawLine( s_screenData, pX1, pY1, pX2, pY2 );\r\n\t\ts_setImageDirty( s_screenData );\r\n\t};\r\n\tconst lineFnWrapper = ( x1, y1, x2, y2 ) => {\r\n\t\tif( s_isObjectLiteral( x1 ) ) {\r\n\t\t\tlineFn( x1.x1 , x1.y1, x1.x2, x1.y2 );\r\n\t\t} else {\r\n\t\t\tlineFn( x1, y1, x2, y2 );\r\n\t\t}\r\n\t};\r\n\r\n\tm_api.line = lineFnWrapper;\r\n\ts_screenData.api.line = lineFnWrapper;\r\n\t\r\n\t/**********************************************************************************************\r\n\t * PSET Command\r\n\t **********************************************************************************************/\r\n\r\n\tconst psetFn = ( x, y ) => {\r\n\t\tconst pX = s_getInt( x, null );\r\n\t\tconst pY = s_getInt( y, null );\r\n\r\n\t\t// Make sure x and y are integers\r\n\t\tif( pX === null || pY === null ) {\r\n\t\t\tconst error = new TypeError( \"pset: Parameters x and y must be integers.\" );\r\n\t\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Draw the pixel\r\n\t\ts_drawPixel( s_screenData, pX, pY, s_pointsBatch );\r\n\t\ts_setImageDirty( s_screenData );\r\n\r\n\t\t// Set the cursor after drawing\r\n\t\ts_screenData.cursor.x = x;\r\n\t\ts_screenData.cursor.y = y;\r\n\t};\r\n\tconst psetFnWrapper = ( x, y ) => {\r\n\t\tif( s_isObjectLiteral( x ) ) {\r\n\t\t\tpsetFn( x.x , x.y );\r\n\t\t} else {\r\n\t\t\tpsetFn( x, y );\r\n\t\t}\r\n\t};\r\n\tm_api.pset = psetFnWrapper;\r\n\ts_screenData.api.pset = psetFnWrapper;\r\n\r\n\t/**********************************************************************************************\r\n\t * RECT Command\r\n\t **********************************************************************************************/\r\n\r\n\tconst rectFn = ( x, y, width, height, fillColor ) => {\r\n\t\tconst pX = s_getInt( x, null );\r\n\t\tconst pY = s_getInt( y, null );\r\n\t\tconst pWidth = s_getInt( width, null );\r\n\t\tconst pHeight = s_getInt( height, null );\r\n\r\n\t\tif( pX === null || pY === null || pWidth === null || pHeight === null ) {\r\n\t\t\tconst error = new TypeError( \"rect: Parameters x, y, width, height must be integers.\" );\r\n\t\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\tif( pWidth < 1 || pHeight < 1 ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Parse and validate fillColor here (single source of truth)\r\n\t\tlet fillColorValue = null;\r\n\t\tif( fillColor != null ) {\r\n\t\t\tfillColorValue = s_getColorValueByRawInput( s_screenData, fillColor );\r\n\t\t\tif( fillColorValue === null ) {\r\n\t\t\t\tconst error = new TypeError( \"rect: Parameter 'fillColor' must be a valid color.\" );\r\n\t\t\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\r\n\t\t\t// Fill in the rectangle\r\n\t\t\tconst fWidth = pWidth - 2;\r\n\t\t\tconst fHeight = pHeight - 2;\r\n\t\t\tif( fWidth > 0 && fHeight > 0 ) {\r\n\t\t\t\ts_drawRectFilled( s_screenData, pX + 1, pY + 1, fWidth, fHeight, fillColorValue );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Draw the rect border\r\n\t\ts_drawRect( s_screenData, pX, pY, pWidth, pHeight );\r\n\t\ts_setImageDirty( s_screenData );\r\n\t};\r\n\tconst rectFnWrapper = ( x, y, width, height, fillColor ) => {\r\n\t\tif( s_isObjectLiteral( x ) ) {\r\n\t\t\trectFn( x.x , x.y, x.width, x.height, x.fillColor );\r\n\t\t} else {\r\n\t\t\trectFn( x, y, width, height, fillColor );\r\n\t\t}\r\n\t};\r\n\r\n\tm_api.rect = rectFnWrapper;\r\n\ts_screenData.api.rect = rectFnWrapper;\r\n\r\n\t/**********************************************************************************************\r\n\t * BLIT IMAGE Command\r\n\t **********************************************************************************************/\r\n\r\n\t// Draw image with blending disabled\r\n\tconst blitImageFn = ( img, x, y, color, anchorX, anchorY, scaleX, scaleY, angleRad ) => {\r\n\t\tconst pAnchorX = anchorX ?? s_screenData.defaultAnchorX;\r\n\t\tconst pAnchorY = anchorY ?? s_screenData.defaultAnchorY;\r\n\t\tconst pColor = color ?? DEFAULT_BLIT_COLOR;\r\n\t\ts_drawImage(\r\n\t\t\ts_screenData, img, x, y, pColor, pAnchorX, pAnchorY, scaleX, scaleY, angleRad,\r\n\t\t\ts_imageReplaceBatch\r\n\t\t);\r\n\t\ts_setImageDirty( s_screenData );\r\n\t};\r\n\r\n\tconst blitImageFnWrapper = (\r\n\t\timg,\r\n\t\tx = 0,\r\n\t\ty = 0,\r\n\t\tcolor,\r\n\t\tanchorX,\r\n\t\tanchorY,\r\n\t\tscaleX = 1,\r\n\t\tscaleY = 1,\r\n\t\tangleRad = 0\r\n\t) => {\r\n\t\tif( s_isObjectLiteral( img ) ) {\r\n\t\t\tblitImageFn(\r\n\t\t\t\timg.img, img.x, img.y, img.color, img.anchorX, img.anchorY, img.scaleX, img.scaleY,\r\n\t\t\t\timg.angleRad\r\n\t\t\t);\r\n\t\t} else {\r\n\t\t\tblitImageFn( img, x, y, color, anchorX, anchorY, scaleX, scaleY, angleRad );\r\n\t\t}\r\n\t};\r\n\tm_api.blitImage = blitImageFnWrapper;\r\n\ts_screenData.api.blitImage = blitImageFnWrapper;\r\n\r\n\t/**********************************************************************************************\r\n\t * BLIT SPRITE Command\r\n\t **********************************************************************************************/\r\n\r\n\t// Draw image with blending disabled\r\n\tconst blitSpriteFn = (\r\n\t\tname, frame, x, y, color, anchorX, anchorY, scaleX, scaleY, angleRad\r\n\t) => {\r\n\t\tconst spriteData = s_getStoredImage( name );\r\n\t\tconst frameData = spriteData.frames[ frame ];\r\n\t\tconst img = spriteData.image;\r\n\t\tconst pAnchorX = anchorX ?? s_screenData.defaultAnchorX;\r\n\t\tconst pAnchorY = anchorY ?? s_screenData.defaultAnchorY;\r\n\t\tconst pColor = color ?? DEFAULT_BLIT_COLOR;\r\n\t\ts_drawSprite(\r\n\t\t\ts_screenData, img,\r\n\t\t\tframeData.x, frameData.y, frameData.width, frameData.height,\r\n\t\t\tx, y, frameData.width, frameData.height,\r\n\t\t\tpColor, pAnchorX, pAnchorY, scaleX, scaleY, angleRad,\r\n\t\t\ts_imageReplaceBatch\r\n\t\t);\r\n\t\ts_setImageDirty( s_screenData );\r\n\t};\r\n\r\n\tconst blitSpriteFnWrapper = (\r\n\t\tname,\r\n\t\tframe = 0,\r\n\t\tx = 0,\r\n\t\ty = 0,\r\n\t\tcolor,\r\n\t\tanchorX,\r\n\t\tanchorY,\r\n\t\tscaleX = 1,\r\n\t\tscaleY = 1,\r\n\t\tangleRad = 0\r\n\t) => {\r\n\t\tif( s_isObjectLiteral( name ) ) {\r\n\t\t\tblitSpriteFn(\r\n\t\t\t\tname.name, name.frame, name.x, name.y, name.color, name.anchorX, name.anchorY,\r\n\t\t\t\tname.scaleX, name.scaleY, name.angleRad\r\n\t\t\t);\r\n\t\t} else {\r\n\t\t\tblitSpriteFn( name, frame, x, y, color, anchorX, anchorY, scaleX, scaleY, angleRad );\r\n\t\t}\r\n\t};\r\n\tm_api.blitSprite = blitSpriteFnWrapper;\r\n\ts_screenData.api.blitSprite = blitSpriteFnWrapper;\r\n\r\n\t/**********************************************************************************************\r\n\t * DRAW IMAGE Command\r\n\t **********************************************************************************************/\r\n\r\n\tconst drawImageFn = ( image, x, y, color, anchorX, anchorY, scaleX, scaleY, angle ) => {\r\n\t\tx = s_getInt( x, null );\r\n\t\ty = s_getInt( y, null );\r\n\t\tcolor = color ?? DEFAULT_BLIT_COLOR;\r\n\t\tanchorX = s_getFloat( anchorX, s_screenData.defaultAnchorX );\r\n\t\tanchorY = s_getFloat( anchorY, s_screenData.defaultAnchorY );\r\n\t\tscaleX = s_getFloat( scaleX, 1 );\r\n\t\tscaleY = s_getFloat( scaleY, 1 );\r\n\t\tangle = s_getFloat( angle, 0 );\r\n\t\timage = s_getImageFromRawInput( image, \"drawImage\" );\r\n\t\r\n\t\t// Validate coordinates\r\n\t\tif( x === null || y === null ) {\r\n\t\t\tconst error = new TypeError( \"drawImage: Parameters x and y must be numbers.\" );\r\n\t\t\terror.code = \"INVALID_COORDINATES\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\r\n\t\t// Parses the color and makes sure it's in a valid format\r\n\t\tcolor = s_getColorValueByRawInput( s_screenData, color );\r\n\t\tif( color === null ) {\r\n\t\t\tcolor = DEFAULT_BLIT_COLOR;\r\n\t\t}\r\n\t\t\t\r\n\t\t// Convert angle from degrees to radians\r\n\t\tconst angleRad = s_degreesToRadian( angle );\r\n\t\r\n\t\t// Draw using renderer-specific implementation\r\n\t\ts_drawImage(\r\n\t\t\ts_screenData, image, x, y, color, anchorX, anchorY, scaleX, scaleY, angleRad\r\n\t\t);\r\n\t\r\n\t\t// Mark screen as dirty\r\n\t\ts_setImageDirty( s_screenData );\r\n\t};\r\n\r\n\tconst drawImageFnWrapper = ( image, x, y, color, anchorX, anchorY, scaleX, scaleY, angle ) => {\r\n\t\tif( s_isObjectLiteral( image ) ) {\r\n\t\t\tdrawImageFn(\r\n\t\t\t\timage.image, image.x, image.y, image.color, image.anchorX, image.anchorY,\r\n\t\t\t\timage.scaleX, image.scaleY, image.angle\r\n\t\t\t);\r\n\t\t} else {\r\n\t\t\tdrawImageFn( image, x, y, color, anchorX, anchorY, scaleX, scaleY, angle );\r\n\t\t}\r\n\t};\r\n\r\n\tm_api.drawImage = drawImageFnWrapper;\r\n\ts_screenData.api.drawImage = drawImageFnWrapper;\r\n\r\n\t/**********************************************************************************************\r\n\t * DRAW SPRITE Command\r\n\t **********************************************************************************************/\r\n\r\n\tconst drawSpriteFn = ( name, frame, x, y, color, anchorX, anchorY, scaleX, scaleY, angle ) => {\r\n\t\tframe = frame ?? 0;\r\n\t\tx = s_getInt( x, null );\r\n\t\ty = s_getInt( y, null );\r\n\t\tcolor = color ?? DEFAULT_BLIT_COLOR;\r\n\t\tanchorX = s_getFloat( anchorX, s_screenData.defaultAnchorX );\r\n\t\tanchorY = s_getFloat( anchorY, s_screenData.defaultAnchorY );\r\n\t\tscaleX = s_getFloat( scaleX, 1 );\r\n\t\tscaleY = s_getFloat( scaleY, 1 );\r\n\t\tangle = s_getFloat( angle, 0 );\r\n\r\n\t\t// Validate name\r\n\t\tif( typeof name !== \"string\" ) {\r\n\t\t\tconst error = new TypeError( \"drawSprite: Parameter name must be a string.\" );\r\n\t\t\terror.code = \"INVALID_NAME\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\tconst spriteData = s_getStoredImage( name );\r\n\t\tif( !spriteData ) {\r\n\t\t\tconst error = new Error( `drawSprite: Spritesheet \"${name}\" not found.` );\r\n\t\t\terror.code = \"IMAGE_NOT_FOUND\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Validate it's a spritesheet\r\n\t\tif( spriteData.type !== \"spritesheet\" ) {\r\n\t\t\tconst error = new Error( `drawSprite: Image \"${name}\" is not a spritesheet.` );\r\n\t\t\terror.code = \"NOT_A_SPRITESHEET\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\tif( spriteData.status !== \"ready\" ) {\r\n\t\t\tconst imgName = `Spritesheet \"${name}\"`;\r\n\t\t\tif( spriteData.status === \"loading\" ) {\r\n\t\t\t\tconst error = new Error(\r\n\t\t\t\t\t`drawSprite: ${imgName} is still loading. Use $.ready() to wait for it.`\r\n\t\t\t\t);\r\n\t\t\t\terror.code = \"IMAGE_NOT_READY\";\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\r\n\t\t\tif( spriteData.status === \"error\" ) {\r\n\t\t\t\tconst error = new Error( `drawSprite: ${imgName} failed to load.` );\r\n\t\t\t\terror.code = \"IMAGE_LOAD_FAILED\";\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Validate frame\r\n\t\tif( !Number.isInteger( frame ) || frame >= spriteData.frames.length || frame < 0 ) {\r\n\t\t\tconst error = new RangeError(\r\n\t\t\t\t`drawSprite: Frame ${frame} is not valid. Spritesheet has ` +\r\n\t\t\t\t`${spriteData.frames.length} frames.`\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_FRAME\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Validate coordinates\r\n\t\tif( x === null || y === null ) {\r\n\t\t\tconst error = new TypeError( \"drawSprite: Parameters x and y must be numbers.\" );\r\n\t\t\terror.code = \"INVALID_COORDINATES\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Parses the color and makes sure it's in a valid format\r\n\t\tcolor = s_getColorValueByRawInput( s_screenData, color );\r\n\t\tif( color === null ) {\r\n\t\t\tcolor = DEFAULT_BLIT_COLOR;\r\n\t\t}\r\n\r\n\t\t// Convert angle from degrees to radians\r\n\t\tconst angleRad = s_degreesToRadian( angle );\r\n\r\n\t\t// Get frame data\r\n\t\tconst frameData = spriteData.frames[ frame ];\r\n\t\tconst img = spriteData.image;\r\n\r\n\t\t// Draw using renderer-specific implementation\r\n\t\tg_renderer.drawSprite(\r\n\t\t\ts_screenData, img,\r\n\t\t\tframeData.x, frameData.y, frameData.width, frameData.height,\r\n\t\t\tx, y, frameData.width, frameData.height,\r\n\t\t\tcolor, anchorX, anchorY, scaleX, scaleY, angleRad\r\n\t\t);\r\n\r\n\t\t// Mark screen as dirty\r\n\t\ts_setImageDirty( s_screenData );\r\n\t};\r\n\r\n\tconst drawSpriteFnWrapper = (\r\n\t\tname, frame, x, y, color, anchorX, anchorY, scaleX, scaleY, angle\r\n\t) => {\r\n\t\tif( s_isObjectLiteral( name ) ) {\r\n\t\t\tdrawSpriteFn(\r\n\t\t\t\tname.name, name.frame, name.x, name.y, name.color, name.anchorX, name.anchorY,\r\n\t\t\t\tname.scaleX, name.scaleY, name.angle\r\n\t\t\t);\r\n\t\t} else {\r\n\t\t\tdrawSpriteFn( name, frame, x, y, color, anchorX, anchorY, scaleX, scaleY, angle );\r\n\t\t}\r\n\t};\r\n\r\n\tm_api.drawSprite = drawSpriteFnWrapper;\r\n\ts_screenData.api.drawSprite = drawSpriteFnWrapper;\r\n}\r\n\r\n/**\r\n * Clear the screen or a rectangular region\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Options containing x, y, width, height\r\n * @returns {void}\r\n */\r\nfunction cls( screenData, options ) {\r\n\tconst view = screenData.view;\r\n\tconst localW = view.width;\r\n\tconst localH = view.height;\r\n\tconst x = g_utils.clamp( g_utils.getInt( options.x, 0 ), 0, localW );\r\n\tconst y = g_utils.clamp( g_utils.getInt( options.y, 0 ), 0, localH );\r\n\tconst width = g_utils.clamp(\r\n\t\tg_utils.getInt( options.width, localW - x ), 0, localW - x\r\n\t);\r\n\tconst height = g_utils.clamp(\r\n\t\tg_utils.getInt( options.height, localH - y ), 0, localH - y\r\n\t);\r\n\r\n\tconst phys = g_view.toScreen( screenData, x, y );\r\n\tconst clip = g_view.intersectRects(\r\n\t\tphys.x, phys.y, width, height,\r\n\t\tview.clipX, view.clipY, view.clipWidth, view.clipHeight\r\n\t);\r\n\r\n\tif( clip.width > 0 && clip.height > 0 ) {\r\n\t\tg_renderer.cls( screenData, clip.x, clip.y, clip.width, clip.height );\r\n\t\tg_renderer.setImageDirty( screenData );\r\n\t}\r\n\r\n\t// Reset cursor for no-arg / full requested-view clears\r\n\tif( x === 0 && y === 0 && width === localW && height === localH ) {\r\n\t\tscreenData.printCursor.x = 0;\r\n\t\tscreenData.printCursor.y = 0;\r\n\t}\r\n}\r\n", "/**\r\n * Pi.js - Colors Module\r\n * \r\n * Manages the color palettes and color values.\r\n * Simplified version focused on WebGL2 rendering.\r\n * \r\n * @module api/colors\r\n */\r\n\r\n\"use strict\";\r\n\r\n// Import modules directly\r\nimport * as g_commands from \"../core/commands.js\";\r\nimport * as g_utils from \"../core/utils.js\";\r\nimport * as g_screenManager from \"../core/screen-manager.js\";\r\nimport * as g_images from \"./images.js\";\r\n\r\n// Max color difference used in find color by index\r\nconst MAX_DIFFERENCE = ( 255 * 255 ) * 3.25;\r\n\r\nlet m_defaultPal = [];\r\nlet m_defaultPalMap = new Map();\r\nlet m_defaultColor = -1;\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Commands\r\n **************************************************************************************************/\r\n\r\n\r\n// Initialize color defaults\r\nexport function init( api ) {\r\n\r\n\t// Default 256-color palette (CGA + extended colors) - raw hex strings\r\n\tconst defaultPaletteHex = [\r\n\t\t\"#0000AA\", \"#00AA00\", \"#00AAAA\", \"#AA0000\", \"#AA00AA\", \"#AA5500\", \"#AAAAAA\", \"#555555\",\r\n\t\t\"#5555FF\", \"#55FF55\", \"#55FFFF\", \"#FF5555\", \"#FF55FF\", \"#FFFF55\", \"#FFFFFF\", \"#000000\",\r\n\t\t\"#141414\", \"#202020\", \"#2D2D2D\", \"#393939\", \"#454545\", \"#515151\", \"#616161\", \"#717171\",\r\n\t\t\"#828282\", \"#929292\", \"#A2A2A2\", \"#B6B6B6\", \"#CACACA\", \"#E3E3E3\", \"#FFFFFF\", \"#0000FF\",\r\n\t\t\"#4100FF\", \"#7D00FF\", \"#BE00FF\", \"#FF00FF\", \"#FF00BE\", \"#FF007D\", \"#FF0041\", \"#FF0000\",\r\n\t\t\"#FF4100\", \"#FF7D00\", \"#FFBE00\", \"#FFFF00\", \"#BEFF00\", \"#7DFF00\", \"#41FF00\", \"#00FF00\",\r\n\t\t\"#00FF41\", \"#00FF7D\", \"#00FFBE\", \"#00FFFF\", \"#00BEFF\", \"#007DFF\", \"#0041FF\", \"#7D7DFF\",\r\n\t\t\"#9E7DFF\", \"#BE7DFF\", \"#DF7DFF\", \"#FF7DFF\", \"#FF7DDF\", \"#FF7DBE\", \"#FF7D9E\", \"#FF7D7D\",\r\n\t\t\"#FF9E7D\", \"#FFBE7D\", \"#FFDF7D\", \"#FFFF7D\", \"#DFFF7D\", \"#BEFF7D\", \"#9EFF7D\", \"#7DFF7D\",\r\n\t\t\"#7DFF9E\", \"#7DFFBE\", \"#7DFFDF\", \"#7DFFFF\", \"#7DDFFF\", \"#7DBEFF\", \"#7D9EFF\", \"#B6B6FF\",\r\n\t\t\"#C6B6FF\", \"#DBB6FF\", \"#EBB6FF\", \"#FFB6FF\", \"#FFB6EB\", \"#FFB6DB\", \"#FFB6C6\", \"#FFB6B6\",\r\n\t\t\"#FFC6B6\", \"#FFDBB6\", \"#FFEBB6\", \"#FFFFB6\", \"#EBFFB6\", \"#DBFFB6\", \"#C6FFB6\", \"#B6FFB6\",\r\n\t\t\"#B6FFC6\", \"#B6FFDB\", \"#B6FFEB\", \"#B6FFFF\", \"#B6EBFF\", \"#B6DBFF\", \"#B6C6FF\", \"#000071\",\r\n\t\t\"#1C0071\", \"#390071\", \"#550071\", \"#710071\", \"#710055\", \"#710039\", \"#71001C\", \"#710000\",\r\n\t\t\"#711C00\", \"#713900\", \"#715500\", \"#717100\", \"#557100\", \"#397100\", \"#1C7100\", \"#007100\",\r\n\t\t\"#00711C\", \"#007139\", \"#007155\", \"#007171\", \"#005571\", \"#003971\", \"#001C71\", \"#393971\",\r\n\t\t\"#453971\", \"#553971\", \"#613971\", \"#713971\", \"#713961\", \"#713955\", \"#713945\", \"#713939\",\r\n\t\t\"#714539\", \"#715539\", \"#716139\", \"#717139\", \"#617139\", \"#557139\", \"#457139\", \"#397139\",\r\n\t\t\"#397145\", \"#397155\", \"#397161\", \"#397171\", \"#396171\", \"#395571\", \"#394571\", \"#515171\",\r\n\t\t\"#595171\", \"#615171\", \"#695171\", \"#715171\", \"#715169\", \"#715161\", \"#715159\", \"#715151\",\r\n\t\t\"#715951\", \"#716151\", \"#716951\", \"#717151\", \"#697151\", \"#617151\", \"#597151\", \"#517151\",\r\n\t\t\"#517159\", \"#517161\", \"#517169\", \"#517171\", \"#516971\", \"#516171\", \"#515971\", \"#000041\",\r\n\t\t\"#100041\", \"#200041\", \"#310041\", \"#410041\", \"#410031\", \"#410020\", \"#410010\", \"#410000\",\r\n\t\t\"#411000\", \"#412000\", \"#413100\", \"#414100\", \"#314100\", \"#204100\", \"#104100\", \"#004100\",\r\n\t\t\"#004110\", \"#004120\", \"#004131\", \"#004141\", \"#003141\", \"#002041\", \"#001041\", \"#202041\",\r\n\t\t\"#282041\", \"#312041\", \"#392041\", \"#412041\", \"#412039\", \"#412031\", \"#412028\", \"#412020\",\r\n\t\t\"#412820\", \"#413120\", \"#413920\", \"#414120\", \"#394120\", \"#314120\", \"#284120\", \"#204120\",\r\n\t\t\"#204128\", \"#204131\", \"#204139\", \"#204141\", \"#203941\", \"#203141\", \"#202841\", \"#2D2D41\",\r\n\t\t\"#312D41\", \"#352D41\", \"#3D2D41\", \"#412D41\", \"#412D3D\", \"#412D35\", \"#412D31\", \"#412D2D\",\r\n\t\t\"#41312D\", \"#41352D\", \"#413D2D\", \"#41412D\", \"#3D412D\", \"#35412D\", \"#31412D\", \"#2D412D\",\r\n\t\t\"#2D4131\", \"#2D4135\", \"#2D413D\", \"#2D4141\", \"#2D3D41\", \"#2D3541\", \"#2D3141\", \"#000000\",\r\n\t\t\"#000000\", \"#000000\", \"#000000\", \"#000000\", \"#000000\", \"#000000\"\r\n\t];\r\n\r\n\t// Set the default pal and color\r\n\tsetDefaultPal( { \"pal\": defaultPaletteHex } );\r\n\tsetDefaultColor( { \"color\": 7 } );\r\n\r\n\t// Add getters for screen manager to get defaults for dynamic items\r\n\tg_screenManager.addScreenDataItemGetter( \"pal\", () => m_defaultPal );\r\n\tg_screenManager.addScreenDataItemGetter( \"color\", () => m_defaultColor );\r\n\tg_screenManager.addScreenDataItemGetter( \"palMap\", () => m_defaultPalMap );\r\n\r\n\t// Add external API commands\r\n\tregisterCommands( api );\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * External API Commands\r\n **************************************************************************************************/\r\n\r\nfunction registerCommands() {\r\n\r\n\t// Register non-screen commands\r\n\tg_commands.addCommand( \"setDefaultPal\", setDefaultPal, false, [ \"pal\" ] );\r\n\tg_commands.addCommand( \"getDefaultPal\", getDefaultPal, false, [ \"include0\" ] );\r\n\tg_commands.addCommand( \"setDefaultColor\", setDefaultColor, false, [ \"color\" ] );\r\n\tg_commands.addCommand( \"getDefaultColor\", getDefaultColor, false, [ \"asIndex\" ] );\r\n\tg_commands.addCommand( \"createColor\", createColor, false, [ \"color\" ] );\r\n\r\n\t// Register screen commands\r\n\tg_commands.addCommand( \"setColor\", setColor, true, [ \"color\" ] );\r\n\tg_commands.addCommand( \"getColor\", getColor, true, [ \"asIndex\" ] );\r\n\tg_commands.addCommand( \"getPal\", getPal, true, [ \"include0\" ] );\r\n\tg_commands.addCommand( \"setPal\", setPal, true, [ \"pal\" ] );\r\n\tg_commands.addCommand( \"getPalIndex\", getPalIndex, true, [ \"color\", \"tolerance\" ] );\r\n\tg_commands.addCommand( \"setBgColor\", setBgColor, true, [ \"color\" ] );\r\n\tg_commands.addCommand( \"setContainerBgColor\", setContainerBgColor, true, [ \"color\" ] );\r\n\tg_commands.addCommand( \"setPalColors\", setPalColors, true, [ \"indices\", \"colors\" ] );\r\n\tg_commands.addCommand( \"addPalColors\", addPalColors, true, [ \"colors\" ] );\r\n\tg_commands.addCommand( \"getPalColor\", getPalColor, true, [ \"index\" ] );\r\n}\r\n\r\n// Set default pal\r\nfunction setDefaultPal( options ) {\r\n\tconst pal = options.pal;\r\n\r\n\tif( !Array.isArray( pal ) ) {\r\n\t\tconst error = new TypeError( \"setDefaultPal: Parameter pal must be an array.\" );\r\n\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif( pal.length === 0 ) {\r\n\t\tconst error = new RangeError(\r\n\t\t\t\"setDefaultPal: Parameter pal must have at least one color value.\"\r\n\t\t);\r\n\t\terror.code = \"EMPTY_PALETTE\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Create default pal with the 0'th item set as a black transparent color\r\n\tm_defaultPal = [ g_utils.convertToColor( [ 0, 0, 0, 0 ] ) ];\r\n\r\n\t// Convert palette to color format\r\n\tfor( let i = 0; i < pal.length; i++ ) {\r\n\t\tconst c = g_utils.convertToColor( pal[ i ] );\r\n\t\tif( c === null ) {\r\n\t\t\tconsole.warn( `setDefaultPal: Invalid color value inside array pal at index: ${i}.` );\r\n\t\t\tm_defaultPal.push( g_utils.convertToColor( \"#000000\" ) );\r\n\t\t} else {\r\n\t\t\tm_defaultPal.push( c );\r\n\t\t}\r\n\t}\r\n\r\n\t// Set the default pal map\r\n\tm_defaultPalMap = new Map();\r\n\tfor( let i = 0; i < m_defaultPal.length; i++ ) {\r\n\t\tm_defaultPalMap.set( m_defaultPal[ i ].key, i );\r\n\t}\r\n\r\n\t// Make sure default color is in the new palette\r\n\tif( !m_defaultPalMap.has( m_defaultColor.key ) ) {\r\n\t\tm_defaultColor = m_defaultPal[ 1 ];\r\n\t}\r\n}\r\n\r\n// Get default pal\r\nfunction getDefaultPal( options ) {\r\n\tconst include0 = options.include0 ?? null;\r\n\tconst filteredPal = [];\r\n\t\r\n\t// Set the start index to 0 if including 0 which is the transparent black color\r\n\tlet startIndex = 0;\r\n\tif( include0 === null ) {\r\n\t\tstartIndex = 1;\r\n\t}\r\n\r\n\t// Need to explicitly convert each color because I don't want the default pal to be modified\r\n\t// outside.\r\n\tfor( let i = startIndex; i < m_defaultPal.length; i += 1 ) {\r\n\t\tfilteredPal.push( g_utils.rgbToColor(\r\n\t\t\tm_defaultPal[ i ].r,\r\n\t\t\tm_defaultPal[ i ].g,\r\n\t\t\tm_defaultPal[ i ].b,\r\n\t\t\tm_defaultPal[ i ].a\r\n\t\t) );\r\n\t}\r\n\treturn filteredPal;\r\n}\r\n\r\n// Set default color\r\nfunction setDefaultColor( options ) {\r\n\tlet c = options.color;\r\n\r\n\tif( !isNaN( Number( c ) ) && m_defaultPal.length > c ) {\r\n\t\tm_defaultColor = m_defaultPal[ c ];\r\n\t} else {\r\n\t\tc = g_utils.convertToColor( c );\r\n\t\tif( c === null ) {\r\n\t\t\tconst error = new TypeError(\r\n\t\t\t\t\"setDefaultColor: Parameter color is not a valid color format.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\tm_defaultColor = c;\r\n\t}\r\n}\r\n\r\n// Get default color\r\nfunction getDefaultColor( options ) {\r\n\tconst asIndex = options.asIndex ?? true;\r\n\tif( asIndex ) {\r\n\t\tconst fakeScreenData = { \"pal\": m_defaultPal, \"palMap\": m_defaultPalMap };\r\n\t\treturn findColorIndexByColorValue( fakeScreenData, m_defaultColor );\r\n\t}\r\n\treturn g_utils.createColor( m_defaultColor.array );\r\n}\r\n\r\nfunction createColor( options ) {\r\n\tconst color = g_utils.convertToColor( options.color );\r\n\tif( color === null ) {\r\n\t\tconst error = new TypeError(\r\n\t\t\t`createColor: Parameter color is not a valid color format.`\r\n\t\t);\r\n\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\tthrow error;\r\n\t}\r\n\treturn color\r\n}\r\n\r\n// Set color\r\nfunction setColor( screenData, options ) {\r\n\tconst colorInput = options.color;\r\n\r\n\tlet colorValue;\r\n\r\n\t// If colorInput is an number then get colorValue for pal\r\n\tif( typeof colorInput === \"number\" ) {\r\n\t\tif( colorInput >= screenData.pal.length ) {\r\n\t\t\tconst error = new TypeError(\r\n\t\t\t\t`setColor: Parameter color index is not in pal.`\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\tcolorValue = screenData.pal[ colorInput ];\r\n\t} else {\r\n\r\n\t\t// Convert the color to a colorValue\r\n\t\tcolorValue = g_utils.convertToColor( colorInput );\r\n\r\n\t\t// If we were unable to convert this color than it is not a valid color format\r\n\t\tif( colorValue === null ) {\r\n\t\t\tconst error = new TypeError(\r\n\t\t\t\t`setColor: Parameter color is not a valid color format.`\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t}\r\n\r\n\t// Update the color values\r\n\tscreenData.color = colorValue;\r\n}\r\n\r\nfunction getColor( screenData, options ) {\r\n\tconst asIndex = !!options.asIndex;\r\n\tif( asIndex ) {\r\n\t\treturn findColorIndexByColorValue( screenData, screenData.color );\r\n\t}\r\n\treturn g_utils.createColor( screenData.color.array );\r\n}\r\n\r\n\r\n// Get palette\r\nfunction getPal( screenData, options ) {\r\n\tconst include0 = options.include0 ?? null;\r\n\tconst filteredPal = [];\r\n\t\r\n\t// Set the start index to 0 if including 0 which is the transparent black color\r\n\tlet startIndex = 0;\r\n\tif( include0 === null ) {\r\n\t\tstartIndex = 1;\r\n\t}\r\n\r\n\t// Need to explicitly convert each color because I don't want the pal to be modified\r\n\t// outside.\r\n\tfor( let i = startIndex; i < screenData.pal.length; i += 1 ) {\r\n\t\tfilteredPal.push( g_utils.rgbToColor(\r\n\t\t\tscreenData.pal[ i ].r,\r\n\t\t\tscreenData.pal[ i ].g,\r\n\t\t\tscreenData.pal[ i ].b,\r\n\t\t\tscreenData.pal[ i ].a\r\n\t\t) );\r\n\t}\r\n\treturn filteredPal;\r\n}\r\n\r\n// Set entire palette\r\nfunction setPal( screenData, options ) {\r\n\tconst pal = options.pal;\r\n\r\n\tif( !Array.isArray( pal ) ) {\r\n\t\tconst error = new TypeError( \"setPal: Parameter pal is must be an array.\" );\r\n\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif( pal.length === 0 ) {\r\n\t\tconst error = new RangeError(\r\n\t\t\t\"setPal: Parameter pal must have at least one color value.\"\r\n\t\t);\r\n\t\terror.code = \"EMPTY_PALETTE\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Create a new pal with 0'th color set to black transparent\r\n\tconst newPal = [ g_utils.rgbToColor( 0, 0, 0, 0 ) ];\r\n\r\n\t// Convert all colors and validate\r\n\tfor( let i = 0; i < pal.length; i++ ) {\r\n\t\tconst c = g_utils.convertToColor( pal[ i ] );\r\n\t\tif( c === null ) {\r\n\t\t\tconsole.warn( `setPal: Invalid color value inside array pal at index: ${i}.` );\r\n\t\t\tnewPal.push( g_utils.convertToColor( \"#000000\" ) );\r\n\t\t} else {\r\n\t\t\tnewPal.push( c );\r\n\t\t}\r\n\t}\r\n\r\n\t// Set the new palette\r\n\tscreenData.pal = newPal;\r\n\r\n\t// Clear the palMap since we've replaced the entire palette\r\n\tscreenData.palMap = new Map();\r\n\r\n\t// Rebuild palMap for new palette colors\r\n\tfor( let i = 0; i < newPal.length; i++ ) {\r\n\t\tscreenData.palMap.set( newPal[ i ].key, i );\r\n\t}\r\n\r\n\t// Check if current drawing color needs to be updated\r\n\t// Find the new palette index that best matches the current color\r\n\tconst currentColor = screenData.color;\r\n\tconst newIndex = findColorIndexByColorValue( screenData, currentColor );\r\n\tif( newIndex !== null ) {\r\n\t\tscreenData.color = newPal[ newIndex ];\r\n\t} else {\r\n\r\n\t\t// If current color not found, default to palette index 1\r\n\t\tscreenData.color = newPal[ 1 ];\r\n\t}\r\n\r\n\t// Trigger images to update color palletes\r\n\tg_images.palettizeImages( screenData );\r\n}\r\n\r\n// Get palette index for a color\r\nfunction getPalIndex( screenData, options ) {\r\n\tlet color = options.color;\r\n\tlet tolerance = g_utils.getFloat( options.tolerance, 0 );\r\n\r\n\t// Validate tolerance variable\r\n\tif( tolerance < 0 || tolerance > 1 ) {\r\n\t\tconst error = new RangeError(\r\n\t\t\t\"getPalIndex: Parameter tolerance must be a number between 0 and 1 (0 = exact match, 1 = any color).\"\r\n\t\t);\r\n\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Convert to color value\r\n\tconst colorValue = g_utils.convertToColor( color );\r\n\tif( colorValue === null ) {\r\n\t\tconst error = new TypeError(\r\n\t\t\t`getPalIndex: Parameter color is not a valid color format.`\r\n\t\t);\r\n\t\terror.code = \"INVALID_COLOR\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tconst index = findColorIndexByColorValue( screenData, colorValue, tolerance );\r\n\treturn index;\r\n}\r\n\r\n// Set the background color of the canvas\r\nfunction setBgColor( screenData, options ) {\r\n\tconst colorRaw = options.color;\r\n\tconst color = getColorValueByRawInput( screenData, colorRaw );\r\n\tif( color !== null ) {\r\n\t\tscreenData.canvas.style.backgroundColor = g_utils.colorToHex( color );\r\n\t} else {\r\n\t\tconst error = new TypeError( \"setBgColor: invalid color value for parameter color.\" );\r\n\t\terror.code = \"INVALID_COLOR\";\r\n\t\tthrow error;\r\n\t}\r\n}\r\n\r\n// Set the background color of the container\r\nfunction setContainerBgColor( screenData, options ) {\r\n\tif( !screenData.container ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst colorRaw = options.color;\r\n\tconst color = getColorValueByRawInput( screenData, colorRaw );\r\n\t\r\n\tif( color !== null ) {\r\n\t\tscreenData.container.style.backgroundColor = g_utils.colorToHex( color );\r\n\t} else {\r\n\t\tconst error = new TypeError(\r\n\t\t\t\"setContainerBgColor: invalid color value for parameter color.\"\r\n\t\t);\r\n\t\terror.code = \"INVALID_COLOR\";\r\n\t\tthrow error;\r\n\t}\r\n}\r\n\r\n// Set palette colors\r\nfunction setPalColors( screenData, options ) {\r\n\tconst indices = options.indices;\r\n\tconst colors = options.colors;\r\n\r\n\t// Validate indices array\r\n\tif( !Array.isArray( indices ) ) {\r\n\t\tconst error = new TypeError( \"setPalColors: Parameter indices must be an array.\" );\r\n\t\terror.code = \"INVALID_INDICES\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Validate colors array\r\n\tif( !Array.isArray( colors ) ) {\r\n\t\tconst error = new TypeError( \"setPalColors: Parameter colors must be an array.\" );\r\n\t\terror.code = \"INVALID_COLORS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Arrays must have the same length\r\n\tif( indices.length !== colors.length ) {\r\n\t\tconst error = new RangeError(\r\n\t\t\t\"setPalColors: Parameters indices and colors must have the same length.\"\r\n\t\t);\r\n\t\terror.code = \"LENGTH_MISMATCH\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Arrays must not be empty\r\n\tif( indices.length === 0 ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tlet colorSwapped = false;\r\n\r\n\t// Validate each index and color\r\n\tfor( let i = 0; i < indices.length; i += 1 ) {\r\n\t\tconst index = indices[ i ];\r\n\t\tconst color = colors[ i ];\r\n\r\n\t\t// index must be an integer\r\n\t\tif(\r\n\t\t\t!Number.isInteger( index ) ||\r\n\t\t\tindex < 0 ||\r\n\t\t\tindex >= screenData.pal.length\r\n\t\t) {\r\n\t\t\tconsole.warn(\r\n\t\t\t\t`setPalColors: Parameter indices[${i}] must be an integer value between 0 and ` +\r\n\t\t\t\t`${screenData.pal.length - 1}.`\r\n\t\t\t);\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// index cannot be 0\r\n\t\tif( index === 0 ) {\r\n\t\t\tconsole.warn(\r\n\t\t\t\t`setPalColors: Parameter indices[${i}] cannot be 0, this is reserved for ` +\r\n\t\t\t\t\"transparency. To set background color of the screen use the setBgColor command.\"\r\n\t\t\t);\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// Get the color value\r\n\t\tconst colorValue = g_utils.convertToColor( color );\r\n\t\tif( colorValue === null ) {\r\n\t\t\tconsole.warn(\r\n\t\t\t\t`setPalColors: Parameter colors[${i}] is not a valid color format.`\r\n\t\t\t);\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// Store the old color before replacing\r\n\t\tconst oldColor = screenData.pal[ index ];\r\n\r\n\t\t// Skip if color is not changing\r\n\t\tif( colorValue.key === oldColor.key ) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// Check if we are changing the current selected fore color\r\n\t\tif( screenData.color.key === oldColor.key ) {\r\n\t\t\tscreenData.color = colorValue;\r\n\t\t}\r\n\r\n\t\t// Set the new palette color\r\n\t\tscreenData.pal[ index ] = colorValue;\r\n\r\n\t\t// Update the palMap - remove old color entry and add new one\r\n\t\tscreenData.palMap.delete( oldColor.key );\r\n\t\tscreenData.palMap.set( colorValue.key, index );\r\n\r\n\t\t// Set color swapped to true indicated a palette color has been changed\r\n\t\tcolorSwapped = true;\r\n\t}\r\n\r\n\t// Trigger images to update color palletes\r\n\tif( colorSwapped ) {\r\n\t\tg_images.palettizeImages( screenData );\r\n\t}\r\n}\r\n\r\n// Add palette colors\r\nfunction addPalColors( screenData, options ) {\r\n\tconst colors = options.colors;\r\n\r\n\t// Validate colors array\r\n\tif( !Array.isArray( colors ) ) {\r\n\t\tconst error = new TypeError( \"addPalColors: Parameter colors must be an array.\" );\r\n\t\terror.code = \"INVALID_COLORS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Array must not be empty\r\n\tif( colors.length === 0 ) {\r\n\t\treturn [];\r\n\t}\r\n\r\n\tconst newIndices = [];\r\n\tlet colorsAdded = false;\r\n\r\n\t// Convert and add each color to the palette\r\n\tfor( let i = 0; i < colors.length; i += 1 ) {\r\n\t\tconst color = colors[ i ];\r\n\r\n\t\t// Get the color value\r\n\t\tconst colorValue = g_utils.convertToColor( color );\r\n\t\tif( colorValue === null ) {\r\n\t\t\tconsole.warn( `addPalColors: Parameter colors[${i}] is not a valid color format.` );\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// Check if color already exists in palette\r\n\t\tconst existingIndex = screenData.palMap.get( colorValue.key );\r\n\t\tif( existingIndex !== undefined ) {\r\n\t\t\t// Color already exists, skip it\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// Add the new color to the palette\r\n\t\tconst newIndex = screenData.pal.length;\r\n\t\tscreenData.pal.push( colorValue );\r\n\t\tscreenData.palMap.set( colorValue.key, newIndex );\r\n\t\tnewIndices.push( newIndex );\r\n\r\n\t\tcolorsAdded = true;\r\n\t}\r\n\r\n\t// Trigger images to update color palletes\r\n\tif( colorsAdded ) {\r\n\t\tg_images.palettizeImages( screenData );\r\n\t}\r\n\r\n\treturn newIndices;\r\n}\r\n\r\nfunction getPalColor( screenData, options ) {\r\n\tconst index = options.index;\r\n\r\n\tif( screenData.pal[ index ] ) {\r\n\t\tconst color = screenData.pal[ index ];\r\n\t\treturn g_utils.createColor( color.array );\r\n\t}\r\n\treturn null;\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Internal Commands\r\n **************************************************************************************************/\r\n\r\n\r\nexport function getColorValueByRawInput( screenData, rawInput ) {\r\n\tlet colorValue;\r\n\r\n\t// If it is an integer than get from pal array\r\n\tif( Number.isInteger( rawInput ) ) {\r\n\t\tif( rawInput >= screenData.pal.length ) {\r\n\t\t\treturn null;\r\n\t\t}\r\n\t\treturn screenData.pal[ rawInput ];\r\n\t}\r\n\t\r\n\t// Convert to a color value\r\n\tcolorValue = g_utils.convertToColor( rawInput );\r\n\r\n\treturn colorValue;\r\n}\r\n\r\n// Finds a color index without adding it to palette\r\n// @param {Object} screenData - The screen data object\r\n// @param {Object} color - Color object to find\r\n// @param {number} tolerance - Color matching tolerance (0 = exact match, 1 = any color)\r\nexport function findColorIndexByColorValue( screenData, color, tolerance = 0 ) {\r\n\r\n\t// First check by key - fastest lookup\r\n\tif( screenData.palMap.has( color.key ) ) {\r\n\t\treturn screenData.palMap.get( color.key );\r\n\t}\r\n\r\n\t// Calculate minimum similarity threshold for color comparison\r\n\t// Tolerance: 0 = exact match only, 1 = any color\r\n\tconst minSimularity = ( 1 - tolerance * tolerance ) * MAX_DIFFERENCE;\r\n\r\n\t// Collect all matches meeting the target similarity, then return the most similar\r\n\tlet bestMatchIndex = null;\r\n\tlet bestMatchSimularity = 0;\r\n\tfor( let i = 0; i < screenData.pal.length; i++ ) {\r\n\t\tconst palColor = screenData.pal[ i ];\r\n\t\tif( palColor.key === color.key ) {\r\n\r\n\t\t\t// Exact match found; this is the best possible\r\n\t\t\treturn i;\r\n\t\t}\r\n\r\n\t\tlet difference;\r\n\r\n\t\t// Special case for color 0: weight alpha higher for transparent color\r\n\t\tif( i === 0 ) {\r\n\t\t\tdifference = g_utils.calcColorDifference( palColor, color, [ 0.2, 0.2, 0.2, 0.4 ] );\r\n\t\t} else {\r\n\t\t\tdifference = g_utils.calcColorDifference( palColor, color );\r\n\t\t}\r\n\r\n\t\tconst similarity = MAX_DIFFERENCE - difference;\r\n\t\tif( similarity >= minSimularity ) {\r\n\t\t\tif( similarity > bestMatchSimularity ) {\r\n\t\t\t\tbestMatchIndex = i;\r\n\t\t\t\tbestMatchSimularity = similarity;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn bestMatchIndex;\r\n}\r\n\r\nexport function getColorValueByIndex( screenData, palIndex ) {\r\n\tif( palIndex >= screenData.pal.length ) {\r\n\t\treturn null;\r\n\t}\r\n\treturn screenData.pal[ palIndex ];\r\n}\r\n", "/**\r\n * Pi.js - Images Module\r\n * \r\n * Image loading, storage, and management for WebGL2 renderer.\r\n * \r\n * @module api/images\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_utils from \"../core/utils.js\";\r\nimport * as g_commands from \"../core/commands.js\";\r\nimport * as g_screenManager from \"../core/screen-manager.js\";\r\nimport * as g_renderer from \"../renderer/renderer.js\";\r\nimport * as g_colors from \"./colors.js\";\r\n\r\n// Image storage by name\r\nconst m_images = {};\r\nconst m_paletteImages = [];\r\nlet m_imageCount = 0;\r\n\r\n\r\n/**************************************************************************************************\r\n * Module Initialization\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Initialize images module\r\n * \r\n * @param {Object} api - The main Pi.js API object\r\n * @returns {void}\r\n */\r\nexport function init( api ) {\r\n\tregisterCommands( api );\r\n\r\n\tg_screenManager.addScreenDataItem( \"defaultAnchorX\", 0 );\r\n\tg_screenManager.addScreenDataItem( \"defaultAnchorY\", 0 );\r\n\tg_screenManager.addScreenDataItem( \"palImagesData\", {} );\r\n\r\n\t// Palettize all images when screen is loaded\r\n\tg_screenManager.addScreenInitFunction( palettizeImages );\r\n}\r\n\r\n/**\r\n * Register image commands\r\n * \r\n * @returns {void}\r\n */\r\nfunction registerCommands( api ) {\r\n\tg_commands.addCommand(\r\n\t\t\"loadImage\", loadImage, false,\r\n\t\t[ \"src\", \"name\", \"usePalette\", \"paletteKeys\", \"onLoad\", \"onError\" ]\r\n\t);\r\n\tg_commands.addCommand(\r\n\t\t\"loadSpritesheet\", loadSpritesheet, false,\r\n\t\t[\r\n\t\t\t\"src\", \"name\", \"width\", \"height\", \"margin\", \"usePalette\", \"paletteKeys\", \"onLoad\",\r\n\t\t\t\"onError\"\r\n\t\t]\r\n\t);\r\n\tg_commands.addCommand( \"getImage\", getImage, false, [ \"name\" ] );\r\n\tg_commands.addCommand( \"getSpritesheetData\", getSpritesheetData, true, [ \"name\" ], true );\r\n\tg_commands.addCommand( \"removeImage\", removeImage, false, [ \"name\" ] );\r\n\tg_commands.addCommand(\r\n\t\t\"createImageFromScreen\", createImageFromScreen, true,\r\n\t\t[ \"name\", \"x1\", \"y1\", \"x2\", \"y2\" ]\r\n\t);\r\n\tg_commands.addCommand( \"setDefaultAnchor\", setDefaultAnchor, true, [ \"x\", \"y\" ] );\r\n}\r\n\r\n\r\n/**************************************************************************************************\r\n * External API Commands\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Load an image from URL or use provided Image/Canvas element\r\n * \r\n * @param {Object} options - Load options\r\n * @param {string|HTMLImageElement|HTMLCanvasElement|OffscreenCanvas} options.src - Image source\r\n * @param {string} [options.name] - Optional name for the image\r\n * @param {boolean} [options.usePalette] - Set image colors to be linked to screen canvas\r\n * @param {Array} [options.paletteKeys] - An array of colors used as key colors from the image to\r\n * \t\t\t\t\t\t\t\t\t\t  use as indices to look up palette colors\r\n * @param {Function} [options.onLoad] - Callback when image loads\r\n * @param {Function} [options.onError] - Callback when image fails to load\r\n * @returns {string} Image name\r\n */\r\nfunction loadImage( options ) {\r\n\tconst src = options.src;\r\n\tlet name = options.name;\r\n\tconst usePalette = !!options.usePalette;\r\n\tconst paletteKeys = options.paletteKeys;\r\n\tconst onLoadCallback = options.onLoad;\r\n\tconst onErrorCallback = options.onError;\r\n\tconst srcErrMsg = \"loadImage: Parameter src must be a string URL, Image element, or Canvas \" +\r\n\t\t\"element.\";\r\n\r\n\t// Validate src parameter - can be string URL, Image element, or Canvas element\r\n\tif( typeof src === \"string\" ) {\r\n\t\tif( src === \"\" ) {\r\n\t\t\tconst error = new TypeError( srcErrMsg );\r\n\t\t\terror.code = \"INVALID_SRC\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t} else if( src && typeof src === \"object\" ) {\r\n\t\tif( src.tagName !== \"IMG\" && src.tagName !== \"CANVAS\" ) {\r\n\t\t\tconst error = new TypeError( srcErrMsg );\r\n\t\t\terror.code = \"INVALID_SRC\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t} else {\r\n\t\tconst error = new TypeError( srcErrMsg );\r\n\t\terror.code = \"INVALID_SRC\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Validate name\r\n\tif( name && typeof name !== \"string\" ) {\r\n\t\tconst error = new TypeError( \"loadImage: Parameter name must be a string.\" );\r\n\t\terror.code = \"INVALID_NAME\";\r\n\t\tthrow error;\r\n\t}\r\n\t// Generate a name if none is provided\r\n\tif( !name || name === \"\" ) {\r\n\t\tm_imageCount += 1;\r\n\t\tname = \"\" + m_imageCount;\r\n\t}\r\n\tif( m_images[ name ] ) {\r\n\t\tconst error = new TypeError( \"loadImage: Parameter name must be unique.\" );\r\n\t\terror.code = \"INVALID_NAME\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Validate callbacks if provided\r\n\tif( onLoadCallback != null && !g_utils.isFunction( onLoadCallback ) ) {\r\n\t\tconst error = new TypeError( \"loadImage: Parameter onLoad must be a function.\" );\r\n\t\terror.code = \"INVALID_CALLBACK\";\r\n\t\tthrow error;\r\n\t}\r\n\tif( onErrorCallback != null && !g_utils.isFunction( onErrorCallback ) ) {\r\n\t\tconst error = new TypeError( \"loadImage: Parameter onError must be a function.\" );\r\n\t\terror.code = \"INVALID_CALLBACK\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Validate paletteKeys\r\n\tlet palColors = null;\r\n\tlet palColorMap = null;\r\n\tif( usePalette ) {\r\n\t\tif( !Array.isArray( paletteKeys ) || paletteKeys.length === 0 ) {\r\n\t\t\tconst error = new TypeError(\r\n\t\t\t\t\"loadImage: Parameter paletteKeys must be non empty Array when usePalette is set.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_PALETTE\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Create a color map\r\n\t\tpalColorMap = new Map();\r\n\r\n\t\t// Initialize palColors with 0 for transparent black\r\n\t\tpalColors = [ g_utils.convertToColor( \"rgba(0, 0, 0, 0)\" ) ];\r\n\t\tpalColorMap.set( palColors[ 0 ].key, 0 );\r\n\r\n\t\tfor( let i = 0; i < paletteKeys.length; i += 1 ) {\r\n\t\t\tconst palColorRaw = paletteKeys[ i ];\r\n\t\t\tconst palColor = g_utils.convertToColor( palColorRaw );\r\n\t\t\tpalColors.push( palColor );\r\n\t\t\tpalColorMap.set( palColor.key, i + 1 );\r\n\t\t}\r\n\t}\r\n\r\n\t// Create blank image object\r\n\tm_images[ name ] = {\r\n\t\t\"status\": \"loading\",\r\n\t\t\"image\": null,\r\n\t\t\"width\": null,\r\n\t\t\"height\": null,\r\n\t\t\"usePalette\": usePalette,\r\n\t\t\"palColors\": palColors,\r\n\t\t\"palColorMap\": palColorMap\r\n\t};\r\n\r\n\t// Update function for when image is loaded to update the image object\r\n\tconst updateImageFn = ( img ) => {\r\n\r\n\t\t// Use the element directly\r\n\t\tconst imageObj = m_images[ name ];\r\n\t\timageObj.image = img;\r\n\t\timageObj.status = \"ready\";\r\n\t\timageObj.width = img.width;\r\n\t\timageObj.height = img.height;\r\n\r\n\t\t// If using palette then push the image to the use palette array\r\n\t\tif( imageObj.usePalette ) {\r\n\t\t\taddPaletteImage( name );\r\n\t\t}\r\n\r\n\t\t// Call user callback if provided\r\n\t\tif( onLoadCallback ) {\r\n\t\t\tonLoadCallback( name );\r\n\t\t}\r\n\t};\r\n\r\n\t// Handle Image or Canvas element passed directly\r\n\tif( typeof src !== \"string\" ) {\r\n\r\n\t\t// Use the element directly\r\n\t\tupdateImageFn( src );\r\n\t\treturn name;\r\n\t}\r\n\r\n\t// Create the new image\r\n\tconst img = new Image();\r\n\t\r\n\t// Increment wait count for ready() - will be decremented in onload/onerror\r\n\tg_commands.wait();\r\n\r\n\t// Setup onload handler\r\n\timg.onload = function() {\r\n\t\tupdateImageFn( img );\r\n\r\n\t\t// Decrement wait count\r\n\t\tg_commands.done();\r\n\t};\r\n\r\n\t// Setup onerror handler\r\n\timg.onerror = function( error ) {\r\n\r\n\t\t// Mark image as failed\r\n\t\tm_images[ name ] = {\r\n\t\t\t\"status\": \"error\",\r\n\t\t\t\"error\": error\r\n\t\t};\r\n\r\n\t\t// Call user error callback if provided\r\n\t\tif( onErrorCallback ) {\r\n\t\t\tonErrorCallback( error );\r\n\t\t}\r\n\r\n\t\t// Decrement wait count even on error\r\n\t\tg_commands.done();\r\n\t};\r\n\r\n\t// Set source - may trigger onload synchronously if cached\r\n\timg.src = src;\r\n\r\n\treturn name;\r\n}\r\n\r\n\r\n/**\r\n * Remove an image from storage\r\n * \r\n * @param {Object} options - Load options\r\n * @param {string} [options.name] - Name of the image to remove\r\n */\r\nfunction removeImage( options ) {\r\n\tconst name = options.name;\r\n\tif( typeof name !== \"string\" ) {\r\n\t\tconst error = new TypeError( \"removeImage: Parameter name must be a string.\" );\r\n\t\terror.code = \"INVALID_NAME\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tconst imageObj = m_images[ name ];\r\n\tif( imageObj && imageObj.image ) {\r\n\r\n\t\tconst img = imageObj.image;\r\n\r\n\t\t// Explicitly delete WebGL2 textures to free GPU memory\r\n\t\t// WebGLTextures hold GPU memory that is NOT automatically freed by JS garbage collection\r\n\t\t// Must call gl.deleteTexture() explicitly to prevent memory leaks\r\n\t\tfor( const screenData of g_screenManager.getAllScreensData() ) {\r\n\t\t\tg_renderer.deleteWebGL2Texture( screenData, img );\r\n\t\t}\r\n\r\n\t\t// Remove from paletteImages\r\n\t\tif( imageObj.usePalette ) {\r\n\r\n\t\t\t// Since name is guaranteed to be unique we can assume there are no duplicate names in\r\n\t\t\t// the array\r\n\t\t\tm_paletteImages.splice( m_paletteImages.indexOf( name ), 1 );\r\n\t\t}\r\n\r\n\t\t// Delete the image object\r\n\t\tdelete m_images[ name ];\r\n\t}\r\n}\r\n\r\n/**\r\n * Load a spritesheet from URL or use provided Image/Canvas element\r\n * \r\n * @param {Object} options - Load options\r\n * @param {string|HTMLImageElement|HTMLCanvasElement|OffscreenCanvas} options.src - Image source\r\n * @param {string} [options.name] - Optional name for the spritesheet\r\n * @param {number} [options.width] - Sprite width (required for fixed grid mode)\r\n * @param {number} [options.height] - Sprite height (required for fixed grid mode)\r\n * @param {number} [options.margin] - Margin between sprites (default: 0)\r\n * @param {boolean} [options.usePalette] - Set image colors to be linked to screen canvas\r\n * @param {Array} [options.paletteKeys] - An array of colors used as key colors from the image to\r\n * \t\t\t\t\t\t\t\t\t\t  use as indices to look up palette colors\r\n * @param {Function} [options.onLoad] - Callback when spritesheet loads\r\n * @param {Function} [options.onError] - Callback when spritesheet fails to load\r\n * @returns {string} Spritesheet name\r\n */\r\nfunction loadSpritesheet( options ) {\r\n\tconst src = options.src;\r\n\tlet name = options.name;\r\n\tlet spriteWidth = options.width;\r\n\tlet spriteHeight = options.height;\r\n\tlet margin = options.margin;\r\n\tconst usePalette = !!options.usePalette;\r\n\tconst paletteKeys = options.paletteKeys;\r\n\tconst onLoadCallback = options.onLoad;\r\n\tconst onErrorCallback = options.onError;\r\n\tlet isAuto = false;\r\n\r\n\tif( margin === null ) {\r\n\t\tmargin = 0;\r\n\t}\r\n\r\n\tif( spriteWidth === null && spriteHeight === null ) {\r\n\t\tisAuto = true;\r\n\t\tspriteWidth = 0;\r\n\t\tspriteHeight = 0;\r\n\t\tmargin = 0;\r\n\t} else {\r\n\t\tspriteWidth = Math.round( spriteWidth );\r\n\t\tspriteHeight = Math.round( spriteHeight );\r\n\t\tmargin = Math.round( margin );\r\n\t}\r\n\r\n\t// Validate spriteWidth and spriteHeight for fixed mode\r\n\tif( !isAuto && ( !Number.isInteger( spriteWidth ) || !Number.isInteger( spriteHeight ) ) ) {\r\n\t\tconst error = new TypeError( \"loadSpritesheet: width and height must be integers.\" );\r\n\t\terror.code = \"INVALID_DIMENSIONS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Size cannot be less than 1\r\n\tif( !isAuto && ( spriteWidth < 1 || spriteHeight < 1 ) ) {\r\n\t\tconst error = new RangeError(\r\n\t\t\t\"loadSpritesheet: width and height must be greater than 0.\"\r\n\t\t);\r\n\t\terror.code = \"INVALID_DIMENSIONS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Validate margin\r\n\tif( !Number.isInteger( margin ) ) {\r\n\t\tconst error = new TypeError( \"loadSpritesheet: margin must be an integer.\" );\r\n\t\terror.code = \"INVALID_MARGIN\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Generate a name if none is provided\r\n\tif( !name || name === \"\" ) {\r\n\t\tm_imageCount += 1;\r\n\t\tname = \"\" + m_imageCount;\r\n\t}\r\n\r\n\t// Validate name\r\n\tif( typeof name !== \"string\" ) {\r\n\t\tconst error = new TypeError( \"loadSpritesheet: Parameter name must be a string.\" );\r\n\t\terror.code = \"INVALID_NAME\";\r\n\t\tthrow error;\r\n\t}\r\n\tif( m_images[ name ] ) {\r\n\t\tconst error = new TypeError( \"loadSpritesheet: Parameter name must be unique.\" );\r\n\t\terror.code = \"INVALID_NAME\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Validate callbacks if provided\r\n\tif( onLoadCallback != null && !g_utils.isFunction( onLoadCallback ) ) {\r\n\t\tconst error = new TypeError( \"loadSpritesheet: Parameter onLoad must be a function.\" );\r\n\t\terror.code = \"INVALID_CALLBACK\";\r\n\t\tthrow error;\r\n\t}\r\n\tif( onErrorCallback != null && !g_utils.isFunction( onErrorCallback ) ) {\r\n\t\tconst error = new TypeError( \"loadSpritesheet: Parameter onError must be a function.\" );\r\n\t\terror.code = \"INVALID_CALLBACK\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Validate paletteKeys\r\n\tlet palColors = null;\r\n\tlet palColorMap = null;\r\n\tif( usePalette ) {\r\n\t\tif( !Array.isArray( paletteKeys ) || paletteKeys.length === 0 ) {\r\n\t\t\tconst error = new TypeError(\r\n\t\t\t\t\"loadSpritesheet: Parameter paletteKeys must be non empty Array when usePalette \" +\r\n\t\t\t\t\"is set.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_PALETTE\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Create a color map\r\n\t\tpalColorMap = new Map();\r\n\r\n\t\t// Initialize palColors with 0 for transparent black\r\n\t\tpalColors = [ g_utils.convertToColor( \"rgba(0, 0, 0, 0)\" ) ];\r\n\t\tpalColorMap.set( palColors[ 0 ].key, 0 );\r\n\r\n\t\tfor( let i = 0; i < paletteKeys.length; i += 1 ) {\r\n\t\t\tconst palColorRaw = paletteKeys[ i ];\r\n\t\t\tconst palColor = g_utils.convertToColor( palColorRaw );\r\n\t\t\tpalColors.push( palColor );\r\n\t\t\tpalColorMap.set( palColor.key, i + 1 );\r\n\t\t}\r\n\t}\r\n\r\n\t// Load the image first, then process frames in callback\r\n\tloadImage( {\r\n\t\t\"src\": src,\r\n\t\t\"name\": name,\r\n\t\t\"usePalette\": usePalette,\r\n\t\t\"paletteKeys\": paletteKeys,\r\n\t\t\"onLoad\": function( imageName ) {\r\n\r\n\t\t\t// Update the image data to spritesheet type\r\n\t\t\tconst imageData = m_images[ imageName ];\r\n\t\t\timageData.type = \"spritesheet\";\r\n\t\t\timageData.spriteWidth = spriteWidth;\r\n\t\t\timageData.spriteHeight = spriteHeight;\r\n\t\t\timageData.margin = margin;\r\n\t\t\timageData.frames = [];\r\n\t\t\timageData.isAuto = isAuto;\r\n\r\n\t\t\tconst width = imageData.width;\r\n\t\t\tconst height = imageData.height;\r\n\r\n\t\t\tif( isAuto ) {\r\n\r\n\t\t\t\t// Auto-detect sprites using connected component analysis\r\n\t\t\t\tprocessSpriteSheetAuto( imageData, width, height );\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// Fixed grid of sprites\r\n\t\t\t\tprocessSpriteSheetFixed( imageData, width, height );\r\n\t\t\t}\r\n\r\n\t\t\t// Call user callback if provided\r\n\t\t\tif( onLoadCallback ) {\r\n\t\t\t\tonLoadCallback( imageName );\r\n\t\t\t}\r\n\t\t},\r\n\t\t\"onError\": onErrorCallback\r\n\t} );\r\n\r\n\treturn name;\r\n}\r\n\r\n/**\r\n * Gets the image by name and returns the DOM element (Image or Canvas).\r\n * \r\n * @param {Object} options - Options\r\n * @param {string} [options.name] - Optional name for the image\r\n * @returns {Object} Actual image\r\n */\r\nfunction getImage( options ) {\r\n\tconst img = getImageFromRawInput( options.name, \"getImage\" );\r\n\r\n\t// For offscreen screens then call createImageFromScreen\r\n\tif( img.isMock ) {\r\n\t\tconst imgScreenData = g_screenManager.getScreenData( \"getImage\", img.dataset.screenId );\r\n\t\treturn createImageFromScreen( imgScreenData );\r\n\t}\r\n\treturn img;\r\n}\r\n\r\n/**\r\n * Create an image from a region of the screen (FBO)\r\n * Defaults to fullscreen if no coordinates are provided\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Options\r\n * @param {string} [options.name] - Optional name for the image\r\n * @param {number} [options.x1] - Left coordinate (defaults to 0)\r\n * @param {number} [options.y1] - Top coordinate (defaults to 0)\r\n * @param {number} [options.x2] - Right coordinate (defaults to screen width)\r\n * @param {number} [options.y2] - Bottom coordinate (defaults to screen height)\r\n * @returns {string} Image name\r\n */\r\nfunction createImageFromScreen( screenData, options ) {\r\n\tlet name = options.name;\r\n\tconst view = screenData.view;\r\n\tlet x1 = g_utils.getInt( options.x1, 0 );\r\n\tlet y1 = g_utils.getInt( options.y1, 0 );\r\n\tlet x2 = g_utils.getInt( options.x2, view.width - 1 );\r\n\tlet y2 = g_utils.getInt( options.y2, view.height - 1 );\r\n\r\n\tif( view.clipWidth <= 0 || view.clipHeight <= 0 ) {\r\n\t\tconst error = new RangeError(\r\n\t\t\t\"createImageFromScreen: Region width and height must be greater than 0.\"\r\n\t\t);\r\n\t\terror.code = \"INVALID_DIMENSIONS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Inclusive local clip limits from the effective physical clip\r\n\tconst minLocalX = view.clipX - view.originX;\r\n\tconst minLocalY = view.clipY - view.originY;\r\n\tconst maxLocalX = view.clipX + view.clipWidth - 1 - view.originX;\r\n\tconst maxLocalY = view.clipY + view.clipHeight - 1 - view.originY;\r\n\r\n\tx1 = g_utils.clamp( x1, minLocalX, maxLocalX );\r\n\ty1 = g_utils.clamp( y1, minLocalY, maxLocalY );\r\n\tx2 = g_utils.clamp( x2, minLocalX, maxLocalX );\r\n\ty2 = g_utils.clamp( y2, minLocalY, maxLocalY );\r\n\r\n\tconst width = Math.abs( x2 - x1 ) + 1;\r\n\tconst height = Math.abs( y2 - y1 ) + 1;\r\n\r\n\tif( width === 0 || height === 0 ) {\r\n\t\tconst error = new RangeError(\r\n\t\t\t\"createImageFromScreen: Region width and height must be greater than 0.\"\r\n\t\t);\r\n\t\terror.code = \"INVALID_DIMENSIONS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Physical top-left of the clamped inclusive corners\r\n\tconst actualX = Math.min( x1, x2 ) + view.originX;\r\n\tconst actualY = Math.min( y1, y2 ) + view.originY;\r\n\r\n\t// Generate a name if none is provided\r\n\tif( !name || name === \"\" ) {\r\n\t\tm_imageCount += 1;\r\n\t\tname = \"\" + m_imageCount;\r\n\t} else if( typeof name !== \"string\" ) {\r\n\t\tconst error = new TypeError( \"createImageFromScreen: Parameter name must be a string.\" );\r\n\t\terror.code = \"INVALID_NAME\";\r\n\t\tthrow error;\r\n\t} else if( m_images[ name ] ) {\r\n\t\tconst error = new Error(\r\n\t\t\t`createImageFromScreen: name \"${name}\" is already used; name must be unique.`\r\n\t\t);\r\n\t\terror.code = \"DUPLICATE_NAME\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Create canvas copy using helper function\r\n\tconst canvas = createCanvasFromScreenRegion( screenData, actualX, actualY, width, height );\r\n\r\n\t// Store in m_images\r\n\tm_images[ name ] = {\r\n\t\t\"status\": \"ready\",\r\n\t\t\"image\": canvas,\r\n\t\t\"width\": width,\r\n\t\t\"height\": height,\r\n\t\t\"usePalette\": false,\r\n\t\t\"palColors\": null,\r\n\t\t\"palColorMap\": null\r\n\t};\r\n\r\n\treturn name;\r\n}\r\n\r\n/**\r\n * Set the default anchor point for images on this screen\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Options\r\n * @param {number} options.anchorX - Anchor point X (0-1)\r\n * @param {number} options.anchorY - Anchor point Y (0-1)\r\n * @returns {void}\r\n */\r\nfunction setDefaultAnchor( screenData, options ) {\r\n\tconst anchorX = g_utils.getFloat( options.x, null );\r\n\tconst anchorY = g_utils.getFloat( options.y, null );\r\n\r\n\t// Validate anchorX\r\n\tif( anchorX === null || anchorX < 0 || anchorX > 1 ) {\r\n\t\tconst error = new TypeError(\r\n\t\t\t\"setDefaultAnchor: Parameter x must be a number between 0 and 1.\"\r\n\t\t);\r\n\t\terror.code = \"INVALID_ANCHOR\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Validate anchorY\r\n\tif( anchorY === null || anchorY < 0 || anchorY > 1 ) {\r\n\t\tconst error = new TypeError(\r\n\t\t\t\"setDefaultAnchor: Parameter y must be a number between 0 and 1.\"\r\n\t\t);\r\n\t\terror.code = \"INVALID_ANCHOR\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Update default anchor values\r\n\tscreenData.defaultAnchorX = anchorX;\r\n\tscreenData.defaultAnchorY = anchorY;\r\n}\r\n\r\n/**\r\n * Get spritesheet data including frame information\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Options\r\n * @param {string} options.name - Spritesheet name\r\n * @returns {Object} Spritesheet data with frameCount and frames array\r\n */\r\nfunction getSpritesheetData( screenData, options ) {\r\n\tconst name = options.name;\r\n\r\n\t// Validate name\r\n\tif( typeof name !== \"string\" ) {\r\n\t\tconst error = new TypeError( \"getSpritesheetData: Parameter name must be a string.\" );\r\n\t\terror.code = \"INVALID_NAME\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tconst spriteData = getStoredImage( name );\r\n\tif( !spriteData ) {\r\n\t\tconst error = new Error( `getSpritesheetData: Spritesheet \"${name}\" not found.` );\r\n\t\terror.code = \"IMAGE_NOT_FOUND\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif( spriteData.type !== \"spritesheet\" ) {\r\n\t\tconst error = new Error( `getSpritesheetData: Image \"${name}\" is not a spritesheet.` );\r\n\t\terror.code = \"NOT_A_SPRITESHEET\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tconst spriteDataResult = {\r\n\t\t\"frameCount\": spriteData.frames.length,\r\n\t\t\"frames\": []\r\n\t};\r\n\r\n\tfor( let i = 0; i < spriteData.frames.length; i++ ) {\r\n\t\tspriteDataResult.frames.push( {\r\n\t\t\t\"index\": i,\r\n\t\t\t\"x\": spriteData.frames[ i ].x,\r\n\t\t\t\"y\": spriteData.frames[ i ].y,\r\n\t\t\t\"width\": spriteData.frames[ i ].width,\r\n\t\t\t\"height\": spriteData.frames[ i ].height,\r\n\t\t\t\"left\": spriteData.frames[ i ].x,\r\n\t\t\t\"top\": spriteData.frames[ i ].y,\r\n\t\t\t\"right\": spriteData.frames[ i ].right,\r\n\t\t\t\"bottom\": spriteData.frames[ i ].bottom\r\n\t\t} );\r\n\t}\r\n\r\n\treturn spriteDataResult;\r\n}\r\n\r\n\r\n/**************************************************************************************************\r\n * Internal Helper Functions\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Create a canvas copy from a region of the screen (FBO)\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {number} x - X coordinate of region\r\n * @param {number} y - Y coordinate of region\r\n * @param {number} width - Width of region\r\n * @param {number} height - Height of region\r\n * @returns {HTMLCanvasElement} Canvas element with copy of screen region\r\n */\r\nfunction createCanvasFromScreenRegion( screenData, x, y, width, height ) {\r\n\r\n\t// TODO-LATER: Research if it's possible to use blitFrameBuffer or another faster method than\r\n\t// readPixels.\r\n\t\r\n\t// Read pixel data from FBO using readPixelsRaw\r\n\tconst pixelData = g_renderer.readPixelsRaw( screenData, x, y, width, height );\r\n\r\n\tif( !pixelData ) {\r\n\t\tconst error = new Error(\r\n\t\t\t\"createCanvasFromScreenRegion: Failed to read pixel data from screen.\"\r\n\t\t);\r\n\t\terror.code = \"READ_FAILED\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Create canvas\r\n\tconst canvas = document.createElement( \"canvas\" );\r\n\tcanvas.width = width;\r\n\tcanvas.height = height;\r\n\tconst context = canvas.getContext( \"2d\" );\r\n\r\n\t// Create ImageData for canvas (top-left origin)\r\n\tconst imageData = context.createImageData( width, height );\r\n\tconst canvasData = imageData.data;\r\n\r\n\t// Convert from bottom-left origin (WebGL) to top-left origin (Canvas)\r\n\t// pixelData is ordered from bottom row to top row\r\n\t// canvasData needs to be ordered from top row to bottom row\r\n\tfor( let row = 0; row < height; row++ ) {\r\n\t\tfor( let col = 0; col < width; col++ ) {\r\n\r\n\t\t\t// Source row in bottom-left origin (pixelData)\r\n\t\t\tconst srcRow = ( height - 1 ) - row;\r\n\t\t\tconst srcIndex = ( srcRow * width + col ) * 4;\r\n\r\n\t\t\t// Destination row in top-left origin (canvasData)\r\n\t\t\tconst dstIndex = ( row * width + col ) * 4;\r\n\r\n\t\t\t// Copy RGBA values\r\n\t\t\tcanvasData[ dstIndex     ] = pixelData[ srcIndex     ];\r\n\t\t\tcanvasData[ dstIndex + 1 ] = pixelData[ srcIndex + 1 ];\r\n\t\t\tcanvasData[ dstIndex + 2 ] = pixelData[ srcIndex + 2 ];\r\n\t\t\tcanvasData[ dstIndex + 3 ] = pixelData[ srcIndex + 3 ];\r\n\t\t}\r\n\t}\r\n\r\n\t// Put image data into canvas\r\n\tcontext.putImageData( imageData, 0, 0 );\r\n\r\n\treturn canvas;\r\n}\r\n\r\nexport function getImageFromRawInput( imageOrName, fnName ) {\r\n\tlet img = null;\r\n\r\n\t// Resolve image from name parameter\r\n\tif( typeof imageOrName === \"string\" ) {\r\n\r\n\t\t// Handle string image name\r\n\t\tconst imageData = getStoredImage( imageOrName );\r\n\t\tif( !imageData ) {\r\n\t\t\tconst error = new Error( `${fnName}: Image \"${imageOrName}\" not found.` );\r\n\t\t\terror.code = \"IMAGE_NOT_FOUND\"\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Make sure image is ready\r\n\t\tif( imageData.status !== \"ready\" ) {\r\n\t\t\tconst imgName = `Image \"${imageOrName}\"`;\r\n\t\t\tif( imageData.status === \"loading\" ) {\r\n\t\t\t\tconst error = new Error(\r\n\t\t\t\t\t`${fnName}: \"${imgName}\" is still loading. Use $.ready() to wait for it.`\r\n\t\t\t\t);\r\n\t\t\t\terror.code = \"IMAGE_NOT_READY\";\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\t\t\tif( imageData.status === \"error\" ) {\r\n\t\t\t\tconst error = new Error( `${fnName}: \"${imgName}\" failed to load.` );\r\n\t\t\t\terror.code = \"IMAGE_LOAD_FAILED\";\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Set the image\r\n\t\timg = imageData.image;\r\n\t} else if( imageOrName && typeof imageOrName === \"object\" ) {\r\n\t\tif( isTexImageCompatible( imageOrName ) ) {\r\n\t\t\timg = imageOrName;\r\n\t\t} else if( imageOrName.screen === true ) {\r\n\t\t\tconst imgScreenData = g_screenManager.getScreenData( fnName, imageOrName.id );\r\n\t\t\timg = imgScreenData.canvas;\r\n\t\t}\r\n\t}\r\n\r\n\tif( img === null ) {\r\n\t\tconst error = new TypeError(\r\n\t\t\t`${fnName}: Parameter name must be a string, canvas element, or image element.`\r\n\t\t);\r\n\t\terror.code = \"INVALID_NAME\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\treturn img;\r\n}\r\n\r\nfunction isTexImageCompatible( img ) {\r\n\treturn (\r\n\t\timg instanceof HTMLImageElement ||\r\n\t\timg instanceof HTMLVideoElement ||\r\n\t\timg instanceof HTMLCanvasElement ||\r\n\t\timg instanceof ImageBitmap ||\r\n\t\timg instanceof ImageData ||\r\n\t\t( typeof OffscreenCanvas !== \"undefined\" && img instanceof OffscreenCanvas )\r\n\t);\r\n}\r\n\r\n/**\r\n * Get stored image by name\r\n * \r\n * @param {string} name - Image name\r\n * @returns {Object|null} Image data object or null if not found\r\n */\r\nexport function getStoredImage( name ) {\r\n\tif( typeof name !== \"string\" ) {\r\n\t\treturn null;\r\n\t}\r\n\treturn m_images[ name ] || null;\r\n}\r\n\r\nfunction addPaletteImage( name ) {\r\n\tm_paletteImages.push( name );\r\n\r\n\t// Get the color object data\r\n\tconst imageObj = m_images[ name ];\r\n\r\n\tlet context;\r\n\r\n\t// Create a canvas for manipulating color data of original image\r\n\tif( imageObj.image.tagName !== \"CANVAS\" ) {\r\n\t\tconst canvas = document.createElement( \"canvas\" );\r\n\t\tcanvas.width = imageObj.width;\r\n\t\tcanvas.height = imageObj.height;\r\n\t\tcontext = canvas.getContext( \"2d\" );\r\n\t\tcontext.drawImage( imageObj.image, 0, 0 );\r\n\t\timageObj.image = canvas;\r\n\t} else {\r\n\t\tconst canvas = imageObj.image;\r\n\t\tcontext = canvas.getContext( \"2d\" );\r\n\t}\r\n\r\n\t// Create a fake screen data object so we can use the findColorIndexByColorValue function\r\n\tconst fakeScreenData = { \"pal\": imageObj.palColors, \"palMap\": imageObj.palColorMap };\r\n\r\n\t// Quantize image colors to color keys - Makes sure image only uses colors provided in key map\r\n\tconst imageData = context.getImageData( 0, 0, imageObj.width, imageObj.height );\r\n\tconst data = imageData.data;\r\n\tfor( let i = 0; i < data.length; i += 4 ) {\r\n\t\tconst color = g_utils.rgbToColor( data[ i ], data[ i + 1 ], data[ i + 2 ], data[ i + 3 ] );\r\n\t\tconst index = g_colors.findColorIndexByColorValue( fakeScreenData, color, 1 );\r\n\t\tconst newColor = fakeScreenData.pal[ index ];\r\n\t\tif( newColor.key !== color.key ) {\r\n\t\t\tdata[ i ] = newColor.r;\r\n\t\t\tdata[ i + 1 ] = newColor.g;\r\n\t\t\tdata[ i + 2 ] = newColor.b;\r\n\t\t\tdata[ i + 3 ] = newColor.a;\r\n\t\t}\r\n\t}\r\n\tcontext.putImageData( imageData, 0, 0 );\r\n\r\n\t// Store the imageData.data onto the object so we don't need to call getImageData when palette\r\n\t// swaps. The base canvas never changes after this so we can just store the image data here.\r\n\timageObj.data = data;\r\n\r\n\t// Palettize image on all created screens\r\n\tfor( const screenData of g_screenManager.getAllScreensData() ) {\r\n\t\tpalettizeImage( screenData, name );\r\n\t}\r\n}\r\n\r\n// Palettizes all images for a screen\r\nexport function palettizeImages( screenData ) {\r\n\r\n\t// Loop through all palette images\r\n\tfor( const name of m_paletteImages ) {\r\n\t\tpalettizeImage( screenData, name );\r\n\t}\r\n}\r\n\r\nfunction palettizeImage( screenData, name ) {\r\n\r\n\t// Get the global image object\r\n\tconst imageObj = m_images[ name ];\r\n\r\n\t// Make sure there are enough colors in the screen palette for this image\r\n\tif( imageObj.palColors.length > screenData.pal.length ) {\r\n\t\tconsole.warn(\r\n\t\t\t`There are too many palette colors in image: ${name}. Unable to swap colors for this ` +\r\n\t\t\t\"palette.\"\r\n\t\t);\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Cache the array length\r\n\tconst len = imageObj.width * imageObj.height * 4;\r\n\r\n\t// Create a \r\n\tconst palettizedImageData = new Uint8ClampedArray( len );\r\n\tconst data = imageObj.data;\r\n\t\r\n\t// Swap canvas colors. Should have enough indices for screen palette.\r\n\tfor( let i = 0; i < len; i += 4 ) {\r\n\r\n\t\t// Get the pal index from the original image data\r\n\t\tconst key = g_utils.generateColorKey(\r\n\t\t\tdata[ i ], data[ i + 1 ], data[ i + 2 ], data[i + 3 ]\r\n\t\t);\r\n\t\tconst palIndex = imageObj.palColorMap.get( key );\r\n\r\n\t\t// Set the new color\r\n\t\tconst newColor = screenData.pal[ palIndex ];\r\n\t\tpalettizedImageData[ i ] = newColor.r;\r\n\t\tpalettizedImageData[ i + 1 ] = newColor.g;\r\n\t\tpalettizedImageData[ i + 2 ] = newColor.b;\r\n\t\tpalettizedImageData[ i + 3 ] = newColor.a;\r\n\t}\r\n\r\n\t// Update the texture with the palettized imageData\r\n\tg_renderer.updateWebGL2TextureImage(\r\n\t\tscreenData, imageObj.image, palettizedImageData, imageObj.width, imageObj.height\r\n\t);\r\n}\r\n\r\n/**\r\n * Process spritesheet with fixed grid dimensions\r\n * \r\n * @param {Object} imageData - Image data object\r\n * @param {number} width - Image width\r\n * @param {number} height - Image height\r\n * @returns {void}\r\n */\r\nfunction processSpriteSheetFixed( imageData, width, height ) {\r\n\tlet x1 = imageData.margin;\r\n\tlet y1 = imageData.margin;\r\n\tlet x2 = x1 + imageData.spriteWidth;\r\n\tlet y2 = y1 + imageData.spriteHeight;\r\n\r\n\t// Loop through all the frames in a grid pattern\r\n\twhile( y2 <= height - imageData.margin ) {\r\n\t\twhile( x2 <= width - imageData.margin ) {\r\n\t\t\timageData.frames.push( {\r\n\t\t\t\t\"x\": x1,\r\n\t\t\t\t\"y\": y1,\r\n\t\t\t\t\"width\": imageData.spriteWidth,\r\n\t\t\t\t\"height\": imageData.spriteHeight,\r\n\t\t\t\t\"right\": x1 + imageData.spriteWidth - 1,\r\n\t\t\t\t\"bottom\": y1 + imageData.spriteHeight - 1\r\n\t\t\t} );\r\n\t\t\tx1 += imageData.spriteWidth + imageData.margin;\r\n\t\t\tx2 = x1 + imageData.spriteWidth;\r\n\t\t}\r\n\t\tx1 = imageData.margin;\r\n\t\tx2 = x1 + imageData.spriteWidth;\r\n\t\ty1 += imageData.spriteHeight + imageData.margin;\r\n\t\ty2 = y1 + imageData.spriteHeight;\r\n\t}\r\n}\r\n\r\n/**\r\n * Process spritesheet with auto-detection (finds connected pixel clusters)\r\n * \r\n * @param {Object} imageData - Image data object\r\n * @param {number} width - Image width\r\n * @param {number} height - Image height\r\n * @returns {void}\r\n */\r\nfunction processSpriteSheetAuto( imageData, width, height ) {\r\n\r\n\t// Create canvas to read pixel data\r\n\tconst canvas = document.createElement( \"canvas\" );\r\n\tcanvas.width = width;\r\n\tcanvas.height = height;\r\n\tconst context = canvas.getContext( \"2d\", { \"willReadFrequently\": true } );\r\n\tcontext.drawImage( imageData.image, 0, 0 );\r\n\r\n\tconst data = context.getImageData( 0, 0, width, height ).data;\r\n\tconst searched = new Uint8Array( width * height );\r\n\r\n\t// 8-directional neighbors\r\n\tconst dirs = [\r\n\t\t[ -1, -1 ], [ 0, -1 ], [ 1, -1 ],\r\n\t\t[ -1,  0 ],            [ 1,  0 ],\r\n\t\t[ -1,  1 ], [ 0,  1 ], [ 1,  1 ]\r\n\t];\r\n\r\n\t// Find clusters of non-transparent pixels\r\n\tfor( let i = 3; i < data.length; i += 4 ) {\r\n\t\tif( data[ i ] > 0 ) {\r\n\t\t\tconst index = ( i - 3 ) / 4;\r\n\t\t\tconst x1 = index % width;\r\n\t\t\tconst y1 = Math.floor( index / width );\r\n\t\t\tconst pixelIndex = y1 * width + x1;\r\n\r\n\t\t\t// Skip if already searched\r\n\t\t\tif( searched[ pixelIndex ] ) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t// Find bounding box of this cluster\r\n\t\t\tconst frameData = {\r\n\t\t\t\t\"x\": width,\r\n\t\t\t\t\"y\": height,\r\n\t\t\t\t\"width\": 0,\r\n\t\t\t\t\"height\": 0,\r\n\t\t\t\t\"right\": 0,\r\n\t\t\t\t\"bottom\": 0\r\n\t\t\t};\r\n\r\n\t\t\t// BFS to find all connected pixels\r\n\t\t\tconst queue = [];\r\n\t\t\tqueue.push( { \"x\": x1, \"y\": y1 } );\r\n\t\t\tsearched[ pixelIndex ] = 1;\r\n\r\n\t\t\tlet head = 0;\r\n\t\t\twhile( head < queue.length ) {\r\n\t\t\t\tconst pixel = queue[ head++ ];\r\n\t\t\t\tconst px = pixel.x;\r\n\t\t\t\tconst py = pixel.y;\r\n\r\n\t\t\t\t// Update bounding box\r\n\t\t\t\tframeData.x = Math.min( frameData.x, px );\r\n\t\t\t\tframeData.y = Math.min( frameData.y, py );\r\n\t\t\t\tframeData.right = Math.max( frameData.right, px );\r\n\t\t\t\tframeData.bottom = Math.max( frameData.bottom, py );\r\n\r\n\t\t\t\t// Check all 8 neighbors\r\n\t\t\t\tfor( const dir of dirs ) {\r\n\t\t\t\t\tconst nx = px + dir[ 0 ];\r\n\t\t\t\t\tconst ny = py + dir[ 1 ];\r\n\r\n\t\t\t\t\t// Skip if out of bounds\r\n\t\t\t\t\tif( nx < 0 || nx >= width || ny < 0 || ny >= height ) {\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tconst nIndex = ny * width + nx;\r\n\r\n\t\t\t\t\t// Skip if already searched\r\n\t\t\t\t\tif( searched[ nIndex ] ) {\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Check if pixel is non-transparent\r\n\t\t\t\t\tconst dataIndex = nIndex * 4;\r\n\t\t\t\t\tif( data[ dataIndex + 3 ] > 0 ) {\r\n\t\t\t\t\t\tsearched[ nIndex ] = 1;\r\n\t\t\t\t\t\tqueue.push( { \"x\": nx, \"y\": ny } );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Calculate final dimensions\r\n\t\t\tframeData.width = frameData.right - frameData.x + 1;\r\n\t\t\tframeData.height = frameData.bottom - frameData.y + 1;\r\n\r\n\t\t\t// Only add frames larger than 4 pixels (filters out noise)\r\n\t\t\tif( ( frameData.width + frameData.height ) > 4 ) {\r\n\t\t\t\timageData.frames.push( frameData );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n", "/**\r\n * Pi.js - View Module\r\n *\r\n * Bounded local drawing coordinate system and clip stack for the active screen.\r\n * A batch must never contain geometry from more than one view state. Every\r\n * view-stack change flushes pending batches before mutating view state.\r\n *\r\n * @module api/view\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_utils from \"../core/utils.js\";\r\nimport * as g_commands from \"../core/commands.js\";\r\nimport * as g_screenManager from \"../core/screen-manager.js\";\r\nimport * as g_renderer from \"../renderer/renderer.js\";\r\nimport { updatePrintCursorDimensions } from \"../text/print.js\";\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Initialization\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Initialize view module\r\n *\r\n * @param {Object} api - The main Pi.js API object\r\n * @returns {void}\r\n */\r\nexport function init( api ) {\r\n\tg_screenManager.addScreenDataItem( \"view\", {\r\n\t\t\"stack\": [],\r\n\t\t\"originX\": 0,\r\n\t\t\"originY\": 0,\r\n\t\t\"width\": 0,\r\n\t\t\"height\": 0,\r\n\t\t\"clipX\": 0,\r\n\t\t\"clipY\": 0,\r\n\t\t\"clipWidth\": 0,\r\n\t\t\"clipHeight\": 0\r\n\t} );\r\n\r\n\tg_screenManager.addScreenInitFunction( ( screenData ) => {\r\n\t\tsyncFullScreenCache( screenData );\r\n\t\tafterViewLayoutChange( screenData );\r\n\t} );\r\n\tregisterCommands();\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Command Registration\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Register view commands\r\n *\r\n * @returns {void}\r\n */\r\nfunction registerCommands() {\r\n\tg_commands.addCommand( \"pushView\", pushViewCmd, true, [ \"x\", \"y\", \"width\", \"height\" ] );\r\n\tg_commands.addCommand( \"popView\", popViewCmd, true, [] );\r\n\tg_commands.addCommand( \"resetView\", resetViewCmd, true, [] );\r\n\tg_commands.addCommand( \"viewToScreen\", viewToScreenCmd, true, [ \"x\", \"y\" ] );\r\n\tg_commands.addCommand( \"screenToView\", screenToViewCmd, true, [ \"x\", \"y\" ] );\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Rectangle Helpers\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Intersect two half-open rectangles.\r\n *\r\n * @param {number} aX - First rect left\r\n * @param {number} aY - First rect top\r\n * @param {number} aW - First rect width\r\n * @param {number} aH - First rect height\r\n * @param {number} bX - Second rect left\r\n * @param {number} bY - Second rect top\r\n * @param {number} bW - Second rect width\r\n * @param {number} bH - Second rect height\r\n * @returns {{ x: number, y: number, width: number, height: number }}\r\n */\r\nexport function intersectRects( aX, aY, aW, aH, bX, bY, bW, bH ) {\r\n\tconst left = Math.max( aX, bX );\r\n\tconst top = Math.max( aY, bY );\r\n\tconst right = Math.min( aX + aW, bX + bW );\r\n\tconst bottom = Math.min( aY + aH, bY + bH );\r\n\tconst width = Math.max( 0, right - left );\r\n\tconst height = Math.max( 0, bottom - top );\r\n\r\n\treturn {\r\n\t\t\"x\": left,\r\n\t\t\"y\": top,\r\n\t\t\"width\": width,\r\n\t\t\"height\": height\r\n\t};\r\n}\r\n\r\n/**\r\n * True if the half-open rectangle contains the point.\r\n *\r\n * @param {number} x - Point x\r\n * @param {number} y - Point y\r\n * @param {number} rectX - Rect left\r\n * @param {number} rectY - Rect top\r\n * @param {number} rectW - Rect width\r\n * @param {number} rectH - Rect height\r\n * @returns {boolean}\r\n */\r\nexport function containsPoint( x, y, rectX, rectY, rectW, rectH ) {\r\n\tif( x < rectX || y < rectY ) {\r\n\t\treturn false;\r\n\t}\r\n\tif( x >= rectX + rectW || y >= rectY + rectH ) {\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/**\r\n * Convert local coordinates to physical screen/FBO coordinates.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {number} x - Local x\r\n * @param {number} y - Local y\r\n * @returns {{ x: number, y: number }}\r\n */\r\nexport function toScreen( screenData, x, y ) {\r\n\treturn {\r\n\t\t\"x\": x + screenData.view.originX,\r\n\t\t\"y\": y + screenData.view.originY\r\n\t};\r\n}\r\n\r\n/**\r\n * Copy the current view cache for deferred operations.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @returns {Object} Snapshot of origin, size, and clip\r\n */\r\nexport function snapshotView( screenData ) {\r\n\tconst view = screenData.view;\r\n\treturn {\r\n\t\t\"originX\": view.originX,\r\n\t\t\"originY\": view.originY,\r\n\t\t\"width\": view.width,\r\n\t\t\"height\": view.height,\r\n\t\t\"clipX\": view.clipX,\r\n\t\t\"clipY\": view.clipY,\r\n\t\t\"clipWidth\": view.clipWidth,\r\n\t\t\"clipHeight\": view.clipHeight\r\n\t};\r\n}\r\n\r\n/**\r\n * True if the physical point lies inside the effective clip.\r\n *\r\n * @param {Object} viewState - View cache or snapshot\r\n * @param {number} x - Physical x\r\n * @param {number} y - Physical y\r\n * @returns {boolean}\r\n */\r\nexport function isInsideClip( viewState, x, y ) {\r\n\treturn containsPoint(\r\n\t\tx, y,\r\n\t\tviewState.clipX, viewState.clipY,\r\n\t\tviewState.clipWidth, viewState.clipHeight\r\n\t);\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Cache and Stack\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Set the view cache to the full logical framebuffer.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @returns {void}\r\n */\r\nexport function syncFullScreenCache( screenData ) {\r\n\tconst view = screenData.view;\r\n\tview.originX = 0;\r\n\tview.originY = 0;\r\n\tview.width = screenData.width;\r\n\tview.height = screenData.height;\r\n\tview.clipX = 0;\r\n\tview.clipY = 0;\r\n\tview.clipWidth = screenData.width;\r\n\tview.clipHeight = screenData.height;\r\n}\r\n\r\n/**\r\n * Rebuild derived origin/clip from requested local stack entries.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @returns {void}\r\n */\r\nexport function recomputeViewCache( screenData ) {\r\n\tconst view = screenData.view;\r\n\tconst stack = view.stack;\r\n\r\n\tif( stack.length === 0 ) {\r\n\t\tsyncFullScreenCache( screenData );\r\n\t\treturn;\r\n\t}\r\n\r\n\tlet originX = 0;\r\n\tlet originY = 0;\r\n\tlet clipX = 0;\r\n\tlet clipY = 0;\r\n\tlet clipWidth = screenData.width;\r\n\tlet clipHeight = screenData.height;\r\n\r\n\tfor( let i = 0; i < stack.length; i++ ) {\r\n\t\tconst entry = stack[ i ];\r\n\t\toriginX = originX + entry.localX;\r\n\t\toriginY = originY + entry.localY;\r\n\r\n\t\tconst clip = intersectRects(\r\n\t\t\tclipX, clipY, clipWidth, clipHeight,\r\n\t\t\toriginX, originY, entry.width, entry.height\r\n\t\t);\r\n\t\tclipX = clip.x;\r\n\t\tclipY = clip.y;\r\n\t\tclipWidth = clip.width;\r\n\t\tclipHeight = clip.height;\r\n\t}\r\n\r\n\tconst top = stack[ stack.length - 1 ];\r\n\tview.originX = originX;\r\n\tview.originY = originY;\r\n\tview.width = top.width;\r\n\tview.height = top.height;\r\n\tview.clipX = clipX;\r\n\tview.clipY = clipY;\r\n\tview.clipWidth = clipWidth;\r\n\tview.clipHeight = clipHeight;\r\n}\r\n\r\n/**\r\n * Normalize the stored print cursor into the current local view range.\r\n *\r\n * Insertion points at exactly width/height remain valid.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @returns {void}\r\n */\r\nexport function normalizeCursor( screenData ) {\r\n\tconst printCursor = screenData.printCursor;\r\n\tif( !printCursor ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst view = screenData.view;\r\n\tconst maxX = view.width;\r\n\tconst maxY = view.height;\r\n\r\n\tif( printCursor.x < 0 ) {\r\n\t\tprintCursor.x = 0;\r\n\t} else if( printCursor.x > maxX ) {\r\n\t\tprintCursor.x = maxX;\r\n\t}\r\n\r\n\tif( printCursor.y < 0 ) {\r\n\t\tprintCursor.y = 0;\r\n\t} else if( printCursor.y > maxY ) {\r\n\t\tprintCursor.y = maxY;\r\n\t}\r\n}\r\n\r\n/**\r\n * Refresh print cell cols/rows and normalize the cursor.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @returns {void}\r\n */\r\nfunction afterViewLayoutChange( screenData ) {\r\n\tupdatePrintCursorDimensions( screenData );\r\n\tnormalizeCursor( screenData );\r\n}\r\n\r\n/**\r\n * Recompute views after a logical FBO resize.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @returns {void}\r\n */\r\nexport function onScreenResize( screenData ) {\r\n\trecomputeViewCache( screenData );\r\n\tafterViewLayoutChange( screenData );\r\n}\r\n\r\n/**\r\n * Flush pending batches, then apply a view-stack mutation.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {Function} mutateFn - Mutates the stack\r\n * @returns {void}\r\n */\r\nfunction flushThenMutate( screenData, mutateFn ) {\r\n\tg_renderer.flushBatches( screenData );\r\n\tmutateFn();\r\n\trecomputeViewCache( screenData );\r\n\tafterViewLayoutChange( screenData );\r\n}\r\n\r\n/**\r\n * Parse and validate a local view rectangle.\r\n *\r\n * @param {string} fnName - Command name for errors\r\n * @param {Object} options - x, y, width, height\r\n * @returns {{ x: number, y: number, width: number, height: number }}\r\n */\r\nfunction parseViewRect( fnName, options ) {\r\n\tconst x = g_utils.getInt( options.x, null );\r\n\tconst y = g_utils.getInt( options.y, null );\r\n\tconst width = g_utils.getInt( options.width, null );\r\n\tconst height = g_utils.getInt( options.height, null );\r\n\r\n\tif( x === null || y === null || width === null || height === null ) {\r\n\t\tconst error = new TypeError(\r\n\t\t\t`${fnName}: Parameters x, y, width, and height must be integers.`\r\n\t\t);\r\n\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif( width < 0 || height < 0 ) {\r\n\t\tconst error = new RangeError(\r\n\t\t\t`${fnName}: Parameters width and height must be 0 or greater.`\r\n\t\t);\r\n\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\treturn {\r\n\t\t\"x\": x,\r\n\t\t\"y\": y,\r\n\t\t\"width\": width,\r\n\t\t\"height\": height\r\n\t};\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * External API Commands\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Push a view relative to the current drawing origin.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - x, y, width, height\r\n * @returns {void}\r\n */\r\nfunction pushViewCmd( screenData, options ) {\r\n\tconst rect = parseViewRect( \"pushView\", options );\r\n\tconst printCursor = screenData.printCursor;\r\n\tlet savedX = 0;\r\n\tlet savedY = 0;\r\n\tif( printCursor ) {\r\n\t\tsavedX = printCursor.x;\r\n\t\tsavedY = printCursor.y;\r\n\t}\r\n\r\n\tflushThenMutate( screenData, () => {\r\n\t\tscreenData.view.stack.push( {\r\n\t\t\t\"localX\": rect.x,\r\n\t\t\t\"localY\": rect.y,\r\n\t\t\t\"width\": rect.width,\r\n\t\t\t\"height\": rect.height,\r\n\t\t\t\"savedCursorX\": savedX,\r\n\t\t\t\"savedCursorY\": savedY\r\n\t\t} );\r\n\t\tif( printCursor ) {\r\n\t\t\tprintCursor.x = 0;\r\n\t\t\tprintCursor.y = 0;\r\n\t\t}\r\n\t} );\r\n}\r\n\r\n/**\r\n * Pop the current view and restore the previous cursor.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @returns {void}\r\n */\r\nfunction popViewCmd( screenData ) {\r\n\tif( screenData.view.stack.length === 0 ) {\r\n\t\tconst error = new Error( \"popView: No view to pop.\" );\r\n\t\terror.code = \"VIEW_STACK_EMPTY\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tflushThenMutate( screenData, () => {\r\n\t\tconst popped = screenData.view.stack.pop();\r\n\t\tconst printCursor = screenData.printCursor;\r\n\t\tif( printCursor ) {\r\n\t\t\tprintCursor.x = popped.savedCursorX;\r\n\t\t\tprintCursor.y = popped.savedCursorY;\r\n\t\t}\r\n\t} );\r\n}\r\n\r\n/**\r\n * Clear the view stack and reset to implicit full screen.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @returns {void}\r\n */\r\nfunction resetViewCmd( screenData ) {\r\n\tflushThenMutate( screenData, () => {\r\n\t\tscreenData.view.stack = [];\r\n\t\tconst printCursor = screenData.printCursor;\r\n\t\tif( printCursor ) {\r\n\t\t\tprintCursor.x = 0;\r\n\t\t\tprintCursor.y = 0;\r\n\t\t}\r\n\t} );\r\n}\r\n\r\n/**\r\n * Convert a local point to screen/FBO coordinates using the logical origin.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - x, y\r\n * @returns {{ x: number, y: number }}\r\n */\r\nfunction viewToScreenCmd( screenData, options ) {\r\n\tconst x = g_utils.getInt( options.x, null );\r\n\tconst y = g_utils.getInt( options.y, null );\r\n\tif( x === null || y === null ) {\r\n\t\tconst error = new TypeError( \"viewToScreen: Parameters x and y must be integers.\" );\r\n\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\tthrow error;\r\n\t}\r\n\treturn toScreen( screenData, x, y );\r\n}\r\n\r\n/**\r\n * Convert a screen/FBO point to local view coordinates using the logical origin.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - x, y\r\n * @returns {{ x: number, y: number }}\r\n */\r\nfunction screenToViewCmd( screenData, options ) {\r\n\tconst x = g_utils.getInt( options.x, null );\r\n\tconst y = g_utils.getInt( options.y, null );\r\n\tif( x === null || y === null ) {\r\n\t\tconst error = new TypeError( \"screenToView: Parameters x and y must be integers.\" );\r\n\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\tthrow error;\r\n\t}\r\n\treturn {\r\n\t\t\"x\": x - screenData.view.originX,\r\n\t\t\"y\": y - screenData.view.originY\r\n\t};\r\n}\r\n", "/**\r\n * Pi.js - Print Module\r\n * \r\n * Text printing, cursor positioning, and word wrapping for bitmap fonts.\r\n * \r\n * @module text/print\r\n */\r\n\r\n// Maybe move setFont to print.js from fonts.js?\r\n\r\n\"use strict\";\r\n\r\nimport * as g_utils from \"../core/utils.js\";\r\nimport * as g_commands from \"../core/commands.js\";\r\nimport * as g_screenManager from \"../core/screen-manager.js\";\r\nimport * as g_renderer from \"../renderer/renderer.js\";\r\nimport * as g_textures from \"../renderer/textures.js\";\r\nimport * as g_sprites from \"../renderer/draw/sprites.js\";\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Initialization\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Initialize print module\r\n * \r\n * @param {Object} api - The main Pi.js API object\r\n * @returns {void}\r\n */\r\nexport function init( api ) {\r\n\tg_screenManager.addScreenDataItem( \"printCursor\", {\r\n\t\t\"x\": 0,\r\n\t\t\"y\": 0,\r\n\t\t\"cols\": 0,\r\n\t\t\"rows\": 0,\r\n\t\t\"scaleWidth\": 1,\r\n\t\t\"scaleHeight\": 1,\r\n\t\t\"width\": 0,\r\n\t\t\"height\": 0,\r\n\t\t\"breakWord\": true,\r\n\t\t\"padX\": 0,\r\n\t\t\"padY\": 0\r\n\t} );\r\n\r\n\tregisterCommands();\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Command Registration\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Register print commands\r\n * \r\n * @returns {void}\r\n */\r\nfunction registerCommands() {\r\n\r\n\t// Register screen commands\r\n\tg_commands.addCommand( \"print\", print, true, [ \"msg\", \"isInline\", \"isCentered\" ] );\r\n\tg_commands.addCommand( \"setPos\", setPos, true, [ \"col\", \"row\" ] );\r\n\tg_commands.addCommand( \"setPosPx\", setPosPx, true, [ \"x\", \"y\" ] );\r\n\tg_commands.addCommand( \"getPos\", getPos, true, [] );\r\n\tg_commands.addCommand( \"getPosPx\", getPosPx, true, [] );\r\n\tg_commands.addCommand( \"getCols\", getCols, true, [] );\r\n\tg_commands.addCommand( \"getRows\", getRows, true, [] );\r\n\tg_commands.addCommand( \"setWordBreak\", setWordBreak, true, [ \"isEnabled\" ] );\r\n\tg_commands.addCommand(\r\n\t\t\"setPrintSize\", setPrintSize, true, [ \"scaleWidth\", \"scaleHeight\", \"padX\", \"padY\" ]\r\n\t);\r\n\tg_commands.addCommand( \"calcWidth\", calcWidth, true, [ \"msg\" ] );\r\n}\r\n\r\n\r\n/**************************************************************************************************\r\n * External API Commands\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Print text to screen\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Print options\r\n * @param {string} [options.msg] - Message to print\r\n * @param {boolean} [options.isInline] - If true, don't advance to next line\r\n * @param {boolean} [options.isCentered] - If true, center the text\r\n * @returns {void}\r\n */\r\nfunction print( screenData, options ) {\r\n\tlet msg = options.msg;\r\n\tconst isInline = !!options.isInline;\r\n\tconst isCentered = !!options.isCentered;\r\n\r\n\t// Check if font is set\r\n\tif( !screenData.font ) {\r\n\t\tconst error = new Error( \"print: No font set. Call setFont() first.\" );\r\n\t\terror.code = \"NO_FONT_SET\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tconst viewWidth = getViewWidth( screenData );\r\n\tconst viewHeight = getViewHeight( screenData );\r\n\r\n\t// Zero-size views and lines taller than the view cannot print\r\n\tif( viewWidth <= 0 || viewHeight <= 0 ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Bail if not possible to print an entire line in the view\r\n\tif( screenData.printCursor.height > viewHeight ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif( msg === undefined || msg === null ) {\r\n\t\tmsg = \"\";\r\n\t} else if( typeof msg !== \"string\" ) {\r\n\t\tmsg = \"\" + msg;\r\n\t}\r\n\r\n\t// Replace tabs with spaces\r\n\tmsg = msg.replace( /\\t/g, \"    \" );\r\n\r\n\t// Split messages by newlines\r\n\tconst parts = msg.split( /\\n/ );\r\n\tfor( let i = 0; i < parts.length; i++ ) {\r\n\t\tstartPrint( screenData, parts[ i ], isInline, isCentered );\r\n\t}\r\n}\r\n\r\n/**\r\n * Set cursor position by row/column\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Position options\r\n * @param {number} [options.col] - Column position\r\n * @param {number} [options.row] - Row position\r\n * @returns {void}\r\n */\r\nfunction setPos( screenData, options ) {\r\n\tconst col = options.col;\r\n\tconst row = options.row;\r\n\r\n\tconst font = screenData.font;\r\n\tif( !font ) {\r\n\t\tconst error = new Error( \"setPos: No font set. Call setFont() first.\" );\r\n\t\terror.code = \"NO_FONT_SET\";\r\n\t\tthrow error;\r\n\t}\r\n\tconst printCursor = screenData.printCursor;\r\n\r\n\t// Set the x value\r\n\tif( col !== null ) {\r\n\t\tif( isNaN( col ) ) {\r\n\t\t\tconst error = new TypeError( \"setPos: parameter col must be a number\" );\r\n\t\t\terror.code = \"INVALID_COL\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\tconst viewWidth = getViewWidth( screenData );\r\n\t\tlet x = Math.floor( col * printCursor.width );\r\n\t\tif( x > viewWidth ) {\r\n\t\t\tif( viewWidth - printCursor.width < 0 ) {\r\n\t\t\t\tx = 0;\r\n\t\t\t} else {\r\n\t\t\t\tx = viewWidth - printCursor.width;\r\n\t\t\t}\r\n\t\t}\r\n\t\tscreenData.printCursor.x = x;\r\n\t}\r\n\r\n\t// Set the y value\r\n\tif( row !== null ) {\r\n\t\tif( isNaN( row ) ) {\r\n\t\t\tconst error = new TypeError( \"setPos: parameter row must be a number\" );\r\n\t\t\terror.code = \"INVALID_ROW\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\tconst viewHeight = getViewHeight( screenData );\r\n\t\tlet y = Math.floor( row * screenData.printCursor.height );\r\n\t\tif( y > viewHeight ) {\r\n\t\t\tif( viewHeight - printCursor.height < 0 ) {\r\n\t\t\t\ty = 0;\r\n\t\t\t} else {\r\n\t\t\t\ty = viewHeight - printCursor.height;\r\n\t\t\t}\r\n\t\t}\r\n\t\tscreenData.printCursor.y = y;\r\n\t}\r\n}\r\n\r\n/**\r\n * Set cursor position by pixels\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Position options\r\n * @param {number} [options.x] - X position in pixels\r\n * @param {number} [options.y] - Y position in pixels\r\n * @returns {void}\r\n */\r\nfunction setPosPx( screenData, options ) {\r\n\tconst x = options.x;\r\n\tconst y = options.y;\r\n\r\n\tif( x != null ) {\r\n\t\tif( isNaN( x ) ) {\r\n\t\t\tconst error = new TypeError( \"setPosPx: parameter x must be a number\" );\r\n\t\t\terror.code = \"INVALID_X\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\tscreenData.printCursor.x = Math.round( x );\r\n\t}\r\n\r\n\tif( y != null ) {\r\n\t\tif( isNaN( y ) ) {\r\n\t\t\tconst error = new TypeError( \"setPosPx: parameter y must be a number\" );\r\n\t\t\terror.code = \"INVALID_Y\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\tscreenData.printCursor.y = Math.round( y );\r\n\t}\r\n}\r\n\r\n/**\r\n * Get cursor position as row/column\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @returns {Object} Object with col and row properties\r\n */\r\nfunction getPos( screenData ) {\r\n\tconst font = screenData.font;\r\n\tif( !font ) {\r\n\t\treturn { \"col\": 0, \"row\": 0 };\r\n\t}\r\n\tconst printCursor = screenData.printCursor;\r\n\r\n\treturn {\r\n\t\t\"col\": Math.floor( printCursor.x / printCursor.width ),\r\n\t\t\"row\": Math.floor( printCursor.y / printCursor.height )\r\n\t};\r\n}\r\n\r\n/**\r\n * Get cursor position in pixels\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @returns {Object} Object with x and y properties\r\n */\r\nfunction getPosPx( screenData ) {\r\n\treturn {\r\n\t\t\"x\": screenData.printCursor.x,\r\n\t\t\"y\": screenData.printCursor.y\r\n\t};\r\n}\r\n\r\n/**\r\n * Get number of columns\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @returns {number} Number of columns\r\n */\r\nfunction getCols( screenData ) {\r\n\treturn screenData.printCursor.cols;\r\n}\r\n\r\n/**\r\n * Get number of rows\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @returns {number} Number of rows\r\n */\r\nfunction getRows( screenData ) {\r\n\treturn screenData.printCursor.rows;\r\n}\r\n\r\n/**\r\n * Enable/disable word breaking\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Options\r\n * @param {boolean} options.isEnabled - Enable word breaking\r\n * @returns {void}\r\n */\r\nfunction setWordBreak( screenData, options ) {\r\n\tscreenData.printCursor.breakWord = !!options.isEnabled;\r\n}\r\n\r\n/**\r\n * Set font size for bitmap fonts\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Options\r\n * @param {number} options.scaleWidth - Font scale width\r\n * @param {number} options.scaleHeight - Font scale height\r\n * @param {number} [options.padX] - Horizontal padding between characters\r\n * @param {number} [options.padY] - Vertical padding between lines\r\n * @returns {void}\r\n */\r\nfunction setPrintSize( screenData, options ) {\r\n\tconst scaleWidth = g_utils.getFloat( options.scaleWidth, null );\r\n\tconst scaleHeight = g_utils.getFloat( options.scaleHeight, null );\r\n\tconst padX = g_utils.getInt( options.padX, null );\r\n\tconst padY = g_utils.getInt( options.padY, null );\r\n\r\n\tif(\r\n\t\t( scaleWidth !== null && scaleWidth <= 0 ) || ( scaleHeight !== null && scaleHeight <= 0 )\r\n\t) {\r\n\t\tconst error = new RangeError(\r\n\t\t\t\"setPrintSize: Parameters scaleWidth and scaleHeight must be a number greater than 0.\"\r\n\t\t);\r\n\t\terror.code = \"INVALID_SIZE\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif( scaleWidth !== null ) {\r\n\t\tscreenData.printCursor.scaleWidth = scaleWidth;\r\n\t}\r\n\r\n\tif( scaleHeight !== null ) {\r\n\t\tscreenData.printCursor.scaleHeight = scaleHeight;\r\n\t}\r\n\r\n\t// Update padding if provided\r\n\tif( padX !== null ) {\r\n\t\tscreenData.printCursor.padX = padX;\r\n\t}\r\n\tif( padY !== null ) {\r\n\t\tscreenData.printCursor.padY = padY;\r\n\t}\r\n\r\n\t// Update print cursor dimensions\r\n\tupdatePrintCursorDimensions( screenData );\r\n}\r\n\r\n/**\r\n * Calculate text width\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Options\r\n * @param {string} [options.msg] - Message to calculate width for\r\n * @returns {number} Text width in pixels\r\n */\r\nfunction calcWidth( screenData, options ) {\r\n\tconst msg = options.msg || \"\";\r\n\tconst printCursor = screenData.printCursor;\r\n\t\r\n\treturn printCursor.width * msg.length;\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Internal Functions\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Start printing text\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {string} msg - Message to print\r\n * @param {boolean} isInline - If true, don't advance to next line\r\n * @param {boolean} isCentered - If true, center the text\r\n * @returns {void}\r\n */\r\nfunction startPrint( screenData, msg, isInline, isCentered ) {\r\n\tconst printCursor = screenData.printCursor;\r\n\tconst font = screenData.font;\r\n\r\n\t// Calculate text width\r\n\tconst width = calcWidth( screenData, { \"msg\": msg } );\r\n\r\n\t// Handle centering\r\n\tif( isCentered ) {\r\n\t\tprintCursor.x = Math.floor( ( printCursor.cols - msg.length ) / 2 ) * printCursor.width;\r\n\t}\r\n\r\n\tconst viewWidth = getViewWidth( screenData );\r\n\tconst viewHeight = getViewHeight( screenData );\r\n\r\n\tif( viewWidth <= 0 || viewHeight <= 0 ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Handle text wrapping if text is too wide\r\n\tif(\r\n\t\t!isInline &&\r\n\t\t!isCentered &&\r\n\t\twidth + printCursor.x > viewWidth &&\r\n\t\tmsg.length > 1\r\n\t) {\r\n\t\tconst overlap = ( width + printCursor.x ) - viewWidth;\r\n\t\tconst onScreen = width - overlap;\r\n\t\tif( onScreen <= 0 ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst onScreenPct = onScreen / width;\r\n\t\tlet msgSplit = Math.floor( msg.length * onScreenPct );\r\n\t\tif( msgSplit <= 0 ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tlet msg1 = msg.substring( 0, msgSplit );\r\n\t\tlet msg2 = msg.substring( msgSplit, msg.length );\r\n\r\n\t\t// Word breaking\r\n\t\tif( printCursor.breakWord ) {\r\n\t\t\tconst index = msg1.lastIndexOf( \" \" );\r\n\t\t\tif( index > -1 ) {\r\n\t\t\t\tmsg2 = msg1.substring( index ).trim() + msg2;\r\n\t\t\t\tmsg1 = msg1.substring( 0, index );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tstartPrint( screenData, msg1, isInline, isCentered );\r\n\t\tstartPrint( screenData, msg2, isInline, isCentered );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Handle auto-scroll if text is too tall\r\n\tif( printCursor.y + printCursor.height > viewHeight ) {\r\n\t\tconst view = screenData.view;\r\n\t\tg_renderer.shiftImageUp(\r\n\t\t\tscreenData, printCursor.height,\r\n\t\t\tview.clipX, view.clipY, view.clipWidth, view.clipHeight\r\n\t\t);\r\n\r\n\t\t// Move cursor up\r\n\t\tprintCursor.y -= printCursor.height;\r\n\t}\r\n\r\n\t// Print the text using bitmap font\r\n\tbitmapPrint( screenData, msg, printCursor.x, printCursor.y );\r\n\r\n\t// Advance cursor position\r\n\tif( !isInline ) {\r\n\t\tprintCursor.y += printCursor.height;\r\n\t\tprintCursor.x = 0;\r\n\t} else {\r\n\t\tprintCursor.x += printCursor.width * msg.length;\r\n\t\tif( printCursor.x > viewWidth - printCursor.width ) {\r\n\t\t\tprintCursor.x = 0;\r\n\t\t\tprintCursor.y += printCursor.height;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * Print using bitmap font image\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {string} msg - Message to print\r\n * @param {number} x - X position\r\n * @param {number} y - Y position\r\n * @returns {void}\r\n */\r\nfunction bitmapPrint( screenData, msg, x, y ) {\r\n\tconst font = screenData.font;\r\n\r\n\tif( !font.image ) {\r\n\t\tconsole.warn( \"bitmapPrint: Font image not loaded yet.\" );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Get or create texture for font image\r\n\tg_textures.getWebGL2Texture( screenData, font.image );\r\n\r\n\tconst atlasWidth = font.atlasWidth;\r\n\tconst fontWidth = font.width;\r\n\tconst fontHeight = font.height;\r\n\tconst printWidth = screenData.printCursor.width;\r\n\tconst scaleX = screenData.printCursor.scaleWidth;\r\n\tconst scaleY = screenData.printCursor.scaleHeight;\r\n\tconst margin = font.margin;\r\n\tconst cellWidth = font.cellWidth;\r\n\tconst cellHeight = font.cellHeight;\r\n\tconst columns = Math.floor( atlasWidth / cellWidth );\r\n\r\n\t// Loop through each character in the message\r\n\tfor( let i = 0; i < msg.length; i++ ) {\r\n\r\n\t\t// Get the character index for the character data\r\n\t\tconst charIndex = font.chars[ msg.charCodeAt( i ) ];\r\n\r\n\t\tif( charIndex !== undefined ) {\r\n\r\n\t\t\t// Get the source x & y coordinates in the atlas\r\n\t\t\tconst sx = ( charIndex % columns ) * cellWidth + margin;\r\n\t\t\tconst sy = Math.floor( charIndex / columns ) * cellHeight + margin;\r\n\r\n\t\t\t// Get the destination x coordinate\r\n\t\t\tconst dx = x + printWidth * i;\r\n\r\n\t\t\t// Draw the character using drawSprite\r\n\t\t\tconst color = screenData.color;\r\n\t\t\tg_sprites.drawSprite(\r\n\t\t\t\tscreenData, font.image,\r\n\t\t\t\tsx, sy, fontWidth, fontHeight,\r\n\t\t\t\tdx, y, fontWidth, fontHeight,\r\n\t\t\t\tcolor, 0, 0, scaleX, scaleY, 0\r\n\t\t\t);\r\n\t\t}\r\n\t}\r\n\r\n\t// Mark screen as dirty\r\n\tg_renderer.setImageDirty( screenData );\r\n}\r\n\r\n/**\r\n * Update print cursor rows and columns based on font and size\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @returns {void}\r\n */\r\nexport function updatePrintCursorDimensions( screenData ) {\r\n\tconst font = screenData.font;\r\n\tif( !font ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst printCursor = screenData.printCursor;\r\n\r\n\tprintCursor.width = printCursor.scaleWidth * ( font.width + printCursor.padX );\r\n\tprintCursor.height = printCursor.scaleHeight * ( font.height + printCursor.padY );\r\n\r\n\tconst viewWidth = getViewWidth( screenData );\r\n\tconst viewHeight = getViewHeight( screenData );\r\n\tif( printCursor.width <= 0 || viewWidth <= 0 ) {\r\n\t\tprintCursor.cols = 0;\r\n\t} else {\r\n\t\tprintCursor.cols = Math.floor( viewWidth / printCursor.width );\r\n\t}\r\n\tif( printCursor.height <= 0 || viewHeight <= 0 ) {\r\n\t\tprintCursor.rows = 0;\r\n\t} else {\r\n\t\tprintCursor.rows = Math.floor( viewHeight / printCursor.height );\r\n\t}\r\n}\r\n\r\n/**\r\n * Requested local view width, or the FBO width if no view cache exists.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @returns {number}\r\n */\r\nfunction getViewWidth( screenData ) {\r\n\tif( screenData.view ) {\r\n\t\treturn screenData.view.width;\r\n\t}\r\n\treturn screenData.width;\r\n}\r\n\r\n/**\r\n * Requested local view height, or the FBO height if no view cache exists.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @returns {number}\r\n */\r\nfunction getViewHeight( screenData ) {\r\n\tif( screenData.view ) {\r\n\t\treturn screenData.view.height;\r\n\t}\r\n\treturn screenData.height;\r\n}\r\n", "/**\r\n * Pi.js - Plugin System Core Module\r\n * \r\n * Plugin registration and management for extending Pi.js functionality.\r\n * \r\n * @module core/plugins\r\n */\r\n\r\n\"use strict\";\r\n\r\n// Import modules directly\r\nimport * as g_commands from \"./commands.js\";\r\nimport * as g_screenManager from \"./screen-manager.js\";\r\nimport * as g_utils from \"./utils.js\";\r\n\r\nconst m_plugins = [];\r\nconst m_waitingForDependencies = [];\r\nconst m_clearEventsHandlers = {};\r\nlet m_api = null;\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Commands\r\n **************************************************************************************************/\r\n\r\n\r\nexport function init( api ) {\r\n\tm_api = api;\r\n\r\n\t// Register external API commands\r\n\tg_commands.addCommand(\r\n\t\t\"registerPlugin\", registerPlugin, false,\r\n\t\t[ \"name\", \"init\", \"version\", \"description\", \"dependencies\" ]\r\n\t);\r\n\tg_commands.addCommand(\r\n\t\t\"getPlugins\", getPlugins, false, []\r\n\t);\r\n\tg_commands.addCommand(\r\n\t\t\"clearEvents\", clearEvents, true, [ \"type\" ], true\r\n\t);\r\n\r\n\t// Resolve plugins waiting on dependencies at end of frame\r\n\tqueueMicrotask( () => {\r\n\t\tfor( const pluginInfo of m_waitingForDependencies ) {\r\n\t\t\tlet missingDependencies = [];\r\n\t\t\tfor( const dependency of pluginInfo.dependencies ) {\r\n\t\t\t\tif( !m_plugins.some( pi => pi.name === dependency ) ) {\r\n\t\t\t\t\tmissingDependencies.push( dependency );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif( missingDependencies.length > 0 ) {\r\n\t\t\t\tconsole.error(\r\n\t\t\t\t\t`Unable to initialize plugin \"${pluginInfo.name}\". Missing the following ` +\r\n\t\t\t\t\t`dependencies: ` + missingDependencies.join( \", \" ) + \".\"\r\n\t\t\t\t);\r\n\t\t\t} else {\r\n\t\t\t\tinitializePlugin( pluginInfo );\r\n\t\t\t}\r\n\t\t}\r\n\t} );\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * External API Commands\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Register a plugin with Pi.js\r\n * \r\n * @param {Object} options - Plugin configuration\r\n * @param {string} options.name - Unique name for the plugin\r\n * @param {Function} options.init - Initialization function that receives pluginApi\r\n * @param {string} [options.version] - Optional version string\r\n * @param {string} [options.description] - Optional description\r\n * @param {string} [options.dependencies] - Optional list of dependencies\r\n * @returns {void}\r\n * \r\n * @example\r\n * pi.registerPlugin( {\r\n *   \"name\": \"my-plugin\",\r\n *   \"version\": \"1.0.0\",\r\n *   \"description\": \"My custom plugin\",\r\n *   \"init\": ( pluginApi ) => {\r\n *     pluginApi.addCommand( \"myCommand\", myFn, [ \"param1\" ] );\r\n *   }\r\n * } );\r\n */\r\nfunction registerPlugin( options ) {\r\n\r\n\t// Validate required parameters\r\n\tif( !options.name || typeof options.name !== \"string\" ) {\r\n\t\tconst error = new TypeError( \"registerPlugin: Plugin must have a 'name' property.\" );\r\n\t\terror.code = \"INVALID_PLUGIN_NAME\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif( !options.init || typeof options.init !== \"function\" ) {\r\n\t\tconst error = new TypeError(\r\n\t\t\t`registerPlugin: Plugin '${options.name}' must have an 'init' function.`\r\n\t\t);\r\n\t\terror.code = \"INVALID_PLUGIN_INIT\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// If dependencies is not defined then create empty array\r\n\tif( options.dependencies === null ) {\r\n\t\toptions.dependencies = [];\r\n\t}\r\n\r\n\t// Check for duplicate\r\n\tif( m_plugins.some( p => p.name === options.name ) ) {\r\n\t\tconst error = new Error(\r\n\t\t\t`registerPlugin: Plugin '${options.name}' is already registered.`\r\n\t\t);\r\n\t\terror.code = \"DUPLICATE_PLUGIN\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Store plugin info\r\n\tconst pluginInfo = {\r\n\t\t\"name\": options.name,\r\n\t\t\"version\": options.version || \"unknown\",\r\n\t\t\"description\": options.description || \"\",\r\n\t\t\"config\": options,\r\n\t\t\"initialized\": false\r\n\t};\r\n\r\n\tm_plugins.push( pluginInfo );\r\n\r\n\t// If all dependencies loaded then process immediately\r\n\tlet isWaitingForDependencies = false;\r\n\tfor( const dependency of pluginInfo.config.dependencies ) {\r\n\t\tif( !m_plugins.some( pi => pi.name === dependency ) ) {\r\n\t\t\tisWaitingForDependencies = true;\r\n\t\t}\r\n\t}\r\n\tif( isWaitingForDependencies ) {\r\n\t\tm_waitingForDependencies.push( pluginInfo );\r\n\t} else {\r\n\t\tinitializePlugin( pluginInfo );\r\n\t}\r\n}\r\n\r\n/**\r\n * Get list of registered plugins\r\n * \r\n * @returns {Array<Object>} Array of plugin info objects with name, version, description\r\n * \r\n * @example\r\n * const plugins = pi.getPlugins();\r\n * console.log( plugins ); // [{ name: \"my-plugin\", version: \"1.0.0\", ... }]\r\n */\r\nfunction getPlugins() {\r\n\treturn m_plugins.map( p => ( {\r\n\t\t\"name\": p.name,\r\n\t\t\"version\": p.version,\r\n\t\t\"description\": p.description,\r\n\t\t\"initialized\": p.initialized\r\n\t} ) );\r\n}\r\n\r\n/**\r\n * Clear all events from all plugins or a specific plugin type\r\n * \r\n * @param {Object} screenData - Screen data object (may be null)\r\n * @param {Object} options - Options object\r\n * @param {string} [options.type] - Optional type to clear (e.g., \"keyboard\", \"mouse\", \"touch\", \"press\")\r\n * @returns {void}\r\n * \r\n * @example\r\n * $.clearEvents(); // Clear all events from all plugins\r\n * $.clearEvents( { \"type\": \"keyboard\" } ); // Clear only keyboard events\r\n */\r\nfunction clearEvents( screenData, options ) {\r\n\tconst type = options?.type;\r\n\t\r\n\tif( type ) {\r\n\r\n\t\t// Clear events for specific type\r\n\t\tconst lowerType = String( type ).toLowerCase();\r\n\t\tconst handler = m_clearEventsHandlers[ lowerType ];\r\n\t\t\r\n\t\tif( !handler ) {\r\n\t\t\tconst validTypes = Object.keys( m_clearEventsHandlers );\r\n\t\t\tlet errorMessage = `clearEvents: Invalid type \"${type}\".`;\r\n\t\t\tif( validTypes.length > 0 ) {\r\n\t\t\t\terrorMessage += ` Valid types are: ${validTypes.join( \", \" )}.`;\r\n\t\t\t} else {\r\n\t\t\t\terrorMessage += \" No event handlers are registered.\";\r\n\t\t\t}\r\n\t\t\tconst error = new Error( errorMessage );\r\n\t\t\terror.code = \"INVALID_TYPE\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\t\r\n\t\ttry {\r\n\t\t\thandler( screenData );\r\n\t\t} catch( error ) {\r\n\t\t\tconsole.error(\r\n\t\t\t\t`clearEvents: Error calling clearEvents handler for type \"${type}\": ` +\r\n\t\t\t\t`${error.message}`\r\n\t\t\t);\r\n\t\t}\r\n\t} else {\r\n\r\n\t\t// Clear events for all registered types\r\n\t\tfor( const handlerName in m_clearEventsHandlers ) {\r\n\t\t\tconst handler = m_clearEventsHandlers[ handlerName ];\r\n\t\t\ttry {\r\n\t\t\t\thandler( screenData );\r\n\t\t\t} catch( error ) {\r\n\t\t\t\tconsole.error(\r\n\t\t\t\t\t`clearEvents: Error calling clearEvents handler for type \"${handlerName}\": ` +\r\n\t\t\t\t\t`${error.message}`\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Internal Commands\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Register a clearEvents handler function with a name\r\n * \r\n * @param {string} name - Name of the event type (e.g., \"keyboard\", \"mouse\", \"touch\", \"press\")\r\n * @param {Function} handler - Function to call when clearEvents is invoked for this type\r\n * @param {Object} [handler.screenData] - Screen data passed from clearEvents (may be null)\r\n * @returns {void}\r\n * \r\n * @example\r\n * pluginApi.registerClearEvents( \"keyboard\", ( screenData ) => {\r\n *   // Clear keyboard events for this plugin\r\n * } );\r\n */\r\nfunction registerClearEvents( name, handler ) {\r\n\tif( !name || typeof name !== \"string\" ) {\r\n\t\tconst error = new TypeError( \"registerClearEvents: name must be a non-empty string.\" );\r\n\t\terror.code = \"INVALID_NAME\";\r\n\t\tthrow error;\r\n\t}\r\n\t\r\n\tif( typeof handler !== \"function\" ) {\r\n\t\tconst error = new TypeError( \"registerClearEvents: handler must be a function.\" );\r\n\t\terror.code = \"INVALID_HANDLER\";\r\n\t\tthrow error;\r\n\t}\r\n\t\r\n\tconst lowerName = name.toLowerCase();\r\n\t\r\n\tif( m_clearEventsHandlers[ lowerName ] ) {\r\n\t\tconst error = new Error(\r\n\t\t\t`registerClearEvents: Handler with name \"${name}\" is already registered.`\r\n\t\t);\r\n\t\terror.code = \"DUPLICATE_HANDLER\";\r\n\t\tthrow error;\r\n\t}\r\n\t\r\n\tm_clearEventsHandlers[ lowerName ] = handler;\r\n}\r\n\r\n// Initialize a plugin\r\nfunction initializePlugin( pluginInfo ) {\r\n\tif( pluginInfo.initialized ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Create plugin API\r\n\tconst pluginApi = {\r\n\t\t\"addCommand\": g_commands.addCommand,\r\n\t\t\"addScreenDataItem\": g_screenManager.addScreenDataItem,\r\n\t\t\"addScreenDataItemGetter\": g_screenManager.addScreenDataItemGetter,\r\n\t\t\"addScreenInitFunction\": g_screenManager.addScreenInitFunction,\r\n\t\t\"addScreenCleanupFunction\": g_screenManager.addScreenCleanupFunction,\r\n\t\t\"getActiveScreen\": g_screenManager.getActiveScreen,\r\n\t\t\"getScreenData\": g_screenManager.getScreenData,\r\n\t\t\"getAllScreensData\": g_screenManager.getAllScreensData,\r\n\t\t\"resizeOffscreenScreen\": g_screenManager.resizeOffscreenScreen,\r\n\t\t\"getApi\": () => m_api,\r\n\t\t\"utils\": g_utils,\r\n\t\t\"wait\": g_commands.wait,\r\n\t\t\"done\": g_commands.done,\r\n\t\t\"registerClearEvents\": registerClearEvents\r\n\t};\r\n\r\n\t// Initialize plugin\r\n\ttry {\r\n\t\tpluginInfo.config.init( pluginApi );\r\n\t\tg_commands.processCommands( m_api );\r\n\t\tpluginInfo.initialized = true;\r\n\t} catch( error ) {\r\n\t\tconst pluginError = new Error(\r\n\t\t\t`registerPlugin: Failed to initialize plugin '${pluginInfo.name}': ${error.message}`\r\n\t\t);\r\n\t\tpluginError.code = \"PLUGIN_INIT_FAILED\";\r\n\t\tpluginError.originalError = error;\r\n\t\tthrow pluginError;\r\n\t}\r\n}\r\n", "/**\r\n * Pi.js - Graphics Pixels Module\r\n * \r\n * Commands to read and write pixels from the screen.\r\n * \r\n * @module api/pixels\r\n */\r\n\r\n\"use strict\";\r\n\r\n// Imports\r\nimport * as g_utils from \"../core/utils.js\";\r\nimport * as g_screenManager from \"../core/screen-manager.js\";\r\nimport * as g_colors from \"./colors.js\";\r\nimport * as g_commands from \"../core/commands.js\";\r\nimport * as g_renderer from \"../renderer/renderer.js\";\r\nimport * as g_textures from \"../renderer/textures.js\";\r\nimport * as g_view from \"./view.js\";\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Commands\r\n **************************************************************************************************/\r\n\r\n\r\nexport function init( api ) {\r\n\tregisterCommands();\r\n\r\n\t// Stable API - do not route through addCommand for hot path put\r\n\tapi.put = ( data, x, y, include0 ) => {\r\n\t\treturn putWrapper( g_screenManager.getActiveScreen( \"put\" ), data, x, y, include0 );\r\n\t};\r\n\r\n\t// Also add to each screen's api when screen is created\r\n\tg_screenManager.addScreenInitFunction( ( screenData ) => {\r\n\t\tscreenData.api.put = ( data, x, y, include0 ) => {\r\n\t\t\treturn putWrapper( screenData, data, x, y, include0 );\r\n\t\t};\r\n\t} );\r\n}\r\n\r\n\r\nfunction registerCommands() {\r\n\t\r\n\t// Register screen commands\r\n\tg_commands.addCommand( \"getPixel\", getPixel, true, [ \"x\", \"y\", \"asIndex\" ] );\r\n\tg_commands.addCommand( \"getPixelAsync\", getPixelAsync, true, [ \"x\", \"y\", \"asIndex\" ] );\r\n\tg_commands.addCommand(\r\n\t\t\"get\", get, true, [ \"x\", \"y\", \"width\", \"height\", \"tolerance\", \"asIndex\" ]\r\n\t);\r\n\tg_commands.addCommand(\r\n\t\t\"getAsync\", getAsync, true, [ \"x\", \"y\", \"width\", \"height\", \"tolerance\", \"asIndex\" ]\r\n\t);\r\n\tg_commands.addCommand(\r\n\t\t\"filterImg\", filterImg, true, [ \"filter\", \"x1\", \"y1\", \"x2\", \"y2\" ]\r\n\t);\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Get Pixel and Get Pixel Async\r\n **************************************************************************************************/\r\n\r\n\r\n// getPixel: Returns RGBA8 color object by default; if asIndex===true, returns palette index\r\nfunction getPixel( screenData, options ) {\r\n\tconst px = g_utils.getInt( options.x, null );\r\n\tconst py = g_utils.getInt( options.y, null );\r\n\tif( px === null || py === null ) {\r\n\t\tconst error = new TypeError( \"getPixel: Parameters x and y must be integers.\" );\r\n\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\tthrow error;\r\n\t}\r\n\tconst asIndex = options.asIndex ?? false;\r\n\tconst colorValue = readViewPixel( screenData, px, py );\r\n\tif( asIndex ) {\r\n\t\treturn g_colors.findColorIndexByColorValue( screenData, colorValue );\r\n\t}\r\n\treturn colorValue;\r\n}\r\n\r\nfunction getPixelAsync( screenData, options ) {\r\n\tconst px = g_utils.getInt( options.x, null );\r\n\tconst py = g_utils.getInt( options.y, null );\r\n\tif( px === null || py === null ) {\r\n\t\tconst error = new TypeError( \"getPixelAsync: Parameters x and y must be integers.\" );\r\n\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\tthrow error;\r\n\t}\r\n\tconst asIndex = options.asIndex ?? false;\r\n\tconst resolved = resolveViewPixel( screenData, px, py );\r\n\tif( resolved === null ) {\r\n\t\tconst empty = g_utils.rgbToColor( 0, 0, 0, 0 );\r\n\t\tif( asIndex ) {\r\n\t\t\treturn Promise.resolve(\r\n\t\t\t\tg_colors.findColorIndexByColorValue( screenData, empty )\r\n\t\t\t);\r\n\t\t}\r\n\t\treturn Promise.resolve( empty );\r\n\t}\r\n\treturn g_renderer.readPixelAsync( screenData, resolved.x, resolved.y ).then( ( colorValue ) => {\r\n\t\tif( asIndex ) {\r\n\t\t\treturn g_colors.findColorIndexByColorValue( screenData, colorValue );\r\n\t\t}\r\n\t\treturn colorValue;\r\n\t} );\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Get and Get Async\r\n **************************************************************************************************/\r\n\r\n\r\n// get: Returns a 2D array [height][width] of palette indices by default.\r\n// Set asIndex=false to return colorValue objects instead.\r\n// Optional tolerance passed to findColorIndexByColorValue.\r\nfunction get( screenData, options ) {\r\n\tconst pX = g_utils.getInt( options.x, null );\r\n\tconst pY = g_utils.getInt( options.y, null );\r\n\tconst pWidth = g_utils.getInt( options.width, null );\r\n\tconst pHeight = g_utils.getInt( options.height, null );\r\n\tconst tolerance = g_utils.getFloat( options.tolerance, 1 );\r\n\tconst asIndex = options.asIndex ?? true;\r\n\r\n\tif( pX === null || pY === null || pWidth === null || pHeight === null ) {\r\n\t\tconst error = new TypeError(\r\n\t\t\t\"get: Parameters x, y, width and height must be integers.\"\r\n\t\t);\r\n\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\tthrow error;\r\n\t}\r\n\t\r\n\tif( pWidth <= 0 || pHeight <= 0 ) {\r\n\t\treturn [];\r\n\t}\r\n\r\n\tconst region = resolveViewReadRect( screenData, pX, pY, pWidth, pHeight );\r\n\tif( region === null ) {\r\n\t\treturn [];\r\n\t}\r\n\tconst colors = g_renderer.readPixels(\r\n\t\tscreenData, region.x, region.y, region.width, region.height\r\n\t);\r\n\treturn convertColorsToIndices( screenData, colors, region.width, asIndex, tolerance );\r\n}\r\n\r\nfunction getAsync( screenData, options ) {\r\n\tconst pX = g_utils.getInt( options.x, null );\r\n\tconst pY = g_utils.getInt( options.y, null );\r\n\tconst pWidth = g_utils.getInt( options.width, null );\r\n\tconst pHeight = g_utils.getInt( options.height, null );\r\n\tconst tolerance = g_utils.getFloat( options.tolerance, 1 );\r\n\tconst asIndex = options.asIndex ?? true;\r\n\r\n\tif( pX === null || pY === null || pWidth === null || pHeight === null ) {\r\n\t\tconst error = new TypeError(\r\n\t\t\t\"getAsync: Parameters x, y, width and height must be integers.\"\r\n\t\t);\r\n\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif( pWidth <= 0 || pHeight <= 0 ) {\r\n\t\treturn Promise.resolve( [] );\r\n\t}\r\n\r\n\tconst region = resolveViewReadRect( screenData, pX, pY, pWidth, pHeight );\r\n\tif( region === null ) {\r\n\t\treturn Promise.resolve( [] );\r\n\t}\r\n\r\n\treturn g_renderer.readPixelsAsync(\r\n\t\tscreenData, region.x, region.y, region.width, region.height\r\n\t).then( ( colors ) => {\r\n\t\treturn convertColorsToIndices( screenData, colors, region.width, asIndex, tolerance );\r\n\t} );\r\n}\r\n\r\n/**\r\n * Convert colors array to indices array if needed\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Array} colors - 2D array of color values [height][width]\r\n * @param {number} width - Width of the region\r\n * @param {boolean} asIndex - Whether to convert to indices\r\n * @param {number|undefined} tolerance - Tolerance for color matching\r\n * @returns {Array} 2D array of colors or indices\r\n */\r\nfunction convertColorsToIndices( screenData, colors, width, asIndex, tolerance ) {\r\n\tif( !asIndex ) {\r\n\t\treturn colors;\r\n\t}\r\n\r\n\tconst results = new Array( colors.length );\r\n\tfor( let row = 0; row < colors.length; row++ ) {\r\n\t\tconst resultsRow = new Array( width );\r\n\t\tconst rowLength = colors[ row ] ? colors[ row ].length : 0;\r\n\t\t\r\n\t\tfor( let col = 0; col < width; col++ ) {\r\n\t\t\tif( col < rowLength ) {\r\n\t\t\t\tconst colorValue = colors[ row ][ col ];\r\n\t\t\t\tconst idx = g_colors.findColorIndexByColorValue(\r\n\t\t\t\t\tscreenData, colorValue, tolerance\r\n\t\t\t\t);\r\n\t\t\t\tresultsRow[ col ] = ( idx === null ? 0 : idx );\r\n\t\t\t} else {\r\n\t\t\t\tresultsRow[ col ] = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t\tresults[ row ] = resultsRow;\r\n\t}\r\n\treturn results;\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Filter Image\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Apply a filter function to a region of the screen\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Options object with filter, x1, y1, x2, y2\r\n * @returns {void}\r\n */\r\nfunction filterImg( screenData, options ) {\r\n\tconst filter = options.filter;\r\n\r\n\tconst viewSnap = g_view.snapshotView( screenData );\r\n\tlet x1 = g_utils.getInt( options.x1, 0 );\r\n\tlet y1 = g_utils.getInt( options.y1, 0 );\r\n\tlet x2 = g_utils.getInt( options.x2, viewSnap.width - 1 );\r\n\tlet y2 = g_utils.getInt( options.y2, viewSnap.height - 1 );\r\n\r\n\tif( !g_utils.isFunction( filter ) ) {\r\n\t\tconst error = new TypeError( \"filterImg: Argument filter must be a callback function.\" );\r\n\t\terror.code = \"INVALID_CALLBACK\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Inclusive local corners \u2192 half-open, then intersect the captured clip\r\n\tconst left = Math.min( x1, x2 );\r\n\tconst top = Math.min( y1, y2 );\r\n\tconst right = Math.max( x1, x2 ) + 1;\r\n\tconst bottom = Math.max( y1, y2 ) + 1;\r\n\tconst phys = g_view.intersectRects(\r\n\t\tleft + viewSnap.originX, top + viewSnap.originY,\r\n\t\tright - left, bottom - top,\r\n\t\tviewSnap.clipX, viewSnap.clipY, viewSnap.clipWidth, viewSnap.clipHeight\r\n\t);\r\n\r\n\tif( phys.width <= 0 || phys.height <= 0 ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Queue filter operation to run at end of frame\r\n\tg_utils.queueMicrotask( () => {\r\n\t\tg_utils.queueMicrotask( () => {\r\n\t\t\tapplyFilter( screenData, filter, phys.x, phys.y, phys.width, phys.height, viewSnap );\r\n\t\t} );\r\n\t} );\r\n}\r\n\r\n/**\r\n * Apply filter to pixel region (called at end of frame)\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Function} filter - Filter callback function (pixelData, x, y) => boolean\r\n * \t\t\t\t\t\t\t  pixelData is a Uint8ClampedArray with [r, g, b, a] at indices 0-3\r\n * @param {number} x1 - Left coordinate\r\n * @param {number} y1 - Top coordinate\r\n * @param {number} width - Region width\r\n * @param {number} height - Region height\r\n * @returns {void}\r\n */\r\nfunction applyFilter( screenData, filter, x1, y1, width, height, viewSnap ) {\r\n\r\n\t// Ensure batches are flushed before reading\r\n\tg_renderer.flushBatches( screenData );\r\n\r\n\t// Read pixels as raw Uint8Array (bottom-left origin from WebGL)\r\n\tconst imageData = g_renderer.readPixelsRaw( screenData, x1, y1, width, height );\r\n\r\n\tif( !imageData ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst screenHeight = screenData.height;\r\n\r\n\t// Build filtered pixel data in bottom-left origin format (for WebGL texSubImage2D)\r\n\t// The input pixelData is in bottom-left origin, so we need to flip Y when accessing\r\n\t// for the filter callback (which expects top-left coordinates), then flip back for output\r\n\tconst filteredData = new Uint8Array( width * height * 4 );\r\n\tconst pixelData = new Uint8ClampedArray( 4 );\r\n\r\n\tfor( let y = 0; y < height; y++ ) {\r\n\t\tfor( let x = 0; x < width; x++ ) {\r\n\r\n\t\t\t// Convert top-left y to bottom-left y for reading from pixelData\r\n\t\t\t// pixelData is ordered from bottom row to top row\r\n\t\t\tconst srcRow = ( height - 1 ) - y;\r\n\t\t\tconst srcIndex = ( srcRow * width + x ) * 4;\r\n\r\n\t\t\t// Populate the temporary buffer with current pixel's RGBA8\r\n\t\t\tpixelData[ 0 ] = imageData[ srcIndex ];\r\n\t\t\tpixelData[ 1 ] = imageData[ srcIndex + 1 ];\r\n\t\t\tpixelData[ 2 ] = imageData[ srcIndex + 2 ];\r\n\t\t\tpixelData[ 3 ] = imageData[ srcIndex + 3 ];\r\n\r\n\t\t\t// Output index is in bottom-left origin format (same as pixelData)\r\n\t\t\tconst dstIndex = ( srcRow * width + x ) * 4;\r\n\r\n\t\t\t// Call filter with pixelData array\r\n\t\t\t// x and y are in top-left coordinate system for the filter callback\r\n\t\t\tconst localX = ( x1 + x ) - viewSnap.originX;\r\n\t\t\tconst localY = ( y1 + y ) - viewSnap.originY;\r\n\t\t\tif( filter( pixelData, localX, localY ) ) {\r\n\r\n\t\t\t\t// Update the pixeldata \r\n\t\t\t\tfilteredData[ dstIndex     ] = pixelData[ 0 ];\r\n\t\t\t\tfilteredData[ dstIndex + 1 ] = pixelData[ 1 ];\r\n\t\t\t\tfilteredData[ dstIndex + 2 ] = pixelData[ 2 ];\r\n\t\t\t\tfilteredData[ dstIndex + 3 ] = pixelData[ 3 ];\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// Invalid color format, keep original pixel\r\n\t\t\t\tfilteredData[ dstIndex     ] = 0;\r\n\t\t\t\tfilteredData[ dstIndex + 1 ] = 0;\r\n\t\t\t\tfilteredData[ dstIndex + 2 ] = 0;\r\n\t\t\t\tfilteredData[ dstIndex + 3 ] = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Calculate destination Y in WebGL texture coordinates (bottom-left origin)\r\n\t// The texture Y coordinate is the bottom edge of the region\r\n\tconst dstY = screenHeight - ( y1 + height );\r\n\r\n\t// Update FBO texture directly using texSubImage2D\r\n\t// Pass null as imgKey to use screenData.fboTexture directly\r\n\tg_textures.updateWebGL2TextureSubImage(\r\n\t\tscreenData, null, filteredData, width, height, x1, dstY\r\n\t);\r\n\r\n\t// Mark image as dirty to trigger render\r\n\tg_renderer.setImageDirty( screenData );\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Write API\r\n **************************************************************************************************/\r\n\r\n\r\n// Wrapper for the put commands handles all parsing and data validation\r\nfunction putWrapper( screenData, data, x, y, include0 = false ) {\r\n\r\n\t// Accept either object-literal or positional params without using parseOptions\r\n\tlet pData, pX, pY, pInclude0;\r\n\tif( g_utils.isObjectLiteral( data ) ) {\r\n\t\tpData = data.data;\r\n\t\tpX = g_utils.getInt( data.x, null );\r\n\t\tpY = g_utils.getInt( data.y, null );\r\n\t\tpInclude0 = !!data.include0;\r\n\t} else {\r\n\t\tpData = data;\r\n\t\tpX = g_utils.getInt( x, null );\r\n\t\tpY = g_utils.getInt( y, null );\r\n\t\tpInclude0 = !!include0;\r\n\t}\r\n\r\n\t// Fast bail if no data\r\n\tif( !pData || pData.length < 1 ) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\t// Validate coordinates\r\n\tif( pX === null || pY === null ) {\r\n\t\tconst error = new TypeError( \"put: Parameters x and y must be integers.\" );\r\n\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Clip dest against the effective view clip in local coordinates\r\n\tconst view = screenData.view;\r\n\tconst clipLocalX = view.clipX - view.originX;\r\n\tconst clipLocalY = view.clipY - view.originY;\r\n\tconst dest = g_view.intersectRects(\r\n\t\tpX, pY,\r\n\t\tpData[ 0 ] ? pData[ 0 ].length : 0, pData.length,\r\n\t\tclipLocalX, clipLocalY, view.clipWidth, view.clipHeight\r\n\t);\r\n\r\n\tlet startX = dest.x - pX;\r\n\tlet startY = dest.y - pY;\r\n\tlet width = dest.width;\r\n\tlet height = dest.height;\r\n\r\n\t// If nothing to draw after clipping, exit\r\n\tif( width <= 0 || height <= 0 ) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\t// Prepare the batch by making sure there are enough memory in the batch\r\n\tlet pixelCount = 0;\r\n\r\n\t// Use the already calculated loop bounds\r\n\tfor( let i = startY; i < startY + height; i++ ) {\r\n\t\tconst row = pData[ i ];\r\n\r\n\t\t// Check if row exists\r\n\t\tif( row ) {\r\n\r\n\t\t\t// The actual number of pixels drawn from this row will be `width`\r\n\t\t\tpixelCount += width;\r\n\t\t}\r\n\t}\r\n\r\n\tg_renderer.prepareBatch( screenData, g_renderer.POINTS_REPLACE_BATCH, pixelCount );\r\n\r\n\tput( screenData, pData, pX, pY, pInclude0, startY, startX, width, height );\r\n\r\n\t// Mark image as dirty\r\n\tg_renderer.setImageDirty( screenData );\r\n}\r\n\r\n// put: Hot path inner function. Assumes x/y are integers and data is a 2D array.\r\nfunction put( screenData, data, x, y, include0, startY, startX, width, height ) {\r\n\t\r\n\tconst endY = startY + height;\r\n\tconst endX = startX + width;\r\n\r\n\t// Draw\r\n\tfor( let dataY = startY; dataY < endY; dataY++ ) {\r\n\t\tconst row = data[ dataY ];\r\n\t\tif( !row ) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tfor( let dataX = startX; dataX < endX; dataX++ ) {\r\n\r\n\t\t\t// Double bitwise NOT - fast convert to int function\r\n\t\t\tconst colorIndex = ~~row[ dataX ];\r\n\r\n\t\t\t// Skip transparent unless include0 is true\r\n\t\t\tif( colorIndex === 0 && include0 === false ) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tconst colorValue = g_colors.getColorValueByIndex( screenData, colorIndex );\r\n\t\t\tconst sx = x + dataX;\r\n\t\t\tconst sy = y + dataY;\r\n\r\n\t\t\tg_renderer.drawPixelUnsafe(\r\n\t\t\t\tscreenData, sx, sy, colorValue, g_renderer.POINTS_REPLACE_BATCH\r\n\t\t\t);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/**\r\n * Read one view-local pixel, or transparent black if outside the effective clip.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {number} x - Local x\r\n * @param {number} y - Local y\r\n * @returns {Object} Color value\r\n */\r\nfunction readViewPixel( screenData, x, y ) {\r\n\tconst resolved = resolveViewPixel( screenData, x, y );\r\n\tif( resolved === null ) {\r\n\t\treturn g_utils.rgbToColor( 0, 0, 0, 0 );\r\n\t}\r\n\treturn g_renderer.readPixel( screenData, resolved.x, resolved.y );\r\n}\r\n\r\n/**\r\n * Convert a local point to a physical FBO point if it is inside the clip.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {number} x - Local x\r\n * @param {number} y - Local y\r\n * @returns {{ x: number, y: number }|null}\r\n */\r\nfunction resolveViewPixel( screenData, x, y ) {\r\n\tconst phys = g_view.toScreen( screenData, x, y );\r\n\tif( !g_view.isInsideClip( screenData.view, phys.x, phys.y ) ) {\r\n\t\treturn null;\r\n\t}\r\n\treturn phys;\r\n}\r\n\r\n/**\r\n * Convert a local read rectangle to the visible physical intersection.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {number} x - Local x\r\n * @param {number} y - Local y\r\n * @param {number} width - Requested width\r\n * @param {number} height - Requested height\r\n * @returns {{ x: number, y: number, width: number, height: number }|null}\r\n */\r\nfunction resolveViewReadRect( screenData, x, y, width, height ) {\r\n\tconst view = screenData.view;\r\n\tconst phys = g_view.toScreen( screenData, x, y );\r\n\tconst clip = g_view.intersectRects(\r\n\t\tphys.x, phys.y, width, height,\r\n\t\tview.clipX, view.clipY, view.clipWidth, view.clipHeight\r\n\t);\r\n\tif( clip.width <= 0 || clip.height <= 0 ) {\r\n\t\treturn null;\r\n\t}\r\n\treturn clip;\r\n}\r\n\r\n", "/**\r\n * Pi.js - Paint Module\r\n * \r\n * Flood fill algorithm with tolerance support\r\n * \r\n * @module api/paint\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_colors from \"./colors.js\";\r\nimport * as g_utils from \"../core/utils.js\";\r\nimport * as g_renderer from \"../renderer/renderer.js\";\r\nimport * as g_commands from \"../core/commands.js\";\r\nimport * as g_view from \"./view.js\";\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Commands\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Initialize paint module\r\n * \r\n * @param {Object} api - The main Pi.js API object\r\n * @returns {void}\r\n */\r\nexport function init( api ) {\r\n\tregisterCommands();\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * External API Commands\r\n **************************************************************************************************/\r\n\r\n\r\nfunction registerCommands() {\r\n\tg_commands.addCommand(\r\n\t\t\"paint\", paint, true, [ \"x\", \"y\", \"fillColor\", \"tolerance\", \"boundaryColor\" ]\r\n\t);\r\n}\r\n\r\n\r\n/**\r\n * Paint command - flood fill algorithm with tolerance support\r\n * \r\n * @param {Object} screenData - The screen data object\r\n * @param {Object} options - Options object with x, y, fillColor, tolerance, boundaryColor\r\n * @param {number} options.tolerance - Color matching tolerance (0 = exact match, 1 = any color)\r\n * @returns {void}\r\n */\r\nfunction paint( screenData, options ) {\r\n\tconst x = g_utils.getInt( options.x, null );\r\n\tconst y = g_utils.getInt( options.y, null );\r\n\tlet fillColor = options.fillColor;\r\n\tlet tolerance = g_utils.getFloat( options.tolerance, 0 );\r\n\tlet boundaryColor = options.boundaryColor;\r\n\r\n\tif( x === null || y === null ) {\r\n\t\tconst error = new TypeError( \"paint: Parameters x and y must be integers\" );\r\n\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif( tolerance < 0 || tolerance > 1 ) {\r\n\t\tconst error = new RangeError(\r\n\t\t\t\"paint: Parameter tolerance must be a number between 0 and 1 \" +\r\n\t\t\t\"(0 = exact match, 1 = any color).\"\r\n\t\t);\r\n\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Get fill color\r\n\tfillColor = g_colors.getColorValueByRawInput( screenData, fillColor );\r\n\tif( fillColor === null ) {\r\n\t\tconst error = new RangeError( \"paint: Parameter fillColor is not a valid color format.\" );\r\n\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tconst view = screenData.view;\r\n\tconst clipX = view.clipX;\r\n\tconst clipY = view.clipY;\r\n\tconst clipW = view.clipWidth;\r\n\tconst clipH = view.clipHeight;\r\n\tconst originX = view.originX;\r\n\tconst originY = view.originY;\r\n\tconst startPhys = g_view.toScreen( screenData, x, y );\r\n\r\n\tif( !g_view.isInsideClip( view, startPhys.x, startPhys.y ) ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Optimization: if tolerance is 1 (any color), fill the requested view\r\n\tif( tolerance === 1 ) {\r\n\t\tg_renderer.drawRectFilled( screenData, 0, 0, view.width, view.height, fillColor );\r\n\t\tg_renderer.setImageDirty( screenData );\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst pixels2D = g_renderer.readPixels( screenData, clipX, clipY, clipW, clipH );\r\n\tconst startColor = pixels2D[ startPhys.y - clipY ][ startPhys.x - clipX ];\r\n\r\n\t// Don't fill if the color is the same\r\n\tif( startColor.key === fillColor.key ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Calculate tolerance threshold for color comparison\r\n\t// Using perceptual weights: [0.2, 0.68, 0.07, 0.05] for R, G, B, A\r\n\t// Tolerance: 0 = exact match only, 1 = any color\r\n\tconst weights = [ 0.2, 0.68, 0.07, 0.05 ];\r\n\tconst maxDifference = ( 255 * 255 ) * weights.reduce( ( a, b ) => a + b );\r\n\tconst toleranceThreshold = ( 1 - tolerance * tolerance ) * maxDifference;\r\n\r\n\t// Use Uint8Array for efficient visited pixel tracking\r\n\tconst visited = new Uint8Array( clipW * clipH );\r\n\r\n\t// BFS queue for flood fill - using head pointer for O(1) dequeue\r\n\tconst queue = [];\r\n\tqueue.push( { \"x\": startPhys.x, \"y\": startPhys.y } );\r\n\r\n\t// Mark starting pixel as visited\r\n\tvisited[ ( startPhys.y - clipY ) * clipW + ( startPhys.x - clipX ) ] = 1;\r\n\r\n\t// Define color comparison function based on fill mode (no conditionals in hot loop)\r\n\tlet shouldSkipPixel;\r\n\tif( boundaryColor !== null ) {\r\n\r\n\t\t// Boundary fill mode: skip pixels that match boundary color\r\n\t\tboundaryColor = g_colors.getColorValueByRawInput( screenData, boundaryColor );\r\n\t\tif( boundaryColor === null ) {\r\n\t\t\tconst error = new RangeError(\r\n\t\t\t\t\"paint: Parameter boundaryColor is not a valid color format.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\tshouldSkipPixel = ( pixelColor ) => {\r\n\t\t\tconst difference = g_utils.calcColorDifference( boundaryColor, pixelColor, weights );\r\n\t\t\tconst similarity = maxDifference - difference;\r\n\t\t\treturn similarity >= toleranceThreshold;\r\n\t\t};\r\n\r\n\t} else {\r\n\r\n\t\t// Flood fill mode: skip pixels that don't match start color\r\n\t\tshouldSkipPixel = ( pixelColor ) => {\r\n\t\t\tconst difference = g_utils.calcColorDifference( startColor, pixelColor, weights );\r\n\t\t\tconst similarity = maxDifference - difference;\r\n\t\t\treturn similarity < toleranceThreshold;\r\n\t\t};\r\n\t}\r\n\r\n\t// Prepare batch for drawing pixels\r\n\tconst pixelCount = clipW * clipH;\r\n\tg_renderer.prepareBatch( screenData, g_renderer.POINTS_BATCH, pixelCount );\r\n\r\n\tlet head = 0;\r\n\twhile( head < queue.length ) {\r\n\r\n\t\t// Dequeue using head pointer (O(1) instead of O(n) with shift)\r\n\t\tconst pixel = queue[ head++ ];\r\n\t\tconst px = pixel.x;\r\n\t\tconst py = pixel.y;\r\n\r\n\t\t// Get pixel color\r\n\t\tconst pixelColor = pixels2D[ py - clipY ][ px - clipX ];\r\n\r\n\t\t// Skip if color comparison fails\r\n\t\tif( shouldSkipPixel( pixelColor ) ) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// Fill using local coords so the view origin is applied once\r\n\t\tg_renderer.drawPixelUnsafe(\r\n\t\t\tscreenData, px - originX, py - originY, fillColor, g_renderer.POINTS_BATCH\r\n\t\t);\r\n\r\n\t\taddToQueue( queue, visited, px + 1, py, clipX, clipY, clipW, clipH );\r\n\t\taddToQueue( queue, visited, px - 1, py, clipX, clipY, clipW, clipH );\r\n\t\taddToQueue( queue, visited, px, py + 1, clipX, clipY, clipW, clipH );\r\n\t\taddToQueue( queue, visited, px, py - 1, clipX, clipY, clipW, clipH );\r\n\t}\r\n\r\n\t// Mark image as dirty to trigger render\r\n\tg_renderer.setImageDirty( screenData );\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Internal Commands\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Add pixel to queue if valid and not visited\r\n * \r\n * @param {Array} queue - BFS queue\r\n * @param {Uint8Array} visited - Visited pixel tracking array\r\n * @param {number} x - X coordinate\r\n * @param {number} y - Y coordinate\r\n * @param {number} width - Screen width\r\n * @param {number} height - Screen height\r\n * @returns {void}\r\n */\r\nfunction addToQueue( queue, visited, x, y, clipX, clipY, clipW, clipH ) {\r\n\tif( x < clipX || x >= clipX + clipW || y < clipY || y >= clipY + clipH ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst index = ( y - clipY ) * clipW + ( x - clipX );\r\n\tif( visited[ index ] === 0 ) {\r\n\t\tvisited[ index ] = 1;\r\n\t\tqueue.push( { \"x\": x, \"y\": y } );\r\n\t}\r\n}\r\n\r\n", "/**\r\n * Pi.js - Draw Module\r\n * \r\n * BASIC-style draw command with string syntax for procedural drawing\r\n * \r\n * @module api/draw\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_screenManager from \"../core/screen-manager.js\";\r\nimport * as g_utils from \"../core/utils.js\";\r\nimport * as g_commands from \"../core/commands.js\";\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Commands\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Initialize draw module\r\n * \r\n * @param {Object} api - The main Pi.js API object\r\n * @returns {void}\r\n */\r\nexport function init( api ) {\r\n\tg_screenManager.addScreenDataItem( \"cursor\", { \"x\": 0, \"y\": 0 } );\r\n\tg_screenManager.addScreenDataItem( \"angle\", 0 );\r\n\r\n\tregisterCommands();\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * External API Commands\r\n **************************************************************************************************/\r\n\r\n\r\nfunction registerCommands() {\r\n\tg_commands.addCommand( \"draw\", draw, true, [ \"drawString\" ] );\r\n}\r\n\r\n\r\n/**\r\n * Draw command - BASIC-style draw command with string syntax\r\n * \r\n * @param {Object} screenData - The screen data object\r\n * @param {Object} options - Options object with drawString\r\n * @param {string} options.drawString - The draw command string\r\n * @returns {void}\r\n */\r\nfunction draw( screenData, options ) {\r\n\tlet drawString = options.drawString;\r\n\r\n\tif( typeof drawString !== \"string\" ) {\r\n\t\tconst error = new TypeError( \"draw: Parameter drawString must be a string.\" );\r\n\t\terror.code = \"INVALID_PARAMETER\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Convert to uppercase\r\n\tdrawString = drawString.toUpperCase();\r\n\r\n\t// Get colors\r\n\tconst tempColors = drawString.match( /(#[A-Z0-9]+)/g );\r\n\tif( tempColors ) {\r\n\t\tfor( let i = 0; i < tempColors.length; i++ ) {\r\n\t\t\tdrawString = drawString.replace( \"C\" + tempColors[ i ], \"O\" + i );\r\n\t\t}\r\n\t}\r\n\r\n\t// Remove spaces and invalid characters (keep only valid commands, numbers, #, and commas)\r\n\t// Note: Z is not included because Z is a replacement character and not allowed in original\r\n\t// string\r\n\tdrawString = drawString.replace( /[^CRBFGLATDHUENMPSO0-9#,]/g, \"\" );\r\n\t\r\n\t// Convert TA to T\r\n\tdrawString = drawString.replace( /(TA)/gi, \"T\" );\r\n\r\n\t// Convert ARC to Z\r\n\tdrawString = drawString.replace( /(ARC)/gi, \"Z\" );\r\n\t\r\n\t// Regular expression for the draw commands\r\n\tconst reg = /(?=C|O|R|B|F|G|L|A|T|D|G|H|U|E|N|M|P|S|Z)/;\r\n\r\n\t// Run the regular expression and split into separate commands\r\n\tconst parts = drawString.split( reg );\r\n\r\n\t// This triggers a move back after drawing the next command\r\n\tlet isReturn = false;\r\n\r\n\t// Store the last cursor - use current angle, not 0\r\n\tlet lastCursor = {\r\n\t\t\"x\": screenData.cursor.x,\r\n\t\t\"y\": screenData.cursor.y,\r\n\t\t\"angle\": screenData.angle\r\n\t};\r\n\r\n\t// Move without drawing\r\n\tlet isBlind = false;\r\n\r\n\tlet isArc = false;\r\n\tlet arcRadius, arcAngle1, arcAngle2;\r\n\tlet scale = 1;\r\n\r\n\tfor( let i = 0; i < parts.length; i++ ) {\r\n\t\tconst drawArgs = parts[ i ].split( /(\\d+)/ );\r\n\r\n\t\tswitch( drawArgs[ 0 ] ) {\r\n\r\n\t\t\t// C - Change Color - Using integer\r\n\t\t\tcase \"C\": {\r\n\t\t\t\tconst colorNum = Number( drawArgs[ 1 ] );\r\n\t\t\t\tscreenData.api.setColor( colorNum );\r\n\t\t\t\tisBlind = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// O - Change Color - Using string\r\n\t\t\tcase \"O\": {\r\n\t\t\t\tconst colorStr = tempColors[ drawArgs[ 1 ] ];\r\n\t\t\t\tscreenData.api.setColor( colorStr );\r\n\t\t\t\tisBlind = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// D - Down\r\n\t\t\tcase \"D\": {\r\n\t\t\t\tconst len = g_utils.getInt( drawArgs[ 1 ], 1 ) * scale;\r\n\t\t\t\tconst angle = g_utils.degreesToRadian( 90 ) + screenData.angle;\r\n\t\t\t\tscreenData.cursor.x += Math.round( Math.cos( angle ) * len );\r\n\t\t\t\tscreenData.cursor.y += Math.round( Math.sin( angle ) * len );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// E - Up and Right\r\n\t\t\tcase \"E\": {\r\n\t\t\t\tlet len = g_utils.getInt( drawArgs[ 1 ], 1 ) * scale;\r\n\t\t\t\tlen = Math.sqrt( len * len + len * len );\r\n\t\t\t\tconst angle = g_utils.degreesToRadian( 315 ) + screenData.angle;\r\n\t\t\t\tscreenData.cursor.x += Math.round( Math.cos( angle ) * len );\r\n\t\t\t\tscreenData.cursor.y += Math.round( Math.sin( angle ) * len );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// F - Down and Right\r\n\t\t\tcase \"F\": {\r\n\t\t\t\tlet len = g_utils.getInt( drawArgs[ 1 ], 1 ) * scale;\r\n\t\t\t\tlen = Math.sqrt( len * len + len * len );\r\n\t\t\t\tconst angle = g_utils.degreesToRadian( 45 ) + screenData.angle;\r\n\t\t\t\tscreenData.cursor.x += Math.round( Math.cos( angle ) * len );\r\n\t\t\t\tscreenData.cursor.y += Math.round( Math.sin( angle ) * len );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// G - Down and Left\r\n\t\t\tcase \"G\": {\r\n\t\t\t\tlet len = g_utils.getInt( drawArgs[ 1 ], 1 ) * scale;\r\n\t\t\t\tlen = Math.sqrt( len * len + len * len );\r\n\t\t\t\tconst angle = g_utils.degreesToRadian( 135 ) + screenData.angle;\r\n\t\t\t\tscreenData.cursor.x += Math.round( Math.cos( angle ) * len );\r\n\t\t\t\tscreenData.cursor.y += Math.round( Math.sin( angle ) * len );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// H - Up and Left\r\n\t\t\tcase \"H\": {\r\n\t\t\t\tlet len = g_utils.getInt( drawArgs[ 1 ], 1 ) * scale;\r\n\t\t\t\tlen = Math.sqrt( len * len + len * len );\r\n\t\t\t\tconst angle = g_utils.degreesToRadian( 225 ) + screenData.angle;\r\n\t\t\t\tscreenData.cursor.x += Math.round( Math.cos( angle ) * len );\r\n\t\t\t\tscreenData.cursor.y += Math.round( Math.sin( angle ) * len );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// L - Left\r\n\t\t\tcase \"L\": {\r\n\t\t\t\tconst len = g_utils.getInt( drawArgs[ 1 ], 1 ) * scale;\r\n\t\t\t\tconst angle = g_utils.degreesToRadian( 180 ) + screenData.angle;\r\n\t\t\t\tscreenData.cursor.x += Math.round( Math.cos( angle ) * len );\r\n\t\t\t\tscreenData.cursor.y += Math.round( Math.sin( angle ) * len );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// R - Right\r\n\t\t\tcase \"R\": {\r\n\t\t\t\tconst len = g_utils.getInt( drawArgs[ 1 ], 1 ) * scale;\r\n\t\t\t\tconst angle = g_utils.degreesToRadian( 0 ) + screenData.angle;\r\n\t\t\t\tscreenData.cursor.x += Math.round( Math.cos( angle ) * len );\r\n\t\t\t\tscreenData.cursor.y += Math.round( Math.sin( angle ) * len );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// U - Up\r\n\t\t\tcase \"U\": {\r\n\t\t\t\tconst len = g_utils.getInt( drawArgs[ 1 ], 1 ) * scale;\r\n\t\t\t\tconst angle = g_utils.degreesToRadian( 270 ) + screenData.angle;\r\n\t\t\t\tscreenData.cursor.x += Math.round( Math.cos( angle ) * len );\r\n\t\t\t\tscreenData.cursor.y += Math.round( Math.sin( angle ) * len );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// P - Paint Exact Match\r\n\t\t\tcase \"P\": {\r\n\t\t\t\tconst colorNum = g_utils.getInt( drawArgs[ 1 ], 0 );\r\n\t\t\t\tconst boundryNumber = g_utils.getInt( drawArgs[ 3 ], null );\r\n\t\t\t\tscreenData.api.paint(\r\n\t\t\t\t\tscreenData.cursor.x, screenData.cursor.y, colorNum, 0, boundryNumber\r\n\t\t\t\t);\r\n\t\t\t\tisBlind = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// S - Scale\r\n\t\t\t/*\r\n\t\t\t\tSet scale factor. n may range from 1 to 255. n is divided by 4 to derive the scale \r\n\t\t\t\tfactor. The scale factor is multiplied by the distances given with U, D, L, R, E, \r\n\t\t\t\tF, G, H, or relative M commands to get the actual distance traveled. The default \r\n\t\t\t\tfor S is 4.\r\n\t\t\t*/\r\n\t\t\tcase \"S\": {\r\n\t\t\t\tconst scaleNum = g_utils.getInt( drawArgs[ 1 ], 4 );\r\n\t\t\t\tscale = scaleNum / 4;\r\n\t\t\t\tisBlind = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// Z - Arc Line\r\n\t\t\tcase \"Z\":\r\n\t\t\t\tarcRadius = g_utils.getInt( drawArgs[ 1 ], 1 );\r\n\t\t\t\tarcAngle1 = g_utils.getInt( drawArgs[ 3 ], 1 );\r\n\t\t\t\tarcAngle2 = g_utils.getInt( drawArgs[ 5 ], 1 );\r\n\t\t\t\tisArc = true;\r\n\t\t\t\tbreak;\r\n\r\n\t\t\t// A - Angle\r\n\t\t\t/*\r\n\t\t\t\tSet angle n. n may range from 0 to 3, where 0 is 0\u00B0, 1 is 90\u00B0, 2 is 180\u00B0, and 3 is\r\n\t\t\t\t270\u00B0. Figures rotated 90\u00B0 or 270\u00B0 are scaled so that they will appear the same size\r\n\t\t\t\tas with 0\u00B0 or 180\u00B0 on a monitor screen with the standard aspect ratio of 4:3.\r\n\t\t\t*/\r\n\t\t\tcase \"A\":\r\n\t\t\t\tscreenData.angle = g_utils.degreesToRadian(\r\n\t\t\t\t\tg_utils.clamp( g_utils.getInt( drawArgs[ 1 ], 0 ), 0, 3 ) * 90\r\n\t\t\t\t);\r\n\t\t\t\tisBlind = true;\r\n\t\t\t\tbreak;\r\n\r\n\t\t\t// TA - T - Turn Angle\r\n\t\t\tcase \"T\":\r\n\t\t\t\tscreenData.angle = g_utils.degreesToRadian(\r\n\t\t\t\t\tg_utils.clamp( g_utils.getInt( drawArgs[ 1 ], 0 ), -360, 360 )\r\n\t\t\t\t);\r\n\t\t\t\tisBlind = true;\r\n\t\t\t\tbreak;\r\n\r\n\t\t\t// M - Move\r\n\t\t\tcase \"M\":\r\n\t\t\t\tscreenData.cursor.x = g_utils.getInt( drawArgs[ 1 ], 1 );\r\n\t\t\t\tscreenData.cursor.y = g_utils.getInt( drawArgs[ 3 ], 1 );\r\n\t\t\t\tisBlind = true;\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tdefault:\r\n\t\t\t\tisBlind = true;\r\n\t\t}\r\n\r\n\t\tif( !isBlind ) {\r\n\t\t\tif( isArc ) {\r\n\t\t\t\tscreenData.api.arc(\r\n\t\t\t\t\tscreenData.cursor.x,\r\n\t\t\t\t\tscreenData.cursor.y,\r\n\t\t\t\t\tarcRadius,\r\n\t\t\t\t\tarcAngle1,\r\n\t\t\t\t\tarcAngle2\r\n\t\t\t\t);\r\n\t\t\t} else {\r\n\t\t\t\tscreenData.api.line(\r\n\t\t\t\t\tlastCursor.x,\r\n\t\t\t\t\tlastCursor.y,\r\n\t\t\t\t\tscreenData.cursor.x,\r\n\t\t\t\t\tscreenData.cursor.y\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tisBlind = false;\r\n\t\tisArc = false;\r\n\r\n\t\tif( isReturn ) {\r\n\t\t\tisReturn = false;\r\n\t\t\tscreenData.cursor.x = lastCursor.x;\r\n\t\t\tscreenData.cursor.y = lastCursor.y;\r\n\t\t\tscreenData.angle = lastCursor.angle;\r\n\t\t}\r\n\r\n\t\tif( drawArgs[ 0 ] === \"N\" ) {\r\n\t\t\tisReturn = true;\r\n\t\t} else {\r\n\t\t\tlastCursor = {\r\n\t\t\t\t\"x\": screenData.cursor.x,\r\n\t\t\t\t\"y\": screenData.cursor.y,\r\n\t\t\t\t\"angle\": screenData.angle\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tif( drawArgs[ 0 ] === \"B\" ) {\r\n\t\t\tisBlind = true;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n", "/**\r\n * Pi.js - Post-FX Module\r\n *\r\n * API for custom post-processing shaders (display and FBO).\r\n *\r\n * @module api/postfx\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport * as g_commands from \"../core/commands.js\";\nimport * as g_screenManager from \"../core/screen-manager.js\";\nimport * as g_renderer from \"../renderer/renderer.js\";\nimport * as g_images from \"./images.js\";\n\r\n/** Next id for shader handles */\r\nlet m_nextShaderId = 0;\r\n\r\n/** Shader handles */\r\nlet m_shaderHandles = new Map();\r\n\r\n\r\n/**************************************************************************************************\r\n * Module Commands\r\n **************************************************************************************************/\r\n\r\n\r\nexport function init( api ) {\r\n\tg_screenManager.addScreenDataItem( \"displayShaderHandle\", null );\r\n\tg_screenManager.addScreenDataItem( \"displayShaderUniforms\", {} );\n\tg_screenManager.addScreenDataItem( \"displayShaderUniformBindings\", {} );\n\tg_screenManager.addScreenDataItem( \"displayShaderTextureResolver\", null );\n\tg_screenManager.addScreenDataItem( \"renderToDisplaySize\", false );\n\tg_screenManager.addScreenPreCleanupFunction( invalidateDisplayShaderScreenSource );\n\tregisterCommands();\n}\n\r\n\r\nfunction registerCommands() {\n\tg_commands.addCommand( \"createShader\", createShader, false, [ \"fragmentSource\", \"uniforms\" ] );\n\tg_commands.addCommand( \"removeShader\", removeShader, false, [ \"shaderHandle\" ] );\n\tg_commands.addCommand( \"getShaderInfo\", getShaderInfo, true, [ \"shaderHandle\" ], true );\n\tg_commands.addCommand( \"applyShader\", applyShader, true, [ \"shaderHandle\", \"uniforms\" ] );\n\tg_commands.addCommand(\r\n\t\t\"setDisplayShader\", setDisplayShader, true, [ \"shaderHandle\", \"uniforms\" ]\r\n\t);\r\n\tg_commands.addCommand(\r\n\t\t\"setDisplayShaderUniforms\", setDisplayShaderUniforms, true, [ \"uniforms\" ]\r\n\t);\r\n}\r\n\r\n\r\n/**************************************************************************************************\r\n * External API Commands\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Create a custom shader from fragment source.\r\n *\r\n * @param {Object} options - Parsed options: fragmentSource (string), uniforms (object | null)\r\n * @param {string} options.fragmentSource - Fragment shader GLSL ES 3.00 source\r\n * @param {Object} [options.uniforms] - Optional: { name: value, ... } default values\r\n * @returns {number} Shader handle id\r\n */\r\nfunction createShader( options ) {\r\n\tconst fragmentSource = options.fragmentSource;\r\n\tconst uniforms = options.uniforms ?? null;\r\n\r\n\tif( typeof fragmentSource !== \"string\" ) {\r\n\t\tconst error = new TypeError( \"createShader: Parameter fragmentSource must be a string.\" );\r\n\t\terror.code = \"INVALID_FRAGMENT_SOURCE\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif( fragmentSource.trim().length === 0 ) {\r\n\t\tconst error = new TypeError( \"createShader: Parameter fragmentSource must not be empty.\" );\r\n\t\terror.code = \"INVALID_FRAGMENT_SOURCE\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Make sure the fragment source is valid GLSL ES 3.00\r\n\tif( !fragmentSource.includes( \"#version 300 es\" ) ) {\r\n\t\tconst error = new TypeError(\r\n\t\t\t\"createShader: Parameter fragmentSource must include #version 300 es.\"\r\n\t\t);\r\n\t\terror.code = \"INVALID_FRAGMENT_SOURCE\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tvalidateUniformMap( uniforms, \"createShader\" );\n\r\n\t// Create shader handle\r\n\tconst handle = {\r\n\t\t\"id\": m_nextShaderId++,\r\n\t\t\"fragmentSource\": fragmentSource,\r\n\t\t\"uniforms\": copyUniforms( uniforms )\n\t};\r\n\tm_shaderHandles.set( handle.id, handle );\r\n\t\r\n\treturn handle.id;\n}\n\n\n/**\n * Validate a public numeric shader id.\n *\n * @param {*} shaderId - Caller-provided shader id\n * @param {string} cmdName - Public command name\n * @returns {number} Valid shader id\n */\nfunction validateShaderId( shaderId, cmdName ) {\n\tif( typeof shaderId !== \"number\" || !Number.isInteger( shaderId ) || shaderId < 0 ) {\n\t\tconst error = new TypeError(\n\t\t\t`${cmdName}: Parameter shaderHandle must be a shader id from createShader.`\n\t\t);\n\t\terror.code = \"INVALID_SHADER_HANDLE\";\n\t\tthrow error;\n\t}\n\treturn shaderId;\n}\n\n\n/**\n * Return global and optional current-screen shader diagnostics.\n *\n * @param {Object|null} screenData - Current screen data, if one exists\n * @param {Object} options - Parsed options: shaderHandle\n * @returns {Object} Shader diagnostic snapshot\n */\nfunction getShaderInfo( screenData, options ) {\n\tconst shaderId = validateShaderId( options.shaderHandle, \"getShaderInfo\" );\n\tconst handle = m_shaderHandles.get( shaderId );\n\tif( !handle ) {\n\t\tconst error = new TypeError( `getShaderInfo: Unknown shader handle id ${shaderId}.` );\n\t\terror.code = \"INVALID_SHADER_HANDLE\";\n\t\tthrow error;\n\t}\n\n\tlet compiledScreenCount = 0;\n\tlet queuedPassCount = 0;\n\tlet displayScreenCount = 0;\n\tfor( const currentScreen of g_screenManager.getAllScreensData() ) {\n\t\tif( currentScreen.customShaders[ shaderId ] ) {\n\t\t\tcompiledScreenCount += 1;\n\t\t}\n\t\tqueuedPassCount += g_renderer.countQueuedShaderPasses( currentScreen, shaderId );\n\t\tif(\n\t\t\tcurrentScreen.displayShaderHandle &&\n\t\t\tcurrentScreen.displayShaderHandle.id === shaderId\n\t\t) {\n\t\t\tdisplayScreenCount += 1;\n\t\t}\n\t}\n\n\tconst info = {\n\t\t\"id\": handle.id,\n\t\t\"fragmentSource\": handle.fragmentSource,\n\t\t\"uniforms\": copyUniforms( handle.uniforms ),\n\t\t\"compiledScreenCount\": compiledScreenCount,\n\t\t\"queuedPassCount\": queuedPassCount,\n\t\t\"displayScreenCount\": displayScreenCount\n\t};\n\tif( screenData ) {\n\t\tconst diagnostics = g_renderer.getCustomShaderDiagnostics( screenData, shaderId );\n\t\tinfo.screen = {\n\t\t\t\"compiled\": diagnostics.compiled,\n\t\t\t\"queuedPassCount\": g_renderer.countQueuedShaderPasses( screenData, shaderId ),\n\t\t\t\"displayActive\": !!screenData.displayShaderHandle &&\n\t\t\t\tscreenData.displayShaderHandle.id === shaderId,\n\t\t\t\"uniforms\": diagnostics.uniforms\n\t\t};\n\t}\n\treturn info;\n}\n\n\n/**\n * Remove a shader and release every cached WebGL program.\n *\n * @param {Object} options - Parsed options: shaderHandle\n * @returns {void}\n */\nfunction removeShader( options ) {\n\tconst shaderId = validateShaderId( options.shaderHandle, \"removeShader\" );\n\tif( !m_shaderHandles.has( shaderId ) ) {\n\t\treturn;\n\t}\n\n\tconst screens = g_screenManager.getAllScreensData();\n\tfor( const screenData of screens ) {\n\t\tif( g_renderer.countQueuedShaderPasses( screenData, shaderId ) > 0 ) {\n\t\t\tg_renderer.flushBatches( screenData );\n\t\t}\n\t}\n\n\tfor( const screenData of screens ) {\n\t\tif(\n\t\t\tscreenData.displayShaderHandle &&\n\t\t\tscreenData.displayShaderHandle.id === shaderId\n\t\t) {\n\t\t\tclearDisplayShader( screenData );\n\t\t}\n\t\tg_renderer.deleteCustomShaderProgram( screenData, shaderId );\n\t}\n\tm_shaderHandles.delete( shaderId );\n}\n\r\n\r\n/**\r\n * Resolve shader handle (id or object) to the full handle object.\r\n *\r\n * @param {number|Object} shaderHandle - Shader handle id or handle object\r\n * @param {string} [cmdName=\"applyShader\"] - Command name for error messages\r\n * @returns {{ id: number, fragmentSource: string, uniforms: Object }} Handle object\r\n */\r\nexport function getShaderHandle( shaderHandle, cmdName ) {\r\n\tif( cmdName == null ) {\r\n\t\tcmdName = \"applyShader\";\r\n\t}\r\n\tif( shaderHandle == null ) {\r\n\t\tconst error = new TypeError( `${cmdName}: Parameter shaderHandle is required.` );\r\n\t\terror.code = \"INVALID_SHADER_HANDLE\";\r\n\t\tthrow error;\r\n\t}\r\n\tif( typeof shaderHandle === \"number\" ) {\r\n\t\tconst handle = m_shaderHandles.get( shaderHandle );\r\n\t\tif( !handle ) {\r\n\t\t\tconst error = new TypeError( `${cmdName}: Unknown shader handle id ${shaderHandle}.` );\r\n\t\t\terror.code = \"INVALID_SHADER_HANDLE\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\treturn handle;\r\n\t}\r\n\tif(\r\n\t\ttypeof shaderHandle === \"object\" && \"id\" in shaderHandle && \"fragmentSource\" in shaderHandle\r\n\t) {\r\n\t\treturn shaderHandle;\r\n\t}\r\n\tconst error = new TypeError(\r\n\t\t`${cmdName}: Parameter shaderHandle must be a shader id or handle from createShader.`\r\n\t);\r\n\terror.code = \"INVALID_SHADER_HANDLE\";\r\n\tthrow error;\r\n}\r\n\r\n\r\n/**\r\n * Shallow-copy a caller uniform object so later mutation does not leak.\r\n *\r\n * @param {Object|null} uniforms - Caller-provided uniforms\r\n * @returns {Object} New object (empty if none)\r\n */\r\nfunction copyUniforms( uniforms ) {\n\tif( !uniforms || typeof uniforms !== \"object\" ) {\n\t\treturn {};\n\t}\n\tconst copy = {};\n\tfor( const name of Object.keys( uniforms ) ) {\n\t\tconst value = uniforms[ name ];\n\t\tif( Array.isArray( value ) ) {\n\t\t\tcopy[ name ] = value.slice();\n\t\t} else if(\n\t\t\tvalue instanceof Float32Array || value instanceof Int32Array ||\n\t\t\tvalue instanceof Uint32Array\n\t\t) {\n\t\t\tcopy[ name ] = value.slice();\n\t\t} else {\n\t\t\tcopy[ name ] = value;\n\t\t}\n\t}\n\treturn copy;\n}\n\nfunction mergeUniforms( defaults, overrides ) {\n\tconst merged = copyUniforms( defaults );\n\tconst overrideCopy = copyUniforms( overrides );\n\tfor( const name of Object.keys( overrideCopy ) ) {\n\t\tmerged[ name ] = overrideCopy[ name ];\n\t}\n\treturn merged;\n}\n\nfunction validateUniformMap( uniforms, cmdName ) {\n\tif( uniforms != null && ( typeof uniforms !== \"object\" || Array.isArray( uniforms ) ) ) {\n\t\tconst error = new TypeError( `${cmdName}: Parameter uniforms must be an object.` );\n\t\terror.code = \"INVALID_UNIFORMS\";\n\t\tthrow error;\n\t}\n}\n\nfunction resolveSamplerSource( screenData, input, cmdName ) {\n\tlet source;\n\ttry {\n\t\tsource = g_images.getImageFromRawInput( input, cmdName );\n\t} catch( error ) {\n\t\tif( error.code === \"INVALID_NAME\" ) {\n\t\t\tconst uniformError = new TypeError( `${cmdName}: Invalid sampler2D image input.` );\n\t\t\tuniformError.code = \"INVALID_UNIFORM_VALUE\";\n\t\t\tthrow uniformError;\n\t\t}\n\t\tthrow error;\n\t}\n\tconst sourceData = g_screenManager.screenCanvasMap.get( source );\n\tif( sourceData === screenData ) {\n\t\tconst error = new Error( `${cmdName}: A shader cannot sample its destination screen.` );\n\t\terror.code = \"FRAMEBUFFER_FEEDBACK_LOOP\";\n\t\tthrow error;\n\t}\n\treturn source;\n}\n\nfunction normalizeUniforms( screenData, cache, uniforms, cmdName ) {\n\treturn g_renderer.normalizeCustomUniforms(\n\t\tscreenData.gl, cache, uniforms, cmdName,\n\t\t( input ) => resolveSamplerSource( screenData, input, cmdName )\n\t);\n}\n\nfunction getSamplerTextureMap( screenData, bindings ) {\n\tconst textures = new Map();\n\tfor( const binding of Object.values( bindings ) ) {\n\t\tif( binding.info.family !== \"sampler\" ) {\n\t\t\tcontinue;\n\t\t}\n\t\tfor( const source of binding.sources ) {\n\t\t\tif( !textures.has( source ) ) {\n\t\t\t\ttextures.set( source, g_renderer.getWebGL2Texture( screenData, source ) );\n\t\t\t}\n\t\t}\n\t}\n\treturn textures;\n}\n\nfunction retainSamplerSources( uniforms, bindings ) {\n\tconst retained = copyUniforms( uniforms );\n\tfor( const name of Object.keys( bindings ) ) {\n\t\tconst binding = bindings[ name ];\n\t\tif( binding.info.family !== \"sampler\" ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif( binding.sources.length === 1 ) {\n\t\t\tretained[ name ] = binding.sources[ 0 ];\n\t\t} else {\n\t\t\tretained[ name ] = binding.sources.slice();\n\t\t}\n\t}\n\treturn retained;\n}\n\n/**\n * Clear a persistent display shader and restore the default presentation path.\n *\n * @param {Object} screenData - Screen data object\n * @returns {void}\n */\nfunction clearDisplayShader( screenData ) {\n\tscreenData.displayShaderHandle = null;\n\tscreenData.displayShaderUniforms = {};\n\tscreenData.displayShaderUniformBindings = {};\n\tscreenData.displayShaderTextureResolver = null;\n\tscreenData.renderToDisplaySize = false;\n\tg_renderer.flushBatches( screenData );\n\tg_screenManager.refreshScreenSize( screenData, true );\n}\n\n/**\n * Invalidate display shaders and cached textures that reference a screen being removed.\n *\n * @param {Object} sourceData - Screen data object being removed\n * @returns {void}\n */\nfunction invalidateDisplayShaderScreenSource( sourceData ) {\n\tconst source = sourceData.canvas;\n\tfor( const screenData of g_screenManager.getAllScreensData() ) {\n\t\tif( screenData === sourceData ) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst usesSource = Object.values(\n\t\t\tscreenData.displayShaderUniformBindings ?? {}\n\t\t).some( ( binding ) => {\n\t\t\treturn binding.info.family === \"sampler\" && binding.sources.includes( source );\n\t\t} );\n\t\tif( usesSource ) {\n\t\t\tclearDisplayShader( screenData );\n\t\t}\n\t\tg_renderer.deleteWebGL2Texture( screenData, source );\n\t}\n}\n\r\n\r\n/**\r\n * Queue custom FBO shader at current point in draw order (does not flush).\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Parsed options: shaderHandle (number|Object), uniforms (object | null)\r\n * @returns {void}\r\n */\r\nfunction applyShader( screenData, options ) {\n\tconst handle = getShaderHandle( options.shaderHandle );\n\tvalidateUniformMap( options.uniforms, \"applyShader\" );\n\tconst overrides = copyUniforms( options.uniforms );\n\tconst merged = mergeUniforms( handle.uniforms, overrides );\n\tconst cache = g_renderer.validateCustomShaderProgram( screenData, handle, \"applyShader\" );\n\tconst bindings = normalizeUniforms( screenData, cache, merged, \"applyShader\" );\n\tconst samplerTextures = getSamplerTextureMap( screenData, bindings );\n\tg_renderer.prepareShaderBatch( screenData, handle, bindings, samplerTextures );\n\tg_renderer.setImageDirty( screenData );\n}\r\n\r\n\r\n/**\r\n * Set or clear the display shader. Always invalidates presentation.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Parsed options: shaderHandle, uniforms\r\n * @returns {void}\r\n */\r\nfunction setDisplayShader( screenData, options ) {\n\tif( options.shaderHandle == null ) {\n\t\tclearDisplayShader( screenData );\n\t\treturn;\n\t}\n\r\n\tvalidateUniformMap( options.uniforms, \"setDisplayShader\" );\n\n\tconst handle = getShaderHandle( options.shaderHandle, \"setDisplayShader\" );\n\tconst cache = g_renderer.validateCustomShaderProgram(\n\t\tscreenData, handle, \"setDisplayShader\"\n\t);\n\tconst merged = mergeUniforms( handle.uniforms, options.uniforms );\n\tconst bindings = normalizeUniforms( screenData, cache, merged, \"setDisplayShader\" );\n\tgetSamplerTextureMap( screenData, bindings );\n\tscreenData.displayShaderHandle = handle;\n\tscreenData.displayShaderUniforms = retainSamplerSources( merged, bindings );\n\tscreenData.displayShaderUniformBindings = bindings;\n\tscreenData.displayShaderTextureResolver = ( source ) => {\n\t\treturn g_renderer.getWebGL2Texture( screenData, source );\n\t};\n\tscreenData.renderToDisplaySize = !screenData.isOffscreen;\r\n\tg_renderer.flushBatches( screenData );\r\n\tg_screenManager.refreshScreenSize( screenData, true );\r\n}\r\n\r\n\r\n/**\r\n * Merge persistent display-shader uniform overrides and re-present.\r\n *\r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Parsed options: uniforms\r\n * @returns {void}\r\n */\r\nfunction setDisplayShaderUniforms( screenData, options ) {\r\n\tconst incoming = options.uniforms;\r\n\tvalidateUniformMap( incoming, \"setDisplayShaderUniforms\" );\n\n\tconst values = mergeUniforms( screenData.displayShaderUniforms, incoming );\n\tlet bindings = screenData.displayShaderUniformBindings;\n\tif( screenData.displayShaderHandle ) {\n\t\tconst cache = g_renderer.validateCustomShaderProgram(\n\t\t\tscreenData, screenData.displayShaderHandle, \"setDisplayShaderUniforms\"\n\t\t);\n\t\tbindings = normalizeUniforms(\n\t\t\tscreenData, cache, values, \"setDisplayShaderUniforms\"\n\t\t);\n\t\tgetSamplerTextureMap( screenData, bindings );\n\t}\n\tscreenData.displayShaderUniforms = retainSamplerSources( values, bindings );\n\tscreenData.displayShaderUniformBindings = bindings;\n\r\n\tif( screenData.displayShaderHandle ) {\r\n\t\tg_screenManager.presentCurrentScreen( screenData );\r\n\t}\r\n}\r\n", "/**\r\n * Pi.js - Font Module\r\n * \r\n * Font loading, management, and character data for text rendering.\r\n * Supports bitmap fonts from images only (no base32-encoded data).\r\n * \r\n * @module text/fonts\r\n */\r\n\r\n// TODO-LATER: Add remove font command that removes the font and deletes any WebGL textures\r\n\r\n\"use strict\";\r\n\r\nimport * as g_utils from \"../core/utils.js\";\r\nimport * as g_commands from \"../core/commands.js\";\r\nimport * as g_screenManager from \"../core/screen-manager.js\";\r\nimport * as g_renderer from \"../renderer/renderer.js\";\r\nimport * as g_print from \"./print.js\";\r\n\r\nimport g_fnt6x6 from \"./fonts/font-6x6.webp\";\r\nimport * as g_fnt6x8 from \"./fonts/font-6x8.js\";\r\nimport g_fnt8x8 from \"./fonts/font-8x8.webp\";\r\nimport g_fnt8x14 from \"./fonts/font-8x14.webp\";\r\nimport g_fnt8x16 from \"./fonts/font-8x16.webp\";\r\n\r\nconst m_fontMap = new Map();\r\nlet m_defaultFontId = null;\r\nlet m_nextFontId = 0;\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Initialization\r\n ***************************************************************************************************/\r\n\r\n\r\n/**\r\n * Initialize font module\r\n * \r\n * @param {Object} api - The main Pi.js API object\r\n * @returns {void}\r\n */\r\nexport function init( api ) {\r\n\tg_screenManager.addScreenDataItem( \"font\", null );\r\n\t\r\n\tregisterCommands( api );\r\n\tloadDefaultFonts();\r\n\r\n\t// Set the font when a screen is initialized\r\n\tg_screenManager.addScreenInitFunction(\r\n\t\t( screenData ) => setFont( screenData, { \"fontId\": m_defaultFontId } )\r\n\t);\r\n}\r\n\r\n/**\r\n * Register font commands\r\n * \r\n * @param {Object} api - The main Pi.js API object\r\n * @returns {void}\r\n */\r\nfunction registerCommands( api ) {\r\n\r\n\t// Register non-screen commands\r\n\tg_commands.addCommand(\r\n\t\t\"loadFont\", loadFont, false,\r\n\t\t[ \"src\", \"width\", \"height\", \"margin\", \"charset\" ]\r\n\t);\r\n\tg_commands.addCommand( \"setDefaultFont\", setDefaultFont, false, [ \"fontId\" ] );\r\n\tg_commands.addCommand( \"getAvailableFonts\", getAvailableFonts, false, [] );\r\n\r\n\t// Register screen commands\r\n\tg_commands.addCommand( \"setChar\", setChar, true, [ \"charCode\", \"data\" ] );\r\n\tg_commands.addCommand( \"setFont\", setFont, true, [ \"fontId\" ] );\r\n}\r\n\r\n\r\n\r\n// Load the default fonts\r\nfunction loadDefaultFonts() {\r\n\r\n\t// 6x6 font\r\n\tloadFont( {\r\n\t\t\"src\": g_fnt6x6.data,\r\n\t\t\"width\": 6,\r\n\t\t\"height\": 6,\r\n\t\t\"margin\": 0,\r\n\t\t\"charset\": null\r\n\t} );\r\n\tg_fnt6x6.data = \"\";\r\n\r\n\t// 6x8 font - default font\r\n\tm_defaultFontId = loadFont( {\r\n\t\t\"src\": g_fnt6x8.getFontImage(),\r\n\t\t\"width\": 6,\r\n\t\t\"height\": 8,\r\n\t\t\"margin\": 0,\r\n\t\t\"charset\": null\r\n\t} );\r\n\r\n\t// 8x8 font\r\n\tloadFont( {\r\n\t\t\"src\": g_fnt8x8.data,\r\n\t\t\"width\": 8,\r\n\t\t\"height\": 8,\r\n\t\t\"margin\": 0,\r\n\t\t\"charset\": null\r\n\t} );\r\n\tg_fnt8x8.data = \"\";\r\n\r\n\t// 8x14 font\r\n\tloadFont( {\r\n\t\t\"src\": g_fnt8x14.data,\r\n\t\t\"width\": 8,\r\n\t\t\"height\": 14,\r\n\t\t\"margin\": 0,\r\n\t\t\"charset\": null\r\n\t} );\r\n\tg_fnt8x14.data = \"\";\r\n\r\n\t// 8x16 font\r\n\tloadFont( {\r\n\t\t\"src\": g_fnt8x16.data,\r\n\t\t\"width\": 8,\r\n\t\t\"height\": 16,\r\n\t\t\"margin\": 0,\r\n\t\t\"charset\": null\r\n\t} );\r\n\tg_fnt8x16.data = \"\";\r\n}\r\n\r\n\r\n/**************************************************************************************************\r\n * Load Font Command\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Load font from image source\r\n * \r\n * @param {Object} options - Load options\r\n * @param {string|HTMLImageElement|HTMLCanvasElement|OffscreenCanvas} options.src - Font image\r\n * @param {number} options.width - Character width in pixels\r\n * @param {number} options.height - Character height in pixels\r\n * @param {number} options.margin - Individual character cell width in pixels\r\n * @param {Array<number>|string} [options.charset] - Character set array or string\r\n * @returns {number} Font ID\r\n */\r\nfunction loadFont( options ) {\r\n\tconst fontSrc = options.src;\r\n\tconst width = g_utils.getInt( options.width, null );\r\n\tconst height = g_utils.getInt( options.height, null );\r\n\tconst margin = g_utils.getInt( options.margin, 0 );\r\n\tconst cellWidth = width + margin * 2;\r\n\tconst cellHeight = height + margin * 2;\r\n\tlet charset = options.charset;\r\n\r\n\tif( width === null || height === null ) {\r\n\t\tconst error = new TypeError( \"loadFont: width and height must be integers.\" );\r\n\t\terror.code = \"INVALID_DIMENSIONS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Default charset to 0 to 255\r\n\tif( !charset ) {\r\n\t\tcharset = [];\r\n\t\tfor( let i = 0; i < 256; i += 1 ) {\r\n\t\t\tcharset.push( i );\r\n\t\t}\r\n\t}\r\n\r\n\tif( !( Array.isArray( charset ) || typeof charset === \"string\" ) ) {\r\n\t\tconst error = new TypeError( \"loadFont: charset must be an array or a string.\" );\r\n\t\terror.code = \"INVALID_CHARSET\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Convert charset to array of integers (character codes)\r\n\tif( typeof charset === \"string\" ) {\r\n\t\tconst temp = [];\r\n\t\tfor( let i = 0; i < charset.length; i += 1 ) {\r\n\t\t\ttemp.push( charset.charCodeAt( i ) );\r\n\t\t}\r\n\t\tcharset = temp;\r\n\t}\r\n\r\n\t// Build chars lookup map\r\n\tconst chars = {};\r\n\tfor( let i = 0; i < charset.length; i += 1 ) {\r\n\t\tchars[ charset[ i ] ] = i;\r\n\t}\r\n\r\n\t// Create font object\r\n\tconst font = {\r\n\t\t\"id\": m_nextFontId,\r\n\t\t\"width\": width,\r\n\t\t\"height\": height,\r\n\t\t\"margin\": margin,\r\n\t\t\"cellWidth\": cellWidth,\r\n\t\t\"cellHeight\": cellHeight,\r\n\t\t\"chars\": chars,\r\n\t\t\"charset\": charset,\r\n\t\t\"image\": null,\r\n\t\t\"atlasWidth\": null,\r\n\t\t\"atlasHeight\": null\r\n\t};\r\n\r\n\t// Add to fonts array\r\n\tm_fontMap.set( font.id, font );\r\n\tm_nextFontId += 1;\r\n\r\n\t// Load from image source\r\n\tloadFontFromImage( fontSrc, font );\r\n\r\n\treturn font.id;\r\n}\r\n\r\n/**\r\n * Load font from image source\r\n * \r\n * @param {string|HTMLImageElement} fontSrc - Font image source\r\n * @param {Object} font - Font object to populate\r\n * @returns {void}\r\n */\r\nfunction loadFontFromImage( fontSrc, font ) {\r\n\tlet img;\r\n\r\n\tif( typeof fontSrc === \"string\" ) {\r\n\r\n\t\t// Create a new image\r\n\t\timg = new Image();\r\n\r\n\t\t// Increment wait count\r\n\t\tg_commands.wait();\r\n\r\n\t\timg.onload = function() {\r\n\t\t\tfont.image = img;\r\n\t\t\tfont.atlasWidth = img.width;\r\n\t\t\tfont.atlasHeight = img.height;\r\n\t\t\tg_commands.done();\r\n\t\t};\r\n\r\n\t\timg.onerror = function( err ) {\r\n\t\t\tconsole.error( \"loadFont: Unable to load image for font.\" );\r\n\t\t\tg_commands.done();\r\n\t\t};\r\n\r\n\t\t// Set source after handlers\r\n\t\timg.src = fontSrc;\r\n\t} else if(\r\n\t\tfontSrc instanceof HTMLImageElement || fontSrc instanceof HTMLCanvasElement ||\r\n\t\t( typeof OffscreenCanvas !== \"undefined\" && fontSrc instanceof OffscreenCanvas )\r\n\t) {\r\n\r\n\t\t// Use image element directly\r\n\t\tfont.image = fontSrc;\r\n\t\tfont.atlasWidth = fontSrc.width;\r\n\t\tfont.atlasHeight = fontSrc.height;\r\n\t} else {\r\n\t\tconst error = new TypeError( \"loadFont: fontSrc must be a string or Image element.\" );\r\n\t\terror.code = \"INVALID_FONT_SRC\";\r\n\t\tthrow error;\r\n\t}\r\n}\r\n\r\n\r\n/**************************************************************************************************\r\n * Set Defaault Font Commands\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Set default font\r\n * \r\n * @param {Object} options - Options\r\n * @param {number} options.fontId - Font ID\r\n * @returns {void}\r\n */\r\nfunction setDefaultFont( options ) {\r\n\tconst fontId = g_utils.getInt( options.fontId, null );\r\n\r\n\tif( fontId === null || !m_fontMap.has( fontId ) ) {\r\n\t\tconst error = new RangeError( \"setDefaultFont: invalid fontId\" );\r\n\t\terror.code = \"INVALID_FONT_ID\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tm_defaultFontId = fontId;\r\n}\r\n\r\n/**\r\n * Set font for screen\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Options\r\n * @param {number} options.fontId - Font ID or CSS font string\r\n * @returns {void}\r\n */\r\nexport function setFont( screenData, options ) {\r\n\tconst fontId = g_utils.getInt( options.fontId, null );\r\n\r\n\t// TODO-LATER: setFont should also accept a font object returned by getAvailableFonts\r\n\t\r\n\tif( fontId === null || !m_fontMap.has( fontId ) ) {\r\n\t\tconst error = new RangeError(\r\n\t\t\t\"setFont: Parameter fontId must be an integer and an index in the available fonts.\"\r\n\t\t);\r\n\t\terror.code = \"INVALID_FONT_ID\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tconst font = m_fontMap.get( fontId );\r\n\r\n\t// Get or create texture for font image if it's loaded\r\n\tif( font.image ) {\r\n\t\tg_renderer.getWebGL2Texture( screenData, font.image );\r\n\t}\r\n\r\n\t// Set the screenData font\r\n\tscreenData.font = font;\r\n\r\n\t// Update print cursor dimensions\r\n\tg_print.updatePrintCursorDimensions( screenData );\r\n}\r\n\r\n\r\n/**************************************************************************************************\r\n * Get Available Font Command\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Get available fonts\r\n * \r\n * @returns {Array<Object>} Array of font info objects\r\n */\r\nfunction getAvailableFonts() {\r\n\tconst fonts = [];\r\n\tfor( const [ fontId, font ] of m_fontMap ) {\r\n\t\tfonts.push( {\r\n\t\t\t\"id\": font.id,\r\n\t\t\t\"width\": font.width,\r\n\t\t\t\"height\": font.height\r\n\t\t} );\r\n\t}\r\n\treturn fonts;\r\n}\r\n\r\n\r\n/**************************************************************************************************\r\n * Get Available Font Command\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Set custom character bitmap by drawing into a temporary Canvas2D copy of the\r\n * font atlas, then updating the existing WebGL texture.\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Options\r\n * @param {number|string} options.charCode - Character code or single-character string\r\n * @param {Array<Array<number>>|string} options.data - Character bitmap (2D array or hex string)\r\n * @returns {void}\r\n */\r\nfunction setChar( screenData, options ) {\r\n\tlet charCode = options.charCode;\r\n\tlet data = options.data;\r\n\r\n\tconst font = screenData.font;\r\n\tif( !font || !font.image ) {\r\n\t\tconst error = new Error( \"setChar: No font image loaded on this screen.\" );\r\n\t\terror.code = \"NO_FONT_IMAGE\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Convert string to char code\r\n\tif( typeof charCode === \"string\" ) {\r\n\t\tcharCode = charCode.charCodeAt( 0 );\r\n\t} else {\r\n\t\tcharCode = g_utils.getInt( charCode, null );\r\n\t\tif( charCode === null ) {\r\n\t\t\tconst error = new TypeError( \"setChar: charCode must be an integer or a string\" );\r\n\t\t\terror.code = \"INVALID_CHAR_CODE\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t}\r\n\r\n\t// Normalize data to 2D array\r\n\tif( !Array.isArray( data ) ) {\r\n\t\tif( typeof data === \"string\" ) {\r\n\t\t\tdata = g_utils.hexToData( data, font.width, font.height );\r\n\t\t} else {\r\n\t\t\tconst error = new TypeError( \"setChar: data must be a 2D array or an encoded string\" );\r\n\t\t\terror.code = \"INVALID_DATA\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t}\r\n\r\n\t// Validate dimensions\r\n\tif( data.length !== font.height ) {\r\n\t\tconst error = new RangeError(\r\n\t\t\t`setChar: data height (${data.length}) must match font height (${font.height})`\r\n\t\t);\r\n\t\terror.code = \"INVALID_DATA_HEIGHT\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tfor( let i = 0; i < data.length; i++ ) {\r\n\t\tif( !Array.isArray( data[ i ] ) || data[ i ].length !== font.width ) {\r\n\t\t\tconst error = new RangeError(\r\n\t\t\t\t`setChar: data width at row ${i} must match font width (${font.width})`\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_DATA_WIDTH\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t}\r\n\r\n\t// Locate character cell in atlas\r\n\tconst charIndex = font.chars[ charCode ];\r\n\tif( charIndex === undefined ) {\r\n\t\tconst error = new RangeError( \"setChar: character not in font character set\" );\r\n\t\terror.code = \"CHAR_NOT_IN_FONT\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tconst columns = Math.floor( font.atlasWidth / font.cellWidth );\r\n\tconst cellX = ( charIndex % columns ) * font.cellWidth;\r\n\tconst cellY = Math.floor( charIndex / columns ) * font.cellHeight;\r\n\r\n\t// Inner glyph bounds\r\n\tconst sx = cellX + font.margin;\r\n\tconst sy = cellY + font.margin;\r\n\tconst sw = font.width;\r\n\tconst sh = font.height;\r\n\r\n\t// Create a Uint8ClampedArray for the glyph sub-image pixel data\r\n\tconst buf = new Uint8ClampedArray( sw * sh * 4 );\r\n\tfor( let y = 0; y < sh; y += 1 ) {\r\n\t\tfor( let x = 0; x < sw; x += 1 ) {\r\n\t\t\tconst on = data[ y ][ x ] ? 1 : 0;\r\n\t\t\tif( on ) {\r\n\t\t\t\tconst i = ( y * sw + x ) * 4;\r\n\t\t\t\tbuf[ i + 0 ] = 255;\r\n\t\t\t\tbuf[ i + 1 ] = 255;\r\n\t\t\t\tbuf[ i + 2 ] = 255;\r\n\t\t\t\tbuf[ i + 3 ] = 255;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Update only the glyph region in the GPU texture\r\n\tg_renderer.updateWebGL2TextureSubImage( screenData, font.image, buf, sw, sh, sx, sy );\r\n}\r\n", "export default { \"data\": \"data:image/webp;base64,UklGRs4EAABXRUJQVlA4WAoAAAAYAAAAfwEAFwAAVlA4TNIDAAAvf8EFEA8w//M///Mf8KA+///atl3fR/IvyS+ZrpU99are+RzJUZnkMltW7CVl+fpsWO6j3MnDwEB1DCoFyoxjZgbTmJnR3rxHZSbfwXqL6L/Ctm0bZnT3EOAHLgk/TKsYd1xe4qlTaR2Qugw97NaclAWQcmd9O9/v4LKgmmkpFzwZZiKWWtLcuqPhbfXt7ihvFa5Av7D+QRBFBpZO8Aa2StrmnBTr1YDz73w+XcY0K3/lwOfGIFads3lX6lgHWMOjg+RMq04dFTU355dxdWAhVxybKSNoSRXbr3TZpVKm4rx4iCE5CRCH6docxefKIdYLK2d6io6JCKYqC0a4OJHu2NVzugswenKgXoZa1F309WWdXFaimoQmeePnjB/TUs9Wrkw6V3JHeRyfCBbVQXCN4AG482ZP8YQruSU24nZ3funbyvrD//ocCXAaeAsEPL0WSdTl7Ur9Zom62HCsbf2DitNWHhdqnLVBxm42+eZn3VGe/q1yD0dsYm/NXS8+aO4u0MPFDz2sL3Zs/ZsFtYxmeI4AufqdhVYFhj1+rhAasld53CZDwNnR4eXW5/KGY49viA0L2MGI4OVFAqulYWtzuxJV7VFzuRtMO3iBJnmR2HsLZs/wpa73+98ccQcZHaHdhvcvH18LfBwRWzTlsGGP8JFgO91gCLkmkT2P/xuXAQDToFV9UvWh5QCAvTHpcNoMepUeWUkw7VzfPM/XE/b+pZKoFCuaAGEYbP7JS3UGIUaIg9UMZGiDBqcmvvfCUFfe99S5rge9YTbARwsmhVKjzdPONH3QzHweum/wGURz03ryNLFMTCxT5i4dvvFB9p1vGgb8KdamW3tqAAgOuf/B12WqMzQU4OPYqwR4Epm7mScB5cMV/s0vdr5w7rrYEZXIczf/02EXR3KBSht4+31lXyRnicfa9xfT70fKZi3+Y6jr1MSnvumc9Oeg2jKCPgS4qu0PmsOfh25pPC65U8+N+Xh5T35aT175sGk4x08ofaLuPyL2ZNUyN5ZSoNyoHqahMCBRVkLUEDRG0GQBBoVB2cvW2isoMo2AJ38BOcYP0CC4qo+rLJn0QOn0A6VvBhrTBhj+Kn0K48SrG4WG/WtUBHiBGC4s5Ug1gzAgQKWx/2mfDT8fbWnbPLizbWTrO90SKYzgWEnIMOdL+VLvF9X8x0/RTOmD7tI7a5mPFCOWkTcLN+4vzkWAJwRISUKagVVZzLrye3mRWsxMWxT2W5fLPhtubNaljcrc1NJW/x/TSMgARmx9v5qBmsoT6Az0MK3SJ6FRljwTu5CaazlA2BGACgBFWElG1gAAAElJKgAIAAAABgASAQMAAQAAAAEAAAAaAQUAAQAAAFYAAAAbAQUAAQAAAF4AAAAoAQMAAQAAAAIAAAAxAQIAEAAAAGYAAABphwQAAQAAAHYAAAAAAAAAYAAAAAEAAABgAAAAAQAAAFBhaW50Lk5FVCA1LjEuOQAFAACQBwAEAAAAMDIzMAGgAwABAAAAAQAAAAKgBAABAAAAgAEAAAOgBAABAAAAGAAAAAWgBAABAAAAuAAAAAAAAAACAAEAAgAEAAAAUjk4AAIABwAEAAAAMDEwMAAAAAA=\" };", "/**\r\n * Pi.js - Font 6x8 Module\r\n * \r\n * Default bitmap font for Pi.js with 6x8 pixel character glyphs in 8x10 character cells.\r\n * Uses a custom base32-encoded format for synchronous font loading, enabling immediate text\r\n * rendering without requiring the $.ready() command to wait for font assets to load.\r\n * \r\n * This font is unique among Pi.js fonts in that it uses base32 encoding instead of Base64\r\n * WebP encoding. While WebP offers better compression and ease of use, the base32 encoding\r\n * allows the font data to be embedded directly in JavaScript, enabling synchronous loading\r\n * and making it ideal for simple \"Hello World\" examples that don't require async asset\r\n * management.\r\n * \r\n * The font provides a complete ASCII character set (0-255) with retro-style bitmap glyphs.\r\n * Characters are 6 pixels wide and 8 pixels tall, with each character occupying an 8x10\r\n * pixel cell to provide spacing between characters.\r\n * \r\n * @module text/fonts/font-6x8\r\n * @see /tools/fonts/gen-fonts.js - Font encoding script\r\n * \r\n * @example\r\n * // Font is automatically loaded as the default font on initialization\r\n * $.print( \"Hello, World!\" );\r\n */\r\n\r\n// Font 6x8\r\n// String length: 2431\r\n// Compression: 48x36\r\nconst m_font6x8 = {\r\n\t\"byteSize\": 48,\r\n\t\"byteBase\": 36,\r\n\t\"width\": 6,\r\n\t\"height\": 8,\r\n\t\"margin\": 0,\r\n\t\"str\": \"0,1blc8udu8u,1cbkhzwsm6,wpp1xfvgg,coebolreo,d5nukh2cc,coe2eccv0,65jplhc,2rrpnxyccf,0,0,azkg0jpqw,j5ihd7hxo,nly3soshc,nly42td40,dkvajkdak,1f2tcd2lts,39po4vukg,d6e29q3uw,voa3n9udc,1dd8ay5r40,majymyen0,4r8g0,d6e2i2i4f,d6ebp7j7k,co4b4mebk,7307h2ww,78xcoo3k,80mu96o,g90j3o5c,74q25kao,1j83fxkao,0,d5xai464g,vo9y0dkao,voutnk5q8,d7qk1tfr4,18caako74,cyn4y7kow,co7x9kqgw,cvgmd4740,p51ihjmyo,hnt6v75s,3khmlszk,pow,8bnthc,pog,wl5log0,18hslmrwg0,d2kxm9lkw,18halx058g,18haltkhkw,6japxtny8,2pg5ex9zwg,j3ykqif40,2phicbtjpc,18hqina874,18hqj26t4w,74i0nugw,74i0nuhc,6fqfmdlog,ukzeakg,p51hxkg74,18hajmifpc,18hwjobyf4,cyzwjl3ls,2lzffaao74,j5phy2vpc,2lzfcieqdc,2p3nb23s74,2p3nb23lkw,j5phz0lfk,1huhdyxjsw,17ukqfasqo,lxadcq0ow,26fz67fm4g,2fp5guls3k,1ic4kdfc74,1i8m9a9g8w,18hqkb7shs,2lzff9z94w,18hqkb8hs3,2lzffb8jnk,18hpizqeio,2pokva2znk,1huh678wsg,1huh677nk0,1huh8gfaww,1hi03e73pc,1hua29iwow,2phicbv6v4,2g3ele8o3k,1eo82xhoow,2fi0wks268,cyzw9tpmo,1r,co2068kjk,dtwj5q8,23860tetq8,e2shedc,9eixrx874,e2x5s74,j5hseuwhs,d3a881o,23881h7i4g,chbdmk9hc,34buepwv0,23870bnr7k,11m2zty1vk,pz8ndz4,m3d2d8g,e2ssmww,tqjd4qg,d3uih3i,qu79kao,f1qczy8,pcts9aups,h1ch2f4,h1cfgn4,h3ln400,gxcj3i8,h1cgbzw,um4hny8,9jvh9ef7k,co3z8madc,2311eu3da8,t4svfdzi8,7aoozlhc,18hpkro330,vkry6glc,ipvap80sg,18hleduav4,1h0inglklc,11faaz7pfk,chbclspz4,e28hnkc,18hnlvwutc,1h0kuyo4jk,11fciha9ds,1k4rjs1hj4,18hlfeludc,11fabzz8xs,1h7hguv81s,co0929o5c,9dlbfia9s,orcjkhs,mbrplsz28,cyj2ztqm8,ttkqcjcw,p4zq8wp34,cyj4nraww,p4zrwu9ds,ttme9pr0,1h7hgqgmww,1h0ntdz280,cof2w6djc,j5hsewhkw,1hikteekn4,2m32k36f3m,iyd2l9grc,ipt375gu8,ipt47x0cg,6fiigughs,3mhmfvgg,15lstet6kg,15gjbpd9xc,18jink6l1c,12b0vaw3k0,ch3jttxc0,hcdfk0,h7m8lc,tc5on8j33,tc4p4v62q,e18f6vi8,91vaa29s,zcpsr7r4,rdwjrp3dw,xrpq1jqei,2cwu2vechn,co41gj1fs,co41o0qh4,corq1de6g,fu5215hu2,9p8y2,row8vm0,fuso6leh6,fu51tnssq,ulsat8q,fuso76zgg,fu521r2tc,corq1cohs,8rcw8,co41hlnnk,co41p3cow,9uoso,co41hmdc8,9tz40,co41p42dk,co7hskgso,fu51ttf2i,fu5j1pts0,7gmtnka,fut5enfgg,v2zr98q,fu5j148sq,v30cu80,fut5e1uh6,cov45hcsg,fu521wp34,v30djwo,9uv7u,fu51uf01s,co7hsjr40,7gnfy88,2d66i,fu521xl6y,cov6detjc,co41o00sg,2czrc,2rrvthnxtr,9zldr,2gosa7pa2g,b33j9ynrb,2rrvt7ocg0,cnr79s0,p16ep15s,1iubfwjy8,rrfz0t4w,2phoaj5qbk,f408g74,g19nt3xc,mg0a7ocg,2ov1ky6o8u,j5q8b5xc0,j5pzx5vpc,m7xcjszuo,geqgaku8,1mantcco0,j3ykq5kw0,18hqkb7ssg,r6vxlclc,couodj5hc,ckirtofwg,cvghtiikg,9kr8exk3s,co41glw60,j00j709hc,mfz9m9s0,j5ifndeyo,3dqjuo,1vf9c,b0fboebd8,2g6yvj277k,12an04etc0,e13wsn4,0\"\r\n};\r\n\r\nexport function getFontImage() {\r\n\tconst charWidth = m_font6x8.width;\r\n\tconst charHeight = m_font6x8.height;\r\n\tconst margin = m_font6x8.margin;\r\n\tconst cellWidth = m_font6x8.width + margin * 2;\r\n\tconst cellHeight = m_font6x8.height + margin * 2;\r\n\tconst width = cellWidth * 64;\r\n\tconst height = cellHeight * 4;\r\n\tconst chars = decompressFont( m_font6x8 );\r\n\t\r\n\t// Clear memory\r\n\tm_font6x8.str = \"\";\r\n\r\n\t// Create a Uint8ClampedArray for pixel data\r\n\tconst data = new Uint8ClampedArray( width * height * 4 );\r\n\r\n\tlet x = margin;\r\n\tlet y = margin;\r\n\tfor( const char of chars ) {\r\n\r\n\t\t// Write the char data to the screen\r\n\t\tfor( let dataY = 0; dataY < charHeight; dataY += 1 ) {\r\n\t\t\tfor( let dataX = 0; dataX < charWidth; dataX += 1 ) {\r\n\t\t\t\tconst bit = char[ dataY ][ dataX ];\r\n\t\t\t\tif( bit === 1 ) {\r\n\t\t\t\t\tconst i = ( ( width * ( y + dataY ) ) + ( x + dataX ) ) * 4;\r\n\t\t\t\t\tdata[ i ] = 255;\r\n\t\t\t\t\tdata[ i + 1 ] = 255;\r\n\t\t\t\t\tdata[ i + 2 ] = 255;\r\n\t\t\t\t\tdata[ i + 3 ] = 255;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Increment to next character\r\n\t\tx += cellWidth;\r\n\t\tif( x >= width ) {\r\n\t\t\tx = margin;\r\n\t\t\ty += cellHeight;\r\n\t\t}\r\n\t}\r\n\r\n\t// Create ImageData from the array\r\n\tconst imageData = new ImageData( data, width, height );\r\n\r\n\t// Create the canvas and draw the image data\r\n\tconst canvas = document.createElement( \"canvas\" );\r\n\tcanvas.width = width;\r\n\tcanvas.height = height;\r\n\tconst context = canvas.getContext( \"2d\" );\r\n\tcontext.putImageData( imageData, 0, 0 );\r\n\r\n\treturn canvas;\r\n}\r\n\r\nfunction decompressFont( fontData ) {\r\n\tlet numStr = fontData.str;\r\n\tconst width = fontData.width;\r\n\tconst height = fontData.height;\r\n\tconst byteSize = fontData.byteSize;\r\n\tconst byteBase = fontData.byteBase;\r\n\tlet bin = \"\";\r\n\tconst data = [];\r\n\t\r\n\tnumStr = \"\" + numStr;\r\n\tconst nums = numStr.split( \",\" );\r\n\r\n\t// Loop through all the base-32 numbers\r\n\tfor( let i = 0; i < nums.length; i++ ) {\r\n\r\n\t\t// Convert base-32 string to binary string\r\n\t\tlet num = parseInt( nums[ i ], byteBase ).toString( 2 );\r\n\r\n\t\t// Pad the front with 0's so that num has length of 32\r\n\t\twhile( num.length < byteSize ) {\r\n\t\t\tnum = \"0\" + num;\r\n\t\t}\r\n\r\n\t\t// Add to the binary string\r\n\t\tbin += num;\r\n\t}\r\n\r\n\t// Loop through all the bits and build character data\r\n\tlet i = 0;\r\n\tif( bin.length % byteSize > 0 ) {\r\n\t\tconsole.warn( \"loadFont: Invalid font data.\" );\r\n\t\treturn data;\r\n\t}\r\n\r\n\twhile( i < bin.length ) {\r\n\r\n\t\t// Push a new character onto data\r\n\t\tdata.push( [] );\r\n\r\n\t\t// Store the index of the font character\r\n\t\tconst index = data.length - 1;\r\n\r\n\t\t// Loop through all rows\r\n\t\tfor( let y = 0; y < height; y += 1 ) {\r\n\r\n\t\t\t// Push a new row onto the character data\r\n\t\t\tdata[ index ].push( [] );\r\n\r\n\t\t\t// Loop through columns in this row\r\n\t\t\tfor( let x = 0; x < width; x += 1 ) {\r\n\r\n\t\t\t\tlet num;\r\n\t\t\t\tif( i >= bin.length ) {\r\n\t\t\t\t\tnum = 0;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tnum = parseInt( bin[ i ] );\r\n\t\t\t\t\tif( isNaN( num ) ) {\r\n\t\t\t\t\t\tnum = 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Push the bit onto the character\r\n\t\t\t\tdata[ index ][ y ].push( num );\r\n\r\n\t\t\t\t// Increment the bit position\r\n\t\t\t\ti += 1;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn data;\r\n}", "export default { \"data\": \"data:image/webp;base64,UklGRpQFAABXRUJQVlA4WAoAAAAYAAAA/wEAHwAAVlA4TJcEAAAv/8EHEA8w//M///Mf8LCs/p8bSdK3EUTW4U+On/kPJf5af3Kx/CEmoYRi/Wmv3hYIop3I6vWmCol+jH6Ate/g25z6AQrWezfem6K0Rm2fIKL/CtO2YRQ6T2Ec0069wwzPtyenV858SMvpEarKMpKSUAcNAOx3YrbJdTYDJRiX56nuFv5Qbt74/OpSW359g7ZVFd6lM5ZS16cgUgSI/dq9rYK7iwjifP/XU1fX+nd4vpycts3RWH5dM44aQ1XaGUtT5XUVtBVAvy4xpqaK7iIha+TyPE1T116FnxW58fdp0vK7hKpOUzWPI0Iy3RJ0zmTkUOraY6PWQUVUfnq166apvQreyo2/N0dajtM46hhDVeYWYYqyxy0tHEiIU3TxCAEVrvy9rrtO/w6u67+1q0sjx/XYaqsyvWtWIDXFESkiSHVW3KO7uIpIFrg87+zUNTP4+MDZz5/5UFuOfVRVlhGS9Fs0gCBnupztO2ZiaxElCOMIXccMpqvqCigYM3eVwB0SADrJbTNNrdt3zj7Q93W2bNm9732yynYQVmyoWUlcrW+xs7TR1ZbeSkmf+ERxiSV8+2wqXvx9C30IWiMEIokAQW4hS6Kyt3PopSqPP165xBSmg754WYl7n/yDQTShFixa2KZ1LOKN7W33us697z2LCvWhd1Uxq7JEC9Nh33m3FveLtWlQ7SF23vkDvpWYZHIvvq3E/WLyJ1dsSId50b7u4ukTF7/eh720Efeplk+GqEBXKs/Bi0RbKibuU+0iKvSVl5I+EYqLl9L3KVhxcft2khL2FfDiXoWuiCe56N51Ib7XbUrdexbMc9tMDxy52dmp7+sHNmfNsvS9TfYhA7Z7trUH4lnzs9a7hfhAo1tJfcwbXTFxr5lZpgED4IHvsEwDAMZm9JUw+sq7VS8bjgwMrrrW3lza1EBua4GrVxU+9pNfq+oAw8AwKO5cBeEq0FMLJPeVr1zR5H4Mm01DSkDf601/6FPP3kGFtWZmrdm6XifyqQNA6+N7zNXWgKck4E4pi9YMNAfDdDA0uPt+jLEq7qLSW4iTmbl78eqB/JU2innz1FEdcj78tfrNhz717UXT/WF/f1DM81HXddWYs6hMbqfu7ktBeu3E3TNUVbz5tC5b0xxMzcFwME1No14Vd7dQVaLS53BLda2PZ/NL6uLue2PnVSyv3u496DAMgMbRTsZxjK2ZtdZ7Pv26mY1jVNMs/e5oNrqDgb+k8L/3HRgA1NwxDSjy5zW3y/O/AP7/vj1VFNVhYNF1gEFhUGXmgedngAzkut6wXxsS9JIKNTxva7gPLE9O2UpKQgyeReRYZZsgJr3V68PTJ8/NT8/PzcPM8PrrDPMttu4pjGXP+l7HsXKyhmNlb0Ha2zQREGDR9HZtr6mS7Bb1qe9+/etm0VQztRJTaHl9nl+f59efPnl6fu7p+bl5nueT118/mefm9Xl+4Hke8SqF3aLeJ//1rytHgqqyRfWpZC2gi8bAMDCALv6Dogt7TZV8t1NLyccxeAZ0V/aABPfDtqpSXgeV+ttGqJ2cs+4KLD/3ARVARQaoAEDXAGwAAABFWElG1gAAAElJKgAIAAAABgASAQMAAQAAAAEAAAAaAQUAAQAAAFYAAAAbAQUAAQAAAF4AAAAoAQMAAQAAAAIAAAAxAQIAEAAAAGYAAABphwQAAQAAAHYAAAAAAAAAYAAAAAEAAABgAAAAAQAAAFBhaW50Lk5FVCA1LjEuOQAFAACQBwAEAAAAMDIzMAGgAwABAAAAAQAAAAKgBAABAAAAAAIAAAOgBAABAAAAIAAAAAWgBAABAAAAuAAAAAAAAAACAAEAAgAEAAAAUjk4AAIABwAEAAAAMDEwMAAAAAA=\" };", "export default { \"data\": \"data:image/webp;base64,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\" };", "export default { \"data\": \"data:image/webp;base64,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\" };", "/**\r\n * Pi.js - Main Entry Point\r\n * \r\n * Graphics library for retro-style games and demos.\r\n * \r\n * @module pi.js\r\n * @author Andy Stubbs\r\n * @license Apache-2.0\r\n */\r\n\r\n\"use strict\";\r\n\r\n// This is the lite version entry point (core only, no plugins).\r\n// The full version with plugins is in index-full.js.\r\n\r\n// Core Modules\r\nimport * as g_utils from \"./core/utils.js\";\r\nimport * as g_commands from \"./core/commands.js\";\r\nimport * as g_screenManager from \"./core/screen-manager.js\";\r\nimport * as g_plugins from \"./core/plugins.js\";\r\n\r\n// Renderer\r\nimport * as g_renderer from \"./renderer/renderer.js\";\r\n\r\n// API\r\nimport * as g_colors from \"./api/colors.js\";\r\nimport * as g_graphicsApi from \"./api/graphics.js\";\r\nimport * as g_images from \"./api/images.js\";\r\nimport * as g_pixels from \"./api/pixels.js\";\r\nimport * as g_paint from \"./api/paint.js\";\r\nimport * as g_blends from \"./api/blends.js\";\r\nimport * as g_draw from \"./api/draw.js\";\r\nimport * as g_postfx from \"./api/postfx.js\";\r\nimport * as g_view from \"./api/view.js\";\r\n\r\n// Text\r\nimport * as g_fonts from \"./text/fonts.js\";\r\nimport * as g_print from \"./text/print.js\";\r\n\r\n// Version injected during build from package.json\r\nconst VERSION = \"2.1.0\";\r\n\r\n// Create the main api for all external commands later assinged to globals pi or $\r\nconst api = {\r\n\t\"version\": VERSION\r\n};\r\n\r\n// Store modules in array for ordered initialization\r\nconst mods = [\r\n\tg_utils, g_commands, g_screenManager, g_plugins, g_renderer, g_colors, g_graphicsApi, g_images,\r\n\tg_blends, g_pixels, g_paint, g_draw, g_postfx, g_fonts, g_print, g_view\r\n];\r\n\r\n// Initialize the modules\r\nfor( const mod of mods ) {\r\n\tif( mod.init ) {\r\n\t\tmod.init( api );\r\n\t}\r\n}\r\n\r\n// Process API commands\r\ng_commands.processCommands( api );\r\n\r\n// Set window.pi for browser environments\r\nif( typeof window !== \"undefined\" ) {\r\n\twindow.pi = api;\r\n\r\n\t// Set $ alias only if not already defined (avoid jQuery conflicts)\r\n\tif( window.$ === undefined ) {\r\n\t\twindow.$ = api;\r\n\t}\r\n}\r\n\r\n// Export for different module systems\r\nexport default api;\r\nexport { api as pi };\r\n", "/**\r\n * Gamepad Plugin for Pi.js\r\n * \r\n * Provides gamepad input handling including button state tracking, axis handling,\r\n * and connect/disconnect event management.\r\n * \r\n * @module plugins/gamepad\r\n * @version 1.0.0\r\n */\r\n\r\n\"use strict\";\r\n\r\n\r\n/***************************************************************************************************\r\n * Module State\r\n **************************************************************************************************/\r\n\r\n\r\nconst m_gamepads = {};\r\nconst m_onConnectHandlers = [];\r\nconst m_onDisconnectHandlers = [];\r\n\r\nlet m_isInitialized = false;\r\nlet m_isStopped = false;\r\nlet m_isLooping = false;\r\nlet m_gamepadLoopId = null;\r\nlet m_axesSensitivity = 0.2;\r\nlet m_tick = 0;\r\nlet m_lastGamepadUpdateTick = -1;\r\n\r\n\r\n/***************************************************************************************************\r\n * Plugin Initialization\r\n **************************************************************************************************/\r\n\r\n\r\nexport default function gamepadPlugin( pluginApi ) {\r\n\r\n\t// Add window blur/focus handlers\r\n\twindow.addEventListener( \"blur\", onWindowBlur );\r\n\twindow.addEventListener( \"focus\", onWindowFocus );\r\n\r\n\t// Register global commands\r\n\tpluginApi.addCommand( \"startGamepad\", startGamepad, false, [] );\r\n\tpluginApi.addCommand( \"stopGamepad\", stopGamepad, false, [] );\r\n\tpluginApi.addCommand( \"ingamepad\", ingamepad, false, [ \"gamepadIndex\" ] );\r\n\tpluginApi.addCommand(\r\n\t\t\"setGamepadSensitivity\", setGamepadSensitivity, false, [ \"sensitivity\" ]\r\n\t);\r\n\tpluginApi.addCommand( \"onGamepadConnected\", onGamepadConnected, false, [ \"fn\" ] );\r\n\tpluginApi.addCommand( \"onGamepadDisconnected\", onGamepadDisconnected, false, [ \"fn\" ] );\r\n\r\n\t// Register clearEvents handler\r\n\tpluginApi.registerClearEvents( \"gamepad\", clearGamepadEvents );\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * External API Commands\r\n **************************************************************************************************/\r\n\r\n\r\nfunction startGamepad() {\r\n\tif( !m_isInitialized ) {\r\n\t\twindow.addEventListener( \"gamepadconnected\", gamepadConnected );\r\n\t\twindow.addEventListener( \"gamepaddisconnected\", gamepadDisconnected );\r\n\t\tm_isInitialized = true;\r\n\t\t\r\n\t\t// Scan for already-connected gamepads\r\n\t\tscanForGamepads();\r\n\t}\r\n\r\n\t// Remove explicit stops\r\n\tm_isStopped = false;\r\n\r\n\tif( !m_isLooping ) {\r\n\t\tm_isLooping = true;\r\n\t\tm_gamepadLoopId = requestAnimationFrame( gamepadLoop );\r\n\t}\r\n}\r\n\r\nfunction stopGamepad() {\r\n\r\n\t// Explicitly stop gamepad to prevent autostart when ingamepad is called\r\n\tm_isStopped = true;\r\n\tif( m_isLooping ) {\r\n\t\tm_isLooping = false;\r\n\t\tif( m_gamepadLoopId ) {\r\n\t\t\tcancelAnimationFrame( m_gamepadLoopId );\r\n\t\t\tm_gamepadLoopId = null;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfunction ingamepad( options ) {\r\n\tconst gamepadIndex = options.gamepadIndex;\r\n\r\n\t// If stopped explicitly then return without auto starting\r\n\tif( m_isStopped ) {\r\n\t\treturn null;\r\n\t}\r\n\tstartGamepad();\r\n\tupdateGamepads();\r\n\r\n\t// If no index specified, return all gamepads\r\n\tif( gamepadIndex === null || gamepadIndex === undefined ) {\r\n\t\treturn Object.values( m_gamepads ).sort( ( a, b ) => a.index - b.index );\r\n\t}\r\n\r\n\t// Validate gamepadIndex\r\n\tif( !Number.isInteger( gamepadIndex ) || gamepadIndex < 0 ) {\r\n\t\tconst error = new TypeError(\r\n\t\t\t\"ingamepad: gamepadIndex must be a non-negative integer or null.\"\r\n\t\t);\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Return specific gamepad or undefined if not found\r\n\treturn m_gamepads[ gamepadIndex ];\r\n}\r\n\r\nfunction setGamepadSensitivity( options ) {\r\n\tconst sensitivity = options.sensitivity;\r\n\r\n\tif( typeof sensitivity !== \"number\" || sensitivity < 0 || sensitivity > 1 ) {\r\n\t\tconst error = new TypeError(\r\n\t\t\t\"setGamepadSensitivity: sensitivity must be a number between 0 and 1.\"\r\n\t\t);\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif( sensitivity === 1 ) {\r\n\t\tm_axesSensitivity = 0.99999;\r\n\t} else {\r\n\t\tm_axesSensitivity = sensitivity;\r\n\t}\r\n}\r\n\r\nfunction onGamepadConnected( options ) {\r\n\tconst fn = options.fn;\r\n\r\n\tif( typeof fn !== \"function\" ) {\r\n\t\tconst error = new TypeError( \"onGamepadConnected: fn must be a function.\" );\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tm_onConnectHandlers.push( fn );\r\n\tstartGamepad();\r\n}\r\n\r\nfunction onGamepadDisconnected( options ) {\r\n\tconst fn = options.fn;\r\n\r\n\tif( typeof fn !== \"function\" ) {\r\n\t\tconst error = new TypeError( \"onGamepadDisconnected: fn must be a function.\" );\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tm_onDisconnectHandlers.push( fn );\r\n\tstartGamepad();\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Internal Helper Functions\r\n **************************************************************************************************/\r\n\r\n\r\nfunction gamepadConnected( e ) {\r\n\r\n\tupdateGamepad( e.gamepad );\r\n\r\n\t// Trigger connect handlers\r\n\tconst gamepadData = m_gamepads[ e.gamepad.index ];\r\n\tfor( const handler of m_onConnectHandlers ) {\r\n\t\thandler( gamepadData );\r\n\t}\r\n}\r\n\r\nfunction gamepadDisconnected( e ) {\r\n\r\n\t// Trigger disconnect handlers\r\n\tconst data = {\r\n\t\t\"index\": e.gamepad.index,\r\n\t\t\"id\": e.gamepad.id,\r\n\t\t\"mapping\": e.gamepad.mapping,\r\n\t\t\"connected\": e.gamepad.connected\r\n\t};\r\n\r\n\tfor( const handler of m_onDisconnectHandlers ) {\r\n\t\thandler( data );\r\n\t}\r\n\r\n\tdelete m_gamepads[ e.gamepad.index ];\r\n}\r\n\r\nfunction gamepadLoop() {\r\n\tif( !m_isLooping ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tupdateGamepads();\r\n\r\n\tm_tick += 1;\r\n\tm_gamepadLoopId = requestAnimationFrame( gamepadLoop );\r\n}\r\n\r\nfunction scanForGamepads() {\r\n\tlet gamepads;\r\n\r\n\tif( \"getGamepads\" in navigator ) {\r\n\t\tgamepads = navigator.getGamepads();\r\n\t} else if( \"webkitGetGamepads\" in navigator ) {\r\n\t\tgamepads = navigator.webkitGetGamepads();\r\n\t} else {\r\n\t\tgamepads = [];\r\n\t}\r\n\r\n\t// Add any gamepads that are already connected but not in our list\r\n\tfor( let i = 0; i < gamepads.length; i++ ) {\r\n\t\tif( gamepads[ i ] && !( gamepads[ i ].index in m_gamepads ) ) {\r\n\t\t\tupdateGamepad( gamepads[ i ] );\r\n\t\t\t\r\n\t\t\t// Trigger connect handlers for pre-connected gamepads\r\n\t\t\tconst gamepadData = m_gamepads[ gamepads[ i ].index ];\r\n\t\t\tfor( const handler of m_onConnectHandlers ) {\r\n\t\t\t\thandler( gamepadData );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfunction updateGamepads() {\r\n\tlet gamepads;\r\n\r\n\t// Prevent updateGamepads from triggering multiple times in the same loop\r\n\tif( m_lastGamepadUpdateTick === m_tick ) {\r\n\t\treturn;\r\n\t}\r\n\tm_lastGamepadUpdateTick = m_tick;\r\n\r\n\tif( \"getGamepads\" in navigator ) {\r\n\t\tgamepads = navigator.getGamepads();\r\n\t} else if( \"webkitGetGamepads\" in navigator ) {\r\n\t\tgamepads = navigator.webkitGetGamepads();\r\n\t} else {\r\n\t\tgamepads = [];\r\n\t}\r\n\r\n\tfor( const gamepad of gamepads ) {\r\n\t\tif( !gamepad || !gamepad.connected ) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tupdateGamepad( gamepad );\r\n\t}\r\n}\r\n\r\nfunction createNewGamepadData( gamepadDataRaw ) {\r\n\r\n\t// Create the new gamepad data object\r\n\tconst newGamepadData = {\r\n\t\t\"index\": gamepadDataRaw.index,\r\n\t\t\"id\": gamepadDataRaw.id,\r\n\t\t\"connected\": gamepadDataRaw.connected,\r\n\t\t\"mapping\": gamepadDataRaw.mapping,\r\n\t\t\"timestamp\": gamepadDataRaw.timestamp,\r\n\t\t\"vibrationActuator\": gamepadDataRaw.vibrationActuator,\r\n\t\t\"axes\": [],\r\n\t\t\"lastAxes\": [],\r\n\t\t\"buttons\": []\r\n\t};\r\n\r\n\t// Attach event listeners with helper functions\r\n\tnewGamepadData.getButton = function( buttonIndex ) {\r\n\t\tif( buttonIndex < 0 || buttonIndex >= this.buttons.length ) {\r\n\t\t\treturn null;\r\n\t\t}\r\n\t\treturn this.buttons[ buttonIndex ];\r\n\t};\r\n\tnewGamepadData.getButtonPressed = function( buttonIndex ) {\r\n\t\tif( buttonIndex < 0 || buttonIndex >= this.buttons.length ) {\r\n\t\t\treturn null;\r\n\t\t}\r\n\t\treturn this.buttons[ buttonIndex ].pressed;\r\n\t};\r\n\tnewGamepadData.getButtonJustPressed = function( buttonIndex ) {\r\n\t\tif( buttonIndex < 0 || buttonIndex >= this.buttons.length ) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\treturn this.buttons[ buttonIndex ].pressStarted;\r\n\t};\r\n\tnewGamepadData.getButtonJustReleased = function( buttonIndex ) {\r\n\t\tif( buttonIndex < 0 || buttonIndex >= this.buttons.length ) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\treturn this.buttons[ buttonIndex ].pressReleased;\r\n\t};\r\n\tnewGamepadData.getAxis = function( axisIndex ) {\r\n\t\tif( axisIndex < 0 || axisIndex >= this.axes.length ) {\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\treturn this.axes[ axisIndex ];\r\n\t};\r\n\tnewGamepadData.getAxisChanged = function( axisIndex ) {\r\n\t\tif( axisIndex < 0 || axisIndex >= this.axes.length ) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tconst current = this.axes[ axisIndex ];\r\n\t\tconst last = this.lastAxes[ axisIndex ] || 0;\r\n\t\treturn current !== last;\r\n\t};\r\n\r\n\treturn newGamepadData;\r\n}\r\n\r\nfunction updateGamepad( gamepadRawData ) {\r\n\tlet gamepadData = m_gamepads[ gamepadRawData.index ];\r\n\tif( !gamepadData ) {\r\n\t\tgamepadData = createNewGamepadData( gamepadRawData );\r\n\t\tm_gamepads[ gamepadRawData.index ] = gamepadData;\r\n\t}\r\n\r\n\t// Update buttons\r\n\tconst newButtons = [];\r\n\tfor( let i = 0; i < gamepadRawData.buttons.length; i += 1 ) {\r\n\t\tconst buttonNew = gamepadRawData.buttons[ i ];\r\n\t\tconst buttonOld = gamepadData.buttons[ i ] || { \"pressed\": false };\r\n\t\tnewButtons.push( {\r\n\t\t\t\"pressed\": buttonNew.pressed,\r\n\t\t\t\"value\": buttonNew.value,\r\n\t\t\t\"pressStarted\": !buttonOld.pressed && buttonNew.pressed,\r\n\t\t\t\"pressReleased\": buttonOld.pressed && !buttonNew.pressed\r\n\t\t} );\r\n\t}\r\n\tgamepadData.buttons = newButtons;\r\n\r\n\t// Update Axes\r\n\tgamepadData.lastAxes = gamepadData.axes.slice();\r\n\tgamepadData.axes = [];\r\n\tfor( let i = 0; i < gamepadRawData.axes.length; i++ ) {\r\n\t\tgamepadData.axes.push( smoothAxis( gamepadRawData.axes[ i ] ) );\r\n\t}\r\n\r\n\t// Update Raw Data\r\n\tgamepadData.timestamp = gamepadRawData.timestamp;\r\n\tgamepadData.connected = gamepadRawData.connected;\r\n\tgamepadData.vibrationActuator = gamepadRawData.vibrationActuator;\r\n}\r\n\r\nfunction smoothAxis( axis ) {\r\n\tif( Math.abs( axis ) < m_axesSensitivity ) {\r\n\t\treturn 0;\r\n\t}\r\n\taxis = axis - Math.sign( axis ) * m_axesSensitivity;\r\n\taxis = axis / ( 1 - m_axesSensitivity );\r\n\treturn axis;\r\n}\r\n\r\nfunction onWindowBlur() {\r\n\r\n\t// Pause gamepad loop when window loses focus\r\n\tif( m_isLooping ) {\r\n\t\tif( m_gamepadLoopId ) {\r\n\t\t\tcancelAnimationFrame( m_gamepadLoopId );\r\n\t\t\tm_gamepadLoopId = null;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfunction onWindowFocus() {\r\n\r\n\t// Resume gamepad loop when window regains focus\r\n\tif( m_isLooping && !m_gamepadLoopId ) {\r\n\t\tm_gamepadLoopId = requestAnimationFrame( gamepadLoop );\r\n\t}\r\n}\r\n\r\n/**\r\n * Clear all gamepad event handlers\r\n * Called by clearEvents command\r\n * \r\n * @param {Object} [screenData] - Screen data (not used for gamepad events)\r\n * @returns {void}\r\n */\r\nfunction clearGamepadEvents( screenData ) {\r\n\tm_onConnectHandlers.length = 0;\r\n\tm_onDisconnectHandlers.length = 0;\r\n}\r\n\r\n// Auto-register in IIFE mode (when loaded via <script> tag)\r\nif( typeof window !== \"undefined\" && window.pi ) {\r\n\twindow.pi.registerPlugin( {\r\n\t\t\"name\": \"gamepad\",\r\n\t\t\"version\": \"1.0.0\",\r\n\t\t\"description\": \"Gamepad input handling for Pi.js\",\r\n\t\t\"init\": gamepadPlugin\r\n\t} );\r\n}\r\n", "/**\r\n * Keyboard Input Command for Pi.js\r\n * \r\n * Provides text input functionality with cursor blinking and validation.\r\n * \r\n * @module plugins/keyboard/input\r\n */\r\n\r\n\"use strict\";\r\n\r\nconst CURSOR_BLINK = 500;\r\n\r\n// Input state\r\nlet m_inputData = null;\r\n\r\n// Store pluginApi reference for use in functions\r\nlet m_pluginApi = null;\r\n\r\n\r\n\r\n/***************************************************************************************************\r\n * Input Command Registration\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Initialize input command\r\n * \r\n * @param {Object} pluginApi - Plugin API provided by Pi.js\r\n * @returns {void}\r\n */\r\nexport function initInput( pluginApi ) {\r\n\r\n\tm_pluginApi = pluginApi;\r\n\r\n\t// Register screen commands\r\n\tpluginApi.addCommand(\r\n\t\t\"input\", input, true,\r\n\t\t[ \"prompt\", \"fn\", \"cursor\", \"isNumber\", \"isInteger\", \"allowNegative\", \"maxLength\" ]\r\n\t);\r\n\tpluginApi.addCommand( \"cancelInput\", cancelInput, true, [] );\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * External API Commands\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Input command - Get text input from user\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Input options\r\n * @param {string} options.prompt - Prompt text to display\r\n * @param {Function} [options.fn] - Callback function called with result\r\n * @param {string} [options.cursor] - Cursor character (default: block character)\r\n * @param {boolean} [options.isNumber] - If true, only allow numeric input\r\n * @param {boolean} [options.isInteger] - If true, only allow integer input\r\n * @param {boolean} [options.allowNegative] - If true, allow negative numbers\r\n * @param {number} [options.maxLength] - Maximum length of input string\r\n * @returns {Promise} Promise that resolves with input value or rejects on cancel\r\n */\r\nfunction input( screenData, options ) {\r\n\tconst prompt = options.prompt;\r\n\tconst fn = options.fn;\r\n\tconst cursor = options.cursor ? options.cursor : String.fromCharCode( 219 );\r\n\tconst isNumber = !!options.isNumber;\r\n\tconst isInteger = !!options.isInteger;\r\n\tconst allowNegative = !!options.allowNegative;\r\n\tconst maxLength = options.maxLength;\r\n\r\n\tif( typeof prompt !== \"string\" ) {\r\n\t\tconst error = new TypeError( \"input: prompt must be a string\" );\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif( fn && typeof fn !== \"function\" ) {\r\n\t\tconst error = new TypeError( \"input: fn must be a function.\" );\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif( typeof cursor !== \"string\" ) {\r\n\t\tconst error = new TypeError( \"input: cursor must be a string\" );\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif(\r\n\t\tmaxLength !== null &&\r\n\t\t( typeof maxLength !== \"number\" || maxLength < 0 || !Number.isInteger( maxLength ) )\r\n\t) {\r\n\t\tconst error = new TypeError( \"input: maxLength must be a non-negative integer\" );\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Create promise for async/await support\r\n\tlet resolvePromise, rejectPromise;\r\n\tconst promise = new Promise( ( resolve, reject ) => {\r\n\t\tresolvePromise = resolve;\r\n\t\trejectPromise = reject;\r\n\t} );\r\n\r\n\tif( m_inputData ) {\r\n\t\tfinishInput( true );\r\n\t}\r\n\r\n\tm_inputData = {\r\n\t\t\"screenData\": screenData,\r\n\t\t\"prompt\": prompt,\r\n\t\t\"cursor\": cursor,\r\n\t\t\"lastCursorBlink\": Date.now(),\r\n\t\t\"showCursor\": true,\r\n\t\t\"isNumber\": isNumber,\r\n\t\t\"isInteger\": isInteger,\r\n\t\t\"allowNegative\": allowNegative,\r\n\t\t\"maxLength\": maxLength,\r\n\t\t\"val\": \"\",\r\n\t\t\"fn\": fn,\r\n\t\t\"resolve\": resolvePromise,\r\n\t\t\"reject\": rejectPromise,\r\n\t\t\"backgroundImageName\": null,\r\n\t\t\"backgroundImage\": null,\r\n\t\t\"captureX\": null,\r\n\t\t\"captureY\": null\r\n\t};\r\n\r\n\tstartInput();\r\n\r\n\treturn promise;\r\n}\r\n\r\n/**\r\n * Cancel input command - Cancel current input\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @returns {void}\r\n */\r\nfunction cancelInput( screenData ) {\r\n\tif( m_inputData && m_inputData.screenData === screenData ) {\r\n\t\tfinishInput( true );\r\n\t}\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Internal Helper Functions\r\n **************************************************************************************************/\r\n\r\n\r\nfunction startInput() {\r\n\tconst api = m_pluginApi.getApi();\r\n\r\n\t// Create unique image name for background\r\n\tconst key = `${Date.now()}_${Math.random().toString( 36 ).substring( 2, 9 )}`;\r\n\tm_inputData.backgroundImageName = `__input_bg_${key}`;\r\n\r\n\t// Capture the background image\r\n\tcaptureBackground();\r\n\r\n\t// Add input event listener\r\n\tapi.onkey( \"any\", \"down\", onInputKeyDown, false, true );\r\n\r\n\t// Add interval for blinking cursor\r\n\tm_inputData.interval = setInterval( showPrompt, 100 );\r\n}\r\n\r\nfunction captureBackground() {\r\n\tconst screenData = m_inputData.screenData;\r\n\r\n\t// Check if need to scroll first\r\n\tlet pos = screenData.api.getPos();\r\n\tif( pos.row >= screenData.api.getRows() ) {\r\n\t\tscreenData.api.print( \"\" );\r\n\t\tscreenData.api.setPos( pos.col, pos.row - 1 );\r\n\t}\r\n\t\r\n\t// Get current position to capture background region\r\n\tconst posPx = screenData.api.getPosPx();\r\n\tconst font = screenData.font;\r\n\tconst width = screenData.width;\r\n\tconst height = font.height;\r\n\r\n\t// Capture background region using createImageFromScreen\r\n\t// Capture from the pixel position until the end the screen\r\n\tconst captureWidth = width - posPx.x;\r\n\tconst captureHeight = height;\r\n\t\r\n\tscreenData.api.createImageFromScreen( {\r\n\t\t\"name\": m_inputData.backgroundImageName ,\r\n\t\t\"x1\": posPx.x,\r\n\t\t\"y1\": posPx.y,\r\n\t\t\"x2\": posPx.x + captureWidth - 1,\r\n\t\t\"y2\": posPx.y + captureHeight - 1\r\n\t} );\r\n\tm_inputData.backgroundImage = m_pluginApi.getApi().getImage( m_inputData.backgroundImageName  );\r\n\tm_inputData.captureX = posPx.x;\r\n\tm_inputData.captureY = posPx.y;\r\n\tm_inputData.captureWidth = captureWidth;\r\n\tm_inputData.captureHeight = captureHeight;\r\n}\r\n\r\nfunction onInputKeyDown( keyData ) {\r\n\r\n\t// Handle Enter Key - Complete Input\r\n\tif( keyData.key === \"Enter\" ) {\r\n\t\tfinishInput();\r\n\t\treturn;\r\n\t\r\n\t// Handle Escape - Cancel Input\r\n\t} else if( keyData.key === \"Escape\" ) {\r\n\t\tfinishInput( true );\r\n\t\treturn;\r\n\t\r\n\t// Handle Backspace - Erase last character\r\n\t} else if( keyData.key === \"Backspace\" ) {\r\n\t\tif( m_inputData.val.length > 0 ) {\r\n\t\t\tm_inputData.val = m_inputData.val.substring( 0, m_inputData.val.length - 1 );\r\n\t\t}\r\n\t\r\n\t// Handle single length keys\r\n\t} else if( keyData.key && keyData.key.length === 1 ) {\r\n\r\n\t\tlet inputHandled = false;\r\n\r\n\t\t// Handle +/- numbers\r\n\t\tif( m_inputData.isNumber && m_inputData.allowNegative ) {\r\n\r\n\t\t\t// If user enters a \"-\" then insert \"-\" at the start\r\n\t\t\tif( keyData.key === \"-\" ) {\r\n\t\t\t\tif( m_inputData.val.charAt( 0 ) !== \"-\" ) {\r\n\t\t\t\t\tm_inputData.val = \"-\" + m_inputData.val;\r\n\t\t\t\t}\r\n\t\t\t\tinputHandled = true;\r\n\t\t\t\r\n\t\t\t// Any time the user enters a \"+\" key then replace the minus symbol\r\n\t\t\t} else if(\r\n\t\t\t\t( keyData.key === \"+\" || keyData.code === \"Equal\" ) &&\r\n\t\t\t\tm_inputData.val.charAt( 0 ) === \"-\"\r\n\t\t\t) {\r\n\t\t\t\tm_inputData.val = m_inputData.val.substring( 1 );\r\n\t\t\t\tinputHandled = true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Don't allow decimal points for integer number\r\n\t\tif( m_inputData.isInteger && keyData.code === \"Period\" ) {\r\n\t\t\tinputHandled = true;\r\n\t\t}\r\n\r\n\t\t// If the input is valid append the next character and validate\r\n\t\tif( !inputHandled ) {\r\n\t\t\t\r\n\t\t\t// Check maxLength before appending\r\n\t\t\tif(\r\n\t\t\t\tm_inputData.maxLength !== null && m_inputData.val.length >= m_inputData.maxLength\r\n\t\t\t) {\r\n\t\t\t\tinputHandled = true;\r\n\t\t\t} else {\r\n\t\t\t\tm_inputData.val += keyData.key;\r\n\r\n\t\t\t\t// Make sure it's a valid number or valid integer\r\n\t\t\t\tif(\r\n\t\t\t\t\t( m_inputData.isNumber && isNaN( Number( m_inputData.val ) ) ) ||\r\n\t\t\t\t\t( m_inputData.isInteger && !Number.isInteger( Number( m_inputData.val ) ) )\r\n\t\t\t\t) {\r\n\t\t\t\t\tm_inputData.val = m_inputData.val.substring( 0, m_inputData.val.length - 1 );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tshowPrompt();\r\n}\r\n\r\nfunction showPrompt( hideCursorOverride ) {\r\n\tconst screenData = m_inputData.screenData;\r\n\tlet msg = m_inputData.prompt + m_inputData.val;\r\n\r\n\t// Blink cursor after every blink duration\r\n\tif( !hideCursorOverride ) {\r\n\t\tconst now = Date.now();\r\n\t\tif( now - m_inputData.lastCursorBlink > CURSOR_BLINK ) {\r\n\t\t\tm_inputData.lastCursorBlink = now;\r\n\t\t\tm_inputData.showCursor = !m_inputData.showCursor;\r\n\t\t}\r\n\r\n\t\t// Show cursor if not hidden\r\n\t\tif( m_inputData.showCursor ) {\r\n\t\t\tmsg += m_inputData.cursor;\r\n\t\t}\r\n\t}\r\n\r\n\t// Restore the background image over the prompt area\r\n\tscreenData.api.blitImage( \r\n\t\tm_inputData.backgroundImage,\r\n\t\tm_inputData.captureX,\r\n\t\tm_inputData.captureY\r\n\t);\r\n\t\r\n\t// Get cursor position\r\n\tconst posPx = $.getPosPx();\r\n\r\n\t// Print the prompt + input + cursor\r\n\t$.setPosPx( m_inputData.captureX, m_inputData.captureY );\r\n\tscreenData.api.print( msg, true );\r\n\r\n\t// Restore the cursor\r\n\tscreenData.api.setPosPx( posPx );\r\n}\r\n\r\nfunction finishInput( isCancel ) {\r\n\tconst screenData = m_inputData.screenData;\r\n\tconst api = m_pluginApi.getApi();\r\n\r\n\t// Remove input key handler\r\n\tapi.offkey( \"any\", \"down\", onInputKeyDown, false, true );\r\n\r\n\t// Show prompt on complete, without the cursor\r\n\tshowPrompt( true );\r\n\r\n\t// Move cursor down one line\r\n\tscreenData.printCursor.y += screenData.font.height;\r\n\r\n\t// Clear the interval\r\n\tclearInterval( m_inputData.interval );\r\n\r\n\t// Process Input Value\r\n\tlet val = m_inputData.val;\r\n\tif( m_inputData.isNumber ) {\r\n\t\tif( val === \"\" || val === \"-\" ) {\r\n\t\t\tval = 0;\r\n\t\t} else {\r\n\t\t\tval = Number( val );\r\n\t\t\tif( m_inputData.isInteger ) {\r\n\t\t\t\tval = Math.floor( val );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Clean up background image texture\r\n\tapi.removeImage( m_inputData.backgroundImageName );\r\n\t\r\n\t// Clear out the inputData\r\n\tconst tempInputData = m_inputData;\r\n\tm_inputData = null;\r\n\r\n\t// Handle cancel input\r\n\tif( isCancel ) {\r\n\t\ttempInputData.resolve( null );\r\n\r\n\t\t// Callback function\r\n\t\tif( tempInputData.fn ) {\r\n\t\t\ttempInputData.fn( null );\r\n\t\t}\r\n\t\r\n\t// Handle successful input\r\n\t} else {\r\n\t\ttempInputData.resolve( val );\r\n\r\n\t\t// Callback function\r\n\t\tif( tempInputData.fn ) {\r\n\t\t\ttempInputData.fn( val );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * Cancel all active input prompts\r\n * Called by clearKeyboardEvents\r\n * \r\n * @param {Object} [screenData] - Optional screen data to cancel input for specific screen only\r\n * @returns {void}\r\n */\r\nexport function cancelAllInputs( screenData ) {\r\n\tif( m_inputData ) {\r\n\t\tif( screenData === null || screenData === undefined ) {\r\n\r\n\t\t\t// Cancel all inputs (there can only be one active at a time)\r\n\t\t\tfinishInput( true );\r\n\t\t} else if( m_inputData.screenData === screenData ) {\r\n\r\n\t\t\t// Cancel input for specific screen\r\n\t\t\tfinishInput( true );\r\n\t\t}\r\n\t}\r\n}\r\n", "/**\r\n * Keyboard Plugin for Pi.js\r\n * \r\n * Provides keyboard input handling including key state tracking, event handlers,\r\n * and action key management.\r\n * \r\n * @module plugins/keyboard\r\n * @version 1.0.0\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport { initInput, cancelAllInputs } from \"./input.js\";\r\n\r\n// Input tags that we don't want to capture\r\nconst INPUT_TAGS = new Set( [ \"INPUT\", \"TEXTAREA\", \"SELECT\", \"BUTTON\" ] );\r\n\r\n// Key information containers\r\nconst m_inCodes = {};\r\nconst m_inKeys = {};\r\nconst m_actionKeys = new Set();\r\nconst m_onKeyHandlers = {};\r\n\r\n// Status variables\r\nlet m_isKeyboardActive = false;\r\n\r\n\r\n/***************************************************************************************************\r\n * Plugin Initialization\r\n **************************************************************************************************/\r\n\r\n\r\nexport default function keyboardPlugin( pluginApi ) {\r\n\r\n\t// Initialize keyboard on plugin load\r\n\tstartKeyboard();\r\n\twindow.addEventListener( \"blur\", clearInKeys );\r\n\r\n\t// Add screen cleanup function to clear keyboard events when screen is removed\r\n\tpluginApi.addScreenCleanupFunction( () => {\r\n\t\t// Keyboard events are global, so we don't need screen-specific cleanup\r\n\t\t// But we can use this hook if needed in the future\r\n\t} );\r\n\r\n\t// Register global commands\r\n\tpluginApi.addCommand( \"startKeyboard\", startKeyboard, false, [] );\r\n\tpluginApi.addCommand( \"stopKeyboard\", stopKeyboard, false, [] );\r\n\tpluginApi.addCommand( \"inkey\", inkey, false, [ \"key\" ] );\r\n\tpluginApi.addCommand( \"setActionKeys\", setActionKeys, false, [ \"keys\" ] );\r\n\tpluginApi.addCommand( \"removeActionKeys\", removeActionKeys, false, [ \"keys\" ] );\r\n\tpluginApi.addCommand( \"onkey\", onkey, false, [ \"key\", \"mode\", \"fn\", \"once\", \"allowRepeat\" ] );\r\n\tpluginApi.addCommand( \"offkey\", offkey, false, [ \"key\", \"mode\", \"fn\", \"once\", \"allowRepeat\" ] );\r\n\r\n\t// Initialize input command\r\n\tinitInput( pluginApi );\r\n\r\n\t// Register clearEvents handler\r\n\tpluginApi.registerClearEvents( \"keyboard\", clearKeyboardEvents );\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * External API Commands\r\n **************************************************************************************************/\r\n\r\n\r\nfunction startKeyboard() {\r\n\tif( m_isKeyboardActive ) {\r\n\t\treturn;\r\n\t}\r\n\twindow.addEventListener( \"keydown\", onKeyDown, { \"capture\": true } );\r\n\twindow.addEventListener( \"keyup\", onKeyUp, { \"capture\": true } );\r\n\tm_isKeyboardActive = true;\r\n\tif( document.activeElement ) {\r\n\t\tdocument.activeElement.blur();\r\n\t}\r\n}\r\n\r\nfunction stopKeyboard() {\r\n\tif( !m_isKeyboardActive ) {\r\n\t\treturn;\r\n\t}\r\n\twindow.removeEventListener( \"keydown\", onKeyDown, { \"capture\": true } );\r\n\twindow.removeEventListener( \"keyup\", onKeyUp, { \"capture\": true } );\r\n\tm_isKeyboardActive = false;\r\n\r\n\t// Clear keys to prevent any after effects\r\n\tclearInKeys();\r\n}\r\n\r\nfunction inkey( options ) {\r\n\tconst key = options.key;\r\n\r\n\tif( key ) {\r\n\r\n\t\tif( typeof key !== \"string\" ) {\r\n\t\t\tconst error = new TypeError( \"inkey: key must be a string.\" );\r\n\t\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Get key by code property\r\n\t\tif( m_inCodes[ key ] ) {\r\n\t\t\treturn m_inCodes[ key ];\r\n\t\t}\r\n\r\n\t\t// Get key by key property\r\n\t\tif( m_inKeys[ key ] ) {\r\n\t\t\treturn m_inKeys[ key ];\r\n\t\t}\r\n\r\n\t\treturn null;\r\n\t}\r\n\r\n\t// If inkey is blank return all key codes\r\n\tconst keyCodes = [];\r\n\tfor( const code in m_inCodes ) {\r\n\t\tif( m_inCodes[ code ] ) {\r\n\t\t\tkeyCodes.push( m_inCodes[ code ] );\r\n\t\t}\r\n\t}\r\n\r\n\treturn keyCodes;\r\n}\r\n\r\nfunction setActionKeys( options ) {\r\n\tconst keys = options.keys;\r\n\r\n\tif( !Array.isArray( keys ) ) {\r\n\t\tconst error = new TypeError( \"setActionKeys: keys must be an array.\" );\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\tfor( const key of keys ) {\r\n\t\tm_actionKeys.add( key );\r\n\t}\r\n}\r\n\r\nfunction removeActionKeys( options ) {\r\n\tconst keys = options.keys;\r\n\r\n\tif( !Array.isArray( keys ) ) {\r\n\t\tconst error = new TypeError( \"removeActionKeys: keys must be an array.\" );\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\tfor( const key of keys ) {\r\n\t\tm_actionKeys.delete( key );\r\n\t}\r\n}\r\n\r\nfunction onkey( options ) {\r\n\tconst key = options.key;\r\n\tconst mode = options.mode;\r\n\tconst fn = options.fn;\r\n\tconst once = !!options.once;\r\n\tconst allowRepeat = !!options.allowRepeat;\r\n\t\r\n\tif( !key || ( typeof key !== \"string\" && !Array.isArray( key ) ) ) {\r\n\t\tconst error = new TypeError( \"onkey: key must be a string or an array of strings.\" );\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif( !mode || ( typeof mode !== \"string\" ) ) {\r\n\t\tconst error = new TypeError( \"onkey: mode must be a string with value of up or down.\" );\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif( typeof fn !== \"function\" ) {\r\n\t\tconst error = new TypeError( \"onkey: fn must be a function.\" );\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Normalize key into an array for easier processing\r\n\tconst combo = typeof key === \"string\" ? [ key ] : key;\r\n\r\n\tconst handler = {\r\n\t\t\"comboKey\": combo.sort().join( \"\" ),\r\n\t\t\"combo\": combo,\r\n\t\t\"mode\": mode,\r\n\t\t\"fn\": fn,\r\n\t\t\"once\": once,\r\n\t\t\"allowRepeat\": allowRepeat,\r\n\t\t\"isRemoved\": false\r\n\t};\r\n\t\r\n\t// Add a on key handler for each of the key codes - in combo all must be pressed\r\n\tfor( const key of combo ) {\r\n\t\tif( !m_onKeyHandlers[ key ] ) {\r\n\t\t\tm_onKeyHandlers[ key ] = [];\r\n\t\t}\r\n\t\tm_onKeyHandlers[ key ].push( handler );\r\n\t}\r\n}\r\n\r\nfunction offkey( options ) {\r\n\tconst key = options.key;\r\n\tconst mode = options.mode;\r\n\tconst fn = options.fn;\r\n\tconst once = !!options.once;\r\n\tconst allowRepeat = !!options.allowRepeat;\r\n\r\n\tif( !key || ( typeof key !== \"string\" && !Array.isArray( key ) ) ) {\r\n\t\tconst error = new TypeError( \"offkey: key must be a string or an array of strings.\" );\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif( typeof fn !== \"function\" ) {\r\n\t\tconst error = new TypeError( \"offkey: callback must be a function.\" );\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Normalize key into an array for easier processing\r\n\tconst combo = typeof key === \"string\" ? [ key ] : key;\r\n\tconst comboKey = combo.sort().join( \"\" );\r\n\r\n\t// Find the handlers and remove them\r\n\tfor( const key of combo ) {\r\n\t\tconst handlers = m_onKeyHandlers[ key ];\r\n\t\tif( !handlers ) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tconst toRemove = [];\r\n\t\tfor( let i = 0; i < handlers.length; i += 1 ) {\r\n\t\t\tconst handler = handlers[ i ];\r\n\t\t\tif(\r\n\t\t\t\thandler.comboKey === comboKey &&\r\n\t\t\t\thandler.mode === mode &&\r\n\t\t\t\thandler.fn === fn &&\r\n\t\t\t\thandler.once === once &&\r\n\t\t\t\thandler.allowRepeat === allowRepeat\r\n\t\t\t) {\r\n\t\t\t\ttoRemove.push( i );\r\n\t\t\t\thandler.isRemoved = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor( let i = toRemove.length - 1; i >= 0; i -= 1 ) {\r\n\t\t\thandlers.splice( toRemove[ i ], 1 );\r\n\t\t}\r\n\t\tif( handlers.length === 0 ) {\r\n\t\t\tdelete m_onKeyHandlers[ key ];\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Internal Helper Functions\r\n **************************************************************************************************/\r\n\r\n\r\nfunction onKeyDown( event ) {\r\n\r\n\t// Ignore typing when focus is inside an editable\r\n\tif( isFromEditableTarget( event ) ) {\r\n\t\tclearInKeys();\r\n\t\treturn;\r\n\t}\r\n\tconst keyData = {\r\n\t\t\"code\": event.code,\r\n\t\t\"key\": event.key,\r\n\t\t\"location\": event.location,\r\n\t\t\"altKey\": event.altKey,\r\n\t\t\"ctrlKey\": event.ctrlKey,\r\n\t\t\"metaKey\": event.metaKey,\r\n\t\t\"shiftKey\": event.shiftKey,\r\n\t\t\"repeat\": event.repeat\r\n\t};\r\n\tm_inCodes[ event.code ] = keyData;\r\n\tm_inKeys[ event.key ] = keyData;\r\n\r\n\ttriggerKeyEventHandlers( event, \"down\", event.code );\r\n\tif( event.code !== event.key ) {\r\n\t\ttriggerKeyEventHandlers( event, \"down\", event.key );\r\n\t}\r\n\ttriggerKeyEventHandlers( event, \"down\", \"any\" );\r\n\tif( m_actionKeys.has( event.code ) || m_actionKeys.has( event.key ) ) {\r\n\t\tevent.preventDefault();\r\n\t}\r\n}\r\n\r\nfunction onKeyUp( event ) {\r\n\t\r\n\t// Ignore typing when focus is inside an editable\r\n\tif( isFromEditableTarget( event ) ) {\r\n\t\tclearInKeys();\r\n\t\treturn;\r\n\t}\r\n\ttriggerKeyEventHandlers( event, \"up\", event.code );\r\n\r\n\tif( event.code !== event.key ) {\r\n\t\ttriggerKeyEventHandlers( event, \"up\", event.key );\r\n\t}\r\n\ttriggerKeyEventHandlers( event, \"up\", \"any\" );\r\n\r\n\tdelete m_inCodes[ event.code ];\r\n\tdelete m_inKeys[ event.key ];\r\n\r\n\tif( m_actionKeys.has( event.code ) || m_actionKeys.has( event.key ) ) {\r\n\t\tevent.preventDefault();\r\n\t}\r\n}\r\n\r\nfunction triggerKeyEventHandlers( event, mode, keyOrCode ) {\r\n\tconst handlers = m_onKeyHandlers[ keyOrCode ];\r\n\tif( !handlers ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst isAnyKey = keyOrCode === \"any\";\r\n\tconst handlersCopy = handlers.slice();\r\n\tconst toRemove = new Set();\r\n\r\n\tfor( let i = 0; i < handlersCopy.length; i += 1 ) {\r\n\t\tconst handler = handlersCopy[ i ];\r\n\r\n\t\tif( handler.mode !== mode ) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif( event.repeat && !handler.allowRepeat ) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// Need to check if handler has been removed in case a previous handler includes an offkey\r\n\t\tif( handler.isRemoved ) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// For \"any\" key handlers, pass the current key data\r\n\t\tif( isAnyKey ) {\r\n\t\t\tlet keyData = m_inCodes[ event.code ];\r\n\t\t\tif( !keyData ) {\r\n\t\t\t\tkeyData = m_inKeys[ event.key ];\r\n\t\t\t}\r\n\r\n\t\t\t// In case stopKeyboard gets called in another key event handler keyData will be blank\r\n\t\t\tif( keyData !== undefined ) {\r\n\t\t\t\thandler.fn( keyData );\r\n\t\t\t}\r\n\r\n\t\t\tif( handler.once ) {\r\n\t\t\t\ttoRemove.add( handler );\r\n\t\t\t\thandler.isRemoved = true;\r\n\t\t\t}\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// For specific key handlers, check combo and pass combo data\r\n\t\tconst isAllKeysPressed = handler.combo.every( key => m_inKeys[ key ] || m_inCodes[ key ] );\r\n\r\n\t\tif( isAllKeysPressed ) {\r\n\t\t\tconst comboData = handler.combo.map( key => {\r\n\t\t\t\tif( m_inKeys[ key ] ) {\r\n\t\t\t\t\treturn m_inKeys[ key ];\r\n\t\t\t\t}\r\n\t\t\t\treturn m_inCodes[ key ];\r\n\t\t\t} );\r\n\r\n\t\t\tif( comboData.length === 1 ) {\r\n\t\t\t\thandler.fn( comboData[ 0 ] );\r\n\t\t\t} else {\r\n\t\t\t\thandler.fn( comboData );\r\n\t\t\t}\r\n\r\n\t\t\tif( handler.once ) {\r\n\t\t\t\ttoRemove.add( handler );\r\n\t\t\t\thandler.isRemoved = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Remove the handlers that are one time only calls\r\n\tif( toRemove.size > 0 ) {\r\n\t\tm_onKeyHandlers[ keyOrCode ] = handlers.filter( h => !toRemove.has( h ) );\r\n\t\t\r\n\t\t// Delete the array if empty\r\n\t\tif( m_onKeyHandlers[ keyOrCode ].length === 0 ) {\r\n\t\t\tdelete m_onKeyHandlers[ keyOrCode ];\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfunction isFromEditableTarget ( event ) {\r\n\tconst element = event.target;\r\n\tif( !element ) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// Standard form controls\r\n\tif( INPUT_TAGS.has( element.tagName ) ) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Contenteditable\r\n\tif( element.isContentEditable ) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Inputs inside shadow roots\r\n\tconst role = element.getAttribute && element.getAttribute( \"role\" );\r\n\tif( role === \"textbox\" || role === \"searchbox\" ) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nfunction clearInKeys() {\r\n\r\n\t// Clear all key states\r\n\tfor( const code in m_inCodes ) {\r\n\t\tdelete m_inCodes[ code ];\r\n\t}\r\n\tfor( const key in m_inKeys ) {\r\n\t\tdelete m_inKeys[ key ];\r\n\t}\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Module Exports for Other Modules\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Clear all keyboard event handlers\r\n * Called by clearEvents command and exported for use by other modules\r\n * \r\n * @param {Object} [screenData] - Screen data to clear events for specific screen\r\n * @returns {void}\r\n */\r\nexport function clearKeyboardEvents( screenData ) {\r\n\t\r\n\t// Clear all keyboard event handlers\r\n\tfor( const mode in m_onKeyHandlers ) {\r\n\t\tdelete m_onKeyHandlers[ mode ];\r\n\t}\r\n\t\r\n\t// Cancel all active input prompts\r\n\tcancelAllInputs( screenData );\r\n}\r\n\r\n\r\n// Auto-register in IIFE mode (when loaded via <script> tag)\r\nif( typeof window !== \"undefined\" && window.pi ) {\r\n\twindow.pi.registerPlugin( {\r\n\t\t\"name\": \"keyboard\",\r\n\t\t\"version\": \"1.0.0\",\r\n\t\t\"description\": \"Keyboard input handling for Pi.js\",\r\n\t\t\"init\": keyboardPlugin\r\n\t} );\r\n}\r\n\r\n", "/**\r\n * Pi.js - Sound Module (Plugin)\r\n * \r\n * Sound effects, audio files, and volume control using Web Audio API.\r\n * \r\n * @module plugins/sound/sound\r\n */\r\n\r\n\"use strict\";\r\n\r\nlet m_audioContext = null;\r\nlet m_masterGain = null;\r\nlet m_audioPools = {};\r\nlet m_nextAudioId = 0;\r\nlet m_soundPool = {};\r\nlet m_nextSoundId = 0;\r\nlet m_volume = 0.75;\r\n\r\n// Cap concurrent oscillators to avoid renderer overload / tab crashes\r\nconst MAX_VOICES = 64;\r\n\r\n\r\n/***************************************************************************************************\r\n * Internal Functions\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Load an audio element and add to pool when ready\r\n * \r\n * @param {Object} pluginApi - Plugin API\r\n * @param {Object} audioItem - Audio pool item\r\n * @param {HTMLAudioElement} audio - Audio element\r\n * @param {number} retryCount - Number of retries remaining\r\n */\r\nfunction loadAudioItem( pluginApi, audioItem, audio, retryCount = 3 ) {\r\n\r\n\t// Audio ready callback\r\n\tfunction audioReady() {\r\n\t\taudioItem.pool.push( {\r\n\t\t\t\"audio\": audio,\r\n\t\t\t\"timeout\": 0,\r\n\t\t\t\"volume\": 1\r\n\t\t} );\r\n\t\taudio.removeEventListener( \"canplay\", audioReady );\r\n\t\tpluginApi.done();\r\n\t}\r\n\r\n\t// Audio error callback\r\n\tfunction audioError() {\r\n\t\tconst errors = [\r\n\t\t\t\"MEDIA_ERR_ABORTED - fetching process aborted by user\",\r\n\t\t\t\"MEDIA_ERR_NETWORK - error occurred when downloading\",\r\n\t\t\t\"MEDIA_ERR_DECODE - error occurred when decoding\",\r\n\t\t\t\"MEDIA_ERR_SRC_NOT_SUPPORTED - audio/video not supported\"\r\n\t\t];\r\n\r\n\t\tconst errorCode = audio.error.code;\r\n\t\tconst index = errorCode - 1;\r\n\r\n\t\tif( index >= 0 && index < errors.length ) {\r\n\t\t\tconsole.error( \"loadAudio: \" + errors[ index ] );\r\n\r\n\t\t\t// Retry loading if retries remain\r\n\t\t\tif( retryCount > 0 ) {\r\n\t\t\t\tsetTimeout( () => {\r\n\t\t\t\t\taudio.removeEventListener( \"canplay\", audioReady );\r\n\t\t\t\t\taudio.removeEventListener( \"error\", audioError );\r\n\t\t\t\t\tconst newAudio = new Audio( audio.src );\r\n\t\t\t\t\tloadAudioItem( pluginApi, audioItem, newAudio, retryCount - 1 );\r\n\t\t\t\t}, 100 );\r\n\t\t\t} else {\r\n\t\t\t\tconsole.error( \"loadAudio: Max retries exceeded for \" + audio.src );\r\n\t\t\t\tpluginApi.done();\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tconsole.error( \"loadAudio: Unknown error - \" + errorCode );\r\n\t\t\tpluginApi.done();\r\n\t\t}\r\n\t}\r\n\r\n\t// Wait for audio to load (only on first attempt)\r\n\tif( retryCount === 3 ) {\r\n\t\tpluginApi.wait();\r\n\t}\r\n\r\n\t// Set up event listeners\r\n\taudio.addEventListener( \"canplay\", audioReady );\r\n\taudio.addEventListener( \"error\", audioError );\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Exported Functions (for play.js)\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Get the shared AudioContext, creating it if needed\r\n * \r\n * @returns {AudioContext} Shared audio context\r\n */\r\nexport function getAudioContext() {\r\n\tif( !m_audioContext ) {\r\n\t\tconst AudioContextClass = window.AudioContext || window.webkitAudioContext;\r\n\t\tm_audioContext = new AudioContextClass();\r\n\t}\r\n\r\n\treturn m_audioContext;\r\n}\r\n\r\n/**\r\n * Get the shared master gain node connected to the destination\r\n * \r\n * @returns {GainNode} Shared master gain\r\n */\r\nfunction getMasterGain() {\r\n\tconst audioContext = getAudioContext();\r\n\r\n\tif( !m_masterGain ) {\r\n\t\tm_masterGain = audioContext.createGain();\r\n\t\tm_masterGain.gain.value = 1;\r\n\t\tm_masterGain.connect( audioContext.destination );\r\n\t}\r\n\r\n\treturn m_masterGain;\r\n}\r\n\r\n/**\r\n * Disconnect nodes and remove a sound from the pool\r\n * \r\n * @param {string} soundId - Sound ID to clean up\r\n * @returns {void}\r\n */\r\nfunction cleanupSound( soundId ) {\r\n\tconst sound = m_soundPool[ soundId ];\r\n\tif( !sound ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\ttry {\r\n\t\tsound.oscillator.disconnect();\r\n\t} catch( _e ) {\r\n\t\t// Already disconnected\r\n\t}\r\n\r\n\ttry {\r\n\t\tsound.envelope.disconnect();\r\n\t} catch( _e ) {\r\n\t\t// Already disconnected\r\n\t}\r\n\r\n\ttry {\r\n\t\tsound.master.disconnect();\r\n\t} catch( _e ) {\r\n\t\t// Already disconnected\r\n\t}\r\n\r\n\tdelete m_soundPool[ soundId ];\r\n}\r\n\r\n/**\r\n * Stop oldest voices that have already started when the active voice\r\n * limit is exceeded. Future-scheduled notes from $.play() are left alone\r\n * so long melodies are not cut off while being queued.\r\n * \r\n * @returns {void}\r\n */\r\nfunction enforceVoiceLimit() {\r\n\tconst audioContext = getAudioContext();\r\n\tconst now = audioContext.currentTime;\r\n\tconst activeIds = [];\r\n\r\n\tfor( const soundId in m_soundPool ) {\r\n\t\tconst sound = m_soundPool[ soundId ];\r\n\t\tif( sound.startTime <= now ) {\r\n\t\t\tactiveIds.push( soundId );\r\n\t\t}\r\n\t}\r\n\r\n\tif( activeIds.length < MAX_VOICES ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst removeCount = activeIds.length - MAX_VOICES + 1;\r\n\tfor( let i = 0; i < removeCount; i++ ) {\r\n\t\tstopSoundById( activeIds[ i ] );\r\n\t}\r\n}\r\n\r\n/**\r\n * Stop a sound by ID (internal function for play module)\r\n * \r\n * @param {string} soundId - Sound ID to stop\r\n */\r\nexport function stopSoundById( soundId ) {\r\n\tconst sound = m_soundPool[ soundId ];\r\n\tif( !sound ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\ttry {\r\n\t\tsound.oscillator.stop();\r\n\t} catch( _e ) {\r\n\r\n\t\t// Already stopped; clean up immediately\r\n\t\tcleanupSound( soundId );\r\n\t}\r\n}\r\n\r\n/**\r\n * Create a sound using Web Audio API (internal function exported for play module)\r\n * \r\n * @param {AudioContext} audioContext - Audio context\r\n * @param {number} frequency - Frequency in Hz\r\n * @param {number} volume - Volume (0-1)\r\n * @param {number} attackTime - Attack time in seconds\r\n * @param {number} sustainTime - Sustain time in seconds\r\n * @param {number} decayTime - Decay time in seconds\r\n * @param {number} stopTime - Total sound duration\r\n * @param {string} oType - Oscillator type\r\n * @param {Array} waveTables - Custom wave tables (if oType is \"custom\")\r\n * @param {number} delay - Delay before playing\r\n * @returns {string} Sound ID\r\n */\r\nexport function createSound(\r\n\taudioContext, frequency, volume, attackTime, sustainTime,\r\n\tdecayTime, stopTime, oType, waveTables, delay\r\n) {\r\n\tenforceVoiceLimit();\r\n\r\n\tconst oscillator = audioContext.createOscillator();\r\n\tconst envelope = audioContext.createGain();\r\n\tconst master = audioContext.createGain();\r\n\tconst startTime = audioContext.currentTime + delay;\r\n\r\n\tmaster.gain.value = m_volume;\r\n\toscillator.frequency.value = frequency;\r\n\r\n\t// Set oscillator type\r\n\tif( oType === \"custom\" ) {\r\n\t\tconst real = waveTables[ 0 ];\r\n\t\tconst imag = waveTables[ 1 ];\r\n\t\tconst wave = audioContext.createPeriodicWave( real, imag );\r\n\t\toscillator.setPeriodicWave( wave );\r\n\t} else {\r\n\t\toscillator.type = oType;\r\n\t}\r\n\r\n\t// Connect through shared master to limit destination fan-out\r\n\toscillator.connect( envelope );\r\n\tenvelope.connect( master );\r\n\tmaster.connect( getMasterGain() );\r\n\r\n\tconst soundId = \"sound_\" + m_nextSoundId;\r\n\tm_nextSoundId += 1;\r\n\tm_soundPool[ soundId ] = {\r\n\t\t\"oscillator\": oscillator,\r\n\t\t\"envelope\": envelope,\r\n\t\t\"master\": master,\r\n\t\t\"audioContext\": audioContext,\r\n\t\t\"startTime\": startTime\r\n\t};\r\n\r\n\t// Disconnect nodes and remove from pool when playback ends\r\n\toscillator.onended = function() {\r\n\t\tcleanupSound( soundId );\r\n\t};\r\n\r\n\ttry {\r\n\t\tconst attackEnd = startTime + attackTime;\r\n\t\tconst sustainEnd = attackEnd + sustainTime;\r\n\t\tconst decayEnd = sustainEnd + decayTime;\r\n\t\tlet endTime = startTime + stopTime;\r\n\r\n\t\tif( endTime < decayEnd ) {\r\n\t\t\tendTime = decayEnd;\r\n\t\t}\r\n\r\n\t\t// Use linear ramps instead of setValueCurveAtTime. Abutting curves on a\r\n\t\t// long-lived shared context often throw InvalidStateError; callers that\r\n\t\t// swallow errors then leak connected nodes until the tab crashes.\r\n\t\tif( attackTime > 0 ) {\r\n\t\t\tenvelope.gain.setValueAtTime( 0, startTime );\r\n\t\t\tenvelope.gain.linearRampToValueAtTime( volume, attackEnd );\r\n\t\t} else {\r\n\t\t\tenvelope.gain.setValueAtTime( volume, startTime );\r\n\t\t}\r\n\r\n\t\tif( sustainTime > 0 ) {\r\n\t\t\tenvelope.gain.linearRampToValueAtTime( 0.8 * volume, sustainEnd );\r\n\t\t}\r\n\r\n\t\tif( decayTime > 0 ) {\r\n\t\t\tenvelope.gain.linearRampToValueAtTime( 0.1 * volume, sustainEnd + decayTime * 0.5 );\r\n\t\t\tenvelope.gain.linearRampToValueAtTime( 0, decayEnd );\r\n\t\t} else {\r\n\t\t\tenvelope.gain.linearRampToValueAtTime( 0, endTime );\r\n\t\t}\r\n\r\n\t\toscillator.start( startTime );\r\n\t\toscillator.stop( endTime );\r\n\t} catch( err ) {\r\n\t\tcleanupSound( soundId );\r\n\t\tthrow err;\r\n\t}\r\n\r\n\treturn soundId;\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Plugin Registration\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Register sound module commands\r\n * \r\n * @param {Object} pluginApi - Plugin API\r\n */\r\nexport function registerSound( pluginApi ) {\r\n\tconst utils = pluginApi.utils;\r\n\r\n\t/**\r\n\t * Create an audio pool for playing multiple instances of the same sound file\r\n\t * \r\n\t * @param {Object} options - Command options\r\n\t * @param {string} options.src - Audio file URL\r\n\t * @param {number} options.poolSize - Number of audio instances (default: 1)\r\n\t * @returns {string} Audio ID for use with playAudio\r\n\t */\r\n\tpluginApi.addCommand( \"loadAudio\", loadAudio, false, [ \"src\", \"name\", \"poolSize\" ] );\r\n\tfunction loadAudio( options ) {\r\n\t\tconst src = options.src;\r\n\t\tlet poolSize = utils.getInt( options.poolSize, 1 );\r\n\t\tlet audioName = options.name;\r\n\r\n\t\t// Validate src\r\n\t\tif( !src || typeof src !== \"string\" ) {\r\n\t\t\tconst error = new TypeError( \"loadAudio: Parameter src must be a non-empty string.\" );\r\n\t\t\terror.code = \"INVALID_SRC\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\tlet audioId = \"audioPool_\" + m_nextAudioId;\r\n\t\tif( audioName ) {\r\n\r\n\t\t\t// Name must be unique\r\n\t\t\tif( m_audioPools[ audioName ] ) {\r\n\t\t\t\tconst error = new Error(\r\n\t\t\t\t\t`loadAudio: Audio pool name \"${audioName}\" is already in use.`\r\n\t\t\t\t);\r\n\t\t\t\terror.code = \"DUPLICATE_AUDIO_NAME\";\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\t\t\taudioId = audioName;\r\n\t\t} else {\r\n\t\t\tm_nextAudioId += 1;\r\n\t\t}\r\n\r\n\t\t// Validate poolSize\r\n\t\tif( poolSize < 1 ) {\r\n\t\t\tconst error = new RangeError(\r\n\t\t\t\t\"loadAudio: Parameter poolSize must be an integer greater than 0.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_POOL_SIZE\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Create the audio pool item\r\n\t\tconst audioItem = {\r\n\t\t\t\"pool\": [],\r\n\t\t\t\"index\": 0\r\n\t\t};\r\n\r\n\t\t// Create each audio instance in the pool\r\n\t\tfor( let i = 0; i < poolSize; i++ ) {\r\n\t\t\tconst audio = new Audio( src );\r\n\t\t\tloadAudioItem( pluginApi, audioItem, audio );\r\n\t\t}\r\n\r\n\t\t// Save audioId to global array\r\n\t\tm_audioPools[ audioId ] = audioItem;\r\n\r\n\t\treturn audioId;\r\n\t}\r\n\r\n\t/**\r\n\t * Delete an audio pool and free its resources\r\n\t * \r\n\t * @param {Object} options - Command options\r\n\t * @param {string} options.audioId - Audio pool ID returned from loadAudio\r\n\t */\r\n\tpluginApi.addCommand( \"removeAudio\", removeAudio, false, [ \"audioId\" ] );\r\n\tfunction removeAudio( options ) {\r\n\t\tconst audioId = options.audioId;\r\n\r\n\t\t// Validate audioId\r\n\t\tif( !m_audioPools[ audioId ] ) {\r\n\t\t\tconst error = new Error( `removeAudio: Audio pool \"${audioId}\" not found.` );\r\n\t\t\terror.code = \"AUDIO_POOL_NOT_FOUND\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Stop all audio and clear timeouts in the pool\r\n\t\tfor( let i = 0; i < m_audioPools[ audioId ].pool.length; i++ ) {\r\n\t\t\tconst poolItem = m_audioPools[ audioId ].pool[ i ];\r\n\t\t\tpoolItem.audio.pause();\r\n\t\t\tclearTimeout( poolItem.timeout );\r\n\t\t}\r\n\r\n\t\t// Delete the pool\r\n\t\tdelete m_audioPools[ audioId ];\r\n\t}\r\n\r\n\t/**\r\n\t * Play audio from an audio pool\r\n\t * \r\n\t * @param {Object} options - Command options\r\n\t * @param {string} options.audioId - Audio pool ID\r\n\t * @param {number} options.volume - Volume (0-1, default: 1)\r\n\t * @param {number} options.startTime - Start time in seconds (default: 0)\r\n\t * @param {number} options.duration - Play duration in seconds (default: 0 = play full)\r\n\t */\r\n\tpluginApi.addCommand(\r\n\t\t\"playAudio\", playAudio, false, [ \"audioId\", \"volume\", \"startTime\", \"duration\" ]\r\n\t);\r\n\tfunction playAudio( options ) {\r\n\t\tconst audioId = options.audioId;\r\n\t\tconst volume = utils.getFloat( options.volume, 1 );\r\n\t\tconst startTime = utils.getFloat( options.startTime, 0 );\r\n\t\tconst duration = utils.getFloat( options.duration, 0 );\r\n\r\n\t\t// Validate audioId\r\n\t\tif( !m_audioPools[ audioId ] ) {\r\n\t\t\tconst error = new Error( `playAudio: Audio pool \"${audioId}\" not found.` );\r\n\t\t\terror.code = \"AUDIO_POOL_NOT_FOUND\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Validate volume\r\n\t\tif( volume < 0 || volume > 1 ) {\r\n\t\t\tconst error = new RangeError(\r\n\t\t\t\t\"playAudio: Parameter volume must be a number between 0 and 1.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_VOLUME\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Validate startTime\r\n\t\tif( startTime < 0 ) {\r\n\t\t\tconst error = new RangeError(\r\n\t\t\t\t\"playAudio: Parameter startTime must be a number greater than or equal to 0.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_START_TIME\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Validate duration\r\n\t\tif( duration < 0 ) {\r\n\t\t\tconst error = new RangeError(\r\n\t\t\t\t\"playAudio: Parameter duration must be a number greater than or equal to 0.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_DURATION\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Get the audio pool\r\n\t\tconst audioItem = m_audioPools[ audioId ];\r\n\r\n\t\t// Make sure pool has sounds loaded\r\n\t\tif( audioItem.pool.length === 0 ) {\r\n\t\t\tconst error = new Error( \"playAudio: Audio pool has no sounds loaded.\" );\r\n\t\t\terror.code = \"EMPTY_POOL\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Get the next audio player from the pool\r\n\t\tconst poolItem = audioItem.pool[ audioItem.index ];\r\n\t\tconst audio = poolItem.audio;\r\n\r\n\t\t// Set volume and start time\r\n\t\taudio.volume = m_volume * volume;\r\n\t\tpoolItem.volume = volume;\r\n\t\taudio.currentTime = startTime;\r\n\r\n\t\t// Set duration if specified\r\n\t\tif( duration > 0 ) {\r\n\t\t\tclearTimeout( poolItem.timeout );\r\n\t\t\tpoolItem.timeout = setTimeout( () => {\r\n\t\t\t\taudio.pause();\r\n\t\t\t\taudio.currentTime = 0;\r\n\t\t\t}, duration * 1000 );\r\n\t\t}\r\n\r\n\t\t// Play the sound\r\n\t\t// Note: audio.play() returns a promise that may be rejected due to browser autoplay policies\r\n\t\tconst playPromise = audio.play();\r\n\t\tif( playPromise !== undefined ) {\r\n\t\t\tplayPromise.catch( ( error ) => {\r\n\t\t\t\tconsole.warn( \"playAudio: Audio playback failed:\", error.message );\r\n\t\t\t} );\r\n\t\t}\r\n\r\n\t\t// Move to next sound in pool (round-robin)\r\n\t\taudioItem.index += 1;\r\n\t\tif( audioItem.index >= audioItem.pool.length ) {\r\n\t\t\taudioItem.index = 0;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Stop audio from an audio pool or all audio pools\r\n\t * \r\n\t * @param {Object} options - Command options\r\n\t * @param {string} options.audioId - Audio pool ID (null to stop all pools)\r\n\t */\r\n\tpluginApi.addCommand( \"stopAudio\", stopAudio, false, [ \"audioId\" ] );\r\n\tfunction stopAudio( options ) {\r\n\t\tconst audioId = options.audioId;\r\n\r\n\t\t// If no audioId, stop all audio pools\r\n\t\tif( audioId == null ) {\r\n\t\t\tfor( const poolId in m_audioPools ) {\r\n\t\t\t\tfor( let j = 0; j < m_audioPools[ poolId ].pool.length; j++ ) {\r\n\t\t\t\t\tconst poolItem = m_audioPools[ poolId ].pool[ j ];\r\n\t\t\t\t\tpoolItem.audio.pause();\r\n\t\t\t\t\tclearTimeout( poolItem.timeout );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Validate audioId\r\n\t\tif( !m_audioPools[ audioId ] ) {\r\n\t\t\tconst error = new Error( `stopAudio: Audio pool \"${audioId}\" not found.` );\r\n\t\t\terror.code = \"AUDIO_POOL_NOT_FOUND\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Stop all audio and clear timeouts in the specified pool\r\n\t\tfor( let i = 0; i < m_audioPools[ audioId ].pool.length; i++ ) {\r\n\t\t\tconst poolItem = m_audioPools[ audioId ].pool[ i ];\r\n\t\t\tpoolItem.audio.pause();\r\n\t\t\tclearTimeout( poolItem.timeout );\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Play a sound by frequency using Web Audio API\r\n\t * \r\n\t * @param {Object} options - Command options\r\n\t * @param {number} options.frequency - Frequency in Hz\r\n\t * @param {number} options.duration - Duration in seconds (default: 1)\r\n\t * @param {number} options.volume - Volume 0-1 (default: 1)\r\n\t * @param {string|Array} options.oType - Oscillator type or custom wave table (default: \"triangle\")\r\n\t * @param {number} options.delay - Delay before playing in seconds (default: 0)\r\n\t * @param {number} options.attack - Attack time in seconds (default: 0)\r\n\t * @param {number} options.decay - Decay time in seconds (default: 0.1)\r\n\t * @returns {string} Sound ID for use with stopSound\r\n\t */\r\n\tpluginApi.addCommand( \"sound\", sound, false, [\r\n\t\t\"frequency\", \"duration\", \"volume\", \"oType\", \"delay\", \"attack\", \"decay\"\r\n\t] );\r\n\tfunction sound( options ) {\r\n\t\tconst frequency = Math.round( utils.getFloat( options.frequency, 440 ) );\r\n\t\tconst duration = utils.getFloat( options.duration, 1 );\r\n\t\tconst volume = utils.getFloat( options.volume, 1 );\r\n\t\tlet oType = options.oType != null ? options.oType : \"triangle\";\r\n\t\tconst delay = utils.getFloat( options.delay, 0 );\r\n\t\tconst attack = utils.getFloat( options.attack, 0 );\r\n\t\tconst decay = utils.getFloat( options.decay, 0.1 );\r\n\r\n\t\t// Validate duration\r\n\t\tif( duration < 0 ) {\r\n\t\t\tconst error = new RangeError(\r\n\t\t\t\t\"sound: Parameter duration must be a number greater than or equal to 0.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_DURATION\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Validate volume\r\n\t\tif( volume < 0 || volume > 1 ) {\r\n\t\t\tconst error = new RangeError( \"sound: Parameter volume must be a number between 0 and 1.\" );\r\n\t\t\terror.code = \"INVALID_VOLUME\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Validate attack\r\n\t\tif( attack < 0 ) {\r\n\t\t\tconst error = new RangeError(\r\n\t\t\t\t\"sound: Parameter attack must be a number greater than or equal to 0.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_ATTACK\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Validate delay\r\n\t\tif( delay < 0 ) {\r\n\t\t\tconst error = new RangeError(\r\n\t\t\t\t\"sound: Parameter delay must be a number greater than or equal to 0.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_DELAY\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\tlet waveTables = null;\r\n\r\n\t\t// Check for custom waveform (array)\r\n\t\tif( Array.isArray( oType ) ) {\r\n\t\t\tif(\r\n\t\t\t\toType.length !== 2 ||\r\n\t\t\t\toType[ 0 ].length === 0 ||\r\n\t\t\t\toType[ 1 ].length === 0 ||\r\n\t\t\t\toType[ 0 ].length !== oType[ 1 ].length\r\n\t\t\t) {\r\n\t\t\t\tconst error = new TypeError(\r\n\t\t\t\t\t\"sound: Parameter oType array must contain two non-empty arrays of equal length.\"\r\n\t\t\t\t);\r\n\t\t\t\terror.code = \"INVALID_WAVE_TABLE\";\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\r\n\t\t\twaveTables = [];\r\n\r\n\t\t\t// Validate all values are numbers\r\n\t\t\tfor( let i = 0; i < oType.length; i++ ) {\r\n\t\t\t\tfor( let j = 0; j < oType[ i ].length; j++ ) {\r\n\t\t\t\t\tif( isNaN( oType[ i ][ j ] ) ) {\r\n\t\t\t\t\t\tconst error = new TypeError(\r\n\t\t\t\t\t\t\t\"sound: Parameter oType array must only contain numbers.\"\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t\terror.code = \"INVALID_WAVE_TABLE_VALUE\";\r\n\t\t\t\t\t\tthrow error;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\twaveTables.push( new Float32Array( oType[ i ] ) );\r\n\t\t\t}\r\n\r\n\t\t\toType = \"custom\";\r\n\t\t} else if( typeof oType !== \"string\" ) {\r\n\t\t\tconst error = new TypeError( \"sound: Parameter oType must be a string or an array.\" );\r\n\t\t\terror.code = \"INVALID_OTYPE\";\r\n\t\t\tthrow error;\r\n\t\t} else {\r\n\r\n\t\t\t// Validate oType string\r\n\t\t\tconst validTypes = [ \"triangle\", \"sine\", \"square\", \"sawtooth\" ];\r\n\t\t\tif( validTypes.indexOf( oType ) === -1 ) {\r\n\t\t\t\tconst error = new Error(\r\n\t\t\t\t\t\"sound: Parameter oType must be one of: triangle, sine, square, sawtooth.\"\r\n\t\t\t\t);\r\n\t\t\t\terror.code = \"INVALID_OTYPE\";\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Calculate stop time\r\n\t\tconst stopTime = attack + duration + decay;\r\n\r\n\t\treturn createSound(\r\n\t\t\tgetAudioContext(), frequency, volume, attack, duration,\r\n\t\t\tdecay, stopTime, oType, waveTables, delay\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Stop a playing sound or all sounds\r\n\t * \r\n\t * @param {Object} options - Command options\r\n\t * @param {string} options.soundId - Sound ID (null to stop all sounds)\r\n\t */\r\n\tpluginApi.addCommand( \"stopSound\", stopSound, false, [ \"soundId\" ] );\r\n\tfunction stopSound( options ) {\r\n\t\tconst soundId = options.soundId;\r\n\r\n\t\t// If no soundId, stop all sounds\r\n\t\tif( soundId == null ) {\r\n\t\t\tconst soundIds = Object.keys( m_soundPool );\r\n\t\t\tfor( let i = 0; i < soundIds.length; i++ ) {\r\n\t\t\t\tstopSoundById( soundIds[ i ] );\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tstopSoundById( soundId );\r\n\t}\r\n\r\n\t/**\r\n\t * Set global volume for all sounds\r\n\t * \r\n\t * @param {Object} options - Command options\r\n\t * @param {number} options.volume - Volume (0-1)\r\n\t */\r\n\tpluginApi.addCommand( \"setVolume\", setVolume, false, [ \"volume\" ] );\r\n\tfunction setVolume( options ) {\r\n\t\tconst volume = utils.getFloat( options.volume, 0.75 );\r\n\r\n\t\t// Validate volume\r\n\t\tif( volume < 0 || volume > 1 ) {\r\n\t\t\tconst error = new RangeError(\r\n\t\t\t\t\"setVolume: Parameter volume must be a number between 0 and 1.\"\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_VOLUME\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\tm_volume = volume;\r\n\r\n\t\t// Update all active sounds\r\n\t\tfor( const soundId in m_soundPool ) {\r\n\t\t\tconst sound = m_soundPool[ soundId ];\r\n\t\t\tif( volume === 0 ) {\r\n\r\n\t\t\t\t// Use exponential ramp to near-zero, then set to zero\r\n\t\t\t\tsound.master.gain.exponentialRampToValueAtTime(\r\n\t\t\t\t\t0.01, sound.audioContext.currentTime + 0.1\r\n\t\t\t\t);\r\n\t\t\t\tsound.master.gain.setValueAtTime(\r\n\t\t\t\t\t0, sound.audioContext.currentTime + 0.11\r\n\t\t\t\t);\r\n\t\t\t} else {\r\n\t\t\t\tsound.master.gain.exponentialRampToValueAtTime(\r\n\t\t\t\t\tvolume, sound.audioContext.currentTime + 0.1\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Update all audio pools\r\n\t\tfor( const poolId in m_audioPools ) {\r\n\t\t\tfor( let j = 0; j < m_audioPools[ poolId ].pool.length; j++ ) {\r\n\t\t\t\tconst poolItem = m_audioPools[ poolId ].pool[ j ];\r\n\t\t\t\tpoolItem.audio.volume = m_volume * poolItem.volume;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n", "/**\r\n * Pi.js - Play Module (Plugin)\r\n * \r\n * BASIC-style music notation playback (inspired by QBasic PLAY command).\r\n * \r\n * @module plugins/sound/play\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport { createSound, getAudioContext, stopSoundById } from \"./sound.js\";\r\n\r\nconst m_tracks = {};\r\nconst m_allTracks = [];\r\nlet m_lastTrackId = 0;\r\nlet m_playData = [];\r\nlet m_utils = null;\r\n\r\n// Note frequency data (in Hz) by note name and octave\r\nconst m_notesData = {\r\n\t\"A\": [ 27.50, 55.00, 110, 220, 440, 880, 1760, 3520, 7040, 14080 ],\r\n\t\"A#\": [ 29.14, 58.27, 116.541, 233.082, 466.164, 932.328, 1864.655, 3729.31, 7458.62, 14917.24 ],\r\n\t\"B\": [ 30.87, 61.74, 123.471, 246.942, 493.883, 987.767, 1975.533, 3951.066, 7902.132, 15804.264 ],\r\n\t\"C\": [ 16.35, 32.70, 65.41, 130.813, 261.626, 523.251, 1046.502, 2093.005, 4186.009, 8372.018 ],\r\n\t\"C#\": [ 17.32, 34.65, 69.296, 138.591, 277.183, 554.365, 1108.731, 2217.461, 4434.922, 8869.844 ],\r\n\t\"D\": [ 18.35, 36.71, 73.416, 146.832, 293.665, 587.33, 1174.659, 2349.318, 4698.636, 9397.272 ],\r\n\t\"D#\": [ 19.45, 38.89, 77.782, 155.563, 311.127, 622.254, 1244.508, 2489.016, 4978.032, 9956.064 ],\r\n\t\"E\": [ 20.60, 41.20, 82.407, 164.814, 329.628, 659.255, 1318.51, 2637.021, 5274.042, 10548.084 ],\r\n\t\"F\": [ 21.83, 43.65, 87.307, 174.614, 349.228, 698.456, 1396.913, 2793.826, 5587.652, 11175.304 ],\r\n\t\"F#\": [ 23.12, 46.25, 92.499, 184.997, 369.994, 739.989, 1479.978, 2959.955, 5919.91, 11839.82 ],\r\n\t\"G\": [ 24.50, 49.00, 97.999, 195.998, 391.995, 783.991, 1567.982, 3135.964, 6271.928, 12543.856 ],\r\n\t\"G#\": [ 25.96, 51.91, 103.826, 207.652, 415.305, 830.609, 1661.219, 3322.438, 6644.876, 13289.752 ]\r\n};\r\n\r\n// All notes by number (for N command)\r\nconst m_allNotes = [\r\n\t0, 16.35, 17.32, 18.35, 19.45, 20.60, 21.83, 23.12, 24.50, 25.96, 27.50, 29.14, 30.87, 32.70,\r\n\t34.65, 36.71, 38.89, 41.20, 43.65, 46.25, 49.00, 51.91, 55.00, 58.27, 61.74, 65.406, 69.296,\r\n\t73.416, 77.782, 82.407, 87.307, 92.499, 97.999, 103.826, 110, 116.541, 123.471, 130.813,\r\n\t138.591, 146.832, 155.563, 164.814, 174.614, 184.997, 195.998, 207.652, 220, 233.082, 246.942,\r\n\t261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440, 466.164,\r\n\t493.883, 523.251, 554.365, 587.33, 622.254, 659.255, 698.456, 739.989, 783.991, 830.609, 880,\r\n\t932.328, 987.767, 1046.502, 1108.731, 1174.659, 1244.508, 1318.51, 1396.913, 1479.978, 1567.982,\r\n\t1661.219, 1760, 1864.655, 1975.533, 2093.005, 2217.461, 2349.318, 2489.016, 2637.021, 2793.826,\r\n\t2959.955, 3135.964, 3322.438, 3520, 3729.31, 3951.066, 4186.009, 4434.922, 4698.636, 4978.032,\r\n\t5274.042, 5587.652, 5919.91, 6271.928, 6644.876, 7040, 7458.62, 7902.132, 8372.018, 8869.844,\r\n\t9397.272, 9956.064, 10548.084, 11175.304, 11839.82, 13289.752, 14080, 14917.24, 15804.264\r\n];\r\n\r\n\r\n/***************************************************************************************************\r\n * Internal Functions\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Create a track from a play string\r\n * \r\n * @param {string} playString - Music notation string\r\n * @returns {number} First track ID\r\n */\r\nfunction createTrack( playString ) {\r\n\tlet firstTrackId;\r\n\r\n\t// Convert to uppercase and remove spaces\r\n\tplayString = playString.split( /\\s+/ ).join( \"\" ).toUpperCase();\r\n\r\n\t// Find and extract wavetables\r\n\tconst waveTables = [];\r\n\tlet start = 0;\r\n\twhile( start > -1 ) {\r\n\t\tstart = playString.indexOf( \"[[\" );\r\n\t\tif( start > -1 ) {\r\n\t\t\tconst end = playString.indexOf( \"]]\", start );\r\n\t\t\twaveTables.push( playString.substring( start, end + 2 ) );\r\n\t\t\tconst i = waveTables.length - 1;\r\n\t\t\tplayString = playString.replace( waveTables[ i ], \"W\" + i );\r\n\t\t}\r\n\t}\r\n\r\n\t// Convert wavetables to arrays\r\n\tfor( let i = 0; i < waveTables.length; i++ ) {\r\n\t\twaveTables[ i ] = JSON.parse( waveTables[ i ] );\r\n\r\n\t\t// Validate wavetable\r\n\t\tif(\r\n\t\t\twaveTables[ i ].length !== 2 ||\r\n\t\t\twaveTables[ i ][ 0 ].length !== waveTables[ i ][ 1 ].length\r\n\t\t) {\r\n\t\t\tconsole.error(\r\n\t\t\t\t\"play: Wavetables must have 2 arrays of same length. Defaulting to triangle wave.\"\r\n\t\t\t);\r\n\t\t\twaveTables[ i ] = \"triangle\";\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// Validate all values are numbers\r\n\t\tfor( let j = 0; j < 2; j++ ) {\r\n\t\t\tfor( let k = 0; k < waveTables[ i ][ j ].length; k++ ) {\r\n\t\t\t\twaveTables[ i ][ j ][ k ] = parseFloat( waveTables[ i ][ j ][ k ] );\r\n\t\t\t\tif( isNaN( waveTables[ i ][ j ][ k ] ) ) {\r\n\t\t\t\t\twaveTables[ i ][ j ][ k ] = 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\twaveTables[ i ][ j ] = new Float32Array( waveTables[ i ][ j ] );\r\n\t\t}\r\n\t}\r\n\r\n\t// Split tracks by commas\r\n\tconst trackStrings = playString.split( \",\" );\r\n\tconst trackIds = [];\r\n\r\n\t// Regular expression for parsing play commands\r\n\tconst regString =\r\n\t\t\"(?=WS|WQ|WW|WT|W\\\\d[\\\\d]?|V\\\\d|Q\\\\d|O\\\\d|\\\\<|\\\\>|N\\\\d\\\\d?|\" +\r\n\t\t\"L\\\\d\\\\d?|MS|MN|ML|MU\\\\d|MU\\\\-\\\\d|MK\\\\d[\\\\d]?[\\\\d]?|\" +\r\n\t\t\"MZ\\\\d[\\\\d]?[\\\\d]?|MX\\\\d[\\\\d]?[\\\\d]?|MY\\\\d[\\\\d]?[\\\\d]?|\" +\r\n\t\t\"MW|P[\\\\d]?|T\\\\d|\" +\r\n\t\t\"[[A|B|C|D|E|F|G][\\\\d]?[\\\\+|\\\\-|\\\\#|\\\\.\\\\.?]?)\";\r\n\tconst reg = new RegExp( regString );\r\n\r\n\tlet lastNote;\r\n\r\n\tfor( let i = 0; i < trackStrings.length; i++ ) {\r\n\r\n\t\t// Replace complex keywords with short symbols\r\n\t\ttrackStrings[ i ] = trackStrings[ i ].replace( /SINE/g, \"WS\" );\r\n\t\ttrackStrings[ i ] = trackStrings[ i ].replace( /SQUARE/g, \"WQ\" );\r\n\t\ttrackStrings[ i ] = trackStrings[ i ].replace( /SAWTOOTH/g, \"WW\" );\r\n\t\ttrackStrings[ i ] = trackStrings[ i ].replace( /TRIANGLE/g, \"WT\" );\r\n\r\n\t\t// Replace conflicting symbols\r\n\t\ttrackStrings[ i ] = trackStrings[ i ].replace( /MD/g, \"MZ\" );\r\n\t\ttrackStrings[ i ] = trackStrings[ i ].replace( /MA/g, \"MY\" );\r\n\t\ttrackStrings[ i ] = trackStrings[ i ].replace( /MT/g, \"MX\" );\r\n\t\ttrackStrings[ i ] = trackStrings[ i ].replace( /MO/g, \"MU\" );\r\n\r\n\t\t// Remove deprecated symbols\r\n\t\ttrackStrings[ i ] = trackStrings[ i ].replace( /MB/g, \"\" );\r\n\t\ttrackStrings[ i ] = trackStrings[ i ].replace( /MF/g, \"\" );\r\n\r\n\t\t// Create track\r\n\t\tconst trackId = m_lastTrackId;\r\n\t\tif( firstTrackId === undefined ) {\r\n\t\t\tfirstTrackId = trackId;\r\n\t\t}\r\n\t\tm_lastTrackId += 1;\r\n\r\n\t\tm_tracks[ trackId ] = {\r\n\t\t\t\"id\": trackId,\r\n\t\t\t\"notes\": [],\r\n\t\t\t\"noteId\": 0,\r\n\t\t\t\"decayRate\": 0.20,\r\n\t\t\t\"attackRate\": 0.15,\r\n\t\t\t\"sustainRate\": 0.65,\r\n\t\t\t\"fullNote\": false,\r\n\t\t\t\"extra\": 1,\r\n\t\t\t\"space\": \"normal\",\r\n\t\t\t\"interval\": 0,\r\n\t\t\t\"time\": 0,\r\n\t\t\t\"simultaneousPlay\": i > 0,\r\n\t\t\t\"tempo\": 60 / 120,\r\n\t\t\t\"noteLength\": 0.25,\r\n\t\t\t\"pace\": 0.875,\r\n\t\t\t\"octave\": 4,\r\n\t\t\t\"octaveExtra\": 0,\r\n\t\t\t\"volume\": 1,\r\n\t\t\t\"trackIds\": trackIds,\r\n\t\t\t\"type\": \"triangle\",\r\n\t\t\t\"waveTables\": waveTables,\r\n\t\t\t\"sounds\": []\r\n\t\t};\r\n\t\tm_allTracks.push( trackId );\r\n\t\ttrackIds.push( trackId );\r\n\r\n\t\t// Mark previous note for simultaneous play\r\n\t\tif( i > 0 ) {\r\n\t\t\tlastNote.simultaneousPlay = trackId;\r\n\t\t}\r\n\r\n\t\t// Split track into command parts\r\n\t\tconst trackParts = trackStrings[ i ].split( reg );\r\n\r\n\t\tfor( let j = 0; j < trackParts.length; j++ ) {\r\n\t\t\tconst index = trackParts[ j ].indexOf( \"-\" );\r\n\r\n\t\t\t// Split minus symbol (only if not a music note)\r\n\t\t\tif( index > -1 && \"ABCDEFG\".indexOf( trackParts[ j ][ 0 ] ) === -1 ) {\r\n\t\t\t\tconst noteData = {\r\n\t\t\t\t\t\"name\": trackParts[ j ].substring( 0, index ),\r\n\t\t\t\t\t\"val\": trackParts[ j ].substring( index )\r\n\t\t\t\t};\r\n\t\t\t\tm_tracks[ trackId ].notes.push( noteData );\r\n\t\t\t\tlastNote = noteData;\r\n\t\t\t} else {\r\n\t\t\t\tconst noteParts = trackParts[ j ].split( /(\\d+)/ );\r\n\t\t\t\tconst noteData = {\r\n\t\t\t\t\t\"name\": noteParts[ 0 ]\r\n\t\t\t\t};\r\n\t\t\t\tif( noteParts.length > 1 ) {\r\n\t\t\t\t\tnoteData.val = noteParts[ 1 ];\r\n\t\t\t\t}\r\n\t\t\t\tm_tracks[ trackId ].notes.push( noteData );\r\n\t\t\t\tlastNote = noteData;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn firstTrackId;\r\n}\r\n\r\n/**\r\n * Play a track recursively\r\n * \r\n * @param {number} trackId - Track ID to play\r\n */\r\nfunction playTrack( trackId ) {\r\n\tconst track = m_tracks[ trackId ];\r\n\tif( track.noteId >= track.notes.length ) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst cmd = track.notes[ track.noteId ];\r\n\tlet frequency = 0;\r\n\tlet val;\r\n\tlet wait = false;\r\n\ttrack.extra = 0;\r\n\r\n\tswitch( cmd.name.charAt( 0 ) ) {\r\n\t\tcase \"A\":\r\n\t\tcase \"B\":\r\n\t\tcase \"C\":\r\n\t\tcase \"D\":\r\n\t\tcase \"E\":\r\n\t\tcase \"F\":\r\n\t\tcase \"G\":\r\n\t\t\tfrequency = processNote( track, cmd );\r\n\t\t\twait = true;\r\n\t\t\tbreak;\r\n\t\tcase \"N\":\r\n\t\t\tif( !isNaN( Number( cmd.val ) ) ) {\r\n\t\t\t\tval = m_utils.getInt( cmd.val, 0 );\r\n\t\t\t\tif( val >= 0 && val < m_allNotes.length ) {\r\n\t\t\t\t\tfrequency = m_allNotes[ val ];\r\n\t\t\t\t}\r\n\t\t\t\twait = true;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"O\":\r\n\t\t\tif( !isNaN( Number( cmd.val ) ) ) {\r\n\t\t\t\tval = m_utils.getInt( cmd.val, 4 );\r\n\t\t\t\tif( val >= 0 && val < m_notesData[ \"A\" ].length ) {\r\n\t\t\t\t\ttrack.octave = val;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \">\":\r\n\t\t\ttrack.octave += 1;\r\n\t\t\tif( track.octave >= m_notesData[ \"A\" ].length ) {\r\n\t\t\t\ttrack.octave = m_notesData[ \"A\" ].length - 1;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"<\":\r\n\t\t\ttrack.octave -= 1;\r\n\t\t\tif( track.octave < 0 ) {\r\n\t\t\t\ttrack.octave = 0;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"L\":\r\n\t\t\tif( !isNaN( Number( cmd.val ) ) ) {\r\n\t\t\t\tval = m_utils.getInt( cmd.val, 1 );\r\n\t\t\t\ttrack.noteLength = getNoteLength( val );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"T\":\r\n\t\t\tif( !isNaN( Number( cmd.val ) ) ) {\r\n\t\t\t\tval = m_utils.getInt( cmd.val, 120 );\r\n\t\t\t\tif( val >= 32 && val < 256 ) {\r\n\t\t\t\t\ttrack.tempo = 60 / val;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"M\":\r\n\t\t\tprocessMusic( track, cmd );\r\n\t\t\tbreak;\r\n\t\tcase \"P\":\r\n\t\t\tif( !isNaN( Number( cmd.val ) ) ) {\r\n\t\t\t\twait = true;\r\n\t\t\t\tval = m_utils.getInt( cmd.val, 1 );\r\n\t\t\t\ttrack.extra = getNoteLength( val );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"V\":\r\n\t\t\tif( !isNaN( Number( cmd.val ) ) ) {\r\n\t\t\t\tval = m_utils.getInt( cmd.val, 50 );\r\n\t\t\t\tif( val < 0 ) {\r\n\t\t\t\t\tval = 0;\r\n\t\t\t\t} else if( val > 100 ) {\r\n\t\t\t\t\tval = 100;\r\n\t\t\t\t}\r\n\t\t\t\ttrack.volume = val / 100;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"W\":\r\n\t\t\tprocessWaveform( track, cmd );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\t// Calculate interval for next note\r\n\tif( track.extra > 0 ) {\r\n\t\ttrack.interval = track.tempo * track.extra * track.pace * 4;\r\n\t} else {\r\n\t\ttrack.interval = track.tempo * track.noteLength * track.pace * 4;\r\n\t}\r\n\r\n\t// Play simultaneous track\r\n\tif( m_tracks[ cmd.simultaneousPlay ] ) {\r\n\t\tm_tracks[ cmd.simultaneousPlay ].time = track.time;\r\n\t\tcopyTrackData( m_tracks[ cmd.simultaneousPlay ].id, trackId );\r\n\t\tplayTrack( m_tracks[ cmd.simultaneousPlay ].id );\r\n\t}\r\n\r\n\t// Play note if frequency > 0\r\n\tif( frequency > 0 ) {\r\n\t\tplayNote( track, frequency );\r\n\t}\r\n\r\n\t// Move to next instruction\r\n\ttrack.noteId += 1;\r\n\r\n\t// Continue playing track\r\n\tif( track.noteId < track.notes.length ) {\r\n\t\tif( wait ) {\r\n\t\t\ttrack.time += track.interval;\r\n\t\t}\r\n\t\tplayTrack( trackId );\r\n\t} else {\r\n\r\n\t\t// Schedule track removal after completion\r\n\t\tsetTimeout( () => {\r\n\t\t\tif( m_tracks[ trackId ] ) {\r\n\t\t\t\tremoveTrack( trackId );\r\n\t\t\t}\r\n\t\t}, ( track.time + track.interval ) * 1000 );\r\n\t}\r\n}\r\n\r\n/**\r\n * Process a note command (A-G)\r\n * \r\n * @param {Object} track - Track object\r\n * @param {Object} cmd - Command object\r\n * @returns {number} Frequency in Hz\r\n */\r\nfunction processNote( track, cmd ) {\r\n\tlet note = cmd.name;\r\n\r\n\t// Convert + to sharp\r\n\tnote = note.replace( /\\+/g, \"#\" );\r\n\r\n\t// Convert flats to equivalent sharps\r\n\tnote = note.replace( \"C-\", \"B\" );\r\n\tnote = note.replace( \"D-\", \"C#\" );\r\n\tnote = note.replace( \"E-\", \"D#\" );\r\n\tnote = note.replace( \"G-\", \"F#\" );\r\n\tnote = note.replace( \"A-\", \"G#\" );\r\n\tnote = note.replace( \"B-\", \"A#\" );\r\n\r\n\t// Convert enharmonic equivalents\r\n\tnote = note.replace( \"E#\", \"F\" );\r\n\tnote = note.replace( \"B#\", \"C\" );\r\n\r\n\t// Check for extra note length (dotted notes)\r\n\tif( cmd.name.indexOf( \"..\" ) > 0 ) {\r\n\t\ttrack.extra = 1.75 * track.noteLength;\r\n\t} else if( cmd.name.indexOf( \".\" ) > 0 ) {\r\n\t\ttrack.extra = 1.5 * track.noteLength;\r\n\t}\r\n\r\n\t// Remove dots from note\r\n\tnote = note.replace( /\\./g, \"\" );\r\n\r\n\t// Get note frequency\r\n\tlet frequency = 0;\r\n\tif( m_notesData[ note ] ) {\r\n\t\tconst octave = track.octave + track.octaveExtra;\r\n\t\tif( octave < m_notesData[ note ].length ) {\r\n\t\t\tfrequency = m_notesData[ note ][ octave ];\r\n\t\t}\r\n\t}\r\n\r\n\t// Check if note length included\r\n\tif( !isNaN( Number( cmd.val ) ) ) {\r\n\t\tconst val = m_utils.getInt( cmd.val, 1 );\r\n\t\ttrack.extra = getNoteLength( val );\r\n\t}\r\n\r\n\treturn frequency;\r\n}\r\n\r\n/**\r\n * Process music style commands (M...)\r\n * \r\n * @param {Object} track - Track object\r\n * @param {Object} cmd - Command object\r\n */\r\nfunction processMusic( track, cmd ) {\r\n\tswitch( cmd.name ) {\r\n\t\tcase \"MS\":\r\n\r\n\t\t\t// Staccato\r\n\t\t\ttrack.pace = 0.75;\r\n\t\t\tbreak;\r\n\t\tcase \"MN\":\r\n\r\n\t\t\t// Normal\r\n\t\t\ttrack.pace = 0.875;\r\n\t\t\tbreak;\r\n\t\tcase \"ML\":\r\n\r\n\t\t\t// Legato\r\n\t\t\ttrack.pace = 1;\r\n\t\t\tbreak;\r\n\t\tcase \"MU\":\r\n\t\t\tif( !isNaN( Number( cmd.val ) ) ) {\r\n\r\n\t\t\t\t// Modify octave\r\n\t\t\t\tconst val = m_utils.getInt( cmd.val, 0 );\r\n\t\t\t\ttrack.octaveExtra = val;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"MY\":\r\n\t\t\tif( !isNaN( Number( cmd.val ) ) ) {\r\n\r\n\t\t\t\t// Modify attack rate\r\n\t\t\t\tconst val = m_utils.getInt( cmd.val, 25 );\r\n\t\t\t\ttrack.attackRate = val / 100;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"MX\":\r\n\t\t\tif( !isNaN( Number( cmd.val ) ) ) {\r\n\r\n\t\t\t\t// Modify sustain rate\r\n\t\t\t\tconst val = m_utils.getInt( cmd.val, 25 );\r\n\t\t\t\ttrack.sustainRate = val / 100;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"MZ\":\r\n\t\t\tif( !isNaN( Number( cmd.val ) ) ) {\r\n\r\n\t\t\t\t// Modify decay rate\r\n\t\t\t\tconst val = m_utils.getInt( cmd.val, 25 );\r\n\t\t\t\ttrack.decayRate = val / 100;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase \"MW\":\r\n\r\n\t\t\t// Toggle full note\r\n\t\t\ttrack.fullNote = !track.fullNote;\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/**\r\n * Process waveform commands (W...)\r\n * \r\n * @param {Object} track - Track object\r\n * @param {Object} cmd - Command object\r\n */\r\nfunction processWaveform( track, cmd ) {\r\n\tif( cmd.name === \"WS\" ) {\r\n\t\ttrack.type = \"sine\";\r\n\t} else if( cmd.name === \"WQ\" ) {\r\n\t\ttrack.type = \"square\";\r\n\t} else if( cmd.name === \"WW\" ) {\r\n\t\ttrack.type = \"sawtooth\";\r\n\t} else if( cmd.name === \"WT\" ) {\r\n\t\ttrack.type = \"triangle\";\r\n\t} else if( !isNaN( Number( cmd.val ) ) ) {\r\n\r\n\t\t// Custom wavetable\r\n\t\tconst val = m_utils.getInt( cmd.val, -1 );\r\n\t\tif( track.waveTables[ val ] ) {\r\n\t\t\ttrack.type = val;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * Play a single note\r\n * \r\n * @param {Object} track - Track object\r\n * @param {number} frequency - Frequency in Hz\r\n */\r\nfunction playNote( track, frequency ) {\r\n\tconst volume = track.volume;\r\n\tconst attackTime = track.interval * track.attackRate;\r\n\tconst sustainTime = track.interval * track.sustainRate;\r\n\tconst decayTime = track.interval * track.decayRate;\r\n\r\n\tlet stopTime;\r\n\tif( track.fullNote && attackTime + sustainTime + decayTime > track.interval ) {\r\n\t\tstopTime = track.interval;\r\n\t} else {\r\n\t\tstopTime = attackTime + sustainTime + decayTime;\r\n\t}\r\n\r\n\tlet oType;\r\n\tlet waveTables = null;\r\n\tif( typeof track.type === \"string\" ) {\r\n\t\toType = track.type;\r\n\t} else {\r\n\t\twaveTables = track.waveTables[ track.type ];\r\n\t\tif( Array.isArray( waveTables ) ) {\r\n\t\t\toType = \"custom\";\r\n\t\t} else {\r\n\t\t\toType = waveTables;\r\n\t\t\twaveTables = null;\r\n\t\t}\r\n\t}\r\n\r\n\tconst soundData = {\r\n\t\t\"frequency\": frequency,\r\n\t\t\"volume\": volume,\r\n\t\t\"attackTime\": attackTime,\r\n\t\t\"sustainTime\": sustainTime,\r\n\t\t\"decayTime\": decayTime,\r\n\t\t\"stopTime\": stopTime,\r\n\t\t\"oType\": oType,\r\n\t\t\"waveTables\": waveTables,\r\n\t\t\"time\": track.time,\r\n\t\t\"track\": track\r\n\t};\r\n\r\n\tm_playData.push( soundData );\r\n}\r\n\r\n/**\r\n * Copy track data from source to destination\r\n * \r\n * @param {number} trackDestId - Destination track ID\r\n * @param {number} trackSourceId - Source track ID\r\n */\r\nfunction copyTrackData( trackDestId, trackSourceId ) {\r\n\tconst trackDest = m_tracks[ trackDestId ];\r\n\tconst trackSource = m_tracks[ trackSourceId ];\r\n\r\n\ttrackDest.decayRate = trackSource.decayRate;\r\n\ttrackDest.attackRate = trackSource.attackRate;\r\n\ttrackDest.sustainRate = trackSource.sustainRate;\r\n\ttrackDest.fullNote = trackSource.fullNote;\r\n\ttrackDest.extra = trackSource.extra;\r\n\ttrackDest.space = trackSource.space;\r\n\ttrackDest.interval = trackSource.interval;\r\n\ttrackDest.tempo = trackSource.tempo;\r\n\ttrackDest.noteLength = trackSource.noteLength;\r\n\ttrackDest.pace = trackSource.pace;\r\n\ttrackDest.octave = trackSource.octave;\r\n\ttrackDest.octaveExtra = trackSource.octaveExtra;\r\n\ttrackDest.volume = trackSource.volume;\r\n\ttrackDest.type = trackSource.type;\r\n}\r\n\r\n/**\r\n * Remove a track and all its sub-tracks\r\n * \r\n * @param {number} trackId - Track ID to remove\r\n */\r\nfunction removeTrack( trackId ) {\r\n\r\n\t// Delete all sub-tracks as well as main track\r\n\tconst trackIds = m_tracks[ trackId ].trackIds;\r\n\tfor( let i = trackIds.length; i >= 0; i-- ) {\r\n\t\tdelete m_tracks[ trackIds[ i ] ];\r\n\t}\r\n\r\n\t// Remove track from all tracks array\r\n\tfor( let i = m_allTracks.length - 1; i >= 0; i-- ) {\r\n\t\tif( !m_tracks[ m_allTracks[ i ] ] ) {\r\n\t\t\tm_allTracks.splice( i, 1 );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * Get note length from note value\r\n * \r\n * @param {number} val - Note value (1-64)\r\n * @returns {number} Note length\r\n */\r\nfunction getNoteLength( val ) {\r\n\tif( val >= 1 && val < 65 ) {\r\n\t\treturn 1 / val;\r\n\t}\r\n\treturn 0.875;\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Plugin Registration\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Register play module commands\r\n * \r\n * @param {Object} pluginApi - Plugin API\r\n */\r\nexport function registerPlay( pluginApi ) {\r\n\tm_utils = pluginApi.utils;\r\n\r\n\t/**\r\n\t * Play music using BASIC-style notation\r\n\t * \r\n\t * Format: \"NOTE[length][.][#|+|-] ...\"\r\n\t * - Notes: A-G (can include sharps # or +, flats -)\r\n\t * - Length: 1-64 (1=whole, 4=quarter, etc.)\r\n\t * - Dot modifiers: . (1.5x), .. (1.75x)\r\n\t * - Multiple tracks: separated by commas\r\n\t * \r\n\t * Commands:\r\n\t * - O[n]: Set octave (0-9)\r\n\t * - L[n]: Set default note length\r\n\t * - T[n]: Set tempo (32-255 BPM)\r\n\t * - V[n]: Set volume (0-100)\r\n\t * - P[n]: Pause for note length\r\n\t * - N[n]: Play note by number (0-127)\r\n\t * - W[type]: Set waveform (SINE, SQUARE, SAWTOOTH, TRIANGLE)\r\n\t * - MS: Staccato (75% of note length)\r\n\t * - MN: Normal (87.5% of note length)\r\n\t * - ML: Legato (100% of note length)\r\n\t * - MW: Toggle full note mode\r\n\t * - MO[n]: Modify octave offset\r\n\t * - MA[n]: Modify attack rate (0-100)\r\n\t * - MT[n]: Modify sustain rate (0-100)\r\n\t * - MD[n]: Modify decay rate (0-100)\r\n\t * - <: Decrease octave\r\n\t * - >: Increase octave\r\n\t * \r\n\t * @param {Object} options - Command options\r\n\t * @param {string} options.playString - Music notation string\r\n\t */\r\n\tpluginApi.addCommand( \"play\", play, false, [ \"playString\" ] );\r\n\tfunction play( options ) {\r\n\t\tlet playString = options.playString;\r\n\r\n\t\t// Validate playString\r\n\t\tif( typeof playString !== \"string\" ) {\r\n\t\t\tconst error = new TypeError( \"play: Parameter playString must be a string.\" );\r\n\t\t\terror.code = \"INVALID_PLAY_STRING\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\r\n\t\t// Create track from play string\r\n\t\tconst trackId = createTrack( playString );\r\n\r\n\t\t// Generate all play data\r\n\t\tm_playData = [];\r\n\t\tplayTrack( trackId );\r\n\r\n\t\t// Sort by time\r\n\t\tm_playData.sort( ( a, b ) => a.time - b.time );\r\n\r\n\t\t// Reuse shared audio context for all notes\r\n\t\tconst audioContext = getAudioContext();\r\n\r\n\t\t// Create all sounds\r\n\t\tfor( let i = 0; i < m_playData.length; i++ ) {\r\n\t\t\tconst playData = m_playData[ i ];\r\n\t\t\tplayData.track.sounds.push(\r\n\t\t\t\tcreateSound(\r\n\t\t\t\t\taudioContext, playData.frequency, playData.volume, playData.attackTime,\r\n\t\t\t\t\tplayData.sustainTime, playData.decayTime, playData.stopTime, playData.oType,\r\n\t\t\t\t\tplayData.waveTables, playData.time\r\n\t\t\t\t)\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\treturn trackId;\r\n\t}\r\n\r\n\t/**\r\n\t * Stop playing music\r\n\t * \r\n\t * @param {Object} options - Command options\r\n\t * @param {number} options.trackId - Track ID to stop (null to stop all tracks)\r\n\t */\r\n\tpluginApi.addCommand( \"stopPlay\", stopPlay, false, [ \"trackId\" ] );\r\n\tfunction stopPlay( options ) {\r\n\t\tconst trackId = options.trackId;\r\n\r\n\t\t// Stop all tracks\r\n\t\tif( trackId === null ) {\r\n\t\t\tfor( let i = 0; i < m_allTracks.length; i++ ) {\r\n\t\t\t\tconst track = m_tracks[ m_allTracks[ i ] ];\r\n\t\t\t\tif( track ) {\r\n\t\t\t\t\tfor( let j = 0; j < track.sounds.length; j++ ) {\r\n\t\t\t\t\t\tstopSoundById( track.sounds[ j ] );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdelete m_tracks[ m_allTracks[ i ] ];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tm_allTracks.length = 0;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Stop specific track\r\n\t\tif( m_tracks[ trackId ] ) {\r\n\t\t\tconst track = m_tracks[ trackId ];\r\n\t\t\tfor( let j = 0; j < track.sounds.length; j++ ) {\r\n\t\t\t\tstopSoundById( track.sounds[ j ] );\r\n\t\t\t}\r\n\t\t\tremoveTrack( trackId );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n", "/**\r\n * Pi.js - Play-Sound Plugin\r\n * \r\n * Music playback and sound effects using Web Audio API.\r\n * Combines play.js (BASIC-style music notation) and sound.js (sound effects).\r\n * \r\n * @module plugins/sound\r\n * @version 1.0.0\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport { registerSound } from \"./sound.js\";\r\nimport { registerPlay } from \"./play.js\";\r\n\r\n\r\n/***************************************************************************************************\r\n * Plugin Initialization\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Play-sound plugin initialization\r\n * \r\n * @param {Object} pluginApi - Plugin API provided by Pi.js\r\n */\r\nexport default function playSoundPlugin( pluginApi ) {\r\n\r\n\t// Register sound module commands\r\n\tregisterSound( pluginApi );\r\n\r\n\t// Register play module commands\r\n\tregisterPlay( pluginApi );\r\n}\r\n\r\n\r\n// Auto-register in IIFE mode (when loaded via <script> tag)\r\nif( typeof window !== \"undefined\" && window.pi ) {\r\n\twindow.pi.registerPlugin( {\r\n\t\t\"name\": \"sound\",\r\n\t\t\"version\": \"1.0.0\",\r\n\t\t\"description\": \"Music playback and sound effects using Web Audio API\",\r\n\t\t\"init\": playSoundPlugin\r\n\t} );\r\n}\r\n\r\n", "/**\r\n * Shared event helper utilities for the Pointer plugin.\r\n */\r\n\r\n\"use strict\";\r\n\r\nexport function createEventHelpers( pluginApi ) {\r\n\t\r\n\tconst utils = pluginApi.utils;\r\n\t\r\n\tfunction onevent(\r\n\t\tmode, fn, once, hitBox, modes, name, listenerArr, extraId, extraData, customData\r\n\t) {\r\n\t\tlet modeFound = false;\r\n\t\t\r\n\t\tfor( let i = 0; i < modes.length; i++ ) {\r\n\t\t\tif( mode === modes[ i ] ) {\r\n\t\t\t\tmodeFound = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tif( !modeFound ) {\r\n\t\t\tconst error = new Error(\r\n\t\t\t\t`${name}: mode needs to be one of the following: ${modes.join( \", \" )}.`\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_MODE\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\t\r\n\t\tonce = !!( once );\r\n\t\t\r\n\t\tif( typeof fn !== \"function\" ) {\r\n\t\t\tconst error = new Error( `${name}: fn is not a valid function.` );\r\n\t\t\terror.code = \"INVALID_FUNCTION\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\t\r\n\t\tif( hitBox ) {\r\n\t\t\tif(\r\n\t\t\t\t!Number.isInteger( hitBox.x ) ||\r\n\t\t\t\t!Number.isInteger( hitBox.y ) ||\r\n\t\t\t\t!Number.isInteger( hitBox.width ) ||\r\n\t\t\t\t!Number.isInteger( hitBox.height )\r\n\t\t\t) {\r\n\t\t\t\tconst error = new Error(\r\n\t\t\t\t\t`${name}: hitBox must have properties x, y, width, and height whose values ` +\r\n\t\t\t\t\t\"are integers.\"\r\n\t\t\t\t);\r\n\t\t\t\terror.code = \"INVALID_HITBOX\";\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tsetTimeout( () => {\r\n\t\t\tconst originalFn = fn;\r\n\t\t\tlet newMode = mode;\r\n\t\t\t\r\n\t\t\tif( typeof extraId === \"string\" ) {\r\n\t\t\t\tnewMode = mode + extraId;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tlet wrappedFn = fn;\r\n\t\t\tif( once ) {\r\n\t\t\t\twrappedFn = ( data, customData ) => {\r\n\t\t\t\t\toffevent( mode, originalFn, modes, name, listenerArr, extraId );\r\n\t\t\t\t\toriginalFn( data, customData );\r\n\t\t\t\t};\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif( !listenerArr[ newMode ] ) {\r\n\t\t\t\tlistenerArr[ newMode ] = [];\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tlistenerArr[ newMode ].push( {\r\n\t\t\t\t\"fn\": wrappedFn,\r\n\t\t\t\t\"hitBox\": hitBox,\r\n\t\t\t\t\"extraData\": extraData,\r\n\t\t\t\t\"clickDown\": false,\r\n\t\t\t\t\"originalFn\": originalFn,\r\n\t\t\t\t\"customData\": customData\r\n\t\t\t} );\r\n\t\t}, 1 );\r\n\t\t\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\tfunction offevent( mode, fn, modes, name, listenerArr, extraId ) {\r\n\t\tlet modeFound = false;\r\n\t\t\r\n\t\tfor( let i = 0; i < modes.length; i++ ) {\r\n\t\t\tif( mode === modes[ i ] ) {\r\n\t\t\t\tmodeFound = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tif( !modeFound ) {\r\n\t\t\tconst error = new Error(\r\n\t\t\t\t`${name}: mode needs to be one of the following: ${modes.join( \", \" )}.`\r\n\t\t\t);\r\n\t\t\terror.code = \"INVALID_MODE\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\t\r\n\t\tif( typeof extraId === \"string\" ) {\r\n\t\t\tmode += extraId;\r\n\t\t}\r\n\t\t\r\n\t\tconst isClear = fn == null;\r\n\t\t\r\n\t\tif( !isClear && typeof fn !== \"function\" ) {\r\n\t\t\tconst error = new Error( `${name}: fn is not a valid function.` );\r\n\t\t\terror.code = \"INVALID_FUNCTION\";\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\t\r\n\t\tif( listenerArr[ mode ] ) {\r\n\t\t\tif( isClear ) {\r\n\t\t\t\tdelete listenerArr[ mode ];\r\n\t\t\t} else {\r\n\t\t\t\tfor( let i = listenerArr[ mode ].length - 1; i >= 0; i-- ) {\r\n\t\t\t\t\tif( listenerArr[ mode ][ i ].originalFn === fn ) {\r\n\t\t\t\t\t\tlistenerArr[ mode ].splice( i, 1 );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif( listenerArr[ mode ].length === 0 ) {\r\n\t\t\t\t\tdelete listenerArr[ mode ];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tfunction triggerEventListeners( mode, data, listenerArr, clickStatus ) {\r\n\t\tif( !listenerArr[ mode ] ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t\r\n\t\tconst temp = listenerArr[ mode ].slice();\r\n\t\t\r\n\t\tfor( let i = 0; i < temp.length; i++ ) {\r\n\t\t\tconst listener = temp[ i ];\r\n\t\t\t\r\n\t\t\tif( clickStatus === \"up\" && !listener.clickDown ) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif( listener.hitBox ) {\r\n\t\t\t\tlet isHit = false;\r\n\t\t\t\tlet newData;\r\n\t\t\t\t\r\n\t\t\t\tif( Array.isArray( data ) ) {\r\n\t\t\t\t\tnewData = [];\r\n\t\t\t\t\tfor( let j = 0; j < data.length; j++ ) {\r\n\t\t\t\t\t\tconst pos = data[ j ];\r\n\t\t\t\t\t\tif( utils.inRange( pos, listener.hitBox ) ) {\r\n\t\t\t\t\t\t\tnewData.push( pos );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif( newData.length > 0 ) {\r\n\t\t\t\t\t\tisHit = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tnewData = data;\r\n\t\t\t\t\tif( utils.inRange( data, listener.hitBox ) ) {\r\n\t\t\t\t\t\tisHit = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif( isHit ) {\r\n\t\t\t\t\tif( clickStatus === \"down\" ) {\r\n\t\t\t\t\t\tlistener.clickDown = true;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tlistener.clickDown = false;\r\n\t\t\t\t\t\tlistener.fn( newData, listener.customData );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tlistener.fn( data, listener.customData );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn {\r\n\t\t\"onevent\": onevent,\r\n\t\t\"offevent\": offevent,\r\n\t\t\"triggerEventListeners\": triggerEventListeners\r\n\t};\r\n}\r\n\r\n\r\n", "/**\r\n * Touch registration for Pointer plugin.\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport { triggerPressListeners, triggerClickListeners, getTouchPress } from \"./press.js\";\r\n\r\n// Module-level reference to startTouchInternal function\r\nlet m_startTouchInternal = null;\r\n\r\nexport function startTouchInternal( screenData ) {\r\n\tif( m_startTouchInternal ) {\r\n\t\tm_startTouchInternal( screenData );\r\n\t}\r\n}\r\n\r\nexport function registerTouch( pluginApi, helpers ) {\r\n\t\r\n\tconst m_onevent = helpers.onevent;\r\n\tconst m_offevent = helpers.offevent;\r\n\tconst m_triggerEventListeners = helpers.triggerEventListeners;\r\n\t\r\n\tpluginApi.addScreenDataItem( \"touchStopped\", false );\r\n\tpluginApi.addScreenDataItem( \"touchStarted\", false );\r\n\tpluginApi.addScreenDataItem( \"touches\", {} );\r\n\tpluginApi.addScreenDataItem( \"lastTouches\", {} );\r\n\tpluginApi.addScreenDataItem( \"touchEventListenersActive\", 0 );\r\n\tpluginApi.addScreenDataItem( \"onTouchEventListeners\", {} );\r\n\t\r\n\tpluginApi.addScreenInitFunction( initTouchData );\r\n\twindow.addEventListener( \"blur\", onWindowBlurTouch );\r\n\t\r\n\tpluginApi.addCommand( \"startTouch\", startTouch, true, [] );\r\n\tpluginApi.addCommand( \"stopTouch\", stopTouch, true, [] );\r\n\tpluginApi.addCommand( \"intouch\", intouch, true, [] );\r\n\tpluginApi.addCommand(\r\n\t\t\"ontouch\", ontouch, true, [ \"mode\", \"fn\", \"once\", \"hitBox\", \"customData\" ]\r\n\t);\r\n\tpluginApi.addCommand( \"offtouch\", offtouch, true, [ \"mode\", \"fn\" ] );\r\n\tpluginApi.addCommand( \"setPinchZoom\", setPinchZoom, false, [ \"isEnabled\" ] );\r\n\t\r\n\tfunction initTouchData( screenData ) {\r\n\t\tscreenData.onTouchEventListeners = {\r\n\t\t\t\"start\": [],\r\n\t\t\t\"end\": [],\r\n\t\t\t\"move\": []\r\n\t\t};\r\n\t}\r\n\t\r\n\tfunction startTouchInternal( screenData ) {\r\n\t\tif( !screenData.touchStopped ) {\r\n\t\t\tstartTouch( screenData );\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Store reference for module-level export\r\n\tm_startTouchInternal = startTouchInternal;\r\n\r\n\tfunction startTouch( screenData ) {\r\n\r\n\t\t// Clear explicit touch stopped\r\n\t\tscreenData.touchStopped = false;\r\n\r\n\t\tif( !screenData.touchStarted ) {\r\n\t\t\tconst options = { \"passive\": false };\r\n\t\t\tscreenData.canvas.addEventListener( \"touchstart\", touchStart, options );\r\n\t\t\tscreenData.canvas.addEventListener( \"touchmove\", touchMove, options );\r\n\t\t\tscreenData.canvas.addEventListener( \"touchend\", touchEnd, options );\r\n\t\t\tscreenData.canvas.addEventListener( \"touchcancel\", touchEnd, options );\r\n\t\t\tscreenData.touchStarted = true;\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction stopTouch( screenData ) {\r\n\t\t\r\n\t\t//Clear explicit touchStopped\r\n\t\tscreenData.touchStopped = true;\r\n\r\n\t\tif( screenData.touchStarted ) {\r\n\t\t\tscreenData.canvas.removeEventListener( \"touchstart\", touchStart );\r\n\t\t\tscreenData.canvas.removeEventListener( \"touchmove\", touchMove );\r\n\t\t\tscreenData.canvas.removeEventListener( \"touchend\", touchEnd );\r\n\t\t\tscreenData.canvas.removeEventListener( \"touchcancel\", touchEnd );\r\n\t\t\tscreenData.touchStarted = false;\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction intouch( screenData ) {\r\n\t\tstartTouchInternal( screenData );\r\n\t\treturn getTouch( screenData );\r\n\t}\r\n\t\r\n\tfunction ontouch( screenData, options ) {\r\n\t\tconst mode = options.mode;\r\n\t\tconst fn = options.fn;\r\n\t\tconst once = options.once;\r\n\t\tconst hitBox = options.hitBox;\r\n\t\tconst customData = options.customData;\r\n\t\t\r\n\t\tconst isValid = m_onevent(\r\n\t\t\tmode, fn, once, hitBox, [ \"start\", \"end\", \"move\" ], \"ontouch\",\r\n\t\t\tscreenData.onTouchEventListeners, null, null, customData\r\n\t\t);\r\n\t\t\r\n\t\tif( isValid ) {\r\n\t\t\tstartTouchInternal( screenData );\r\n\t\t\tscreenData.touchEventListenersActive += 1;\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction offtouch( screenData, options ) {\r\n\t\tconst mode = options.mode;\r\n\t\tconst fn = options.fn;\r\n\t\t\r\n\t\tconst isValid = m_offevent(\r\n\t\t\tmode, fn, [ \"start\", \"end\", \"move\" ], \"offtouch\",\r\n\t\t\tscreenData.onTouchEventListeners\r\n\t\t);\r\n\t\t\r\n\t\tif( isValid ) {\r\n\t\t\tif( fn == null ) {\r\n\t\t\t\tscreenData.touchEventListenersActive = 0;\r\n\t\t\t} else {\r\n\t\t\t\tscreenData.touchEventListenersActive -= 1;\r\n\t\t\t\tif( screenData.touchEventListenersActive < 0 ) {\r\n\t\t\t\t\tscreenData.touchEventListenersActive = 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction setPinchZoom( options ) {\r\n\t\tconst isEnabled = !!( options.isEnabled );\r\n\t\tif( isEnabled ) {\r\n\t\t\tdocument.body.style.touchAction = \"\";\r\n\t\t} else {\r\n\t\t\tdocument.body.style.touchAction = \"none\";\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction touchStart( e ) {\r\n\t\tconst screenData = getScreenDataFromEvent( e );\r\n\t\tif( screenData == null ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tupdateTouch( screenData, e, \"start\" );\r\n\t\tconst touchData = getTouch( screenData );\r\n\t\tif( screenData.touchEventListenersActive > 0 ) {\r\n\t\t\tm_triggerEventListeners( \"start\", touchData, screenData.onTouchEventListeners );\r\n\t\t}\r\n\t\ttriggerPressListeners( screenData, \"down\", getTouchPress( screenData ) );\r\n\t\te.preventDefault();\r\n\t\ttriggerClickListeners( screenData, getTouchPress( screenData ), \"down\" );\r\n\t}\r\n\t\r\n\tfunction touchMove( e ) {\r\n\t\tconst screenData = getScreenDataFromEvent( e );\r\n\t\tif( screenData == null ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tupdateTouch( screenData, e, \"move\" );\r\n\t\tconst touchData = getTouch( screenData );\r\n\t\tif( screenData.touchEventListenersActive > 0 ) {\r\n\t\t\tm_triggerEventListeners( \"move\", touchData, screenData.onTouchEventListeners );\r\n\t\t}\r\n\t\ttriggerPressListeners( screenData, \"move\", getTouchPress( screenData ) );\r\n\t}\r\n\t\r\n\tfunction touchEnd( e ) {\r\n\t\tconst screenData = getScreenDataFromEvent( e );\r\n\t\tif( screenData == null ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tupdateTouch( screenData, e, \"end\" );\r\n\t\tconst touchData = getTouch( screenData );\r\n\t\tif( screenData.touchEventListenersActive > 0 ) {\r\n\t\t\tm_triggerEventListeners( \"end\", touchData, screenData.onTouchEventListeners );\r\n\t\t}\r\n\t\ttriggerPressListeners( screenData, \"up\", getTouchPress( screenData ) );\r\n\t\ttriggerClickListeners( screenData, getTouchPress( screenData ), \"up\" );\r\n\t}\r\n\t\r\n\tfunction updateTouch( screenData, e, action ) {\r\n\t\tif( !screenData.clientRect ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t\r\n\t\tconst newTouches = {};\r\n\t\tconst rect = screenData.clientRect;\r\n\t\t\r\n\t\tfor( let j = 0; j < e.touches.length; j++ ) {\r\n\t\t\tconst touch = e.touches[ j ];\r\n\t\t\tconst touchData = {};\r\n\t\t\ttouchData.x = Math.floor(\r\n\t\t\t\t( touch.clientX - rect.left ) / rect.width * screenData.width\r\n\t\t\t);\r\n\t\t\ttouchData.y = Math.floor(\r\n\t\t\t\t( touch.clientY - rect.top ) / rect.height * screenData.height\r\n\t\t\t);\r\n\t\t\ttouchData.id = touch.identifier;\r\n\t\t\tif( screenData.touches[ touchData.id ] ) {\r\n\t\t\t\ttouchData.lastX = screenData.touches[ touchData.id ].x;\r\n\t\t\t\ttouchData.lastY = screenData.touches[ touchData.id ].y;\r\n\t\t\t} else {\r\n\t\t\t\ttouchData.lastX = null;\r\n\t\t\t\ttouchData.lastY = null;\r\n\t\t\t}\r\n\t\t\ttouchData.action = action;\r\n\t\t\tnewTouches[ touchData.id ] = touchData;\r\n\t\t}\r\n\t\t\r\n\t\tscreenData.lastTouches = screenData.touches;\r\n\t\tscreenData.touches = newTouches;\r\n\t\tscreenData.lastEvent = \"touch\";\r\n\t}\r\n\t\r\n\tfunction getTouch( screenData ) {\r\n\t\tconst touchArr = [];\r\n\t\tfor( const i in screenData.touches ) {\r\n\t\t\tconst touch = screenData.touches[ i ];\r\n\t\t\tconst touchData = {\r\n\t\t\t\t\"x\": touch.x,\r\n\t\t\t\t\"y\": touch.y,\r\n\t\t\t\t\"id\": touch.id,\r\n\t\t\t\t\"lastX\": touch.lastX,\r\n\t\t\t\t\"lastY\": touch.lastY,\r\n\t\t\t\t\"action\": touch.action,\r\n\t\t\t\t\"type\": \"touch\"\r\n\t\t\t};\r\n\t\t\ttouchArr.push( touchData );\r\n\t\t}\r\n\t\treturn touchArr;\r\n\t}\r\n\t\r\n\tfunction getScreenDataFromEvent( e ) {\r\n\t\tconst screenId = e.target.dataset?.screenId;\r\n\t\tif( screenId === undefined ) {\r\n\t\t\treturn null;\r\n\t\t}\r\n\t\treturn pluginApi.getScreenData( \"touch-event\", screenId );\r\n\t}\r\n\t\r\n\tfunction onWindowBlurTouch() {\r\n\t\tconst allScreensData = pluginApi.getAllScreensData();\r\n\t\tfor( const screenData of allScreensData ) {\r\n\t\t\tscreenData.lastTouches = screenData.touches;\r\n\t\t\tscreenData.touches = {};\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction clearTouchEvents( screenData ) {\r\n\t\tscreenData.onTouchEventListeners = {};\r\n\t\tscreenData.touchEventListenersActive = 0;\r\n\t}\r\n\t\r\n\treturn {\r\n\t\t\"stopTouch\": stopTouch,\r\n\t\t\"clearTouchEvents\": clearTouchEvents\r\n\t};\r\n}\r\n\r\n\r\n", "/**\r\n * Press and Click registration for Pointer plugin.\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport { startMouseInternal } from \"./mouse.js\";\r\nimport { startTouchInternal } from \"./touch.js\";\r\n\r\nexport function registerPress( pluginApi, helpers ) {\r\n\tconst onevent = helpers.onevent;\r\n\tconst offevent = helpers.offevent;\r\n\tconst triggerEventListenersLocal = helpers.triggerEventListeners;\r\n\t\r\n\t// Expose trigger for other modules via module-level binding\r\n\tm_triggerEventListeners = triggerEventListenersLocal;\r\n\t\r\n\tpluginApi.addScreenDataItem( \"pressEventListenersActive\", 0 );\r\n\tpluginApi.addScreenDataItem( \"onPressEventListeners\", {} );\r\n\tpluginApi.addScreenDataItem( \"clickEventListenersActive\", 0 );\r\n\tpluginApi.addScreenDataItem( \"onClickEventListeners\", {} );\r\n\t\r\n\tpluginApi.addScreenInitFunction( initPressData );\r\n\t\r\n\tpluginApi.addCommand( \"inpress\", inpress, true, [] );\r\n\tpluginApi.addCommand( \"onpress\", onpress, true, [ \"mode\", \"fn\", \"once\", \"hitBox\", \"customData\" ] );\r\n\tpluginApi.addCommand( \"offpress\", offpress, true, [ \"mode\", \"fn\" ] );\r\n\tpluginApi.addCommand( \"onclick\", onclick, true, [ \"fn\", \"once\", \"hitBox\", \"customData\" ] );\r\n\tpluginApi.addCommand( \"offclick\", offclick, true, [ \"fn\" ] );\r\n\t\r\n\tfunction initPressData( screenData ) {\r\n\t\tscreenData.onPressEventListeners = {\r\n\t\t\t\"down\": [],\r\n\t\t\t\"up\": [],\r\n\t\t\t\"move\": []\r\n\t\t};\r\n\t\tscreenData.onClickEventListeners = {\r\n\t\t\t\"click\": []\r\n\t\t};\r\n\t}\r\n\t\r\n\tfunction inpress( screenData ) {\r\n\t\tstartMouseInternal( screenData );\r\n\t\tstartTouchInternal( screenData );\r\n\t\tif( screenData.lastEvent === \"touch\" ) {\r\n\t\t\treturn getTouchPress( screenData );\r\n\t\t} else {\r\n\t\t\treturn screenData.api.inmouse();\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction onpress( screenData, options ) {\r\n\t\tconst mode = options.mode;\r\n\t\tconst fn = options.fn;\r\n\t\tconst once = options.once;\r\n\t\tconst hitBox = options.hitBox;\r\n\t\tconst customData = options.customData;\r\n\t\t\r\n\t\tconst isValid = onevent(\r\n\t\t\tmode, fn, once, hitBox, [ \"down\", \"up\", \"move\" ], \"onpress\",\r\n\t\t\tscreenData.onPressEventListeners, null, null, customData\r\n\t\t);\r\n\t\t\r\n\t\tif( isValid ) {\r\n\t\t\tstartMouseInternal( screenData );\r\n\t\t\tstartTouchInternal( screenData );\r\n\t\t\tscreenData.pressEventListenersActive += 1;\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction offpress( screenData, options ) {\r\n\t\tconst mode = options.mode;\r\n\t\tconst fn = options.fn;\r\n\t\t\r\n\t\tconst isValid = offevent(\r\n\t\t\tmode, fn, [ \"down\", \"up\", \"move\" ], \"offpress\",\r\n\t\t\tscreenData.onPressEventListeners\r\n\t\t);\r\n\t\t\r\n\t\tif( isValid ) {\r\n\t\t\tif( fn == null ) {\r\n\t\t\t\tscreenData.pressEventListenersActive = 0;\r\n\t\t\t} else {\r\n\t\t\t\tscreenData.pressEventListenersActive -= 1;\r\n\t\t\t\tif( screenData.pressEventListenersActive < 0 ) {\r\n\t\t\t\t\tscreenData.pressEventListenersActive = 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction onclick( screenData, options ) {\r\n\t\tconst fn = options.fn;\r\n\t\tconst once = options.once;\r\n\t\tlet hitBox = options.hitBox;\r\n\t\tconst customData = options.customData;\r\n\t\t\r\n\t\tif( hitBox == null ) {\r\n\t\t\thitBox = {\r\n\t\t\t\t\"x\": 0,\r\n\t\t\t\t\"y\": 0,\r\n\t\t\t\t\"width\": screenData.width,\r\n\t\t\t\t\"height\": screenData.height\r\n\t\t\t};\r\n\t\t}\r\n\t\t\r\n\t\tconst isValid = onevent(\r\n\t\t\t\"click\", fn, once, hitBox, [ \"click\" ], \"onclick\",\r\n\t\t\tscreenData.onClickEventListeners, null, null, customData\r\n\t\t);\r\n\t\t\r\n\t\tif( isValid ) {\r\n\t\t\tstartMouseInternal( screenData );\r\n\t\t\tstartTouchInternal( screenData );\r\n\t\t\tscreenData.clickEventListenersActive += 1;\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction offclick( screenData, options ) {\r\n\t\tconst fn = options.fn;\r\n\t\tconst isValid = offevent(\r\n\t\t\t\"click\", fn, [ \"click\" ], \"offclick\",\r\n\t\t\tscreenData.onClickEventListeners\r\n\t\t);\r\n\t\t\r\n\t\tif( isValid ) {\r\n\t\t\tif( fn == null ) {\r\n\t\t\t\tscreenData.clickEventListenersActive = 0;\r\n\t\t\t} else {\r\n\t\t\t\tscreenData.clickEventListenersActive -= 1;\r\n\t\t\t\tif( screenData.clickEventListenersActive < 0 ) {\r\n\t\t\t\t\tscreenData.clickEventListenersActive = 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction clearPressEvents( screenData ) {\r\n\t\tscreenData.onPressEventListeners = {};\r\n\t\tscreenData.pressEventListenersActive = 0;\r\n\t}\r\n\t\r\n\tfunction clearClickEvents( screenData ) {\r\n\t\tscreenData.onClickEventListeners = {};\r\n\t\tscreenData.clickEventListenersActive = 0;\r\n\t}\r\n\t\r\n\treturn {\r\n\t\t\"clearPressEvents\": clearPressEvents,\r\n\t\t\"clearClickEvents\": clearClickEvents\r\n\t};\r\n}\r\n\r\n// Module-level reference to event trigger helper\r\nlet m_triggerEventListeners = null;\r\n\r\nexport function triggerPressListeners( screenData, mode, data ) {\r\n\tif( screenData.pressEventListenersActive > 0 && m_triggerEventListeners ) {\r\n\t\tm_triggerEventListeners( mode, data, screenData.onPressEventListeners );\r\n\t}\r\n}\r\n\r\nexport function triggerClickListeners( screenData, data, clickStatus ) {\r\n\tif( screenData.clickEventListenersActive > 0 && m_triggerEventListeners ) {\r\n\t\tm_triggerEventListeners( \"click\", data, screenData.onClickEventListeners, clickStatus );\r\n\t}\r\n}\r\n\r\nexport function getTouchPress( screenData ) {\r\n\tfunction copyTouches( touches, touchArr, action ) {\r\n\t\tfor( const i in touches ) {\r\n\t\t\tconst touch = touches[ i ];\r\n\t\t\tconst touchData = {\r\n\t\t\t\t\"x\": touch.x,\r\n\t\t\t\t\"y\": touch.y,\r\n\t\t\t\t\"id\": touch.id,\r\n\t\t\t\t\"lastX\": touch.lastX,\r\n\t\t\t\t\"lastY\": touch.lastY,\r\n\t\t\t\t\"action\": touch.action,\r\n\t\t\t\t\"type\": \"touch\"\r\n\t\t\t};\r\n\t\t\tif( action !== undefined ) {\r\n\t\t\t\ttouchData.action = action;\r\n\t\t\t}\r\n\t\t\ttouchArr.push( touchData );\r\n\t\t}\r\n\t}\r\n\t\r\n\tconst touchArr = [];\r\n\tcopyTouches( screenData.touches, touchArr );\r\n\tif( touchArr.length === 0 ) {\r\n\t\tcopyTouches( screenData.lastTouches, touchArr, \"up\" );\r\n\t}\r\n\tif( touchArr.length > 0 ) {\r\n\t\tconst touchData = touchArr[ 0 ];\r\n\t\tif( touchData.action === \"up\" ) {\r\n\t\t\ttouchData.buttons = 0;\r\n\t\t} else {\r\n\t\t\ttouchData.buttons = 1;\r\n\t\t}\r\n\t\ttouchData.touches = touchArr;\r\n\t\treturn touchData;\r\n\t} else {\r\n\t\treturn {\r\n\t\t\t\"x\": -1,\r\n\t\t\t\"y\": -1,\r\n\t\t\t\"id\": -1,\r\n\t\t\t\"lastX\": -1,\r\n\t\t\t\"lastY\": -1,\r\n\t\t\t\"action\": \"none\",\r\n\t\t\t\"buttons\": 0,\r\n\t\t\t\"type\": \"touch\"\r\n\t\t};\r\n\t}\r\n}\r\n\r\n\r\n", "/**\r\n * Mouse registration for Pointer plugin.\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport { triggerPressListeners, triggerClickListeners, getTouchPress } from \"./press.js\";\r\n\r\n// Module-level reference to startMouseInternal function\r\nlet m_startMouseInternal = null;\r\n\r\nexport function startMouseInternal( screenData ) {\r\n\tif( m_startMouseInternal ) {\r\n\t\tm_startMouseInternal( screenData );\r\n\t}\r\n}\r\n\r\nexport function registerMouse( pluginApi, helpers ) {\r\n\tconst m_onevent = helpers.onevent;\r\n\tconst m_offevent = helpers.offevent;\r\n\tconst m_triggerEventListeners = helpers.triggerEventListeners;\r\n\r\n\tpluginApi.addScreenDataItem( \"mouseStopped\", false );\r\n\tpluginApi.addScreenDataItem( \"mouseStarted\", false );\r\n\tpluginApi.addScreenDataItem( \"mouse\", null );\r\n\tpluginApi.addScreenDataItem( \"lastEvent\", null );\r\n\tpluginApi.addScreenDataItem( \"isContextMenuEnabled\", false );\r\n\tpluginApi.addScreenDataItem( \"mouseEventListenersActive\", 0 );\r\n\tpluginApi.addScreenDataItem( \"onMouseEventListeners\", {\r\n\t\t\"down\": [],\r\n\t\t\"up\": [],\r\n\t\t\"move\": []\r\n\t} );\r\n\t\r\n\tpluginApi.addScreenInitFunction( initMouseData );\r\n\twindow.addEventListener( \"blur\", onWindowBlurMouse );\r\n\t\r\n\tpluginApi.addCommand( \"startMouse\", startMouse, true, [] );\r\n\tpluginApi.addCommand( \"stopMouse\", stopMouse, true, [] );\r\n\tpluginApi.addCommand( \"inmouse\", inmouse, true, [] );\r\n\tpluginApi.addCommand( \"setEnableContextMenu\", setEnableContextMenu, true, [ \"isEnabled\" ] );\r\n\tpluginApi.addCommand(\r\n\t\t\"onmouse\", onmouse, true, [ \"mode\", \"fn\", \"once\", \"hitBox\", \"customData\" ]\r\n\t);\r\n\tpluginApi.addCommand( \"offmouse\", offmouse, true, [ \"mode\", \"fn\" ] );\r\n\t\r\n\tfunction initMouseData( screenData ) {\r\n\t\tscreenData.mouse = {\r\n\t\t\t\"x\": Math.floor( screenData.width / 2 ),\r\n\t\t\t\"y\": Math.floor( screenData.height / 2 ),\r\n\t\t\t\"lastX\": Math.floor( screenData.width / 2 ),\r\n\t\t\t\"lastY\": Math.floor( screenData.height / 2 ),\r\n\t\t\t\"buttons\": 0,\r\n\t\t\t\"action\": \"none\"\r\n\t\t};\r\n\t}\r\n\t\r\n\tfunction startMouseInternal( screenData ) {\r\n\r\n\t\t// Do not start mouse if explicitly stopped\r\n\t\tif( screenData.mouseStopped === false ) {\r\n\t\t\tstartMouse( screenData );\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Store reference for module-level export\r\n\tm_startMouseInternal = startMouseInternal;\r\n\r\n\tfunction startMouse( screenData ) {\r\n\r\n\t\t//Clear explicit mouseStopped\r\n\t\tscreenData.mouseStopped = false;\r\n\r\n\t\tif( !screenData.mouseStarted ) {\r\n\t\t\tscreenData.canvas.addEventListener( \"mousemove\", mouseMove );\r\n\t\t\tscreenData.canvas.addEventListener( \"mousedown\", mouseDown );\r\n\t\t\tscreenData.canvas.addEventListener( \"mouseup\", mouseUp );\r\n\t\t\tscreenData.canvas.addEventListener( \"contextmenu\", onContextMenu );\r\n\t\t\tscreenData.mouseStarted = true;\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction stopMouse( screenData ) {\r\n\r\n\t\t// Explicitly set mouse to stoppedto prevent mouse commands from starting mouse when\r\n\t\t// use explicitly sets it to true\r\n\t\tscreenData.mouseStopped = true;\r\n\r\n\t\tif( screenData.mouseStarted ) {\r\n\t\t\tscreenData.canvas.removeEventListener( \"mousemove\", mouseMove );\r\n\t\t\tscreenData.canvas.removeEventListener( \"mousedown\", mouseDown );\r\n\t\t\tscreenData.canvas.removeEventListener( \"mouseup\", mouseUp );\r\n\t\t\tscreenData.canvas.removeEventListener( \"contextmenu\", onContextMenu );\r\n\t\t\tscreenData.mouseStarted = false;\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction getMouse( screenData ) {\r\n\t\tconst mouse = {};\r\n\t\tmouse.x = screenData.mouse.x;\r\n\t\tmouse.y = screenData.mouse.y;\r\n\t\tmouse.lastX = screenData.mouse.lastX;\r\n\t\tmouse.lastY = screenData.mouse.lastY;\r\n\t\tmouse.buttons = screenData.mouse.buttons;\r\n\t\tmouse.action = screenData.mouse.action;\r\n\t\tmouse.type = \"mouse\";\r\n\t\treturn mouse;\r\n\t}\r\n\t\r\n\tfunction inmouse( screenData ) {\r\n\t\tstartMouseInternal( screenData );\r\n\t\treturn getMouse( screenData );\r\n\t}\r\n\t\r\n\tfunction setEnableContextMenu( screenData, options ) {\r\n\t\tscreenData.isContextMenuEnabled = !!( options.isEnabled );\r\n\t\tstartMouseInternal( screenData );\r\n\t}\r\n\t\r\n\tfunction onmouse( screenData, options ) {\r\n\t\tconst mode = options.mode;\r\n\t\tconst fn = options.fn;\r\n\t\tconst once = options.once;\r\n\t\tconst hitBox = options.hitBox;\r\n\t\tconst customData = options.customData;\r\n\t\t\r\n\t\tconst isValid = m_onevent(\r\n\t\t\tmode, fn, once, hitBox, [ \"down\", \"up\", \"move\" ], \"onmouse\",\r\n\t\t\tscreenData.onMouseEventListeners, null, null, customData\r\n\t\t);\r\n\t\t\r\n\t\tif( isValid ) {\r\n\t\t\tstartMouseInternal( screenData );\r\n\t\t\tscreenData.mouseEventListenersActive += 1;\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction offmouse( screenData, options ) {\r\n\t\tconst mode = options.mode;\r\n\t\tconst fn = options.fn;\r\n\t\t\r\n\t\tconst isValid = m_offevent(\r\n\t\t\tmode, fn, [ \"down\", \"up\", \"move\" ], \"offmouse\",\r\n\t\t\tscreenData.onMouseEventListeners\r\n\t\t);\r\n\t\t\r\n\t\tif( isValid ) {\r\n\t\t\tif( fn == null ) {\r\n\t\t\t\tscreenData.mouseEventListenersActive = 0;\r\n\t\t\t} else {\r\n\t\t\t\tscreenData.mouseEventListenersActive -= 1;\r\n\t\t\t\tif( screenData.mouseEventListenersActive < 0 ) {\r\n\t\t\t\t\tscreenData.mouseEventListenersActive = 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction clearMouseEvents( screenData ) {\r\n\t\tscreenData.onMouseEventListeners = {\r\n\t\t\t\"down\": [],\r\n\t\t\t\"up\": [],\r\n\t\t\t\"move\": []\r\n\t\t};\r\n\t\tscreenData.mouseEventListenersActive = 0;\r\n\t}\r\n\t\r\n\tfunction mouseMove( e ) {\r\n\t\tconst screenData = getScreenDataFromEvent( e );\r\n\t\tif( !screenData ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tupdateMouse( screenData, e, \"move\" );\r\n\t\tconst mouseData = getMouse( screenData );\r\n\t\tif( screenData.mouseEventListenersActive > 0 ) {\r\n\t\t\tm_triggerEventListeners( \"move\", mouseData, screenData.onMouseEventListeners );\r\n\t\t}\r\n\t\ttriggerPressListeners( screenData, \"move\", mouseData );\r\n\t}\r\n\t\r\n\tfunction mouseDown( e ) {\r\n\t\tconst screenData = getScreenDataFromEvent( e );\r\n\t\tif( !screenData ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tupdateMouse( screenData, e, \"down\" );\r\n\t\tconst mouseData = getMouse( screenData );\r\n\t\tif( screenData.mouseEventListenersActive > 0 ) {\r\n\t\t\tm_triggerEventListeners( \"down\", mouseData, screenData.onMouseEventListeners );\r\n\t\t}\r\n\t\ttriggerPressListeners( screenData, \"down\", mouseData );\r\n\t\ttriggerClickListeners( screenData, mouseData, \"down\" );\r\n\t}\r\n\t\r\n\tfunction mouseUp( e ) {\r\n\t\tconst screenData = getScreenDataFromEvent( e );\r\n\t\tif( !screenData ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tupdateMouse( screenData, e, \"up\" );\r\n\t\tconst mouseData = getMouse( screenData );\r\n\t\tif( screenData.mouseEventListenersActive > 0 ) {\r\n\t\t\tm_triggerEventListeners( \"up\", mouseData, screenData.onMouseEventListeners );\r\n\t\t}\r\n\t\ttriggerPressListeners( screenData, \"up\", mouseData );\r\n\t\ttriggerClickListeners( screenData, mouseData, \"up\" );\r\n\t}\r\n\t\r\n\tfunction onContextMenu( e ) {\r\n\t\tconst screenData = getScreenDataFromEvent( e );\r\n\t\tif( !screenData ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif( !screenData.isContextMenuEnabled ) {\r\n\t\t\te.preventDefault();\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction updateMouse( screenData, e, action ) {\r\n\t\tconst rect = screenData.clientRect;\r\n\t\tconst x = Math.floor(\r\n\t\t\te.offsetX / rect.width * screenData.width\r\n\t\t);\r\n\t\tconst y = Math.floor(\r\n\t\t\te.offsetY / rect.height * screenData.height\r\n\t\t);\r\n\t\t\r\n\t\tlet lastX = x;\r\n\t\tlet lastY = y;\r\n\t\t\r\n\t\tif( screenData.mouse ) {\r\n\t\t\tif( screenData.mouse.x !== undefined ) {\r\n\t\t\t\tlastX = screenData.mouse.x;\r\n\t\t\t}\r\n\t\t\tif( screenData.mouse.y !== undefined ) {\r\n\t\t\t\tlastY = screenData.mouse.y;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tscreenData.mouse = {\r\n\t\t\t\"x\": x,\r\n\t\t\t\"y\": y,\r\n\t\t\t\"lastX\": lastX,\r\n\t\t\t\"lastY\": lastY,\r\n\t\t\t\"buttons\": e.buttons,\r\n\t\t\t\"action\": action\r\n\t\t};\r\n\t\tscreenData.lastEvent = \"mouse\";\r\n\t}\r\n\t\r\n\tfunction getScreenDataFromEvent( e ) {\r\n\t\tconst screenId = e.target.dataset?.screenId;\r\n\t\tif( screenId === undefined ) {\r\n\t\t\treturn null;\r\n\t\t}\r\n\t\treturn pluginApi.getScreenData( \"mouse-event\", screenId );\r\n\t}\r\n\t\r\n\tfunction onWindowBlurMouse() {\r\n\t\tconst allScreensData = pluginApi.getAllScreensData();\r\n\t\tfor( const screenData of allScreensData ) {\r\n\t\t\tscreenData.mouse.buttons = 0;\r\n\t\t\tscreenData.mouse.action = \"up\";\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn {\r\n\t\t\"stopMouse\": stopMouse,\r\n\t\t\"clearMouseEvents\": clearMouseEvents\r\n\t};\r\n}\r\n\r\n\r\n", "/**\r\n * Pi.js - Pointer Plugin\r\n * \r\n * Mouse, touch, and press handling ported from alpha.1 as a plugin.\r\n * \r\n * @module plugins/pointer\r\n * @version 1.0.0\r\n */\r\n\r\n\"use strict\";\r\n\r\nimport { createEventHelpers } from \"./shared-events.js\";\r\nimport { registerMouse } from \"./mouse.js\";\r\nimport { registerTouch } from \"./touch.js\";\r\nimport { registerPress } from \"./press.js\";\r\n\r\n\r\n/***************************************************************************************************\r\n * Plugin Initialization\r\n **************************************************************************************************/\r\n\r\n\r\nexport default function pointerPlugin( pluginApi ) {\r\n\t\r\n\t// Create shared helpers (onevent/offevent/triggerEventListeners)\r\n\tconst helpers = createEventHelpers( pluginApi );\r\n\t\r\n\t// Register feature modules\r\n\tconst mouseApi = registerMouse( pluginApi, helpers );\r\n\tconst touchApi = registerTouch( pluginApi, helpers );\r\n\tconst pressApi = registerPress( pluginApi, helpers );\r\n\t\r\n\t// Register clearEvents handlers for mouse, touch, and press\r\n\tpluginApi.registerClearEvents( \"mouse\", ( screenData ) => {\r\n\t\tif( screenData !== null ) {\r\n\t\t\t\r\n\t\t\t// Clear mouse events for specific screen\r\n\t\t\tmouseApi.clearMouseEvents( screenData );\r\n\t\t} else {\r\n\t\t\t// Clear mouse events for all screens\r\n\t\t\tconst allScreensData = pluginApi.getAllScreensData();\r\n\t\t\tfor( const sd of allScreensData ) {\r\n\t\t\t\tmouseApi.clearMouseEvents( sd );\r\n\t\t\t}\r\n\t\t}\r\n\t} );\r\n\t\r\n\tpluginApi.registerClearEvents( \"touch\", ( screenData ) => {\r\n\t\tif( screenData !== null ) {\r\n\t\t\t// Clear touch events for specific screen\r\n\t\t\ttouchApi.clearTouchEvents( screenData );\r\n\t\t} else {\r\n\t\t\t// Clear touch events for all screens\r\n\t\t\tconst allScreensData = pluginApi.getAllScreensData();\r\n\t\t\tfor( const sd of allScreensData ) {\r\n\t\t\t\ttouchApi.clearTouchEvents( sd );\r\n\t\t\t}\r\n\t\t}\r\n\t} );\r\n\t\r\n\tpluginApi.registerClearEvents( \"press\", ( screenData ) => {\r\n\t\tif( screenData !== null ) {\r\n\t\t\t// Clear press and click events for specific screen\r\n\t\t\tpressApi.clearPressEvents( screenData );\r\n\t\t\tpressApi.clearClickEvents( screenData );\r\n\t\t} else {\r\n\t\t\t// Clear press and click events for all screens\r\n\t\t\tconst allScreensData = pluginApi.getAllScreensData();\r\n\t\t\tfor( const sd of allScreensData ) {\r\n\t\t\t\tpressApi.clearPressEvents( sd );\r\n\t\t\t\tpressApi.clearClickEvents( sd );\r\n\t\t\t}\r\n\t\t}\r\n\t} );\r\n\t\r\n\t// Screen cleanup\r\n\tpluginApi.addScreenCleanupFunction( ( screenData ) => {\r\n\t\tif( screenData.mouseStarted ) {\r\n\t\t\tmouseApi.stopMouse( screenData );\r\n\t\t}\r\n\t\tif( screenData.touchStarted ) {\r\n\t\t\ttouchApi.stopTouch( screenData );\r\n\t\t}\r\n\t\tmouseApi.clearMouseEvents( screenData );\r\n\t\ttouchApi.clearTouchEvents( screenData );\r\n\t\tpressApi.clearPressEvents( screenData );\r\n\t\tpressApi.clearClickEvents( screenData );\r\n\t} );\r\n}\r\n\r\n\r\n// Auto-register in IIFE mode (when loaded via <script> tag)\r\nif( typeof window !== \"undefined\" && window.pi ) {\r\n\twindow.pi.registerPlugin( {\r\n\t\t\"name\": \"pointer\",\r\n\t\t\"version\": \"1.0.0\",\r\n\t\t\"description\": \"Mouse and touch input handling for Pi.js\",\r\n\t\t\"init\": pointerPlugin\r\n\t} );\r\n}\r\n\r\n\r\n", "/**\r\n * Pi.js - Full Version Entry Point\r\n * \r\n * Includes core Pi.js functionality plus key plugins:\r\n * - gamepad: Gamepad input handling\r\n * - keyboard: Keyboard input handling\r\n * - sound: Music playback and sound effects\r\n * - pointer: Mouse, touch, and press handling\r\n * \r\n * This is the official Pi.js library with essential plugins included.\r\n * \r\n * @module pi.js-full\r\n * @author Andy Stubbs\r\n * @license Apache-2.0\r\n */\r\n\r\n\"use strict\";\r\n\r\n// Import the core API (this initializes everything)\r\nimport api from \"./index.js\";\r\n\r\n// Import plugins\r\nimport \"../plugins/gamepad/index.js\";\r\nimport \"../plugins/keyboard/index.js\";\r\nimport \"../plugins/sound/index.js\";\r\nimport \"../plugins/pointer/index.js\";\r\n\r\n// Export the same API (now with plugins)\r\nexport default api;\r\nexport { api as pi };\r\n\r\n"],
  "mappings": "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AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAC7E;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAC7E;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAC7E;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAC7E;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAC7E;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAC7E;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAC7E;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAC7E;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAC7E;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAC7E;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAC7E;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAC7E;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAC7E;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAC7E;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAAW;AAAA,MAC7E;AAAA,MAAW;AAAA,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",
  "names": ["queueMicrotask", "pad", "init", "init", "cleanup", "init", "display_default", "display_default", "input", "init", "init", "api", "point_default", "image_default", "m_isDebug", "init", "point_default", "image_default", "init", "init", "cleanup", "init", "queueMicrotask", "batch", "x", "y", "a", "b", "m_isDebug", "init", "api", "cleanup", "queueMicrotask", "init", "init", "init", "init", "api", "registerCommands", "img", "init", "api", "registerCommands", "createColor", "init", "init", "init", "api", "registerCommands", "init", "api", "registerCommands", "init", "api", "cls", "init", "api", "resizeScreen", "registerCommands", "screen", "m_api", "init", "api", "registerCommands", "init", "m_api", "init", "api", "init", "init", "api", "registerCommands", "queueMicrotask", "init", "init", "api", "registerCommands", "init", "init", "api", "registerCommands", "init", "init", "api", "registerCommands", "error", "input", "uniformError", "init", "i", "init", "api", "registerCommands", "api", "key", "sound", "wait", "customData", "m_triggerEventListeners", "startTouchInternal", "touchArr", "m_triggerEventListeners", "startMouseInternal"]
}
