From 4a287e65625cf517fa54da70532fa7d739893209 Mon Sep 17 00:00:00 2001 From: Fabio Bettio Date: Sun, 3 Nov 2024 22:30:54 +0100 Subject: [PATCH] Improve style --- jsdoc/template/openlime/publish.js | 177 ++++++++++---------- src/Annotation.js | 2 + src/Draggable.js | 2 +- src/EditorSvgAnnotation.js | 12 +- src/LayerSvgAnnotation.js | 6 +- src/Layout.js | 10 +- src/LayoutTileImages.js | 10 +- src/LayoutTiles.js | 27 +--- src/PointerManager.js | 143 +++++++++++------ src/ScaleBar.js | 1 - src/Shader.js | 27 ---- src/ShaderBRDF.js | 73 ++++----- src/ShaderCombiner.js | 73 ++------- src/ShaderDstretch.js | 78 ++------- src/ShaderFilter.js | 52 +----- src/ShaderFilterColormap.js | 126 ++++----------- src/ShaderFilterVector.js | 163 ++++++++----------- src/ShaderFilterVectorGlyph.js | 93 +++-------- src/ShaderLens.js | 141 ++++++++-------- src/ShaderNeural.js | 165 ++++++++----------- src/ShaderRTI.js | 22 +-- src/Signals.js | 61 ++++--- src/Skin.js | 77 +++++---- src/TextToSpeechPlayer.js | 104 ++++++------ src/Tile.js | 149 ++++++++++++++--- src/Transform.js | 84 +++++----- src/UIBasic.js | 250 +++++++++++++++-------------- src/Util.js | 2 +- src/Viewer.js | 93 ++++++----- 29 files changed, 1008 insertions(+), 1215 deletions(-) diff --git a/jsdoc/template/openlime/publish.js b/jsdoc/template/openlime/publish.js index d4e504f4..951272bb 100644 --- a/jsdoc/template/openlime/publish.js +++ b/jsdoc/template/openlime/publish.js @@ -173,11 +173,11 @@ function addSignatureParams(f) { var element = params[i]; var seperator = (i > 0) ? ', ' : ''; - if (!new RegExp("class=[\"|']" + optionalClass + "[\"|']").test(element)) { + if (!new RegExp("class=[\"|']"+optionalClass+"[\"|']").test(element)) { f.signature += seperator + element; } else { - var regExp = new RegExp("(.*?)<\\/span>", "i"); - f.signature += element.replace(regExp, " $`[" + seperator + "$1$']"); + var regExp = new RegExp("(.*?)<\\/span>", "i"); + f.signature += element.replace(regExp, " $`["+seperator+"$1$']"); } } @@ -222,10 +222,10 @@ function shortenPaths(files, commonPrefix) { // .replace( prefix, '' ); // } ); - Object.keys(files).forEach(function (file) { + Object.keys(files).forEach(function(file) { files[file].shortened = files[file].resolved.replace(commonPrefix, '') - // always use forward slashes - .replace(/\\/g, '/'); + // always use forward slashes + .replace(/\\/g, '/'); }); @@ -255,7 +255,7 @@ function searchData(html) { if (endOfContent > 0) { html = html.substring(0, endOfContent); } - var stripped = sanitizeHtml(html, { allowedTags: [], allowedAttributes: [] }); + var stripped = sanitizeHtml(html, {allowedTags: [], allowedAttributes: []}); stripped = stripped.replace(/\s+/g, ' '); return stripped; } @@ -288,7 +288,7 @@ function generate(docType, title, docs, filename, resolveLinks) { } function generateSourceFiles(sourceFiles) { - Object.keys(sourceFiles).forEach(function (file) { + Object.keys(sourceFiles).forEach(function(file) { var source; // links are keyed to the shortened path in each doclet's `meta.shortpath` property var sourceOutfile = helper.getUniqueFilename(sourceFiles[file].shortened); @@ -323,20 +323,20 @@ function attachModuleSymbols(doclets, modules) { var symbols = {}; // build a lookup table - doclets.forEach(function (symbol) { + doclets.forEach(function(symbol) { symbols[symbol.longname] = symbols[symbol.longname] || []; symbols[symbol.longname].push(symbol); }); - return modules.map(function (module) { + return modules.map(function(module) { if (symbols[module.longname]) { module.modules = symbols[module.longname] - // Only show symbols that have a description. Make an exception for classes, because - // we want to show the constructor-signature heading no matter what. - .filter(function (symbol) { - return symbol.description || symbol.kind === 'class'; - }) - .map(function (symbol) { + // Only show symbols that have a description. Make an exception for classes, because + // we want to show the constructor-signature heading no matter what. + .filter(function(symbol) { + return symbol.description || symbol.kind === 'class'; + }) + .map(function(symbol) { symbol = doop(symbol); if (symbol.kind === 'class' || symbol.kind === 'function') { @@ -369,8 +369,9 @@ function buildNav(members) { var nav = navigationMaster; if (members.modules.length) { - members.modules.forEach(function (m) { + members.modules.forEach(function(m) { if (!hasOwnProp.call(seen, m.longname)) { + nav.module.members.push(linkto(m.longname, m.longname.replace("module:", ""))); } seen[m.longname] = true; @@ -379,7 +380,7 @@ function buildNav(members) { if (members.externals.length) { - members.externals.forEach(function (e) { + members.externals.forEach(function(e) { if (!hasOwnProp.call(seen, e.longname)) { nav.external.members.push(linkto(e.longname, e.name.replace(/(^"|"$)/g, ''))); @@ -390,7 +391,7 @@ function buildNav(members) { if (members.classes.length) { - members.classes.forEach(function (c) { + members.classes.forEach(function(c) { if (!hasOwnProp.call(seen, c.longname)) { nav.class.members.push(linkto(c.longname, c.longname.replace("module:", ""))); @@ -402,7 +403,7 @@ function buildNav(members) { if (members.events.length) { - members.events.forEach(function (e) { + members.events.forEach(function(e) { if (!hasOwnProp.call(seen, e.longname)) { nav.event.members.push(linkto(e.longname, e.longname.replace("module:", ""))); @@ -414,7 +415,7 @@ function buildNav(members) { if (members.namespaces.length) { - members.namespaces.forEach(function (n) { + members.namespaces.forEach(function(n) { if (!hasOwnProp.call(seen, n.longname)) { nav.namespace.members.push(linkto(n.longname, n.longname.replace("module:", ""))); @@ -426,7 +427,7 @@ function buildNav(members) { if (members.mixins.length) { - members.mixins.forEach(function (m) { + members.mixins.forEach(function(m) { if (!hasOwnProp.call(seen, m.longname)) { nav.mixin.members.push(linkto(m.longname, m.longname.replace("module:", ""))); @@ -438,7 +439,7 @@ function buildNav(members) { if (members.interfaces && members.interfaces.length) { - members.interfaces.forEach(function (m) { + members.interfaces.forEach(function(m) { if (!hasOwnProp.call(seen, m.longname)) { nav.interface.members.push(linkto(m.longname, m.longname.replace("module:", ""))); @@ -450,7 +451,7 @@ function buildNav(members) { if (members.tutorials.length) { - members.tutorials.forEach(function (t) { + members.tutorials.forEach(function(t) { nav.tutorial.members.push(tutoriallink(t.name)); }); @@ -458,7 +459,7 @@ function buildNav(members) { } if (members.globals.length) { - members.globals.forEach(function (g) { + members.globals.forEach(function(g) { if (g.kind !== 'typedef' && !hasOwnProp.call(seen, g.longname)) { nav.global.members.push(linkto(g.longname, g.longname.replace("module:", ""))); @@ -473,7 +474,7 @@ function buildNav(members) { } var topLevelNav = []; - _.each(nav, function (entry, name) { + _.each(nav, function(entry, name) { if (entry.members.length > 0 && name !== "index") { topLevelNav.push({ title: entry.title, @@ -490,7 +491,7 @@ function buildNav(members) { @param {object} opts @param {Tutorial} tutorials */ -exports.publish = function (taffyData, opts, tutorials) { +exports.publish = function(taffyData, opts, tutorials) { data = taffyData; conf['default'] = conf['default'] || {}; @@ -510,7 +511,7 @@ exports.publish = function (taffyData, opts, tutorials) { // set up templating view.layout = conf['default'].layoutFile ? path.getResourcePath(path.dirname(conf['default'].layoutFile), - path.basename(conf['default'].layoutFile)) : 'layout.tmpl'; + path.basename(conf['default'].layoutFile) ) : 'layout.tmpl'; // set up tutorials for helper helper.setTutorials(tutorials); @@ -527,11 +528,11 @@ exports.publish = function (taffyData, opts, tutorials) { var sourceFiles = {}; var sourceFilePaths = []; - data().each(function (doclet) { + data().each(function(doclet) { doclet.attribs = ''; if (doclet.examples) { - doclet.examples = doclet.examples.map(function (example) { + doclet.examples = doclet.examples.map(function(example) { var caption, lang; // allow using a markdown parser on the examples captions (surrounded by useless HTML p tags) @@ -558,7 +559,7 @@ exports.publish = function (taffyData, opts, tutorials) { }); } if (doclet.see) { - doclet.see.forEach(function (seeItem, i) { + doclet.see.forEach(function(seeItem, i) { doclet.see[i] = hashToLink(doclet, seeItem); }); } @@ -575,7 +576,7 @@ exports.publish = function (taffyData, opts, tutorials) { //Check to see if the array of source file paths already contains // the source path, if not then add it if (sourceFilePaths.indexOf(sourcePath) === -1) { - sourceFilePaths.push(sourcePath) + sourceFilePaths.push(sourcePath) } } }); @@ -593,41 +594,41 @@ exports.publish = function (taffyData, opts, tutorials) { // } fs.mkPath(outdir); - // copy the template's static files to outdir - var fromDir = path.join(templatePath, 'static'); - var staticFiles = fs.ls(fromDir, 3); - - staticFiles.forEach(function (fileName) { - var toFile = fileName.replace(fromDir, outdir); - var toDir = fs.toDir(toFile); - fs.mkPath(toDir); - fs.copyFileSync(fileName, '', toFile); - }); - - // copy user-specified static files to outdir - var staticFilePaths; - var staticFileFilter; - var staticFileScanner; - if (conf.default.staticFiles) { - // The canonical property name is `include`. We accept `paths` for backwards compatibility - // with a bug in JSDoc 3.2.x. - staticFilePaths = conf.default.staticFiles.include || - conf.default.staticFiles.paths || - []; - staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf.default.staticFiles); - staticFileScanner = new (require('jsdoc/src/scanner')).Scanner(); - - staticFilePaths.forEach(function (filePath) { - var extraStaticFiles = staticFileScanner.scan([filePath], 10, staticFileFilter); - - extraStaticFiles.forEach(function (fileName) { - var sourcePath = fs.toDir(filePath); - var toDir = fs.toDir(fileName.replace(sourcePath, outdir)); - fs.mkPath(toDir); - fs.copyFileSync(fileName, toDir); - }); - }); - } + // copy the template's static files to outdir + var fromDir = path.join( templatePath, 'static' ); + var staticFiles = fs.ls( fromDir, 3 ); + + staticFiles.forEach( function ( fileName ) { + var toFile = fileName.replace( fromDir, outdir ); + var toDir = fs.toDir( toFile ); + fs.mkPath( toDir ); + fs.copyFileSync( fileName, '', toFile ); + } ); + + // copy user-specified static files to outdir + var staticFilePaths; + var staticFileFilter; + var staticFileScanner; + if (conf.default.staticFiles) { + // The canonical property name is `include`. We accept `paths` for backwards compatibility + // with a bug in JSDoc 3.2.x. + staticFilePaths = conf.default.staticFiles.include || + conf.default.staticFiles.paths || + []; + staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf.default.staticFiles); + staticFileScanner = new (require('jsdoc/src/scanner')).Scanner(); + + staticFilePaths.forEach(function(filePath) { + var extraStaticFiles = staticFileScanner.scan([filePath], 10, staticFileFilter); + + extraStaticFiles.forEach(function(fileName) { + var sourcePath = fs.toDir(filePath); + var toDir = fs.toDir( fileName.replace(sourcePath, outdir) ); + fs.mkPath(toDir); + fs.copyFileSync(fileName, toDir); + }); + }); + } if (sourceFilePaths.length) { var payload = navOptions.sourceRootPath; @@ -636,7 +637,7 @@ exports.publish = function (taffyData, opts, tutorials) { } sourceFiles = shortenPaths(sourceFiles, payload); } - data().each(function (doclet) { + data().each(function(doclet) { var url = helper.createLink(doclet); helper.registerLink(doclet.longname, url); @@ -653,7 +654,7 @@ exports.publish = function (taffyData, opts, tutorials) { } }); - data().each(function (doclet) { + data().each(function(doclet) { var url = helper.longnameToUrl[doclet.longname]; if (url.indexOf('#') > -1) { @@ -670,7 +671,7 @@ exports.publish = function (taffyData, opts, tutorials) { }); // do this after the urls have all been generated - data().each(function (doclet) { + data().each(function(doclet) { doclet.ancestors = getAncestorLinks(doclet); if (doclet.kind === 'member') { @@ -701,11 +702,11 @@ exports.publish = function (taffyData, opts, tutorials) { view.nav = navigationMaster; view.navOptions = navOptions; attachModuleSymbols(find({ - kind: ['class', 'function'], - longname: { - left: 'module:' - } - }), + kind: ['class', 'function'], + longname: { + left: 'module:' + } + }), members.modules); // only output pretty-printed source files if requested; do this before generating any other @@ -772,8 +773,8 @@ exports.publish = function (taffyData, opts, tutorials) { // index page displays information from package.json and lists files var files = find({ - kind: 'file' - }), + kind: 'file' + }), packages = find({ kind: 'package' }); @@ -871,30 +872,30 @@ exports.publish = function (taffyData, opts, tutorials) { // tutorials can have only one parent so there is no risk for loops function saveChildren(node) { - node.children.forEach(function (child) { + node.children.forEach(function(child) { generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name)); saveChildren(child); }); } function generateQuickTextSearch(templatePath, searchableDocuments, navOptions) { - var data = { - searchableDocuments: JSON.stringify(searchableDocuments), - navOptions: navOptions - }; + var data = { + searchableDocuments: JSON.stringify(searchableDocuments), + navOptions: navOptions + }; - var tmplString = fs.readFileSync(templatePath + "/quicksearch.tmpl").toString(), - tmpl = _.template(tmplString); + var tmplString = fs.readFileSync(templatePath + "/quicksearch.tmpl").toString(), + tmpl = _.template(tmplString); - var html = tmpl(data), - outpath = path.join(outdir, "quicksearch.html"); + var html = tmpl(data), + outpath = path.join(outdir, "quicksearch.html"); - fs.writeFileSync(outpath, html, "utf8"); + fs.writeFileSync(outpath, html, "utf8"); } saveChildren(tutorials); if (searchEnabled) { - generateQuickTextSearch(templatePath + '/tmpl', searchableDocuments, navOptions); + generateQuickTextSearch(templatePath + '/tmpl', searchableDocuments, navOptions); } }; diff --git a/src/Annotation.js b/src/Annotation.js index 1f22ab63..47628ab6 100644 --- a/src/Annotation.js +++ b/src/Annotation.js @@ -6,6 +6,7 @@ import { BoundingBox } from './BoundingBox.js' * additional information for interpreting underlying drawings. * Each annotation has a unique identifier and can contain various properties * such as description, category, drawing style, labels, etc. + * */ class Annotation { /** @@ -28,6 +29,7 @@ class Annotation { * @param {boolean} [options.ready=false] - Indicates if SVG conversion is complete. * @param {boolean} [options.needsUpdate=true] - Indicates if annotation needs updating. * @param {boolean} [options.editing=false] - Indicates if annotation is being edited. + * @class */ constructor(options) { Object.assign( diff --git a/src/Draggable.js b/src/Draggable.js index 93d70adc..c2abe959 100644 --- a/src/Draggable.js +++ b/src/Draggable.js @@ -15,7 +15,7 @@ * - Touch-enabled dragging support * - Configurable spacing between handle and content * - * @class + * */ class Draggable { /** diff --git a/src/EditorSvgAnnotation.js b/src/EditorSvgAnnotation.js index d5766673..db1cbbde 100644 --- a/src/EditorSvgAnnotation.js +++ b/src/EditorSvgAnnotation.js @@ -5,7 +5,7 @@ import { LayerSvgAnnotation } from './LayerSvgAnnotation.js' import { CoordinateSystem } from './CoordinateSystem.js' /** - * @typedef {Object} Annotation + * @typedef {Object} AnnotationObj * @property {string} id - Unique identifier * @property {string} label - Annotation title * @property {string} description - Detailed description @@ -18,26 +18,26 @@ import { CoordinateSystem } from './CoordinateSystem.js' /** * @callback crudCallback - * @param {Annotation} annotation - The annotation being operated on + * @param {AnnotationObj} annotation - The annotation being operated on * @returns {boolean} Success status of the operation * @description Callback for create/update/delete operations on annotations */ /** * @callback customStateCallback - * @param {Annotation} annotation - The annotation being modified + * @param {AnnotationObj} annotation - The annotation being modified * @description Callback to customize state information saved with annotations */ /** * @callback customDataCallback - * @param {Annotation} annotation - The annotation being modified + * @param {AnnotationObj} annotation - The annotation being modified * @description Callback to customize the annotation data object */ /** * @callback selectedCallback - * @param {Annotation} annotation - The selected annotation + * @param {AnnotationObj} annotation - The selected annotation * @description Callback executed when an annotation is selected in the UI */ @@ -274,7 +274,7 @@ class EditorSvgAnnotation { /** * Shows the annotation editor widget - * @param {Annotation} annotation - Annotation to edit + * @param {AnnotationObj} annotation - Annotation to edit * @private */ showEditWidget(anno) { diff --git a/src/LayerSvgAnnotation.js b/src/LayerSvgAnnotation.js index ae8119aa..30529e24 100644 --- a/src/LayerSvgAnnotation.js +++ b/src/LayerSvgAnnotation.js @@ -5,19 +5,19 @@ import { LayerAnnotation } from './LayerAnnotation' import { CoordinateSystem } from './CoordinateSystem'; /** -* @typedef {Object} AnnotationClass +* @typedef {Object} AnnoClass * @property {string} stroke - CSS color for SVG elements (lines, text, outlines) * @property {string} label - Display name for the class */ /** -* @typedef {Object.} AnnotationClasses +* @typedef {Object.} AnnoClasses * @description Map of class names to their visual properties */ /** * @typedef {Object} LayerSvgAnnotationOptions -* @property {AnnotationClasses} classes - Annotation class definitions with styles +* @property {AnnoClasses} classes - Annotation class definitions with styles * @property {Function} [onClick] - Callback for annotation click events (param: selected annotation) * @property {boolean} [shadow=true] - Whether to use Shadow DOM for SVG elements * @property {HTMLElement} [overlayElement] - Container for SVG overlay diff --git a/src/Layout.js b/src/Layout.js index 14f0a6f8..42d7351c 100644 --- a/src/Layout.js +++ b/src/Layout.js @@ -6,7 +6,7 @@ import { CoordinateSystem } from "./CoordinateSystem"; // Tile level x y index ----- tex missing() start/end (tarzoom) ----- time, priority size(byte) /** - * @typedef {Object} Tile + * @typedef {Object} TileObj * @property {number} level - Zoom level in the image pyramid * @property {number} x - Horizontal position in tile grid * @property {number} y - Vertical position in tile grid @@ -179,7 +179,7 @@ class Layout { /** * Gets URL for specific tile * @param {number} id - Channel identifier - * @param {Tile} tile - Tile object + * @param {TileObj} tile - Tile object * @returns {string} Tile URL * @abstract */ @@ -198,7 +198,7 @@ class Layout { /** * Calculates tile coordinates - * @param {Tile} tile - Tile to calculate coordinates for + * @param Obj} tile - Tile to calculate coordinates for * @returns {{coords: Float32Array, tcoords: Float32Array}} Image and texture coordinates */ tileCoords(tile) { @@ -216,7 +216,7 @@ class Layout { /** * Creates new tile instance * @param {number} index - Tile identifier - * @returns {Tile} New tile object + * @returns {TileObj} New tile object * @private */ newTile(index) { @@ -234,7 +234,7 @@ class Layout { * @param {number} bias - Mipmap bias * @param {Map} tiles - Existing tiles * @param {number} [maxtiles=8] - Maximum tiles to return - * @returns {Tile[]} Array of needed tiles + * @returns {TileObj[]} Array of needed tiles */ needed(viewport, transform, layerTransform, border, bias, tiles, maxtiles = 8) { //FIXME should check if image is withing the viewport (+ border) diff --git a/src/LayoutTileImages.js b/src/LayoutTileImages.js index 50759ca2..30e4e33a 100644 --- a/src/LayoutTileImages.js +++ b/src/LayoutTileImages.js @@ -9,7 +9,7 @@ import { Annotation } from './Annotation.js'; * position and dimensions, rather than a regular grid of tiles like LayoutTiles. */ -/** +/* * @typedef {Object} TileDescriptor * Properties expected in tile descriptors: * @property {boolean} visible - Whether the tile should be rendered @@ -153,7 +153,7 @@ class LayoutTileImages extends Layout { /** * Gets the URL for a specific tile. * @param {number} id - Channel/raster ID - * @param {Tile} tile - Tile object + * @param {TileObj} tile - Tile object * @returns {string} URL to fetch tile image */ getTileURL(id, tile) { @@ -197,7 +197,7 @@ class LayoutTileImages extends Layout { /** * Gets coordinates for a tile in both image space and texture space. - * @param {Tile} tile - The tile to get coordinates for + * @param Obj} tile - The tile to get coordinates for * @returns {Object} Coordinate data * @returns {Float32Array} .coords - Image space coordinates [x,y,z, x,y,z, x,y,z, x,y,z] * @returns {Float32Array} .tcoords - Texture coordinates [u,v, u,v, u,v, u,v] @@ -226,7 +226,7 @@ class LayoutTileImages extends Layout { * @param {number} bias - Resolution bias (unused in this layout) * @param {Map} tiles - Currently available tiles * @param {number} [maxtiles=8] - Maximum number of tiles to return - * @returns {Tile[]} Array of needed tiles sorted by distance to viewport center + * @returns {TileObj[]} Array of needed tiles sorted by distance to viewport center */ needed(viewport, transform, layerTransform, border, bias, tiles, maxtiles = 8) { //look for needed nodes and prefetched nodes (on the pos destination @@ -294,7 +294,7 @@ class LayoutTileImages extends Layout { /** * Creates a new tile instance with properties from its descriptor. * @param {number} index - Index of the tile descriptor - * @returns {Tile} New tile instance with region and image properties + * @returns {TileObj} New tile instance with region and image properties */ newTile(index) { let tile = new Tile(); diff --git a/src/LayoutTiles.js b/src/LayoutTiles.js index 980b2b70..5fb5ee18 100644 --- a/src/LayoutTiles.js +++ b/src/LayoutTiles.js @@ -4,25 +4,6 @@ import { Transform } from "./Transform"; // Tile level x y index ----- tex missing() start/end (tarzoom) ----- time, priority size(byte) -/** - * @typedef {Object} Tile - * Represents a single element of a regular grid that subdivides an image. - * Tiles are identified by their position (x, y) within the grid and the zoom level. - * - * @property {number} level - The zoom level of the tile (0 is top/most zoomed out) - * @property {number} x - Horizontal position of the tile in the grid at the given level - * @property {number} y - Vertical position of the tile in the grid at the given level - * @property {number} index - Unique identifier for the tile across all levels - * @property {number} [start] - Starting byte position in the dataset (used for tarzoom/itarzoom formats) - * @property {number} [end] - Ending byte position in the dataset (used for tarzoom/itarzoom formats) - * @property {number} missing - For multi-channel formats (RTI, BRDF), tracks pending channel data requests - * @property {WebGLTexture[]} tex - Array of WebGL textures (one per channel) - * @property {number} time - Timestamp of tile creation (used by cache algorithms) - * @property {number} priority - Tile priority for cache management (lower = higher priority) - * @property {number} size - Total size of the tile in bytes (used by cache algorithms) - */ - - /** * @typedef {'image'|'deepzoom'|'deepzoom1px'|'google'|'zoomify'|'iiif'|'iip'|'tarzoom'|'itarzoom'} Layout#Type * Supported image layout types including both single-resolution and multi-resolution formats. @@ -265,7 +246,7 @@ class LayoutTiles extends Layout { /** * Gets coordinates for a tile in both image space and texture space. - * @param {Tile} tile - The tile to get coordinates for + * @param {TileObj} tile - The tile to get coordinates for * @returns {Object} Coordinate data * @returns {Float32Array} .coords - Image space coordinates [x,y,z, x,y,z, x,y,z, x,y,z] * @returns {Float32Array} .tcoords - Texture coordinates [u,v, u,v, u,v, u,v] @@ -325,7 +306,7 @@ class LayoutTiles extends Layout { /** * Creates a new tile instance with computed properties. * @param {number} index - Unique tile identifier - * @returns {Tile} New tile instance + * @returns {TileObj} New tile instance */ newTile(index) { let tile = super.newTile(index) @@ -343,7 +324,7 @@ class LayoutTiles extends Layout { * @param {number} bias - Resolution bias (0-1, affects mipmap level selection) * @param {Map} tiles - Currently available tiles * @param {number} [maxtiles=8] - Maximum number of tiles to return - * @returns {Tile[]} Array of needed tiles sorted by priority + * @returns {TileObj[]} Array of needed tiles sorted by priority */ needed(viewport, transform, layerTransform, border, bias, tiles, maxtiles = 8) { let neededBox = this.neededBox(viewport, transform, layerTransform, 0, bias); @@ -467,7 +448,7 @@ class LayoutTiles extends Layout { /** * Gets URL for a specific tile. * @param {number} id - Channel/raster ID - * @param {Tile} tile - Tile to get URL for + * @param {TileObj} tile - Tile to get URL for * @returns {string} URL to fetch tile data * @throws {Error} If layout not defined or ready */ diff --git a/src/PointerManager.js b/src/PointerManager.js index c3ab7ce3..e83afe1c 100644 --- a/src/PointerManager.js +++ b/src/PointerManager.js @@ -1,53 +1,87 @@ /** - * The `PointerManager` class is a high-level event manager that interprets low-level pointer interactions - * (mouse, touch, and stylus) into higher-level gestures such as taps, holds, panning, and pinching. - * It simplifies the process of handling user interactions on devices with touch screens or trackpads by - * converting raw pointer events (e.g., `pointerdown`, `pointermove`, `pointerup`) into easy-to-use gestures. - * - * Key features include: - * - **Event Management**: Registers, unregisters, and broadcasts event handlers for gestures like single/double tap, hold, panning, and pinching. - * - **Gesture Recognition**: Automatically detects and handles gestures such as finger taps, holds (long press), panning (drag), and pinch (zoom). - * - **Idle Detection**: Detects periods of inactivity and can trigger events based on user idleness. - * - **Multiple Pointer Support**: Manages multiple pointers simultaneously, supporting interactions like pinch-to-zoom. - * - **Utility Methods**: Includes helper methods for tasks like calculating device pixels per millimeter (useful for different screen densities). + * The `PointerManager` class serves as a central event manager that interprets raw pointer events + * (like mouse clicks, touch gestures, or stylus inputs) into higher-level gestures. It abstracts + * away the complexity of handling multiple input types and transforms them into common gestures + * like taps, holds, panning (drag), and pinch-to-zoom, which are common in modern user interfaces. * - * Common use cases for `PointerManager` include applications that require touch gestures, such as image or map manipulation, - * or any interactive web application that benefits from handling complex pointer-based interactions. + * Key mechanisms: * - * @module PointerManager - */ - -/** - * High-level event manager for handling pointer interactions. - * Captures and classifies PointerEvents (mouse/touch) into higher-level gestures. + * 1. **Event Handling and Gesture Recognition**: + * - `PointerManager` listens for low-level pointer events (such as `pointerdown`, `pointermove`, + * and `pointerup`) and converts them into higher-level gestures. + * - For example, a quick touch and release is interpreted as a "tap," while a sustained touch + * (greater than 600ms) is recognized as a "hold." + * - It handles both mouse and touch events uniformly, making it ideal for web applications that + * need to support diverse input devices (mouse, trackpad, touch screens). * - * @fires PointerManager#fingerHover - When pointer moves over target - * @fires PointerManager#fingerSingleTap - On quick press/touch - * @fires PointerManager#fingerDoubleTap - On two quick presses/touches - * @fires PointerManager#fingerHold - When press/touch held for >600ms - * @fires PointerManager#mouseWheel - On mouse wheel rotation - * @fires PointerManager#panStart - When pan gesture begins - * @fires PointerManager#panMove - During pan gesture - * @fires PointerManager#panEnd - When pan gesture ends - * @fires PointerManager#pinchStart - When pinch gesture begins - * @fires PointerManager#pinchMove - During pinch gesture - * @fires PointerManager#pinchEnd - When pinch gesture ends + * 2. **Multi-pointer Support**: + * - `PointerManager` supports multiple pointers simultaneously, making it capable of recognizing + * complex gestures involving more than one finger or pointer, such as pinch-to-zoom. + * - For multi-pointer gestures, it tracks each pointer's position and movement separately, + * allowing precise gesture handling. * - * @example - * // Create manager and attach event handler - * const canvas = document.querySelector('canvas'); - * const pointerManager = new PointerManager(canvas); - * const handler = { - * priority: 10, - * fingerSingleTap: (e) => { - * console.log("SINGLE TAP at", e.clientX, e.clientY); - * }, - * fingerHold: (e) => { - * console.log("HOLD at", e.clientX, e.clientY); - * } - * }; - * pointerManager.onEvent(handler); - */ + * 3. **Idle Detection**: + * - The class includes idle detection mechanisms, which can trigger actions or events when no + * pointer activity is detected for a specified period. This can be useful for implementing + * user inactivity warnings or pausing certain interactive elements when the user is idle. + * + * 4. **Callback-based Gesture Management**: + * - The core of the `PointerManager` class revolves around registering and triggering callbacks + * for different gestures. Callbacks are provided by the user of this class for events like + * pan (`onPan`), pinch (`onPinch`), and others. + * - The class ensures that once a gesture starts, it monitors and triggers the appropriate + * callbacks, such as `panStart`, `panMove`, and `panEnd`, depending on the detected gesture. + * + * 5. **Buffer Management**: + * - The `PointerManager` class also includes a buffer system for managing and storing recent + * events, allowing the developer to enqueue, push, pop, or shift pointer data as needed. + * This can be helpful for applications that need to track the history of pointer events + * for gesture recognition or undo functionality. + * + * 6. **Error Handling**: + * - The class includes error handling to ensure that all required gesture handlers are defined + * by the user. For example, it will throw an error if any essential callback functions for + * pan or pinch gestures are missing, ensuring robust gesture management. + * + * Typical usage involves: + * - Registering gesture handlers (e.g., for taps, panning, pinching). + * - The class then monitors all pointer events and triggers the corresponding gesture callbacks + * when appropriate. + * + * Example: + * ```js + * const manager = new PointerManager(); + * manager.onPan({ + * panStart: (e) => console.log('Pan started', e), + * panMove: (e) => console.log('Panning', e), + * panEnd: (e) => console.log('Pan ended', e), + * priority: 1 + * }); + * manager.onPinch({ + * pinchStart: (e) => console.log('Pinch started', e), + * pinchMove: (e) => console.log('Pinching', e), + * pinchEnd: (e) => console.log('Pinch ended', e), + * priority: 1 + * }); + * ``` + * + * In this example, `PointerManager` registers handlers for pan and pinch gestures, automatically + * converting pointer events into the desired interactions. By abstracting the raw pointer events, + * `PointerManager` allows developers to focus on handling higher-level gestures without worrying + * about the underlying complexity. +* @fires PointerManager#fingerHover - Triggered when a pointer moves over a target. +* @fires PointerManager#fingerSingleTap - Triggered on a quick touch or click. +* @fires PointerManager#fingerDoubleTap - Triggered on two quick touches or clicks. +* @fires PointerManager#fingerHold - Triggered when a touch or click is held for more than 600ms. +* @fires PointerManager#mouseWheel - Triggered when the mouse wheel is rotated. +* @fires PointerManager#panStart - Triggered when a pan (drag) gesture begins. +* @fires PointerManager#panMove - Triggered during a pan gesture. +* @fires PointerManager#panEnd - Triggered when a pan gesture ends. +* @fires PointerManager#pinchStart - Triggered when a pinch gesture begins. +* @fires PointerManager#pinchMove - Triggered during a pinch gesture. +* @fires PointerManager#pinchEnd - Triggered when a pinch gesture ends. +* +*/ class PointerManager { /** * Creates a new PointerManager instance. @@ -97,6 +131,7 @@ class PointerManager { * * @param {string} str - The input string to split. * @returns {Array} An array of strings split by whitespace. + * @private */ static splitStr(str) { return str.trim().split(/\s+/g); @@ -220,10 +255,13 @@ class PointerManager { } /** - * Registers pan gesture callbacks. + * Registers callbacks for pan gestures (start, move, and end). * - * @param {Object} handler - The handler object with pan callbacks. - * @throws {Error} If the handler is missing any required pan callbacks. + * @param {Object} handler - The handler object containing pan gesture callbacks. + * @param {function} handler.panStart - Callback function executed when the pan gesture starts. + * @param {function} handler.panMove - Callback function executed during the pan gesture movement. + * @param {function} handler.panEnd - Callback function executed when the pan gesture ends. + * @throws {Error} Throws an error if any required callback functions (`panStart`, `panMove`, `panEnd`) are missing. */ onPan(handler) { const cb_properties = ['panStart', 'panMove', 'panEnd']; @@ -247,10 +285,13 @@ class PointerManager { } /** - * Registers pinch gesture callbacks. + * Registers callbacks for pinch gestures (start, move, and end). * - * @param {Object} handler - The handler object with pinch callbacks. - * @throws {Error} If the handler is missing any required pinch callbacks. + * @param {Object} handler - The handler object containing pinch gesture callbacks. + * @param {function} handler.pinchStart - Callback function executed when the pinch gesture starts. + * @param {function} handler.pinchMove - Callback function executed during the pinch gesture movement. + * @param {function} handler.pinchEnd - Callback function executed when the pinch gesture ends. + * @throws {Error} Throws an error if any required callback functions (`pinchStart`, `pinchMove`, `pinchEnd`) are missing. */ onPinch(handler) { const cb_properties = ['pinchStart', 'pinchMove', 'pinchEnd']; diff --git a/src/ScaleBar.js b/src/ScaleBar.js index 1703048c..16b5d985 100644 --- a/src/ScaleBar.js +++ b/src/ScaleBar.js @@ -1,7 +1,6 @@ import { Util } from './Util' /** - * @fileoverview * ScaleBar module provides measurement scale visualization and unit conversion functionality. * Includes both a base Units class for unit management and a ScaleBar class for visual representation. * diff --git a/src/Shader.js b/src/Shader.js index 6e1fc513..dfe1165d 100644 --- a/src/Shader.js +++ b/src/Shader.js @@ -382,31 +382,4 @@ vec4 data() { * @event Shader#update */ -/** - * Example usage: - * ```javascript - * const shader = new Shader({ - * label: 'RGB Shader', - * samplers: [{ - * id: 0, - * name: 'kd', - * label: 'Diffuse' - * }], - * uniforms: { - * u_brightness: { - * type: 'float', - * value: 1.0 - * } - * }, - * modes: ['normal', 'grayscale'] - * }); - * - * // Set shader mode - * shader.setMode('grayscale'); - * - * // Update uniform - * shader.setUniform('u_brightness', 1.5); - * ``` - */ - export { Shader } diff --git a/src/ShaderBRDF.js b/src/ShaderBRDF.js index c3b97c95..9bba0cbf 100644 --- a/src/ShaderBRDF.js +++ b/src/ShaderBRDF.js @@ -4,49 +4,19 @@ import { Shader } from './Shader.js' * A shader class implementing various BRDF (Bidirectional Reflectance Distribution Function) rendering modes. * Extends the base Shader class to provide specialized material rendering capabilities. * - * @class - * @extends Shader - * - * @param {Object} options - Configuration options for the shader - * @param {string} [options.mode='color'] - Rendering mode to use - * - 'color': Full BRDF rendering using Ward model with ambient light - * - 'diffuse': Shows only diffuse component (kd) - * - 'specular': Shows only specular component (ks * spec * NdotL) - * - 'normals': Visualizes surface normals - * - 'monochrome': Renders using a single material color with diffuse lighting - * @param {Object} [options.colorspaces] - Color space configurations - * @param {string} [options.colorspaces.kd] - Color space for diffuse texture ('linear' or 'sRGB') - * @param {string} [options.colorspaces.ks] - Color space for specular texture ('linear' or 'sRGB') - * @param {number} [options.brightness=1.0] - Overall brightness multiplier - * @param {number} [options.gamma=2.2] - Gamma correction value - * @param {number[]} [options.alphaLimits=[0.01, 0.5]] - Range for surface roughness [min, max] - * @param {number[]} [options.monochromeMaterial=[0.80, 0.79, 0.75]] - RGB color for monochrome mode - * @param {number} [options.kAmbient=0.02] - Ambient light coefficient - * - * @property {string[]} modes - Available rendering modes - * @property {string} mode - Current rendering mode - * @property {Object} uniforms - WebGL uniform variables - * @property {Object} uniforms.uLightInfo - vec4 light position/direction (w=0 for directional, w=1 for spot) - * @property {Object} uniforms.uAlphaLimits - vec2 surface roughness range - * @property {Object} uniforms.uBrightnessGamma - vec2 containing brightness and gamma values - * @property {Object} uniforms.uInputColorSpaceKd - int flag for diffuse texture color space - * @property {Object} uniforms.uInputColorSpaceKs - int flag for specular texture color space - * @property {Object} uniforms.uMonochromeMaterial - vec3 color for monochrome mode - * @property {Object} uniforms.uKAmbient - float ambient light coefficient - * * Shader Features: * - Implements the Ward BRDF model for physically-based rendering * - Supports both directional and spot lights - * - Handles normal mapping + * - Handles normal mapping for more detailed surface rendering * - Supports different color spaces (linear and sRGB) for input textures - * - Multiple visualization modes for material analysis - * - Configurable surface roughness range - * - Ambient light contribution + * - Multiple visualization modes for material analysis (diffuse, specular, normals, monochrome, etc.) + * - Configurable surface roughness range for varying material appearance + * - Ambient light contribution to simulate indirect light * * Required Textures: * - uTexKd: Diffuse color texture (optional) * - uTexKs: Specular color texture (optional) - * - uTexNormals: Normal map + * - uTexNormals: Normal map for surface detail * - uTexGloss: Glossiness map (optional) * * @example @@ -63,10 +33,31 @@ import { Shader } from './Shader.js' * alphaLimits: [0.05, 0.4], * kAmbient: 0.03 * }); + * + * @extends Shader */ class ShaderBRDF extends Shader { + /** + * Creates a new ShaderBRDF instance. + * @param {Object} [options={}] - Configuration options for the shader. + * @param {string} [options.mode='color'] - Rendering mode to use: + * - 'color': Full BRDF rendering using Ward model with ambient light + * - 'diffuse': Shows only diffuse component (kd) + * - 'specular': Shows only specular component (ks * spec * NdotL) + * - 'normals': Visualizes surface normals + * - 'monochrome': Renders using a single material color with diffuse lighting + * @param {Object} [options.colorspaces] - Color space configurations. + * @param {string} [options.colorspaces.kd='sRGB'] - Color space for diffuse texture ('linear' or 'sRGB'). + * @param {string} [options.colorspaces.ks='linear'] - Color space for specular texture ('linear' or 'sRGB'). + * @param {number} [options.brightness=1.0] - Overall brightness multiplier. + * @param {number} [options.gamma=2.2] - Gamma correction value. + * @param {number[]} [options.alphaLimits=[0.01, 0.5]] - Range for surface roughness [min, max]. + * @param {number[]} [options.monochromeMaterial=[0.80, 0.79, 0.75]] - RGB color for monochrome mode. + * @param {number} [options.kAmbient=0.02] - Ambient light coefficient. + * + */ constructor(options) { - super({}); + super(options); this.modes = ['color', 'diffuse', 'specular', 'normals', 'monochrome']; this.mode = 'color'; @@ -154,16 +145,7 @@ class ShaderBRDF extends Shader { * * @param {WebGLRenderingContext|WebGL2RenderingContext} gl - The WebGL context * @returns {string} The complete fragment shader source code - * * @private - * - * Shader Features: - * - Normal mapping with null normal detection - * - Color space conversion (linear <-> sRGB) - * - Ward BRDF implementation (isotropic version) - * - Multiple rendering modes with configurable output - * - Gamma correction - * - Configurable gloss to roughness conversion */ fragShaderSrc(gl) { let gl2 = !(gl instanceof WebGLRenderingContext); @@ -283,5 +265,4 @@ vec4 data() { } - export { ShaderBRDF } diff --git a/src/ShaderCombiner.js b/src/ShaderCombiner.js index 78a8c285..63eb3bc4 100644 --- a/src/ShaderCombiner.js +++ b/src/ShaderCombiner.js @@ -10,8 +10,14 @@ import { Shader } from './Shader.js' */ /** - * @class - * @extends Shader + * Fired when shader combination mode changes. + * @event ShaderCombiner#update + * @type {Object} + * @property {string} mode - New combination mode + * @property {string} previousMode - Previous combination mode + */ + +/** * ShaderCombiner module provides texture combination operations for OpenLIME. * Supports both WebGL 1.0 and 2.0/3.0 GLSL specifications with automatic version detection. * @@ -21,6 +27,8 @@ import { Shader } from './Shader.js' * - Automatic texture sampling * - WebGL 1.0 and 2.0 compatibility * - Alpha channel preservation + * + * @extends Shader */ class ShaderCombiner extends Shader { /** @@ -102,65 +110,4 @@ void main() { } } -/** - * Example usage: - * ```javascript - * // Create shader to average two textures - * const combiner = new ShaderCombiner({ - * mode: 'mean', - * samplers: [ - * { id: 0, name: 'source1', type: 'vec3' }, - * { id: 1, name: 'source2', type: 'vec3' } - * ] - * }); - * - * // Change combination mode - * combiner.setMode('diff'); - * - * // Use first texture only - * combiner.setMode('first'); - * ``` - * - * Advanced usage with custom configuration: - * ```javascript - * const combiner = new ShaderCombiner({ - * mode: 'mean', - * debug: true, - * label: 'Texture Combiner', - * samplers: [ - * { - * id: 0, - * name: 'source1', - * type: 'vec3', - * label: 'First Texture' - * }, - * { - * id: 1, - * name: 'source2', - * type: 'vec3', - * label: 'Second Texture' - * } - * ] - * }); - * - * // Bind textures and render... - * ``` - */ - -/** - * Default class properties - * - * @property {string} mode - Current combination mode (default: 'mean') - * @property {Array} samplers - Texture sampler definitions - * @property {Array} modes - Available combination modes ['first', 'second', 'mean', 'diff'] - * @property {Object.} operations - Shader operations for each mode - */ - -/** - * Fired when shader combination mode changes. - * @event ShaderCombiner#update - * @type {Object} - * @property {string} mode - New combination mode - * @property {string} previousMode - Previous combination mode - */ export { ShaderCombiner } diff --git a/src/ShaderDstretch.js b/src/ShaderDstretch.js index a281d282..3772c85e 100644 --- a/src/ShaderDstretch.js +++ b/src/ShaderDstretch.js @@ -1,23 +1,22 @@ import { Shader } from "./Shader"; /** - * @typedef {Object} ShaderDStretch~Config - * Configuration data for DStretch transformation - * @property {Array>} samples - RGB color samples for statistics computation - * @property {number[]} [transformation] - Optional 4x4 transformation matrix - */ - -/** - * @typedef {Object} ShaderDStretch~UniformData - * Shader uniform data for DStretch processing - * @property {Object} rotation - 4x4 transformation matrix - * @property {Object} min - Minimum RGB values after transformation - * @property {Object} max - Maximum RGB values after transformation + * Fragment Shader Details + * + * The shader performs these steps: + * 1. Centers color values around 127 + * 2. Applies rotation matrix transformation + * 3. Normalizes results using min/max values + * 4. Outputs transformed and normalized color + * + * Uniforms: + * @property {mat4} rotation - Color transformation matrix + * @property {vec3} min - Minimum RGB values for normalization + * @property {vec3} max - Maximum RGB values for normalization + * @property {sampler2D} image - Input image texture */ /** - * @class - * @extends Shader * ShaderDStretch implements the GPU-accelerated portion of the DStretch algorithm. * Handles color space transformation and normalization for image enhancement. * @@ -33,6 +32,7 @@ import { Shader } from "./Shader"; * - Implements color normalization based on sample statistics * - Supports dynamic update of transformation parameters * - Handles WebGL uniform management + * @extends Shader */ class ShaderDstretch extends Shader { /** @@ -225,55 +225,5 @@ vec4 data() { return str; } } -/** - * Example usage: - * ```javascript - * // Create shader with configuration - * const shader = new ShaderDStretch(); - * shader.init({ - * samples: [[255,0,0], [0,255,0], [0,0,255]], // RGB samples - * }); - * - * // Update transformation - * shader.updateRotationMatrix([Math.PI/4, 0, 0]); - * ``` - * - * Advanced usage with pre-computed statistics: - * ```javascript - * const shader = new ShaderDStretch(); - * shader.init({ - * samples: precalculatedSamples, - * transformation: customMatrix - * }); - * - * // Shader will use provided statistics and transformation - * ``` - */ - -/** - * Default class properties - * - * @property {Array>} rotationMatrix - Current color transformation matrix - * @property {Array>} samples - Color samples for statistics - * @property {number[]} min - Minimum RGB values in transformed space - * @property {number[]} max - Maximum RGB values in transformed space - * @property {Object} uniforms - WebGL uniform variables for transformation - */ - -/** - * Fragment Shader Details - * - * The shader performs these steps: - * 1. Centers color values around 127 - * 2. Applies rotation matrix transformation - * 3. Normalizes results using min/max values - * 4. Outputs transformed and normalized color - * - * Uniforms: - * @property {mat4} rotation - Color transformation matrix - * @property {vec3} min - Minimum RGB values for normalization - * @property {vec3} max - Maximum RGB values for normalization - * @property {sampler2D} image - Input image texture - */ export { ShaderDstretch } \ No newline at end of file diff --git a/src/ShaderFilter.js b/src/ShaderFilter.js index 44ed812d..7a7fbc7c 100644 --- a/src/ShaderFilter.js +++ b/src/ShaderFilter.js @@ -15,7 +15,7 @@ */ /** - * @class + * * Base class for WebGL shader filters in OpenLIME. * Provides infrastructure for creating modular shader effects that can be chained together. * @@ -37,7 +37,7 @@ class ShaderFilter { /** * Creates a new shader filter * @param {Object} [options] - Filter configuration - * @param {Object} [options.modes={}] - Available filter modes + * @param {ShaderFilter~Mode} [options.modes={}] - Available filter modes * @param {Object} [options.uniforms={}] - Filter uniform variables * @param {Array} [options.samplers=[]] - Texture samplers */ @@ -205,7 +205,7 @@ class ShaderFilter { } /** - * @class + * * @extends ShaderFilter * Test filter that replaces transparent pixels with a specified color */ @@ -229,7 +229,7 @@ class ShaderFilterTest extends ShaderFilter { } /** - * @class + * * @extends ShaderFilter * Filter that modifies the opacity of rendered content */ @@ -253,7 +253,7 @@ class ShaderFilterOpacity extends ShaderFilter { } /** - * @class + * * @extends ShaderFilter * Filter that applies gamma correction to colors */ @@ -276,47 +276,5 @@ class ShaderGammaFilter extends ShaderFilter { }`; } } -/** - * Example usage: - * ```javascript - * // Create and configure an opacity filter - * const opacityFilter = new ShaderFilterOpacity(0.5); - * shader.addFilter(opacityFilter); - * - * // Later update opacity - * opacityFilter.setUniform('opacity', 0.8); - * - * // Chain multiple filters - * const gammaFilter = new ShaderGammaFilter({ gamma: 1.8 }); - * shader.addFilter(gammaFilter); - * ``` - * - * Advanced usage with custom modes: - * ```javascript - * // Create filter with multiple modes - * const filter = new ShaderFilter({ - * modes: { - * 'blend': [ - * { id: 'normal', enable: true, src: '...' }, - * { id: 'multiply', enable: false, src: '...' } - * ] - * } - * }); - * - * // Switch modes - * filter.setMode('blend', 'multiply'); - * ``` - */ - -/** - * Default class properties - * - * @property {string} name - Filter name (derived from class name) - * @property {Object} uniforms - Uniform variable definitions - * @property {Array} samplers - Texture sampler definitions - * @property {boolean} needsUpdate - Whether filter needs updating - * @property {Shader} shader - Associated shader program - * @property {Object.} modes - Available filter modes - */ export { ShaderFilter, ShaderFilterTest, ShaderFilterOpacity, ShaderGammaFilter } \ No newline at end of file diff --git a/src/ShaderFilterColormap.js b/src/ShaderFilterColormap.js index 5c4d3124..51b41da7 100644 --- a/src/ShaderFilterColormap.js +++ b/src/ShaderFilterColormap.js @@ -12,7 +12,7 @@ import { ShaderFilter } from './ShaderFilter.js' */ /** - * @class + * * @extends ShaderFilter * ShaderFilterColormap implements color mapping and visualization techniques. * Maps input RGB values to a specified colormap using customizable transfer functions. @@ -51,7 +51,7 @@ class ShaderFilterColormap extends ShaderFilter { * maxSteps: 512 * }); * ``` - */ + */ constructor(colorscale, options) { super(options); options = Object.assign({ @@ -61,7 +61,7 @@ class ShaderFilterColormap extends ShaderFilter { }, options); Object.assign(this, options); - if(this.inDomain.length != 2 && this.inDomain[1] <= this.inDomain[0]) { + if (this.inDomain.length != 2 && this.inDomain[1] <= this.inDomain[0]) { throw Error("inDomain bad format"); } @@ -69,10 +69,10 @@ class ShaderFilterColormap extends ShaderFilter { if (this.inDomain.length == 0) this.inDomain = this.colorscale.rangeDomain(); const cscaleDomain = this.colorscale.rangeDomain(); - const scale = (this.inDomain[1]-this.inDomain[0])/(cscaleDomain[1]-cscaleDomain[0]); - const bias = (this.inDomain[0]-cscaleDomain[0])/(cscaleDomain[1]-cscaleDomain[0]); - - this.samplers = [{ name:`${this.samplerName('colormap')}` }]; + const scale = (this.inDomain[1] - this.inDomain[0]) / (cscaleDomain[1] - cscaleDomain[0]); + const bias = (this.inDomain[0] - cscaleDomain[0]) / (cscaleDomain[1] - cscaleDomain[0]); + + this.samplers = [{ name: `${this.samplerName('colormap')}` }]; this.uniforms[this.uniformName('channel_weigths')] = { type: 'vec3', needsUpdate: true, size: 3, value: this.channelWeights }; this.uniforms[this.uniformName('low_color')] = { type: 'vec4', needsUpdate: true, size: 4, value: this.colorscale.lowColor.value() }; @@ -83,45 +83,44 @@ class ShaderFilterColormap extends ShaderFilter { } /** - * Creates the colormap texture in WebGL + * Creates the colormap texture in WebGL. + * Samples colorscale at specified resolution, + * creates 1D RGBA texture, configures texture filtering, + * and associates texture with sampler. + * * @param {WebGLRenderingContext} gl - WebGL context * @returns {Promise} * @private - * - * Implementation details: - * - Samples colorscale at specified resolution - * - Creates 1D RGBA texture - * - Configures texture filtering based on colorscale type - * - Associates texture with sampler - */ + */ async createTextures(gl) { const colormap = this.colorscale.sample(this.maxSteps); - let textureFilter=gl.LINEAR; - if(this.colorscale.type == 'bar') { - textureFilter=gl.NEAREST; + let textureFilter = gl.LINEAR; + if (this.colorscale.type == 'bar') { + textureFilter = gl.NEAREST; } - const tex = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, tex); - gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, textureFilter); - gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, textureFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + const tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, textureFilter); + gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, textureFilter); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.maxSteps, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, colormap.buffer); this.getSampler('colormap').tex = tex; // Link tex to sampler } /** - * Generates the GLSL function for colormap lookup - * @param {WebGLRenderingContext} gl - WebGL context - * @returns {string} GLSL function definition - * @private + * Generates the GLSL function for colormap lookup. * * Processing steps: * 1. Channel-weighted grayscale conversion * 2. Domain scaling and bias * 3. Out-of-range handling * 4. Colormap texture lookup - */ + * + * @param {WebGLRenderingContext} gl - WebGL context + * @returns {string} GLSL function definition + * @private + */ fragDataSrc(gl) { return ` vec4 ${this.functionName()}(vec4 col){ @@ -139,73 +138,4 @@ class ShaderFilterColormap extends ShaderFilter { } -/** - * Default class properties - * - * @property {ColorScale} colorscale - Associated colorscale object - * @property {number[]} inDomain - Input value range for mapping - * @property {number[]} channelWeights - RGB channel weights - * @property {number} maxSteps - Colormap texture resolution - * @property {Object} uniforms - WebGL uniform definitions: - * - channel_weights: vec3 RGB weights - * - low_color: vec4 color for values below range - * - high_color: vec4 color for values above range - * - scale: float domain scaling factor - * - bias: float domain offset - */ - -/** - * Example usage: - * ```javascript - * // Basic usage with default options - * const colormap = new ShaderFilterColormap(myColorScale); - * shader.addFilter(colormap); - * - * // Custom configuration - * const colormap = new ShaderFilterColormap(myColorScale, { - * inDomain: [-50, 50], - * channelWeights: [0.2126, 0.7152, 0.0722], // Luminance weights - * maxSteps: 512 - * }); - * - * // Apply to shader - * shader.addFilter(colormap); - * ``` - * - * Advanced usage with custom colorscale: - * ```javascript - * // Create colorscale with specific range - * const scale = new ColorScale({ - * type: 'sequential', - * range: ['#000000', '#FF0000'], - * domain: [0, 100] - * }); - * - * // Create filter with custom domain mapping - * const colormap = new ShaderFilterColormap(scale, { - * inDomain: [20, 80], // Map input range [20,80] to full colorscale - * channelWeights: [1, 0, 0] // Use only red channel - * }); - * ``` - */ - -/** - * Fragment Shader Implementation - * - * The shader performs these steps: - * 1. Alpha check for transparency - * 2. Channel-weighted RGB to grayscale conversion - * 3. Domain scaling and bias application - * 4. Range clamping with custom colors - * 5. Colormap texture lookup - * - * Uniforms: - * @property {vec3} channel_weights - RGB channel weights - * @property {vec4} low_color - Color for values below range - * @property {vec4} high_color - Color for values above range - * @property {float} scale - Domain scaling factor - * @property {float} bias - Domain offset - * @property {sampler2D} colormap - 1D colormap texture - */ - export { ShaderFilterColormap } \ No newline at end of file diff --git a/src/ShaderFilterVector.js b/src/ShaderFilterVector.js index 7e8e9c61..81817282 100644 --- a/src/ShaderFilterVector.js +++ b/src/ShaderFilterVector.js @@ -21,8 +21,7 @@ import { ShaderFilter } from './ShaderFilter.js' */ /** - * @class - * @extends ShaderFilter + * * ShaderFilterVector implements 2D vector field visualization techniques. * Based on techniques from "2D vector field visualization by Morgan McGuire" * and enhanced by Matthias Reitinger. @@ -41,6 +40,62 @@ import { ShaderFilter } from './ShaderFilter.js' * - Dynamic magnitude scaling * - Colormap-based magnitude visualization * - WebGL 1.0 and 2.0 compatibility + * + * Example usage: + * ```javascript + * // Basic usage with default options + * const vectorField = new ShaderFilterVector(myColorScale); + * shader.addFilter(vectorField); + * + * // Configure visualization modes + * vectorField.setMode('normalize', 'on'); // Normalize arrow lengths + * vectorField.setMode('arrow', 'col'); // Use custom arrow color + * vectorField.setMode('field', 'mag'); // Show magnitude field + * ``` + * + * Advanced usage with custom configuration: + * ```javascript + * const vectorField = new ShaderFilterVector(colorscale, { + * inDomain: [-10, 10], // Vector magnitude range + * maxSteps: 512, // Higher colormap resolution + * arrowColor: [1, 0, 0, 1] // Red arrows + * }); + * + * // Add to shader pipeline + * shader.addFilter(vectorField); + * ``` + * + * GLSL Implementation Details + * + * Key Components: + * 1. Arrow Generation: + * - Tile-based positioning + * - Shaft and head construction + * - Size and direction control + * + * 2. Distance Functions: + * - line3(): Distance to line segment + * - line(): Signed distance to line + * - arrow(): Complete arrow shape + * + * 3. Color Processing: + * - Vector magnitude computation + * - Colormap lookup + * - Mode-based blending + * + * Constants: + * - ARROW_TILE_SIZE: Spacing between arrows (16.0) + * - ISQRT2: 1/sqrt(2) for magnitude normalization + * + * Uniforms: + * - {vec4} arrow_color - Custom arrow color + * - {vec4} low_color - Color for values below range + * - {vec4} high_color - Color for values above range + * - {float} scale - Magnitude scaling factor + * - {float} bias - Magnitude offset + * - {sampler2D} colormap - Magnitude colormap texture + * + * @extends ShaderFilter */ class ShaderFilterVector extends ShaderFilter { /** @@ -58,14 +113,14 @@ class ShaderFilterVector extends ShaderFilter { * arrowColor: [0, 0, 0, 1] * }); * ``` - */ + */ constructor(colorscale, options) { super(options); options = Object.assign({ inDomain: [], maxSteps: 256, arrowColor: [0.0, 0.0, 0.0, 1.0], - + }, options); Object.assign(this, options); @@ -106,17 +161,14 @@ class ShaderFilterVector extends ShaderFilter { } /** - * Creates the colormap texture for magnitude visualization + * Creates the colormap texture for magnitude visualization. + * Samples colorscale at specified resolution, creates 1D RGBA texture, + * configures appropriate texture filtering, and links texture with sampler. + * * @param {WebGLRenderingContext} gl - WebGL context * @returns {Promise} * @private - * - * Implementation details: - * - Samples colorscale at specified resolution - * - Creates 1D RGBA texture - * - Configures appropriate texture filtering - * - Links texture with sampler - */ + */ async createTextures(gl) { const colormap = this.colorscale.sample(this.maxSteps); let textureFilter = gl.LINEAR; @@ -134,10 +186,7 @@ class ShaderFilterVector extends ShaderFilter { } /** - * Generates GLSL code for vector field visualization - * @param {WebGLRenderingContext} gl - WebGL context - * @returns {string} GLSL function definition - * @private + * Generates GLSL code for vector field visualization. * * Shader Features: * - Tile-based arrow placement @@ -145,7 +194,11 @@ class ShaderFilterVector extends ShaderFilter { * - Multiple visualization modes * - Magnitude-based colormapping * - Smooth field interpolation - */ + * + * @param {WebGLRenderingContext} gl - WebGL context + * @returns {string} GLSL function definition + * @private + */ fragDataSrc(gl) { return ` // 2D vector field visualization by Matthias Reitinger, @mreitinger @@ -276,81 +329,5 @@ class ShaderFilterVector extends ShaderFilter { } -/** - * Default class properties - * - * @property {ColorScale} colorscale - Associated colorscale for magnitude mapping - * @property {number[]} inDomain - Input magnitude range for mapping - * @property {number} maxSteps - Colormap texture resolution - * @property {number[]} arrowColor - RGBA color for arrows in 'col' mode - * @property {Object} modes - Visualization mode configurations: - * - normalize: Arrow length normalization - * - arrow: Arrow coloring method - * - field: Background field visualization - * @property {Object} uniforms - WebGL uniform definitions: - * - arrow_color: vec4 custom arrow color - * - low_color: vec4 color for values below range - * - high_color: vec4 color for values above range - * - scale: float magnitude scaling factor - * - bias: float magnitude offset - */ - -/** - * Example usage: - * ```javascript - * // Basic usage with default options - * const vectorField = new ShaderFilterVector(myColorScale); - * shader.addFilter(vectorField); - * - * // Configure visualization modes - * vectorField.setMode('normalize', 'on'); // Normalize arrow lengths - * vectorField.setMode('arrow', 'col'); // Use custom arrow color - * vectorField.setMode('field', 'mag'); // Show magnitude field - * ``` - * - * Advanced usage with custom configuration: - * ```javascript - * const vectorField = new ShaderFilterVector(colorscale, { - * inDomain: [-10, 10], // Vector magnitude range - * maxSteps: 512, // Higher colormap resolution - * arrowColor: [1, 0, 0, 1] // Red arrows - * }); - * - * // Add to shader pipeline - * shader.addFilter(vectorField); - * ``` - */ - -/** - * GLSL Implementation Details - * - * Key Components: - * 1. Arrow Generation: - * - Tile-based positioning - * - Shaft and head construction - * - Size and direction control - * - * 2. Distance Functions: - * - line3(): Distance to line segment - * - line(): Signed distance to line - * - arrow(): Complete arrow shape - * - * 3. Color Processing: - * - Vector magnitude computation - * - Colormap lookup - * - Mode-based blending - * - * Constants: - * - ARROW_TILE_SIZE: Spacing between arrows (16.0) - * - ISQRT2: 1/sqrt(2) for magnitude normalization - * - * Uniforms: - * @property {vec4} arrow_color - Custom arrow color - * @property {vec4} low_color - Color for values below range - * @property {vec4} high_color - Color for values above range - * @property {float} scale - Magnitude scaling factor - * @property {float} bias - Magnitude offset - * @property {sampler2D} colormap - Magnitude colormap texture - */ export { ShaderFilterVector } \ No newline at end of file diff --git a/src/ShaderFilterVectorGlyph.js b/src/ShaderFilterVectorGlyph.js index 05f9fca8..e56f86e4 100644 --- a/src/ShaderFilterVectorGlyph.js +++ b/src/ShaderFilterVectorGlyph.js @@ -24,11 +24,13 @@ import { Util } from './Util' */ /** - * @class - * @extends ShaderFilter * ShaderFilterVectorGlyph implements sprite-based vector field visualization. * Uses pre-rendered glyphs from an SVG sprite sheet for high-quality vector field representation. * + * @class + * @extends ShaderFilter + * @classdesc A shader filter that implements sprite-based vector field visualization. + * * Features: * - SVG glyph-based vector field visualization * - Magnitude-dependent glyph selection @@ -43,6 +45,12 @@ import { Util } from './Util' * - Automatic magnitude mapping * - Alpha-based glyph composition * - WebGL texture management + * + * GLSL Implementation Constants: + * - GLYPH_TILE_SIZE: Spacing between glyphs (16.0) + * - ISQRT2: 1/sqrt(2) for magnitude normalization + * + * */ class ShaderFilterVectorGlyph extends ShaderFilter { /** @@ -62,7 +70,7 @@ class ShaderFilterVectorGlyph extends ShaderFilter { * glyphColor: [0, 0, 0, 1] * }); * ``` - */ + */ constructor(colorscale, glyphsUrl, options) { super(options); options = Object.assign({ @@ -89,7 +97,7 @@ class ShaderFilterVectorGlyph extends ShaderFilter { const scale = Math.sqrt((this.inDomain[1] * this.inDomain[1] + this.inDomain[0] * this.inDomain[0]) / (cscaleDomain[1] * cscaleDomain[1] + cscaleDomain[0] * cscaleDomain[0])); const bias = 0.0; - const gap = this.glyphsStride-this.glyphsSize[1]; + const gap = this.glyphsStride - this.glyphsSize[1]; const glyphCount = Math.round((this.glyphsSize[0] + gap) / this.glyphsStride); this.modes = { @@ -122,10 +130,7 @@ class ShaderFilterVectorGlyph extends ShaderFilter { } /** - * Creates textures for glyphs and colormap - * @param {WebGLRenderingContext} gl - WebGL context - * @returns {Promise} - * @private + * Creates textures for glyphs and colormap. * * Implementation details: * 1. Glyph Texture: @@ -137,7 +142,11 @@ class ShaderFilterVectorGlyph extends ShaderFilter { * - Samples colorscale * - Creates 1D RGBA texture * - Configures appropriate filtering - */ + * + * @param {WebGLRenderingContext} gl - WebGL context + * @returns {Promise} + * @private + */ async createTextures(gl) { // Glyphs const glyphsBuffer = await Util.rasterizeSVG(this.glyphsUrl, this.glyphsSize); @@ -167,10 +176,7 @@ class ShaderFilterVectorGlyph extends ShaderFilter { } /** - * Generates GLSL code for glyph-based vector field visualization - * @param {WebGLRenderingContext} gl - WebGL context - * @returns {string} GLSL function definition - * @private + * Generates GLSL code for glyph-based vector field visualization. * * Shader Features: * - Tile-based glyph placement @@ -178,7 +184,11 @@ class ShaderFilterVectorGlyph extends ShaderFilter { * - Magnitude-based glyph selection * - Alpha-based composition * - Multiple visualization modes - */ + * + * @param {WebGLRenderingContext} gl - WebGL context + * @returns {string} GLSL function definition + * @private + */ fragDataSrc(gl) { return ` // 2D vector glyph visualization @@ -286,60 +296,5 @@ class ShaderFilterVectorGlyph extends ShaderFilter { }`; } } -/** - * Default class properties - * - * @property {string} glyphsUrl - URL to SVG sprite sheet - * @property {ColorScale} colorscale - Associated colorscale for magnitude mapping - * @property {number[]} inDomain - Input magnitude range for mapping - * @property {number[]} glyphsSize - Dimensions of glyph sprite sheet - * @property {number} glyphsStride - Horizontal spacing between glyphs - * @property {Object} modes - Visualization mode configurations: - * - normalize: Glyph size normalization - * - glyph: Glyph coloring method - * - field: Background field visualization - * @property {Object} uniforms - WebGL uniform definitions: - * - glyph_color: vec4 custom glyph color - * - glyph_count: float number of glyphs in sprite sheet - * - glyph_wh: float glyph height/width - * - glyph_stride: float horizontal spacing - * - low_color: vec4 color for values below range - * - high_color: vec4 color for values above range - * - scale: float magnitude scaling factor - * - bias: float magnitude offset - */ - -/** - * GLSL Implementation Details - * - * Key Components: - * 1. Glyph Rendering: - * - Tile-based positioning - * - Dynamic rotation matrix - * - Sprite sheet sampling - * - Alpha composition - * - * 2. Vector Processing: - * - Magnitude computation - * - Direction extraction - * - Level selection - * - Coordinate transformation - * - * Constants: - * - GLYPH_TILE_SIZE: Spacing between glyphs (16.0) - * - ISQRT2: 1/sqrt(2) for magnitude normalization - * - * Uniforms: - * @property {sampler2D} glyphs - Glyph sprite sheet texture - * @property {sampler2D} colormap - Magnitude colormap texture - * @property {vec4} glyph_color - Custom glyph color - * @property {float} glyph_count - Number of glyphs in sprite sheet - * @property {float} glyph_wh - Glyph height/width - * @property {float} glyph_stride - Horizontal spacing between glyphs - * @property {vec4} low_color - Color for values below range - * @property {vec4} high_color - Color for values above range - * @property {float} scale - Magnitude scaling factor - * @property {float} bias - Magnitude offset - */ export { ShaderFilterVectorGlyph } \ No newline at end of file diff --git a/src/ShaderLens.js b/src/ShaderLens.js index 72f671bf..79ab84b6 100644 --- a/src/ShaderLens.js +++ b/src/ShaderLens.js @@ -19,8 +19,6 @@ import { Shader } from './Shader.js' */ /** - * @class - * @extends Shader * ShaderLens implements a circular magnification lens effect with optional overlay. * * Features: @@ -37,6 +35,62 @@ import { Shader } from './Shader.js' * - Alpha blending for overlays * - WebGL 1.0 and 2.0 compatibility * - Viewport coordinate mapping + * + * + * Example usage: + * ```javascript + * // Create lens shader + * const lens = new ShaderLens(); + * + * // Configure lens + * lens.setLensUniforms( + * [400, 300, 100, 10], // center at (400,300), radius 100, border 10 + * [800, 600], // viewport size + * [0.8, 0.8, 0.8, 1], // gray border + * true // show border + * ); + * + * // Enable overlay + * lens.setOverlayLayerEnabled(true); + * ``` + * + * Advanced usage with custom configuration: + * ```javascript + * const lens = new ShaderLens({ + * uniforms: { + * u_lens: { value: [0, 0, 150, 15] }, + * u_border_color: { value: [1, 0, 0, 1] } // red border + * }, + * overlayLayerEnabled: true + * }); + * ``` + * + * GLSL Implementation Details + * + * Key Components: + * 1. Lens Function: + * - Distance-based circle calculation + * - Smooth border transitions + * - Color mixing and blending + * + * 2. Overlay Processing: + * - Grayscale conversion + * - Alpha blending + * - Border preservation + * + * Functions: + * - lensColor(): Handles color transitions between lens regions + * - data(): Main processing function + * + * Uniforms: + * - {vec4} u_lens - Lens parameters [cx, cy, radius, border] + * - {vec2} u_width_height - Viewport dimensions + * - {vec4} u_border_color - Border color and alpha + * - {bool} u_border_enable - Border visibility flag + * - {sampler2D} source0 - Main texture + * - {sampler2D} source1 - Optional overlay texture + * + * @extends Shader */ class ShaderLens extends Shader { /** @@ -95,16 +149,17 @@ class ShaderLens extends Shader { } /** - * Generates fragment shader source code - * @param {WebGLRenderingContext} gl - WebGL context - * @returns {string} Fragment shader source code - * @private + * Generates fragment shader source code. * * Shader Features: * - Circular lens implementation * - Smooth border transitions * - Optional overlay support * - Grayscale conversion outside lens + * + * @param {WebGLRenderingContext} gl - WebGL context + * @returns {string} Fragment shader source code + * @private */ fragShaderSrc(gl) { let gl2 = !(gl instanceof WebGLRenderingContext); @@ -175,7 +230,8 @@ class ShaderLens extends Shader { } /** - * Generates vertex shader source code + * Generates vertex shader source code. + * * @param {WebGLRenderingContext} gl - WebGL context * @returns {string} Vertex shader source code * @private @@ -195,76 +251,5 @@ void main() { }`; } } -/** - * Default class properties - * - * @property {Array} samplers - Texture sampler definitions: - * - source0: Main image texture - * - source1: Optional overlay texture - * @property {Object} uniforms - WebGL uniform definitions: - * - u_lens: vec4 lens parameters - * - u_width_height: vec2 viewport dimensions - * - u_border_color: vec4 border color - * - u_border_enable: bool border visibility - * @property {string} label - Shader label - * @property {boolean} overlayLayerEnabled - Overlay state - */ - -/** - * Example usage: - * ```javascript - * // Create lens shader - * const lens = new ShaderLens(); - * - * // Configure lens - * lens.setLensUniforms( - * [400, 300, 100, 10], // center at (400,300), radius 100, border 10 - * [800, 600], // viewport size - * [0.8, 0.8, 0.8, 1], // gray border - * true // show border - * ); - * - * // Enable overlay - * lens.setOverlayLayerEnabled(true); - * ``` - * - * Advanced usage with custom configuration: - * ```javascript - * const lens = new ShaderLens({ - * uniforms: { - * u_lens: { value: [0, 0, 150, 15] }, - * u_border_color: { value: [1, 0, 0, 1] } // red border - * }, - * overlayLayerEnabled: true - * }); - * ``` - */ - -/** - * GLSL Implementation Details - * - * Key Components: - * 1. Lens Function: - * - Distance-based circle calculation - * - Smooth border transitions - * - Color mixing and blending - * - * 2. Overlay Processing: - * - Grayscale conversion - * - Alpha blending - * - Border preservation - * - * Functions: - * - lensColor(): Handles color transitions between lens regions - * - data(): Main processing function - * - * Uniforms: - * @property {vec4} u_lens - Lens parameters [cx, cy, radius, border] - * @property {vec2} u_width_height - Viewport dimensions - * @property {vec4} u_border_color - Border color and alpha - * @property {bool} u_border_enable - Border visibility flag - * @property {sampler2D} source0 - Main texture - * @property {sampler2D} source1 - Optional overlay texture - */ export { ShaderLens } diff --git a/src/ShaderNeural.js b/src/ShaderNeural.js index 3e2a8456..3badbfef 100644 --- a/src/ShaderNeural.js +++ b/src/ShaderNeural.js @@ -12,8 +12,6 @@ import { Shader } from './Shader.js' */ /** - * @class - * @extends Shader * ShaderNeural implements a WebGL-based neural network for real-time image relighting. * Used in conjunction with LayerNeuralRTI for Neural Reflectance Transformation Imaging. * @@ -33,6 +31,77 @@ import { Shader } from './Shader.js' * - Multi-texture sampling * - Weight matrix management * - Dequantization support + * +/** + * Neural Network Architecture Details + * + * The network consists of three layers: + * 1. Input Layer: + * - Accepts coefficient planes and light direction + * - Applies dequantization and normalization + * + * 2. Hidden Layers: + * - Two fully connected layers + * - ELU activation function + * - Vectorized operations for efficiency + * + * 3. Output Layer: + * - Produces final RGB/XYZ color + * - Linear activation + * + * Implementation Notes: + * - All matrices are packed into vec4 for efficient GPU processing + * - Network dimensions are padded to multiples of 4 + * - Uses texture sampling for coefficient input + * - Implements forward pass only + * + * + * Example usage with LayerNeuralRTI: + * ```javascript + * // Create neural shader + * const shader = new ShaderNeural({ + * mode: 'light', + * nplanes: 9 + * }); + * + * // Configure network + * shader.setShaderInfo(samples, 9, 52, 12, 'rgb'); + * + * // Update weights + * shader.setUniform('layer1_weights', weights1); + * shader.setUniform('layer1_biases', biases1); + * // ... set other layers + * + * // Set light direction + * shader.setLight([0.5, 0.3]); + * ``` + * + * Fragment Shader Implementation + * + * Key Components: + * 1. Input Processing: + * - Texture sampling + * - Dequantization + * - Light direction incorporation + * + * 2. Network Computation: + * - Vectorized matrix multiplication + * - ELU activation function + * - Layer-wise processing + * + * 3. Output Processing: + * - Color space conversion + * - Final color computation + * + * Uniforms: + * - {sampler2D} u_texture_[1-3] - Coefficient plane textures + * - {vec2} lights - Light direction vector + * - {vec4[]} layer[1-3]_weights - Layer weight matrices + * - {vec4[]} layer[1-3]_biases - Layer bias vectors + * - {vec3} min - Minimum values for dequantization + * - {vec3} max - Maximum values for dequantization + * + * @extends Shader */ class ShaderNeural extends Shader { /** @@ -276,97 +345,5 @@ vec4 data1() { } } -/** - * Default class properties - * - * @property {Array} samplers - Texture sampler definitions: - * - u_texture_1: First coefficient plane - * - u_texture_2: Second coefficient plane - * - u_texture_3: Third coefficient plane - * @property {Object} uniforms - WebGL uniform definitions: - * - lights: vec2 light direction - * - min: vec3 minimum values for dequantization - * - max: vec3 maximum values for dequantization - * - layer1_weights: vec4[] first layer weights - * - layer1_biases: vec4[] first layer biases - * - layer2_weights: vec4[] second layer weights - * - layer2_biases: vec4[] second layer biases - * - layer3_weights: vec4[] output layer weights - * - layer3_biases: vec3 output layer biases - */ - -/** - * Neural Network Architecture Details - * - * The network consists of three layers: - * 1. Input Layer: - * - Accepts coefficient planes and light direction - * - Applies dequantization and normalization - * - * 2. Hidden Layers: - * - Two fully connected layers - * - ELU activation function - * - Vectorized operations for efficiency - * - * 3. Output Layer: - * - Produces final RGB/XYZ color - * - Linear activation - * - * Implementation Notes: - * - All matrices are packed into vec4 for efficient GPU processing - * - Network dimensions are padded to multiples of 4 - * - Uses texture sampling for coefficient input - * - Implements forward pass only - */ - -/** - * Example usage with LayerNeuralRTI: - * ```javascript - * // Create neural shader - * const shader = new ShaderNeural({ - * mode: 'light', - * nplanes: 9 - * }); - * - * // Configure network - * shader.setShaderInfo(samples, 9, 52, 12, 'rgb'); - * - * // Update weights - * shader.setUniform('layer1_weights', weights1); - * shader.setUniform('layer1_biases', biases1); - * // ... set other layers - * - * // Set light direction - * shader.setLight([0.5, 0.3]); - * ``` - */ - -/** - * Fragment Shader Implementation - * - * Key Components: - * 1. Input Processing: - * - Texture sampling - * - Dequantization - * - Light direction incorporation - * - * 2. Network Computation: - * - Vectorized matrix multiplication - * - ELU activation function - * - Layer-wise processing - * - * 3. Output Processing: - * - Color space conversion - * - Final color computation - * - * Uniforms: - * @property {sampler2D} u_texture_[1-3] - Coefficient plane textures - * @property {vec2} lights - Light direction vector - * @property {vec4[]} layer[1-3]_weights - Layer weight matrices - * @property {vec4[]} layer[1-3]_biases - Layer bias vectors - * @property {vec3} min - Minimum values for dequantization - * @property {vec3} max - Maximum values for dequantization - */ - export { ShaderNeural } diff --git a/src/ShaderRTI.js b/src/ShaderRTI.js index 74b3ee44..bb32499d 100644 --- a/src/ShaderRTI.js +++ b/src/ShaderRTI.js @@ -21,8 +21,6 @@ import { Shader } from './Shader.js' */ /** - * @class - * @extends Shader * ShaderRTI implements various Reflectance Transformation Imaging techniques. * Works in conjunction with LayerRTI for interactive relighting of cultural heritage objects. * @@ -47,6 +45,8 @@ import { Shader } from './Shader.js' * - Coefficient plane management * - Light vector transformation * - Color space conversion + * + * @extends Shader */ class ShaderRTI extends Shader { /** @@ -684,25 +684,25 @@ class BLN { */ /** - * @class LRGB + * LRGB * Luminance/RGB color space implementation * Separates luminance variation from base color */ /** - * @class RGB + * RGB * RGB color space implementation * Direct RGB coefficient manipulation */ /** - * @class MRGB + * MRGB * Modified RGB color space implementation * PCA-based color space transformation */ /** - * @class MYCC + * MYCC * Modified YCC color space implementation * Luminance/chrominance separation with custom transformation */ @@ -715,31 +715,31 @@ class BLN { */ /** - * @class PTM + * PTM * Polynomial Texture Map basis * Uses 6 coefficients per color channel */ /** - * @class HSH + * HSH * Hemispherical Harmonics basis * Uses 9 coefficients per color channel */ /** - * @class SH + * SH * Spherical Harmonics basis * Uses 9 coefficients per color channel */ /** - * @class RBF + * RBF * Radial Basis Functions * Uses measured light directions with Gaussian interpolation */ /** - * @class BLN + * BLN * Bilinear interpolation * Uses grid-based interpolation of light directions */ diff --git a/src/Signals.js b/src/Signals.js index 420e2a2d..0c03f577 100644 --- a/src/Signals.js +++ b/src/Signals.js @@ -14,6 +14,36 @@ * - Signal initialization * - Signal storage * + * + * Implementation Details + * + * The signal system works by: + * 1. Extending the prototype with signal tracking properties + * 2. Maintaining arrays of callbacks for each signal type + * 3. Providing methods to register and trigger callbacks + * + * Signal Storage Structure: + * ```javascript + * { + * signals: { + * 'eventName1': [callback1, callback2, ...], + * 'eventName2': [callback3, callback4, ...] + * }, + * allSignals: ['eventName1', 'eventName2', ...] + * } + * ``` + * + * Performance Considerations: + * - Callbacks are stored in arrays for fast iteration + * - Signals are initialized lazily on first use + * - Direct property access for quick event emission + * + * Usage Notes: + * - Events must be registered before they can be used + * - Multiple callbacks can be registered for the same event + * - Callbacks are executed synchronously + * - Parameters are passed through to callbacks unchanged + * * @function * @param {Object} proto - The prototype to enhance with signal capabilities * @param {...string} signals - Names of signals to register @@ -114,35 +144,4 @@ function addSignals(proto, ...signals) { } } -/** - * Implementation Details - * - * The signal system works by: - * 1. Extending the prototype with signal tracking properties - * 2. Maintaining arrays of callbacks for each signal type - * 3. Providing methods to register and trigger callbacks - * - * Signal Storage Structure: - * ```javascript - * { - * signals: { - * 'eventName1': [callback1, callback2, ...], - * 'eventName2': [callback3, callback4, ...] - * }, - * allSignals: ['eventName1', 'eventName2', ...] - * } - * ``` - * - * Performance Considerations: - * - Callbacks are stored in arrays for fast iteration - * - Signals are initialized lazily on first use - * - Direct property access for quick event emission - * - * Usage Notes: - * - Events must be registered before they can be used - * - Multiple callbacks can be registered for the same event - * - Callbacks are executed synchronously - * - Parameters are passed through to callbacks unchanged - */ - export { addSignals } \ No newline at end of file diff --git a/src/Skin.js b/src/Skin.js index 761b1611..b939415b 100644 --- a/src/Skin.js +++ b/src/Skin.js @@ -1,8 +1,17 @@ +/** + * @default + */ let url = 'skin/skin.svg'; -let svg = null; + +/** + * @default + */ let pad = 5; +let svg = null; + + /** * @typedef {Object} SkinIcon * A UI icon element from the skin file @@ -30,7 +39,38 @@ let pad = 5; * - Padding management * - Transform handling * - * @class + * + * Default Configuration + * + * - {string} url - Default skin URL ('skin/skin.svg') + * - {number} pad - Icon padding in SVG units (5) + * + * File Structure Requirements: + * ```xml + * + * + * ... + * ... + * ... + * + * ``` + * + * Common Icon Classes: + * - openlime-home: Home/reset view + * - openlime-zoom: Zoom controls + * - openlime-menu: Menu button + * - openlime-close: Close button + * - openlime-next: Next/forward + * - openlime-prev: Previous/back + * + * Usage Notes: + * - Always use async/await with icon methods + * - Icons are cloned to allow multiple instances + * - SVG is loaded once and cached + * - Padding is applied uniformly + * - ViewBox is computed automatically + * + * * @static */ class Skin { @@ -150,37 +190,4 @@ class Skin { } } -/** - * Default Configuration - * - * @property {string} url - Default skin URL ('skin/skin.svg') - * @property {number} pad - Icon padding in SVG units (5) - * @property {SVGElement|null} svg - Cached SVG DOM element - * - * File Structure Requirements: - * ```xml - * - * - * ... - * ... - * ... - * - * ``` - * - * Common Icon Classes: - * - openlime-home: Home/reset view - * - openlime-zoom: Zoom controls - * - openlime-menu: Menu button - * - openlime-close: Close button - * - openlime-next: Next/forward - * - openlime-prev: Previous/back - * - * Usage Notes: - * - Always use async/await with icon methods - * - Icons are cloned to allow multiple instances - * - SVG is loaded once and cached - * - Padding is applied uniformly - * - ViewBox is computed automatically - */ - export { Skin } \ No newline at end of file diff --git a/src/TextToSpeechPlayer.js b/src/TextToSpeechPlayer.js index 67747bec..76bc30a4 100644 --- a/src/TextToSpeechPlayer.js +++ b/src/TextToSpeechPlayer.js @@ -8,7 +8,7 @@ */ /** - * @class + * * TextToSpeechPlayer provides text-to-speech functionality with extensive control options. * Handles voice selection, speech synthesis, text cleaning, and playback control. * @@ -27,6 +27,32 @@ * - Implements Chrome-specific fixes * - Handles browser tab switching * - Manages page unload events + * + * + * Implementation Details + * + * Chrome Bug Workarounds: + * - Implements periodic pause/resume to prevent Chrome from stopping + * - Uses timeout to prevent indefinite speech + * - Handles voice loading race conditions + * + * State Management: + * ```javascript + * { + * isSpeaking: boolean, // Current speech state + * isPaused: boolean, // Pause state + * voice: SpeechSynthesisVoice, // Selected voice + * isOfflineCapable: boolean, // Offline support + * volume: number, // Current volume + * previousVolume: number // Pre-mute volume + * } + * ``` + * + * Event Handling: + * - beforeunload: Stops speech on page close + * - visibilitychange: Handles tab switching + * - voiceschanged: Manages voice loading + * - utterance events: Tracks speech progress */ class TextToSpeechPlayer { /** @@ -112,12 +138,13 @@ class TextToSpeechPlayer { this.isSpeaking = true; } - /** - * @private - * Loads and selects appropriate voice for synthesis - * @returns {Promise} - * @throws {Error} If no suitable voice is found - */ +/** + * Loads and selects appropriate voice for synthesis. + * + * @returns {Promise} + * @throws {Error} If no suitable voice is found + * @private + */ async loadVoice() { console.log(`Loading voice for language: ${this.language}`); return new Promise((resolve, reject) => { @@ -162,10 +189,11 @@ class TextToSpeechPlayer { }); } - /** - * Checks if the selected voice is capable of offline speech synthesis. - * @private - */ +/** + * Checks if the selected voice is capable of offline speech synthesis. + * + * @private + */ checkOfflineCapability() { if (this.voice) { // If a voice is loaded and it's not marked as a network voice, assume it's offline capable @@ -175,19 +203,20 @@ class TextToSpeechPlayer { } } - /** - * @private - * Cleans text by removing HTML tags and formatting - * @param {string} text - Text to clean - * @returns {string} Cleaned text - * - * Cleaning steps: - * 1. Removes 'omissis' class content - * 2. Converts
to spaces - * 3. Strips HTML tags - * 4. Removes escape characters - * 5. Trims whitespace - */ +/** + * Cleans text by removing HTML tags and formatting. + * + * Cleaning steps: + * 1. Removes 'omissis' class content + * 2. Converts
to spaces + * 3. Strips HTML tags + * 4. Removes escape characters + * 5. Trims whitespace + * + * @param {string} text - Text to clean + * @returns {string} Cleaned text + * @private + */ cleanTextForSpeech(text) { // Remove content of any HTML tag with class "omissis" (with or without escaped quotes) let cleanedText = text.replace(/<[^>]+class=(\"omissis\"|"omissis")[^>]*>[\s\S]*?<\/[^>]+>/g, ""); @@ -371,31 +400,4 @@ class TextToSpeechPlayer { } } -/** - * Implementation Details - * - * Chrome Bug Workarounds: - * - Implements periodic pause/resume to prevent Chrome from stopping - * - Uses timeout to prevent indefinite speech - * - Handles voice loading race conditions - * - * State Management: - * ```javascript - * { - * isSpeaking: boolean, // Current speech state - * isPaused: boolean, // Pause state - * voice: SpeechSynthesisVoice, // Selected voice - * isOfflineCapable: boolean, // Offline support - * volume: number, // Current volume - * previousVolume: number // Pre-mute volume - * } - * ``` - * - * Event Handling: - * - beforeunload: Stops speech on page close - * - visibilitychange: Handles tab switching - * - voiceschanged: Manages voice loading - * - utterance events: Tracks speech progress - */ - export { TextToSpeechPlayer } \ No newline at end of file diff --git a/src/Tile.js b/src/Tile.js index 5b1020ed..e6a6afed 100644 --- a/src/Tile.js +++ b/src/Tile.js @@ -1,27 +1,140 @@ // Tile level x y index ----- tex missing() start/end (tarzoom) ----- time, priority size(byte) /** - * A tile represents a single element of a regular grid that subdivides an image. - * A tile is identified by its position (`x`, `y`) within the grid and the zoom `level` of the image. - * @typedef {Object} Tile - * @property {number} level The zoom level of the tile. - * @property {number} x x position of the tile in the grid. - * @property {number} y y position of the tile in the grid. - * @property {number} index Unique tile identifier. - * @property {number} start The position of the first byte of the tile in the image dataset (used only for tarzoom and itarzoom image formats). - * @property {number} end The position of the last byte of the tile in the image dataset (used only for tarzoom and itarzoom image formats). - * @property {number} missing In the case of multi-channel formats (RTI, BRDF), the information content of a tile is distributed over several planes (channels). - * `missing` represents the number of pending channel data requests. - * @property {Array} tex A array of WebGLTexture (one texture per channel). - * @property {time} time Tile creation time (this value is used internally by the cache algorithms). - * @property {number} priority The priority of the tile (this value is used internally by the cache algorithms). - * @property {number} size The total size of the tile in bytes (this value is used internally by the cache algorithms). + * @typedef {Object} TileProperties + * @property {number} index - Unique identifier for the tile + * @property {number[]} bbox - Bounding box coordinates [minX, minY, maxX, maxY] + * @property {number} level - Zoom level in the pyramid (for tiled layouts) + * @property {number} x - Horizontal grid position + * @property {number} y - Vertical grid position + * @property {number} w - Tile width (for image layouts) + * @property {number} h - Tile height (for image layouts) + * @property {number} start - Starting byte position in dataset (for tar-based formats) + * @property {number} end - Ending byte position in dataset (for tar-based formats) + * @property {WebGLTexture[]} tex - Array of WebGL textures (one per channel) + * @property {number} missing - Count of pending channel data requests + * @property {number} time - Creation timestamp for cache management + * @property {number} priority - Loading priority for cache management + * @property {number} size - Total size in bytes for cache management */ +/** + * + * Represents a single tile in an image tiling system. + * Tiles are fundamental units used to manage large images through regular grid subdivision. + * Supports both traditional pyramid tiling and specialized formats like RTI/BRDF. + * + * Features: + * - Multi-channel texture support + * - Cache management properties + * - Format-specific byte positioning + * - Flexible layout compatibility + * - Priority-based loading + * + * Usage Contexts: + * 1. Tiled Layouts: + * - Part of zoom level pyramid + * - Grid-based positioning (x, y, level) + * + * 2. Image Layouts: + * - Direct image subdivision + * - Dimensional specification (w, h) + * + * 3. Specialized Formats: + * - RTI (Reflectance Transformation Imaging) + * - BRDF (Bidirectional Reflectance Distribution Function) + * - TAR-based formats (tarzoom, itarzoom) + * + * + * Implementation Details + * + * Property Categories: + * + * 1. Identification: + * ```javascript + * { + * index: number, // Unique tile ID + * bbox: number[], // Spatial bounds + * } + * ``` + * + * 2. Positioning: + * ```javascript + * { + * // Tiled Layout Properties + * level: number, // Zoom level + * x: number, // Grid X + * y: number, // Grid Y + * + * // Image Layout Properties + * w: number, // Width + * h: number, // Height + * } + * ``` + * + * 3. Data Access: + * ```javascript + * { + * start: number, // Byte start + * end: number, // Byte end + * tex: WebGLTexture[], // Channel textures + * missing: number, // Pending channels + * } + * ``` + * + * 4. Cache Management: + * ```javascript + * { + * time: number, // Creation time + * priority: number, // Load priority + * size: number // Memory size + * } + * ``` + * + * Format-Specific Considerations: + * + * 1. Standard Tiling: + * - Uses level, x, y for pyramid positioning + * - Single texture per tile + * + * 2. RTI/BRDF: + * - Multiple textures per tile (channels) + * - Missing counter tracks channel loading + * + * 3. TAR Formats: + * - Uses start/end for byte positioning + * - Enables direct data access in archives + * + * Cache Management: + * - time: Used for LRU (Least Recently Used) calculations + * - priority: Influences loading order + * - size: Helps manage memory constraints + */ class Tile { + /** + * Creates a new Tile instance with default properties + * + * @example + * ```javascript + * // Create a basic tile + * const tile = new Tile(); + * tile.level = 2; + * tile.x = 3; + * tile.y = 4; + * tile.priority = 1; + * ``` + * + * @example + * ```javascript + * // Create a multi-channel tile + * const tile = new Tile(); + * tile.tex = new Array(3); // For RGB channels + * tile.missing = 3; // Waiting for all channels + * ``` + */ constructor() { Object.assign(this, { - index: null, + index: null, bbox: null, level: null, //used only in LayoutTiles @@ -30,8 +143,8 @@ class Tile { w: null, // used only in LayoutImages h: null, // used only in LayoutImages - start:null, - end:null, + start: null, + end: null, tex: [], missing: null, diff --git a/src/Transform.js b/src/Transform.js index 0f98b2c1..7b8867ec 100644 --- a/src/Transform.js +++ b/src/Transform.js @@ -1,8 +1,17 @@ import { BoundingBox } from "./BoundingBox"; /** - * @typedef {[number, number]} APoint - * Array representation of a 2D point [x, y] + * @typedef {Array} APoint + * A tuple of [x, y] representing a 2D point. + * @property {number} 0 - X coordinate + * @property {number} 1 - Y coordinate + * + * @example + * ```javascript + * const point: APoint = [10, 20]; // [x, y] + * const x = point[0]; // x coordinate + * const y = point[1]; // y coordinate + * ``` */ /** @@ -27,14 +36,16 @@ import { BoundingBox } from "./BoundingBox"; */ /** - * @class + * * Implements a 2D affine transformation system for coordinate manipulation. * Provides a complete set of operations for coordinate system conversions, * camera transformations, and animation support. * * Mathematical Model: * Transformation of point P to P' follows the equation: + * * P' = z * R(a) * P + T + * * where: * - z: scale factor * - R(a): rotation matrix for angle 'a' @@ -47,6 +58,39 @@ import { BoundingBox } from "./BoundingBox"; * - Viewport projection * - Coordinate system conversions * - Bounding box transformations + * + * + * Coordinate Systems and Transformations: + * + * 1. Scene Space: + * - Origin at image center + * - Y-axis points up + * - Unit scale + * + * 2. Viewport Space: + * - Origin at top-left + * - Y-axis points down + * - Pixel units [0..w-1, 0..h-1] + * + * 3. WebGL Space: + * - Origin at center + * - Y-axis points up + * - Range [-1..1, -1..1] + * + * Transform Pipeline: + * ``` + * Scene -> Transform -> Viewport -> WebGL + * ``` + * + * Animation System: + * - Time-based interpolation + * - Multiple easing functions + * - Smooth transitions + * + * Performance Considerations: + * - Matrix operations optimized for 2D + * - Cached transformation results + * - Efficient composition */ class Transform { //FIXME Add translation to P? /** @@ -314,38 +358,4 @@ class Transform { //FIXME Add translation to P? } } -/** - * Coordinate Systems and Transformations: - * - * 1. Scene Space: - * - Origin at image center - * - Y-axis points up - * - Unit scale - * - * 2. Viewport Space: - * - Origin at top-left - * - Y-axis points down - * - Pixel units [0..w-1, 0..h-1] - * - * 3. WebGL Space: - * - Origin at center - * - Y-axis points up - * - Range [-1..1, -1..1] - * - * Transform Pipeline: - * ``` - * Scene -> Transform -> Viewport -> WebGL - * ``` - * - * Animation System: - * - Time-based interpolation - * - Multiple easing functions - * - Smooth transitions - * - * Performance Considerations: - * - Matrix operations optimized for 2D - * - Cached transformation results - * - Efficient composition - */ - export { Transform } diff --git a/src/UIBasic.js b/src/UIBasic.js index 1df5e1c5..34a83703 100644 --- a/src/UIBasic.js +++ b/src/UIBasic.js @@ -33,7 +33,7 @@ import { addSignals } from './Signals' */ /** - * @class + * * UIBasic implements a complete user interface for OpenLIME viewers. * Provides toolbar controls, layer management, and interactive features. * @@ -56,6 +56,52 @@ import { addSignals } from './Signals' * - ruler: Distance measurement * - help: Show help dialog * - snapshot: Save view as image + * + * Implementation Details + * + * Layer Management: + * - Layers can be toggled individually + * - Layer visibility affects associated controllers + * - Overlay layers behave independently + * - Layer state is reflected in menu UI + * + * Mouse/Touch Interaction: + * - Uses PointerManager for event handling + * - Supports multi-touch gestures + * - Handles drag operations for light control + * - Manages tool state transitions + * + * Menu System: + * - Hierarchical structure + * - Dynamic updates based on state + * - Group-based selection + * - Mode-specific entries + * + * Controller Integration: + * - Light direction controller + * - Pan/zoom controller + * - Measurement controller + * - Priority-based event handling + * + * Dialog System: + * - Modal blocking of underlying UI + * - Non-modal floating windows + * - Content injection system + * - Event-based communication + * + * Skin System: + * - SVG-based icons + * - Dynamic loading + * - CSS customization + * - Responsive layout + * + * Keyboard Support: + * - Configurable shortcuts + * - Action mapping + * - Mode-specific keys + * - Focus handling + * + * See the complete example in: {@link https://github.com/cnr-isti-vclab/openlime/tree/main/dist/examples/ui-custom|GitHub ui-custom example} */ class UIBasic { /** @@ -222,7 +268,6 @@ class UIBasic { * Shows overlay message * @param {string} msg - Message to display * @param {number} [duration=2000] - Display duration in ms - * @private */ showOverlayMessage(msg, duration = 2000) { if (this.overlayMessage) { @@ -402,12 +447,12 @@ class UIBasic { } } - /** - * Loads and initializes skin SVG elements - * @returns {Promise} - * @private - * @async - */ + /** + * Loads and initializes skin SVG elements + * @returns {Promise} + * @private + * @async + */ async loadSkin() { let toolbar = document.createElement('div'); toolbar.classList.add('openlime-toolbar'); @@ -485,10 +530,10 @@ class UIBasic { } } - /** - * Initializes action buttons and their event handlers - * @private - */ + /** + * Initializes action buttons and their event handlers + * @private + */ setupActions() { for (let [name, action] of Object.entries(this.actions)) { let element = action.element; @@ -514,6 +559,7 @@ class UIBasic { /** * Toggles light direction control mode * @param {boolean} [on] - Force specific state + * @private */ toggleLightController(on) { let div = this.viewer.containerElement; @@ -531,6 +577,7 @@ class UIBasic { /** * Toggles fullscreen mode * Handles browser-specific fullscreen APIs + * @private */ toggleFullscreen() { let canvas = this.viewer.canvasElement; @@ -553,6 +600,7 @@ class UIBasic { /** * Toggles measurement ruler tool + * @private */ toggleRuler() { if (!this.ruler) { @@ -566,11 +614,12 @@ class UIBasic { this.ruler.end(); } - /** - * Toggles help dialog - * @param {UIBasic~Action} help - Help action configuration - * @param {boolean} [on] - Force specific state - */ + /** + * Toggles help dialog + * @param {UIBasic~Action} help - Help action configuration + * @param {boolean} [on] - Force specific state + * @private + */ toggleHelp(help, on) { if (!help.dialog) { help.dialog = new UIDialog(this.viewer.containerElement, { modal: true, class: 'openlime-help-dialog' }); @@ -579,9 +628,10 @@ class UIBasic { help.dialog.toggle(on); } - /** - * Creates and downloads canvas snapshot - */ + /** + * Creates and downloads canvas snapshot + * @private + */ snapshot() { var e = document.createElement('a'); e.setAttribute('href', this.viewer.canvas.canvasElement.toDataURL()); @@ -594,12 +644,12 @@ class UIBasic { /* Layer management */ - /** - * Creates HTML for menu entry - * @param {UIBasic~MenuEntry} entry - Menu entry to create - * @returns {string} Generated HTML - * @private - */ + /** + * Creates HTML for menu entry + * @param {UIBasic~MenuEntry} entry - Menu entry to create + * @returns {string} Generated HTML + * @private + */ createEntry(entry) { if (!('id' in entry)) entry.id = 'entry_' + (this.entry_count++); @@ -637,11 +687,11 @@ class UIBasic { return html; } - /** - * Attaches event handlers to menu entry elements - * @param {UIBasic~MenuEntry} entry - Menu entry to process - * @private - */ + /** + * Attaches event handlers to menu entry elements + * @param {UIBasic~MenuEntry} entry - Menu entry to process + * @private + */ addEntryCallbacks(entry) { entry.element = this.layerMenu.querySelector('#' + entry.id); if (entry.onclick) @@ -659,11 +709,11 @@ class UIBasic { this.addEntryCallbacks(e); } - /** - * Updates menu entry state - * @param {UIBasic~MenuEntry} entry - Menu entry to update - * @private - */ + /** + * Updates menu entry state + * @param {UIBasic~MenuEntry} entry - Menu entry to update + * @private + */ updateEntry(entry) { let status = entry.status ? entry.status() : ''; entry.element.classList.toggle('active', status == 'active'); @@ -673,19 +723,19 @@ class UIBasic { this.updateEntry(e); } - /** - * Updates all menu entries - * @private - */ + /** + * Updates all menu entries + * @private + */ updateMenu() { for (let entry of this.menu) this.updateEntry(entry); } - /** - * Creates main menu structure - * @private - */ + /** + * Creates main menu structure + * @private + */ createMenu() { this.entry_count = 0; let html = `
`; @@ -711,17 +761,18 @@ class UIBasic { }); */ } - /** - * Toggles layer menu visibility - */ + /** + * Toggles layer menu visibility + * @private + */ toggleLayers() { this.layerMenu.classList.toggle('open'); } - /** - * Sets active layer and updates UI - * @param {Layer|string} layer_on - Layer or layer ID to activate - */ + /** + * Sets active layer and updates UI + * @param {Layer|string} layer_on - Layer or layer ID to activate + */ setLayer(layer_on) { if (typeof layer_on == 'string') layer_on = this.viewer.canvas.layers[layer_on]; @@ -745,12 +796,12 @@ class UIBasic { this.viewer.redraw(); } - /** - * Hides layers menu - */ - closeLayersMenu() { - this.layerMenu.style.display = 'none'; - } + /** + * Hides layers menu + */ + // closeLayersMenu() { + // this.layerMenu.style.display = 'none'; + // } } /** @@ -778,10 +829,10 @@ class UIDialog { //FIXME standalone class this.create(); } - /** - * Creates dialog DOM structure - * @private - */ + /** + * Creates dialog DOM structure + * @private + */ create() { let background = document.createElement('div'); background.classList.add('openlime-dialog-background'); @@ -822,10 +873,10 @@ class UIDialog { //FIXME standalone class this.hide(); } - /** - * Sets dialog content - * @param {string|HTMLElement} html - Content to display - */ + /** + * Sets dialog content + * @param {string|HTMLElement} html - Content to display + */ setContent(html) { if (typeof (html) == 'string') this.content.innerHTML = html; @@ -841,10 +892,10 @@ class UIDialog { //FIXME standalone class this.visible = true; } - /** - * Hides the dialog and emits closed event - * @fires UIDialog#closed - */ + /** + * Hides the dialog and emits closed event + * @fires UIDialog#closed + */ hide() { /** * The event is fired when the dialog is closed. @@ -855,18 +906,18 @@ class UIDialog { //FIXME standalone class this.emit('closed'); } - /** - * Toggles fade effect - * @param {boolean} on - Whether to enable fade effect - */ + /** + * Toggles fade effect + * @param {boolean} on - Whether to enable fade effect + */ fade(on) { //FIXME Does it work? this.element.classList.toggle('fading'); } - /** - * Toggles dialog visibility - * @param {boolean} [force] - Force specific state - */ + /** + * Toggles dialog visibility + * @param {boolean} [force] - Force specific state + */ toggle(force) { //FIXME Why not remove force? this.element.classList.toggle('hidden', force); this.visible = !this.visible; //FIXME not in sync with 'force' @@ -889,49 +940,4 @@ class UIDialog { //FIXME standalone class addSignals(UIDialog, 'closed'); addSignals(UIBasic, 'lightdirection'); -/** - * Implementation Details - * - * Layer Management: - * - Layers can be toggled individually - * - Layer visibility affects associated controllers - * - Overlay layers behave independently - * - Layer state is reflected in menu UI - * - * Mouse/Touch Interaction: - * - Uses PointerManager for event handling - * - Supports multi-touch gestures - * - Handles drag operations for light control - * - Manages tool state transitions - * - * Menu System: - * - Hierarchical structure - * - Dynamic updates based on state - * - Group-based selection - * - Mode-specific entries - * - * Controller Integration: - * - Light direction controller - * - Pan/zoom controller - * - Measurement controller - * - Priority-based event handling - * - * Dialog System: - * - Modal blocking of underlying UI - * - Non-modal floating windows - * - Content injection system - * - Event-based communication - * - * Skin System: - * - SVG-based icons - * - Dynamic loading - * - CSS customization - * - Responsive layout - * - * Keyboard Support: - * - Configurable shortcuts - * - Action mapping - * - Mode-specific keys - * - Focus handling - */ export { UIBasic, UIDialog } diff --git a/src/Util.js b/src/Util.js index f48519d9..023ac540 100644 --- a/src/Util.js +++ b/src/Util.js @@ -5,7 +5,7 @@ window.structuredClone = typeof (structuredClone) == "function" ? structuredClon * Utility class providing various helper functions for OpenLIME. * Includes methods for SVG manipulation, file loading, image processing, and string handling. * - * @class + * * @static */ class Util { diff --git a/src/Viewer.js b/src/Viewer.js index 08798aa0..5bed6973 100644 --- a/src/Viewer.js +++ b/src/Viewer.js @@ -25,6 +25,18 @@ import { addSignals } from './Signals.js' */ /** + * Fired when frame is drawn + * @event Viewer#draw + */ + +/** + * Fired when viewer is resized + * @event Viewer#resize + * @property {Viewport} viewport - New viewport configuration + */ + +/** + * * Central class of the OpenLIME framework. * Creates and manages the main viewer interface, coordinates components, * and handles rendering pipeline. @@ -37,7 +49,40 @@ import { addSignals } from './Signals.js' * - Rendering pipeline * - Resource management * - * @class + * + * + * Component Relationships: + * ``` + * Viewer + * ├── Canvas + * │ └── Layers + * ├── Camera + * ├── PointerManager + * └── Controllers + * ``` + * + * Rendering Pipeline: + * 1. Camera computes current transform + * 2. Canvas prepares render state + * 3. Layers render in order + * 4. Post-processing applied + * 5. Frame timing recorded + * + * Event System: + * - draw: Emitted after each frame render + * - resize: Emitted when viewport changes + * + * Performance Considerations: + * - Uses requestAnimationFrame + * - Tracks frame timing + * - Handles device pixel ratio + * - Optimizes redraw requests + * + * Resource Management: + * - Automatic canvas cleanup + * - Proper event listener removal + * - ResizeObserver handling + * * @fires Viewer#draw * @fires Viewer#resize * @@ -239,50 +284,4 @@ class Viewer { addSignals(Viewer, 'draw'); addSignals(Viewer, 'resize'); //args: viewport -/** - * Component Relationships: - * ``` - * Viewer - * ├── Canvas - * │ └── Layers - * ├── Camera - * ├── PointerManager - * └── Controllers - * ``` - * - * Rendering Pipeline: - * 1. Camera computes current transform - * 2. Canvas prepares render state - * 3. Layers render in order - * 4. Post-processing applied - * 5. Frame timing recorded - * - * Event System: - * - draw: Emitted after each frame render - * - resize: Emitted when viewport changes - * - * Performance Considerations: - * - Uses requestAnimationFrame - * - Tracks frame timing - * - Handles device pixel ratio - * - Optimizes redraw requests - * - * Resource Management: - * - Automatic canvas cleanup - * - Proper event listener removal - * - ResizeObserver handling - */ - -/** - * Fired when frame is drawn - * @event Viewer#draw - */ - -/** - * Fired when viewer is resized - * @event Viewer#resize - * @property {Viewport} viewport - New viewport configuration - */ - - export { Viewer }; \ No newline at end of file