/* X_ITE v8.12.5 */var __webpack_modules__ = ({

/***/ 196:
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

/* provided dependency */ var jQuery = __webpack_require__(659);
/**
 * @preserve jquery.fullscreen 1.1.5
 * https://github.com/code-lts/jquery-fullscreen-plugin
 * Copyright (C) 2012-2013 Klaus Reimer <k@ailis.de>
 * Licensed under the MIT license
 * (See http://www.opensource.org/licenses/mit-license)
 */

(function(jQuery) {

/**
 * Sets or gets the fullscreen state.
 *
 * @param {boolean=} state
 *            True to enable fullscreen mode, false to disable it. If not
 *            specified then the current fullscreen state is returned.
 * @return {boolean|Element|jQuery|null}
 *            When querying the fullscreen state then the current fullscreen
 *            element (or true if browser doesn't support it) is returned
 *            when browser is currently in full screen mode. False is returned
 *            if browser is not in full screen mode. Null is returned if
 *            browser doesn't support fullscreen mode at all. When setting
 *            the fullscreen state then the current jQuery selection is
 *            returned for chaining.
 * @this {jQuery}
 */
function fullScreen(state)
{
    var e, func, doc;

    // Do nothing when nothing was selected
    if (!this.length) return this;

    // We only use the first selected element because it doesn't make sense
    // to fullscreen multiple elements.
    e = (/** @type {Element} */ this[0]);

    // Find the real element and the document (Depends on whether the
    // document itself or a HTML element was selected)
    if (e.ownerDocument)
    {
        doc = e.ownerDocument;
    }
    else
    {
        doc = e;
        e = doc.documentElement;
    }

    // When no state was specified then return the current state.
    if (state == null)
    {
        // When fullscreen mode is not supported then return null
        if (!((/** @type {?Function} */ doc["exitFullscreen"])
            || (/** @type {?Function} */ doc["webkitExitFullscreen"])
            || (/** @type {?Function} */ doc["webkitCancelFullScreen"])
            || (/** @type {?Function} */ doc["msExitFullscreen"])
            || (/** @type {?Function} */ doc["mozCancelFullScreen"])))
        {
            return null;
        }

        // Check fullscreen state
        state = fullScreenState(doc);
        if (!state) return state;

        // Return current fullscreen element or "true" if browser doesn't
        // support this
        return (/** @type {?Element} */ doc["fullscreenElement"])
            || (/** @type {?Element} */ doc["webkitFullscreenElement"])
            || (/** @type {?Element} */ doc["webkitCurrentFullScreenElement"])
            || (/** @type {?Element} */ doc["msFullscreenElement"])
            || (/** @type {?Element} */ doc["mozFullScreenElement"])
            || state;
    }

    // When state was specified then enter or exit fullscreen mode.
    if (state)
    {
        // Enter fullscreen
        func = (/** @type {?Function} */ e["requestFullscreen"])
            || (/** @type {?Function} */ e["webkitRequestFullscreen"])
            || (/** @type {?Function} */ e["webkitRequestFullScreen"])
            || (/** @type {?Function} */ e["msRequestFullscreen"])
            || (/** @type {?Function} */ e["mozRequestFullScreen"]);
        if (func)
        {
            func.call(e);
        }
        return this;
    }
    else
    {
        // Exit fullscreen
        func = (/** @type {?Function} */ doc["exitFullscreen"])
            || (/** @type {?Function} */ doc["webkitExitFullscreen"])
            || (/** @type {?Function} */ doc["webkitCancelFullScreen"])
            || (/** @type {?Function} */ doc["msExitFullscreen"])
            || (/** @type {?Function} */ doc["mozCancelFullScreen"]);
        if (func && fullScreenState(doc)) func.call(doc);
        return this;
    }
}

/**
 * Check fullscreen state
 *
 * @param {Document} doc The content document
 * @return {Boolean}
 */
function fullScreenState(doc) {
    return !!(doc["fullscreenElement"] || doc["msFullscreenElement"] || doc["webkitIsFullScreen"] || doc["mozFullScreen"]);
}

/**
 * Toggles the fullscreen mode.
 *
 * @return {!jQuery}
 *            The jQuery selection for chaining.
 * @this {jQuery}
 */
function toggleFullScreen()
{
    return (/** @type {!jQuery} */ fullScreen.call(this,
        !fullScreen.call(this)));
}

/**
 * Handles the browser-specific fullscreenchange event and triggers
 * a jquery event for it.
 *
 * @param {?Event} event
 *            The fullscreenchange event.
 */
function fullScreenChangeHandler(event)
{
    jQuery(document).trigger(new jQuery.Event("fullscreenchange"));
}

/**
 * Handles the browser-specific fullscreenerror event and triggers
 * a jquery event for it.
 *
 * @param {?Event} event
 *            The fullscreenerror event.
 */
function fullScreenErrorHandler(event)
{
    jQuery(document).trigger(new jQuery.Event("fullscreenerror"));
}

/**
 * Installs the fullscreenchange event handler.
 */
function installFullScreenHandlers()
{
    var e, change, error;

    // Determine event name
    e = document;
    if (e["webkitCancelFullScreen"])
    {
        change = "webkitfullscreenchange";
        error = "webkitfullscreenerror";
    }
    else if (e["msExitFullscreen"])
    {
        change = "MSFullscreenChange";
        error = "MSFullscreenError";
    }
    else if (e["mozCancelFullScreen"])
    {
        change = "mozfullscreenchange";
        error = "mozfullscreenerror";
    }
    else
    {
        change = "fullscreenchange";
        error = "fullscreenerror";
    }

    // Install the event handlers
    jQuery(document).bind(change, fullScreenChangeHandler);
    jQuery(document).bind(error, fullScreenErrorHandler);
}

jQuery.fn["fullScreen"] = fullScreen;
jQuery.fn["toggleFullScreen"] = toggleFullScreen;
installFullScreenHandlers();

})(jQuery);


/***/ }),

/***/ 946:
/***/ ((module, exports, __webpack_require__) => {

var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
 * jQuery Mousewheel 3.1.13
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license
 * http://jquery.org/license
 */

(function (factory) {
    if ( true ) {
        // AMD. Register as an anonymous module.
        !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(659)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
		__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
		(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
		__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
    } else {}
}(function ($) {

    var toFix  = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
        toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ?
                    ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
        slice  = Array.prototype.slice,
        nullLowestDeltaTimeout, lowestDelta;

    if ( $.event.fixHooks ) {
        for ( var i = toFix.length; i; ) {
            $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
        }
    }

    var special = $.event.special.mousewheel = {
        version: '3.1.12',

        setup: function() {
            if ( this.addEventListener ) {
                for ( var i = toBind.length; i; ) {
                    this.addEventListener( toBind[--i], handler, false );
                }
            } else {
                this.onmousewheel = handler;
            }
            // Store the line height and page height for this particular element
            $.data(this, 'mousewheel-line-height', special.getLineHeight(this));
            $.data(this, 'mousewheel-page-height', special.getPageHeight(this));
        },

        teardown: function() {
            if ( this.removeEventListener ) {
                for ( var i = toBind.length; i; ) {
                    this.removeEventListener( toBind[--i], handler, false );
                }
            } else {
                this.onmousewheel = null;
            }
            // Clean up the data we added to the element
            $.removeData(this, 'mousewheel-line-height');
            $.removeData(this, 'mousewheel-page-height');
        },

        getLineHeight: function(elem) {
            var $elem = $(elem),
                $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
            if (!$parent.length) {
                $parent = $('body');
            }
            return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16;
        },

        getPageHeight: function(elem) {
            return $(elem).height();
        },

        settings: {
            adjustOldDeltas: true, // see shouldAdjustOldDeltas() below
            normalizeOffset: true  // calls getBoundingClientRect for each event
        }
    };

    $.fn.extend({
        mousewheel: function(fn) {
            return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
        },

        unmousewheel: function(fn) {
            return this.unbind('mousewheel', fn);
        }
    });


    function handler(event) {
        var orgEvent   = event || window.event,
            args       = slice.call(arguments, 1),
            delta      = 0,
            deltaX     = 0,
            deltaY     = 0,
            absDelta   = 0,
            offsetX    = 0,
            offsetY    = 0;
        event = $.event.fix(orgEvent);
        event.type = 'mousewheel';

        // Old school scrollwheel delta
        if ( 'detail'      in orgEvent ) { deltaY = orgEvent.detail * -1;      }
        if ( 'wheelDelta'  in orgEvent ) { deltaY = orgEvent.wheelDelta;       }
        if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY;      }
        if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; }

        // Firefox < 17 horizontal scrolling related to DOMMouseScroll event
        if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
            deltaX = deltaY * -1;
            deltaY = 0;
        }

        // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
        delta = deltaY === 0 ? deltaX : deltaY;

        // New school wheel delta (wheel event)
        if ( 'deltaY' in orgEvent ) {
            deltaY = orgEvent.deltaY * -1;
            delta  = deltaY;
        }
        if ( 'deltaX' in orgEvent ) {
            deltaX = orgEvent.deltaX;
            if ( deltaY === 0 ) { delta  = deltaX * -1; }
        }

        // No change actually happened, no reason to go any further
        if ( deltaY === 0 && deltaX === 0 ) { return; }

        // Need to convert lines and pages to pixels if we aren't already in pixels
        // There are three delta modes:
        //   * deltaMode 0 is by pixels, nothing to do
        //   * deltaMode 1 is by lines
        //   * deltaMode 2 is by pages
        if ( orgEvent.deltaMode === 1 ) {
            var lineHeight = $.data(this, 'mousewheel-line-height');
            delta  *= lineHeight;
            deltaY *= lineHeight;
            deltaX *= lineHeight;
        } else if ( orgEvent.deltaMode === 2 ) {
            var pageHeight = $.data(this, 'mousewheel-page-height');
            delta  *= pageHeight;
            deltaY *= pageHeight;
            deltaX *= pageHeight;
        }

        // Store lowest absolute delta to normalize the delta values
        absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );

        if ( !lowestDelta || absDelta < lowestDelta ) {
            lowestDelta = absDelta;

            // Adjust older deltas if necessary
            if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
                lowestDelta /= 40;
            }
        }

        // Adjust older deltas if necessary
        if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
            // Divide all the things by 40!
            delta  /= 40;
            deltaX /= 40;
            deltaY /= 40;
        }

        // Get a whole, normalized value for the deltas
        delta  = Math[ delta  >= 1 ? 'floor' : 'ceil' ](delta  / lowestDelta);
        deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
        deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);

        // Normalise offsetX and offsetY properties
        if ( special.settings.normalizeOffset && this.getBoundingClientRect ) {
            var boundingRect = this.getBoundingClientRect();
            offsetX = event.clientX - boundingRect.left;
            offsetY = event.clientY - boundingRect.top;
        }

        // Add information to the event object
        event.deltaX = deltaX;
        event.deltaY = deltaY;
        event.deltaFactor = lowestDelta;
        event.offsetX = offsetX;
        event.offsetY = offsetY;
        // Go ahead and set deltaMode to 0 since we converted to pixels
        // Although this is a little odd since we overwrite the deltaX/Y
        // properties with normalized deltas.
        event.deltaMode = 0;

        // Add event and delta to the front of the arguments
        args.unshift(event, delta, deltaX, deltaY);

        // Clearout lowestDelta after sometime to better
        // handle multiple device types that give different
        // a different lowestDelta
        // Ex: trackpad = 3 and mouse wheel = 120
        if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
        nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);

        return ($.event.dispatch || $.event.handle).apply(this, args);
    }

    function nullLowestDelta() {
        lowestDelta = null;
    }

    function shouldAdjustOldDeltas(orgEvent, absDelta) {
        // If this is an older event and the delta is divisable by 120,
        // then we are assuming that the browser is treating this as an
        // older mouse wheel event and that we should divide the deltas
        // by 40 to try and get a more usable deltaFactor.
        // Side note, this actually impacts the reported scroll distance
        // in older browsers and can cause scrolling to be slower than native.
        // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
        return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
    }

}));


/***/ }),

/***/ 659:
/***/ (function(module, exports) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
 * jQuery JavaScript Library v3.7.1
 * https://jquery.com/
 *
 * Copyright OpenJS Foundation and other contributors
 * Released under the MIT license
 * https://jquery.org/license
 *
 * Date: 2023-08-28T13:37Z
 */
( function( global, factory ) {

	"use strict";

	if (  true && typeof module.exports === "object" ) {

		// For CommonJS and CommonJS-like environments where a proper `window`
		// is present, execute the factory and get jQuery.
		// For environments that do not have a `window` with a `document`
		// (such as Node.js), expose a factory as module.exports.
		// This accentuates the need for the creation of a real `window`.
		// e.g. var jQuery = require("jquery")(window);
		// See ticket trac-14549 for more info.
		module.exports = global.document ?
			factory( global, true ) :
			function( w ) {
				if ( !w.document ) {
					throw new Error( "jQuery requires a window with a document" );
				}
				return factory( w );
			};
	} else {
		factory( global );
	}

// Pass this if window is not defined yet
} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {

// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
// enough that all such attempts are guarded in a try block.
"use strict";

var arr = [];

var getProto = Object.getPrototypeOf;

var slice = arr.slice;

var flat = arr.flat ? function( array ) {
	return arr.flat.call( array );
} : function( array ) {
	return arr.concat.apply( [], array );
};


var push = arr.push;

var indexOf = arr.indexOf;

var class2type = {};

var toString = class2type.toString;

var hasOwn = class2type.hasOwnProperty;

var fnToString = hasOwn.toString;

var ObjectFunctionString = fnToString.call( Object );

var support = {};

var isFunction = function isFunction( obj ) {

		// Support: Chrome <=57, Firefox <=52
		// In some browsers, typeof returns "function" for HTML <object> elements
		// (i.e., `typeof document.createElement( "object" ) === "function"`).
		// We don't want to classify *any* DOM node as a function.
		// Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5
		// Plus for old WebKit, typeof returns "function" for HTML collections
		// (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756)
		return typeof obj === "function" && typeof obj.nodeType !== "number" &&
			typeof obj.item !== "function";
	};


var isWindow = function isWindow( obj ) {
		return obj != null && obj === obj.window;
	};


var document = window.document;



	var preservedScriptAttributes = {
		type: true,
		src: true,
		nonce: true,
		noModule: true
	};

	function DOMEval( code, node, doc ) {
		doc = doc || document;

		var i, val,
			script = doc.createElement( "script" );

		script.text = code;
		if ( node ) {
			for ( i in preservedScriptAttributes ) {

				// Support: Firefox 64+, Edge 18+
				// Some browsers don't support the "nonce" property on scripts.
				// On the other hand, just using `getAttribute` is not enough as
				// the `nonce` attribute is reset to an empty string whenever it
				// becomes browsing-context connected.
				// See https://github.com/whatwg/html/issues/2369
				// See https://html.spec.whatwg.org/#nonce-attributes
				// The `node.getAttribute` check was added for the sake of
				// `jQuery.globalEval` so that it can fake a nonce-containing node
				// via an object.
				val = node[ i ] || node.getAttribute && node.getAttribute( i );
				if ( val ) {
					script.setAttribute( i, val );
				}
			}
		}
		doc.head.appendChild( script ).parentNode.removeChild( script );
	}


function toType( obj ) {
	if ( obj == null ) {
		return obj + "";
	}

	// Support: Android <=2.3 only (functionish RegExp)
	return typeof obj === "object" || typeof obj === "function" ?
		class2type[ toString.call( obj ) ] || "object" :
		typeof obj;
}
/* global Symbol */
// Defining this global in .eslintrc.json would create a danger of using the global
// unguarded in another place, it seems safer to define global only for this module



var version = "3.7.1",

	rhtmlSuffix = /HTML$/i,

	// Define a local copy of jQuery
	jQuery = function( selector, context ) {

		// The jQuery object is actually just the init constructor 'enhanced'
		// Need init if jQuery is called (just allow error to be thrown if not included)
		return new jQuery.fn.init( selector, context );
	};

jQuery.fn = jQuery.prototype = {

	// The current version of jQuery being used
	jquery: version,

	constructor: jQuery,

	// The default length of a jQuery object is 0
	length: 0,

	toArray: function() {
		return slice.call( this );
	},

	// Get the Nth element in the matched element set OR
	// Get the whole matched element set as a clean array
	get: function( num ) {

		// Return all the elements in a clean array
		if ( num == null ) {
			return slice.call( this );
		}

		// Return just the one element from the set
		return num < 0 ? this[ num + this.length ] : this[ num ];
	},

	// Take an array of elements and push it onto the stack
	// (returning the new matched element set)
	pushStack: function( elems ) {

		// Build a new jQuery matched element set
		var ret = jQuery.merge( this.constructor(), elems );

		// Add the old object onto the stack (as a reference)
		ret.prevObject = this;

		// Return the newly-formed element set
		return ret;
	},

	// Execute a callback for every element in the matched set.
	each: function( callback ) {
		return jQuery.each( this, callback );
	},

	map: function( callback ) {
		return this.pushStack( jQuery.map( this, function( elem, i ) {
			return callback.call( elem, i, elem );
		} ) );
	},

	slice: function() {
		return this.pushStack( slice.apply( this, arguments ) );
	},

	first: function() {
		return this.eq( 0 );
	},

	last: function() {
		return this.eq( -1 );
	},

	even: function() {
		return this.pushStack( jQuery.grep( this, function( _elem, i ) {
			return ( i + 1 ) % 2;
		} ) );
	},

	odd: function() {
		return this.pushStack( jQuery.grep( this, function( _elem, i ) {
			return i % 2;
		} ) );
	},

	eq: function( i ) {
		var len = this.length,
			j = +i + ( i < 0 ? len : 0 );
		return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
	},

	end: function() {
		return this.prevObject || this.constructor();
	},

	// For internal use only.
	// Behaves like an Array's method, not like a jQuery method.
	push: push,
	sort: arr.sort,
	splice: arr.splice
};

jQuery.extend = jQuery.fn.extend = function() {
	var options, name, src, copy, copyIsArray, clone,
		target = arguments[ 0 ] || {},
		i = 1,
		length = arguments.length,
		deep = false;

	// Handle a deep copy situation
	if ( typeof target === "boolean" ) {
		deep = target;

		// Skip the boolean and the target
		target = arguments[ i ] || {};
		i++;
	}

	// Handle case when target is a string or something (possible in deep copy)
	if ( typeof target !== "object" && !isFunction( target ) ) {
		target = {};
	}

	// Extend jQuery itself if only one argument is passed
	if ( i === length ) {
		target = this;
		i--;
	}

	for ( ; i < length; i++ ) {

		// Only deal with non-null/undefined values
		if ( ( options = arguments[ i ] ) != null ) {

			// Extend the base object
			for ( name in options ) {
				copy = options[ name ];

				// Prevent Object.prototype pollution
				// Prevent never-ending loop
				if ( name === "__proto__" || target === copy ) {
					continue;
				}

				// Recurse if we're merging plain objects or arrays
				if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
					( copyIsArray = Array.isArray( copy ) ) ) ) {
					src = target[ name ];

					// Ensure proper type for the source value
					if ( copyIsArray && !Array.isArray( src ) ) {
						clone = [];
					} else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {
						clone = {};
					} else {
						clone = src;
					}
					copyIsArray = false;

					// Never move original objects, clone them
					target[ name ] = jQuery.extend( deep, clone, copy );

				// Don't bring in undefined values
				} else if ( copy !== undefined ) {
					target[ name ] = copy;
				}
			}
		}
	}

	// Return the modified object
	return target;
};

jQuery.extend( {

	// Unique for each copy of jQuery on the page
	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),

	// Assume jQuery is ready without the ready module
	isReady: true,

	error: function( msg ) {
		throw new Error( msg );
	},

	noop: function() {},

	isPlainObject: function( obj ) {
		var proto, Ctor;

		// Detect obvious negatives
		// Use toString instead of jQuery.type to catch host objects
		if ( !obj || toString.call( obj ) !== "[object Object]" ) {
			return false;
		}

		proto = getProto( obj );

		// Objects with no prototype (e.g., `Object.create( null )`) are plain
		if ( !proto ) {
			return true;
		}

		// Objects with prototype are plain iff they were constructed by a global Object function
		Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
		return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
	},

	isEmptyObject: function( obj ) {
		var name;

		for ( name in obj ) {
			return false;
		}
		return true;
	},

	// Evaluates a script in a provided context; falls back to the global one
	// if not specified.
	globalEval: function( code, options, doc ) {
		DOMEval( code, { nonce: options && options.nonce }, doc );
	},

	each: function( obj, callback ) {
		var length, i = 0;

		if ( isArrayLike( obj ) ) {
			length = obj.length;
			for ( ; i < length; i++ ) {
				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
					break;
				}
			}
		} else {
			for ( i in obj ) {
				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
					break;
				}
			}
		}

		return obj;
	},


	// Retrieve the text value of an array of DOM nodes
	text: function( elem ) {
		var node,
			ret = "",
			i = 0,
			nodeType = elem.nodeType;

		if ( !nodeType ) {

			// If no nodeType, this is expected to be an array
			while ( ( node = elem[ i++ ] ) ) {

				// Do not traverse comment nodes
				ret += jQuery.text( node );
			}
		}
		if ( nodeType === 1 || nodeType === 11 ) {
			return elem.textContent;
		}
		if ( nodeType === 9 ) {
			return elem.documentElement.textContent;
		}
		if ( nodeType === 3 || nodeType === 4 ) {
			return elem.nodeValue;
		}

		// Do not include comment or processing instruction nodes

		return ret;
	},

	// results is for internal usage only
	makeArray: function( arr, results ) {
		var ret = results || [];

		if ( arr != null ) {
			if ( isArrayLike( Object( arr ) ) ) {
				jQuery.merge( ret,
					typeof arr === "string" ?
						[ arr ] : arr
				);
			} else {
				push.call( ret, arr );
			}
		}

		return ret;
	},

	inArray: function( elem, arr, i ) {
		return arr == null ? -1 : indexOf.call( arr, elem, i );
	},

	isXMLDoc: function( elem ) {
		var namespace = elem && elem.namespaceURI,
			docElem = elem && ( elem.ownerDocument || elem ).documentElement;

		// Assume HTML when documentElement doesn't yet exist, such as inside
		// document fragments.
		return !rhtmlSuffix.test( namespace || docElem && docElem.nodeName || "HTML" );
	},

	// Support: Android <=4.0 only, PhantomJS 1 only
	// push.apply(_, arraylike) throws on ancient WebKit
	merge: function( first, second ) {
		var len = +second.length,
			j = 0,
			i = first.length;

		for ( ; j < len; j++ ) {
			first[ i++ ] = second[ j ];
		}

		first.length = i;

		return first;
	},

	grep: function( elems, callback, invert ) {
		var callbackInverse,
			matches = [],
			i = 0,
			length = elems.length,
			callbackExpect = !invert;

		// Go through the array, only saving the items
		// that pass the validator function
		for ( ; i < length; i++ ) {
			callbackInverse = !callback( elems[ i ], i );
			if ( callbackInverse !== callbackExpect ) {
				matches.push( elems[ i ] );
			}
		}

		return matches;
	},

	// arg is for internal usage only
	map: function( elems, callback, arg ) {
		var length, value,
			i = 0,
			ret = [];

		// Go through the array, translating each of the items to their new values
		if ( isArrayLike( elems ) ) {
			length = elems.length;
			for ( ; i < length; i++ ) {
				value = callback( elems[ i ], i, arg );

				if ( value != null ) {
					ret.push( value );
				}
			}

		// Go through every key on the object,
		} else {
			for ( i in elems ) {
				value = callback( elems[ i ], i, arg );

				if ( value != null ) {
					ret.push( value );
				}
			}
		}

		// Flatten any nested arrays
		return flat( ret );
	},

	// A global GUID counter for objects
	guid: 1,

	// jQuery.support is not used in Core but other projects attach their
	// properties to it so it needs to exist.
	support: support
} );

if ( typeof Symbol === "function" ) {
	jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
}

// Populate the class2type map
jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
	function( _i, name ) {
		class2type[ "[object " + name + "]" ] = name.toLowerCase();
	} );

function isArrayLike( obj ) {

	// Support: real iOS 8.2 only (not reproducible in simulator)
	// `in` check used to prevent JIT error (gh-2145)
	// hasOwn isn't used here due to false negatives
	// regarding Nodelist length in IE
	var length = !!obj && "length" in obj && obj.length,
		type = toType( obj );

	if ( isFunction( obj ) || isWindow( obj ) ) {
		return false;
	}

	return type === "array" || length === 0 ||
		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
}


function nodeName( elem, name ) {

	return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();

}
var pop = arr.pop;


var sort = arr.sort;


var splice = arr.splice;


var whitespace = "[\\x20\\t\\r\\n\\f]";


var rtrimCSS = new RegExp(
	"^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$",
	"g"
);




// Note: an element does not contain itself
jQuery.contains = function( a, b ) {
	var bup = b && b.parentNode;

	return a === bup || !!( bup && bup.nodeType === 1 && (

		// Support: IE 9 - 11+
		// IE doesn't have `contains` on SVG.
		a.contains ?
			a.contains( bup ) :
			a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
	) );
};




// CSS string/identifier serialization
// https://drafts.csswg.org/cssom/#common-serializing-idioms
var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;

function fcssescape( ch, asCodePoint ) {
	if ( asCodePoint ) {

		// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
		if ( ch === "\0" ) {
			return "\uFFFD";
		}

		// Control characters and (dependent upon position) numbers get escaped as code points
		return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
	}

	// Other potentially-special ASCII characters get backslash-escaped
	return "\\" + ch;
}

jQuery.escapeSelector = function( sel ) {
	return ( sel + "" ).replace( rcssescape, fcssescape );
};




var preferredDoc = document,
	pushNative = push;

( function() {

var i,
	Expr,
	outermostContext,
	sortInput,
	hasDuplicate,
	push = pushNative,

	// Local document vars
	document,
	documentElement,
	documentIsHTML,
	rbuggyQSA,
	matches,

	// Instance-specific data
	expando = jQuery.expando,
	dirruns = 0,
	done = 0,
	classCache = createCache(),
	tokenCache = createCache(),
	compilerCache = createCache(),
	nonnativeSelectorCache = createCache(),
	sortOrder = function( a, b ) {
		if ( a === b ) {
			hasDuplicate = true;
		}
		return 0;
	},

	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|" +
		"loop|multiple|open|readonly|required|scoped",

	// Regular expressions

	// https://www.w3.org/TR/css-syntax-3/#ident-token-diagram
	identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace +
		"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",

	// Attribute selectors: https://www.w3.org/TR/selectors/#attribute-selectors
	attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +

		// Operator (capture 2)
		"*([*^$|!~]?=)" + whitespace +

		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" +
		whitespace + "*\\]",

	pseudos = ":(" + identifier + ")(?:\\((" +

		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
		// 1. quoted (capture 3; capture 4 or capture 5)
		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +

		// 2. simple (capture 6)
		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +

		// 3. anything else (capture 2)
		".*" +
		")\\)|)",

	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
	rwhitespace = new RegExp( whitespace + "+", "g" ),

	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
	rleadingCombinator = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" +
		whitespace + "*" ),
	rdescend = new RegExp( whitespace + "|>" ),

	rpseudo = new RegExp( pseudos ),
	ridentifier = new RegExp( "^" + identifier + "$" ),

	matchExpr = {
		ID: new RegExp( "^#(" + identifier + ")" ),
		CLASS: new RegExp( "^\\.(" + identifier + ")" ),
		TAG: new RegExp( "^(" + identifier + "|[*])" ),
		ATTR: new RegExp( "^" + attributes ),
		PSEUDO: new RegExp( "^" + pseudos ),
		CHILD: new RegExp(
			"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" +
				whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" +
				whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
		bool: new RegExp( "^(?:" + booleans + ")$", "i" ),

		// For use in libraries implementing .is()
		// We use this for POS matching in `select`
		needsContext: new RegExp( "^" + whitespace +
			"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace +
			"*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
	},

	rinputs = /^(?:input|select|textarea|button)$/i,
	rheader = /^h\d$/i,

	// Easily-parseable/retrievable ID or TAG or CLASS selectors
	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,

	rsibling = /[+~]/,

	// CSS escapes
	// https://www.w3.org/TR/CSS21/syndata.html#escaped-characters
	runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace +
		"?|\\\\([^\\r\\n\\f])", "g" ),
	funescape = function( escape, nonHex ) {
		var high = "0x" + escape.slice( 1 ) - 0x10000;

		if ( nonHex ) {

			// Strip the backslash prefix from a non-hex escape sequence
			return nonHex;
		}

		// Replace a hexadecimal escape sequence with the encoded Unicode code point
		// Support: IE <=11+
		// For values outside the Basic Multilingual Plane (BMP), manually construct a
		// surrogate pair
		return high < 0 ?
			String.fromCharCode( high + 0x10000 ) :
			String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
	},

	// Used for iframes; see `setDocument`.
	// Support: IE 9 - 11+, Edge 12 - 18+
	// Removing the function wrapper causes a "Permission Denied"
	// error in IE/Edge.
	unloadHandler = function() {
		setDocument();
	},

	inDisabledFieldset = addCombinator(
		function( elem ) {
			return elem.disabled === true && nodeName( elem, "fieldset" );
		},
		{ dir: "parentNode", next: "legend" }
	);

// Support: IE <=9 only
// Accessing document.activeElement can throw unexpectedly
// https://bugs.jquery.com/ticket/13393
function safeActiveElement() {
	try {
		return document.activeElement;
	} catch ( err ) { }
}

// Optimize for push.apply( _, NodeList )
try {
	push.apply(
		( arr = slice.call( preferredDoc.childNodes ) ),
		preferredDoc.childNodes
	);

	// Support: Android <=4.0
	// Detect silently failing push.apply
	// eslint-disable-next-line no-unused-expressions
	arr[ preferredDoc.childNodes.length ].nodeType;
} catch ( e ) {
	push = {
		apply: function( target, els ) {
			pushNative.apply( target, slice.call( els ) );
		},
		call: function( target ) {
			pushNative.apply( target, slice.call( arguments, 1 ) );
		}
	};
}

function find( selector, context, results, seed ) {
	var m, i, elem, nid, match, groups, newSelector,
		newContext = context && context.ownerDocument,

		// nodeType defaults to 9, since context defaults to document
		nodeType = context ? context.nodeType : 9;

	results = results || [];

	// Return early from calls with invalid selector or context
	if ( typeof selector !== "string" || !selector ||
		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {

		return results;
	}

	// Try to shortcut find operations (as opposed to filters) in HTML documents
	if ( !seed ) {
		setDocument( context );
		context = context || document;

		if ( documentIsHTML ) {

			// If the selector is sufficiently simple, try using a "get*By*" DOM method
			// (excepting DocumentFragment context, where the methods don't exist)
			if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) {

				// ID selector
				if ( ( m = match[ 1 ] ) ) {

					// Document context
					if ( nodeType === 9 ) {
						if ( ( elem = context.getElementById( m ) ) ) {

							// Support: IE 9 only
							// getElementById can match elements by name instead of ID
							if ( elem.id === m ) {
								push.call( results, elem );
								return results;
							}
						} else {
							return results;
						}

					// Element context
					} else {

						// Support: IE 9 only
						// getElementById can match elements by name instead of ID
						if ( newContext && ( elem = newContext.getElementById( m ) ) &&
							find.contains( context, elem ) &&
							elem.id === m ) {

							push.call( results, elem );
							return results;
						}
					}

				// Type selector
				} else if ( match[ 2 ] ) {
					push.apply( results, context.getElementsByTagName( selector ) );
					return results;

				// Class selector
				} else if ( ( m = match[ 3 ] ) && context.getElementsByClassName ) {
					push.apply( results, context.getElementsByClassName( m ) );
					return results;
				}
			}

			// Take advantage of querySelectorAll
			if ( !nonnativeSelectorCache[ selector + " " ] &&
				( !rbuggyQSA || !rbuggyQSA.test( selector ) ) ) {

				newSelector = selector;
				newContext = context;

				// qSA considers elements outside a scoping root when evaluating child or
				// descendant combinators, which is not what we want.
				// In such cases, we work around the behavior by prefixing every selector in the
				// list with an ID selector referencing the scope context.
				// The technique has to be used as well when a leading combinator is used
				// as such selectors are not recognized by querySelectorAll.
				// Thanks to Andrew Dupont for this technique.
				if ( nodeType === 1 &&
					( rdescend.test( selector ) || rleadingCombinator.test( selector ) ) ) {

					// Expand context for sibling selectors
					newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
						context;

					// We can use :scope instead of the ID hack if the browser
					// supports it & if we're not changing the context.
					// Support: IE 11+, Edge 17 - 18+
					// IE/Edge sometimes throw a "Permission denied" error when
					// strict-comparing two documents; shallow comparisons work.
					// eslint-disable-next-line eqeqeq
					if ( newContext != context || !support.scope ) {

						// Capture the context ID, setting it first if necessary
						if ( ( nid = context.getAttribute( "id" ) ) ) {
							nid = jQuery.escapeSelector( nid );
						} else {
							context.setAttribute( "id", ( nid = expando ) );
						}
					}

					// Prefix every selector in the list
					groups = tokenize( selector );
					i = groups.length;
					while ( i-- ) {
						groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " +
							toSelector( groups[ i ] );
					}
					newSelector = groups.join( "," );
				}

				try {
					push.apply( results,
						newContext.querySelectorAll( newSelector )
					);
					return results;
				} catch ( qsaError ) {
					nonnativeSelectorCache( selector, true );
				} finally {
					if ( nid === expando ) {
						context.removeAttribute( "id" );
					}
				}
			}
		}
	}

	// All others
	return select( selector.replace( rtrimCSS, "$1" ), context, results, seed );
}

/**
 * Create key-value caches of limited size
 * @returns {function(string, object)} Returns the Object data after storing it on itself with
 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
 *	deleting the oldest entry
 */
function createCache() {
	var keys = [];

	function cache( key, value ) {

		// Use (key + " ") to avoid collision with native prototype properties
		// (see https://github.com/jquery/sizzle/issues/157)
		if ( keys.push( key + " " ) > Expr.cacheLength ) {

			// Only keep the most recent entries
			delete cache[ keys.shift() ];
		}
		return ( cache[ key + " " ] = value );
	}
	return cache;
}

/**
 * Mark a function for special use by jQuery selector module
 * @param {Function} fn The function to mark
 */
function markFunction( fn ) {
	fn[ expando ] = true;
	return fn;
}

/**
 * Support testing using an element
 * @param {Function} fn Passed the created element and returns a boolean result
 */
function assert( fn ) {
	var el = document.createElement( "fieldset" );

	try {
		return !!fn( el );
	} catch ( e ) {
		return false;
	} finally {

		// Remove from its parent by default
		if ( el.parentNode ) {
			el.parentNode.removeChild( el );
		}

		// release memory in IE
		el = null;
	}
}

/**
 * Returns a function to use in pseudos for input types
 * @param {String} type
 */
function createInputPseudo( type ) {
	return function( elem ) {
		return nodeName( elem, "input" ) && elem.type === type;
	};
}

/**
 * Returns a function to use in pseudos for buttons
 * @param {String} type
 */
function createButtonPseudo( type ) {
	return function( elem ) {
		return ( nodeName( elem, "input" ) || nodeName( elem, "button" ) ) &&
			elem.type === type;
	};
}

/**
 * Returns a function to use in pseudos for :enabled/:disabled
 * @param {Boolean} disabled true for :disabled; false for :enabled
 */
function createDisabledPseudo( disabled ) {

	// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
	return function( elem ) {

		// Only certain elements can match :enabled or :disabled
		// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
		// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
		if ( "form" in elem ) {

			// Check for inherited disabledness on relevant non-disabled elements:
			// * listed form-associated elements in a disabled fieldset
			//   https://html.spec.whatwg.org/multipage/forms.html#category-listed
			//   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
			// * option elements in a disabled optgroup
			//   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
			// All such elements have a "form" property.
			if ( elem.parentNode && elem.disabled === false ) {

				// Option elements defer to a parent optgroup if present
				if ( "label" in elem ) {
					if ( "label" in elem.parentNode ) {
						return elem.parentNode.disabled === disabled;
					} else {
						return elem.disabled === disabled;
					}
				}

				// Support: IE 6 - 11+
				// Use the isDisabled shortcut property to check for disabled fieldset ancestors
				return elem.isDisabled === disabled ||

					// Where there is no isDisabled, check manually
					elem.isDisabled !== !disabled &&
						inDisabledFieldset( elem ) === disabled;
			}

			return elem.disabled === disabled;

		// Try to winnow out elements that can't be disabled before trusting the disabled property.
		// Some victims get caught in our net (label, legend, menu, track), but it shouldn't
		// even exist on them, let alone have a boolean value.
		} else if ( "label" in elem ) {
			return elem.disabled === disabled;
		}

		// Remaining elements are neither :enabled nor :disabled
		return false;
	};
}

/**
 * Returns a function to use in pseudos for positionals
 * @param {Function} fn
 */
function createPositionalPseudo( fn ) {
	return markFunction( function( argument ) {
		argument = +argument;
		return markFunction( function( seed, matches ) {
			var j,
				matchIndexes = fn( [], seed.length, argument ),
				i = matchIndexes.length;

			// Match elements found at the specified indexes
			while ( i-- ) {
				if ( seed[ ( j = matchIndexes[ i ] ) ] ) {
					seed[ j ] = !( matches[ j ] = seed[ j ] );
				}
			}
		} );
	} );
}

/**
 * Checks a node for validity as a jQuery selector context
 * @param {Element|Object=} context
 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
 */
function testContext( context ) {
	return context && typeof context.getElementsByTagName !== "undefined" && context;
}

/**
 * Sets document-related variables once based on the current document
 * @param {Element|Object} [node] An element or document object to use to set the document
 * @returns {Object} Returns the current document
 */
function setDocument( node ) {
	var subWindow,
		doc = node ? node.ownerDocument || node : preferredDoc;

	// Return early if doc is invalid or already selected
	// Support: IE 11+, Edge 17 - 18+
	// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
	// two documents; shallow comparisons work.
	// eslint-disable-next-line eqeqeq
	if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) {
		return document;
	}

	// Update global variables
	document = doc;
	documentElement = document.documentElement;
	documentIsHTML = !jQuery.isXMLDoc( document );

	// Support: iOS 7 only, IE 9 - 11+
	// Older browsers didn't support unprefixed `matches`.
	matches = documentElement.matches ||
		documentElement.webkitMatchesSelector ||
		documentElement.msMatchesSelector;

	// Support: IE 9 - 11+, Edge 12 - 18+
	// Accessing iframe documents after unload throws "permission denied" errors
	// (see trac-13936).
	// Limit the fix to IE & Edge Legacy; despite Edge 15+ implementing `matches`,
	// all IE 9+ and Edge Legacy versions implement `msMatchesSelector` as well.
	if ( documentElement.msMatchesSelector &&

		// Support: IE 11+, Edge 17 - 18+
		// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
		// two documents; shallow comparisons work.
		// eslint-disable-next-line eqeqeq
		preferredDoc != document &&
		( subWindow = document.defaultView ) && subWindow.top !== subWindow ) {

		// Support: IE 9 - 11+, Edge 12 - 18+
		subWindow.addEventListener( "unload", unloadHandler );
	}

	// Support: IE <10
	// Check if getElementById returns elements by name
	// The broken getElementById methods don't pick up programmatically-set names,
	// so use a roundabout getElementsByName test
	support.getById = assert( function( el ) {
		documentElement.appendChild( el ).id = jQuery.expando;
		return !document.getElementsByName ||
			!document.getElementsByName( jQuery.expando ).length;
	} );

	// Support: IE 9 only
	// Check to see if it's possible to do matchesSelector
	// on a disconnected node.
	support.disconnectedMatch = assert( function( el ) {
		return matches.call( el, "*" );
	} );

	// Support: IE 9 - 11+, Edge 12 - 18+
	// IE/Edge don't support the :scope pseudo-class.
	support.scope = assert( function() {
		return document.querySelectorAll( ":scope" );
	} );

	// Support: Chrome 105 - 111 only, Safari 15.4 - 16.3 only
	// Make sure the `:has()` argument is parsed unforgivingly.
	// We include `*` in the test to detect buggy implementations that are
	// _selectively_ forgiving (specifically when the list includes at least
	// one valid selector).
	// Note that we treat complete lack of support for `:has()` as if it were
	// spec-compliant support, which is fine because use of `:has()` in such
	// environments will fail in the qSA path and fall back to jQuery traversal
	// anyway.
	support.cssHas = assert( function() {
		try {
			document.querySelector( ":has(*,:jqfake)" );
			return false;
		} catch ( e ) {
			return true;
		}
	} );

	// ID filter and find
	if ( support.getById ) {
		Expr.filter.ID = function( id ) {
			var attrId = id.replace( runescape, funescape );
			return function( elem ) {
				return elem.getAttribute( "id" ) === attrId;
			};
		};
		Expr.find.ID = function( id, context ) {
			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
				var elem = context.getElementById( id );
				return elem ? [ elem ] : [];
			}
		};
	} else {
		Expr.filter.ID =  function( id ) {
			var attrId = id.replace( runescape, funescape );
			return function( elem ) {
				var node = typeof elem.getAttributeNode !== "undefined" &&
					elem.getAttributeNode( "id" );
				return node && node.value === attrId;
			};
		};

		// Support: IE 6 - 7 only
		// getElementById is not reliable as a find shortcut
		Expr.find.ID = function( id, context ) {
			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
				var node, i, elems,
					elem = context.getElementById( id );

				if ( elem ) {

					// Verify the id attribute
					node = elem.getAttributeNode( "id" );
					if ( node && node.value === id ) {
						return [ elem ];
					}

					// Fall back on getElementsByName
					elems = context.getElementsByName( id );
					i = 0;
					while ( ( elem = elems[ i++ ] ) ) {
						node = elem.getAttributeNode( "id" );
						if ( node && node.value === id ) {
							return [ elem ];
						}
					}
				}

				return [];
			}
		};
	}

	// Tag
	Expr.find.TAG = function( tag, context ) {
		if ( typeof context.getElementsByTagName !== "undefined" ) {
			return context.getElementsByTagName( tag );

		// DocumentFragment nodes don't have gEBTN
		} else {
			return context.querySelectorAll( tag );
		}
	};

	// Class
	Expr.find.CLASS = function( className, context ) {
		if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
			return context.getElementsByClassName( className );
		}
	};

	/* QSA/matchesSelector
	---------------------------------------------------------------------- */

	// QSA and matchesSelector support

	rbuggyQSA = [];

	// Build QSA regex
	// Regex strategy adopted from Diego Perini
	assert( function( el ) {

		var input;

		documentElement.appendChild( el ).innerHTML =
			"<a id='" + expando + "' href='' disabled='disabled'></a>" +
			"<select id='" + expando + "-\r\\' disabled='disabled'>" +
			"<option selected=''></option></select>";

		// Support: iOS <=7 - 8 only
		// Boolean attributes and "value" are not treated correctly in some XML documents
		if ( !el.querySelectorAll( "[selected]" ).length ) {
			rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
		}

		// Support: iOS <=7 - 8 only
		if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
			rbuggyQSA.push( "~=" );
		}

		// Support: iOS 8 only
		// https://bugs.webkit.org/show_bug.cgi?id=136851
		// In-page `selector#id sibling-combinator selector` fails
		if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
			rbuggyQSA.push( ".#.+[+~]" );
		}

		// Support: Chrome <=105+, Firefox <=104+, Safari <=15.4+
		// In some of the document kinds, these selectors wouldn't work natively.
		// This is probably OK but for backwards compatibility we want to maintain
		// handling them through jQuery traversal in jQuery 3.x.
		if ( !el.querySelectorAll( ":checked" ).length ) {
			rbuggyQSA.push( ":checked" );
		}

		// Support: Windows 8 Native Apps
		// The type and name attributes are restricted during .innerHTML assignment
		input = document.createElement( "input" );
		input.setAttribute( "type", "hidden" );
		el.appendChild( input ).setAttribute( "name", "D" );

		// Support: IE 9 - 11+
		// IE's :disabled selector does not pick up the children of disabled fieldsets
		// Support: Chrome <=105+, Firefox <=104+, Safari <=15.4+
		// In some of the document kinds, these selectors wouldn't work natively.
		// This is probably OK but for backwards compatibility we want to maintain
		// handling them through jQuery traversal in jQuery 3.x.
		documentElement.appendChild( el ).disabled = true;
		if ( el.querySelectorAll( ":disabled" ).length !== 2 ) {
			rbuggyQSA.push( ":enabled", ":disabled" );
		}

		// Support: IE 11+, Edge 15 - 18+
		// IE 11/Edge don't find elements on a `[name='']` query in some cases.
		// Adding a temporary attribute to the document before the selection works
		// around the issue.
		// Interestingly, IE 10 & older don't seem to have the issue.
		input = document.createElement( "input" );
		input.setAttribute( "name", "" );
		el.appendChild( input );
		if ( !el.querySelectorAll( "[name='']" ).length ) {
			rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" +
				whitespace + "*(?:''|\"\")" );
		}
	} );

	if ( !support.cssHas ) {

		// Support: Chrome 105 - 110+, Safari 15.4 - 16.3+
		// Our regular `try-catch` mechanism fails to detect natively-unsupported
		// pseudo-classes inside `:has()` (such as `:has(:contains("Foo"))`)
		// in browsers that parse the `:has()` argument as a forgiving selector list.
		// https://drafts.csswg.org/selectors/#relational now requires the argument
		// to be parsed unforgivingly, but browsers have not yet fully adjusted.
		rbuggyQSA.push( ":has" );
	}

	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) );

	/* Sorting
	---------------------------------------------------------------------- */

	// Document order sorting
	sortOrder = function( a, b ) {

		// Flag for duplicate removal
		if ( a === b ) {
			hasDuplicate = true;
			return 0;
		}

		// Sort on method existence if only one input has compareDocumentPosition
		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
		if ( compare ) {
			return compare;
		}

		// Calculate position if both inputs belong to the same document
		// Support: IE 11+, Edge 17 - 18+
		// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
		// two documents; shallow comparisons work.
		// eslint-disable-next-line eqeqeq
		compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ?
			a.compareDocumentPosition( b ) :

			// Otherwise we know they are disconnected
			1;

		// Disconnected nodes
		if ( compare & 1 ||
			( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) {

			// Choose the first element that is related to our preferred document
			// Support: IE 11+, Edge 17 - 18+
			// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
			// two documents; shallow comparisons work.
			// eslint-disable-next-line eqeqeq
			if ( a === document || a.ownerDocument == preferredDoc &&
				find.contains( preferredDoc, a ) ) {
				return -1;
			}

			// Support: IE 11+, Edge 17 - 18+
			// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
			// two documents; shallow comparisons work.
			// eslint-disable-next-line eqeqeq
			if ( b === document || b.ownerDocument == preferredDoc &&
				find.contains( preferredDoc, b ) ) {
				return 1;
			}

			// Maintain original order
			return sortInput ?
				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
				0;
		}

		return compare & 4 ? -1 : 1;
	};

	return document;
}

find.matches = function( expr, elements ) {
	return find( expr, null, null, elements );
};

find.matchesSelector = function( elem, expr ) {
	setDocument( elem );

	if ( documentIsHTML &&
		!nonnativeSelectorCache[ expr + " " ] &&
		( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {

		try {
			var ret = matches.call( elem, expr );

			// IE 9's matchesSelector returns false on disconnected nodes
			if ( ret || support.disconnectedMatch ||

					// As well, disconnected nodes are said to be in a document
					// fragment in IE 9
					elem.document && elem.document.nodeType !== 11 ) {
				return ret;
			}
		} catch ( e ) {
			nonnativeSelectorCache( expr, true );
		}
	}

	return find( expr, document, null, [ elem ] ).length > 0;
};

find.contains = function( context, elem ) {

	// Set document vars if needed
	// Support: IE 11+, Edge 17 - 18+
	// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
	// two documents; shallow comparisons work.
	// eslint-disable-next-line eqeqeq
	if ( ( context.ownerDocument || context ) != document ) {
		setDocument( context );
	}
	return jQuery.contains( context, elem );
};


find.attr = function( elem, name ) {

	// Set document vars if needed
	// Support: IE 11+, Edge 17 - 18+
	// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
	// two documents; shallow comparisons work.
	// eslint-disable-next-line eqeqeq
	if ( ( elem.ownerDocument || elem ) != document ) {
		setDocument( elem );
	}

	var fn = Expr.attrHandle[ name.toLowerCase() ],

		// Don't get fooled by Object.prototype properties (see trac-13807)
		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
			fn( elem, name, !documentIsHTML ) :
			undefined;

	if ( val !== undefined ) {
		return val;
	}

	return elem.getAttribute( name );
};

find.error = function( msg ) {
	throw new Error( "Syntax error, unrecognized expression: " + msg );
};

/**
 * Document sorting and removing duplicates
 * @param {ArrayLike} results
 */
jQuery.uniqueSort = function( results ) {
	var elem,
		duplicates = [],
		j = 0,
		i = 0;

	// Unless we *know* we can detect duplicates, assume their presence
	//
	// Support: Android <=4.0+
	// Testing for detecting duplicates is unpredictable so instead assume we can't
	// depend on duplicate detection in all browsers without a stable sort.
	hasDuplicate = !support.sortStable;
	sortInput = !support.sortStable && slice.call( results, 0 );
	sort.call( results, sortOrder );

	if ( hasDuplicate ) {
		while ( ( elem = results[ i++ ] ) ) {
			if ( elem === results[ i ] ) {
				j = duplicates.push( i );
			}
		}
		while ( j-- ) {
			splice.call( results, duplicates[ j ], 1 );
		}
	}

	// Clear input after sorting to release objects
	// See https://github.com/jquery/sizzle/pull/225
	sortInput = null;

	return results;
};

jQuery.fn.uniqueSort = function() {
	return this.pushStack( jQuery.uniqueSort( slice.apply( this ) ) );
};

Expr = jQuery.expr = {

	// Can be adjusted by the user
	cacheLength: 50,

	createPseudo: markFunction,

	match: matchExpr,

	attrHandle: {},

	find: {},

	relative: {
		">": { dir: "parentNode", first: true },
		" ": { dir: "parentNode" },
		"+": { dir: "previousSibling", first: true },
		"~": { dir: "previousSibling" }
	},

	preFilter: {
		ATTR: function( match ) {
			match[ 1 ] = match[ 1 ].replace( runescape, funescape );

			// Move the given value to match[3] whether quoted or unquoted
			match[ 3 ] = ( match[ 3 ] || match[ 4 ] || match[ 5 ] || "" )
				.replace( runescape, funescape );

			if ( match[ 2 ] === "~=" ) {
				match[ 3 ] = " " + match[ 3 ] + " ";
			}

			return match.slice( 0, 4 );
		},

		CHILD: function( match ) {

			/* matches from matchExpr["CHILD"]
				1 type (only|nth|...)
				2 what (child|of-type)
				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
				4 xn-component of xn+y argument ([+-]?\d*n|)
				5 sign of xn-component
				6 x of xn-component
				7 sign of y-component
				8 y of y-component
			*/
			match[ 1 ] = match[ 1 ].toLowerCase();

			if ( match[ 1 ].slice( 0, 3 ) === "nth" ) {

				// nth-* requires argument
				if ( !match[ 3 ] ) {
					find.error( match[ 0 ] );
				}

				// numeric x and y parameters for Expr.filter.CHILD
				// remember that false/true cast respectively to 0/1
				match[ 4 ] = +( match[ 4 ] ?
					match[ 5 ] + ( match[ 6 ] || 1 ) :
					2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" )
				);
				match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" );

			// other types prohibit arguments
			} else if ( match[ 3 ] ) {
				find.error( match[ 0 ] );
			}

			return match;
		},

		PSEUDO: function( match ) {
			var excess,
				unquoted = !match[ 6 ] && match[ 2 ];

			if ( matchExpr.CHILD.test( match[ 0 ] ) ) {
				return null;
			}

			// Accept quoted arguments as-is
			if ( match[ 3 ] ) {
				match[ 2 ] = match[ 4 ] || match[ 5 ] || "";

			// Strip excess characters from unquoted arguments
			} else if ( unquoted && rpseudo.test( unquoted ) &&

				// Get excess from tokenize (recursively)
				( excess = tokenize( unquoted, true ) ) &&

				// advance to the next closing parenthesis
				( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) {

				// excess is a negative index
				match[ 0 ] = match[ 0 ].slice( 0, excess );
				match[ 2 ] = unquoted.slice( 0, excess );
			}

			// Return only captures needed by the pseudo filter method (type and argument)
			return match.slice( 0, 3 );
		}
	},

	filter: {

		TAG: function( nodeNameSelector ) {
			var expectedNodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
			return nodeNameSelector === "*" ?
				function() {
					return true;
				} :
				function( elem ) {
					return nodeName( elem, expectedNodeName );
				};
		},

		CLASS: function( className ) {
			var pattern = classCache[ className + " " ];

			return pattern ||
				( pattern = new RegExp( "(^|" + whitespace + ")" + className +
					"(" + whitespace + "|$)" ) ) &&
				classCache( className, function( elem ) {
					return pattern.test(
						typeof elem.className === "string" && elem.className ||
							typeof elem.getAttribute !== "undefined" &&
								elem.getAttribute( "class" ) ||
							""
					);
				} );
		},

		ATTR: function( name, operator, check ) {
			return function( elem ) {
				var result = find.attr( elem, name );

				if ( result == null ) {
					return operator === "!=";
				}
				if ( !operator ) {
					return true;
				}

				result += "";

				if ( operator === "=" ) {
					return result === check;
				}
				if ( operator === "!=" ) {
					return result !== check;
				}
				if ( operator === "^=" ) {
					return check && result.indexOf( check ) === 0;
				}
				if ( operator === "*=" ) {
					return check && result.indexOf( check ) > -1;
				}
				if ( operator === "$=" ) {
					return check && result.slice( -check.length ) === check;
				}
				if ( operator === "~=" ) {
					return ( " " + result.replace( rwhitespace, " " ) + " " )
						.indexOf( check ) > -1;
				}
				if ( operator === "|=" ) {
					return result === check || result.slice( 0, check.length + 1 ) === check + "-";
				}

				return false;
			};
		},

		CHILD: function( type, what, _argument, first, last ) {
			var simple = type.slice( 0, 3 ) !== "nth",
				forward = type.slice( -4 ) !== "last",
				ofType = what === "of-type";

			return first === 1 && last === 0 ?

				// Shortcut for :nth-*(n)
				function( elem ) {
					return !!elem.parentNode;
				} :

				function( elem, _context, xml ) {
					var cache, outerCache, node, nodeIndex, start,
						dir = simple !== forward ? "nextSibling" : "previousSibling",
						parent = elem.parentNode,
						name = ofType && elem.nodeName.toLowerCase(),
						useCache = !xml && !ofType,
						diff = false;

					if ( parent ) {

						// :(first|last|only)-(child|of-type)
						if ( simple ) {
							while ( dir ) {
								node = elem;
								while ( ( node = node[ dir ] ) ) {
									if ( ofType ?
										nodeName( node, name ) :
										node.nodeType === 1 ) {

										return false;
									}
								}

								// Reverse direction for :only-* (if we haven't yet done so)
								start = dir = type === "only" && !start && "nextSibling";
							}
							return true;
						}

						start = [ forward ? parent.firstChild : parent.lastChild ];

						// non-xml :nth-child(...) stores cache data on `parent`
						if ( forward && useCache ) {

							// Seek `elem` from a previously-cached index
							outerCache = parent[ expando ] || ( parent[ expando ] = {} );
							cache = outerCache[ type ] || [];
							nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
							diff = nodeIndex && cache[ 2 ];
							node = nodeIndex && parent.childNodes[ nodeIndex ];

							while ( ( node = ++nodeIndex && node && node[ dir ] ||

								// Fallback to seeking `elem` from the start
								( diff = nodeIndex = 0 ) || start.pop() ) ) {

								// When found, cache indexes on `parent` and break
								if ( node.nodeType === 1 && ++diff && node === elem ) {
									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
									break;
								}
							}

						} else {

							// Use previously-cached element index if available
							if ( useCache ) {
								outerCache = elem[ expando ] || ( elem[ expando ] = {} );
								cache = outerCache[ type ] || [];
								nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
								diff = nodeIndex;
							}

							// xml :nth-child(...)
							// or :nth-last-child(...) or :nth(-last)?-of-type(...)
							if ( diff === false ) {

								// Use the same loop as above to seek `elem` from the start
								while ( ( node = ++nodeIndex && node && node[ dir ] ||
									( diff = nodeIndex = 0 ) || start.pop() ) ) {

									if ( ( ofType ?
										nodeName( node, name ) :
										node.nodeType === 1 ) &&
										++diff ) {

										// Cache the index of each encountered element
										if ( useCache ) {
											outerCache = node[ expando ] ||
												( node[ expando ] = {} );
											outerCache[ type ] = [ dirruns, diff ];
										}

										if ( node === elem ) {
											break;
										}
									}
								}
							}
						}

						// Incorporate the offset, then check against cycle size
						diff -= last;
						return diff === first || ( diff % first === 0 && diff / first >= 0 );
					}
				};
		},

		PSEUDO: function( pseudo, argument ) {

			// pseudo-class names are case-insensitive
			// https://www.w3.org/TR/selectors/#pseudo-classes
			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
			// Remember that setFilters inherits from pseudos
			var args,
				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
					find.error( "unsupported pseudo: " + pseudo );

			// The user may use createPseudo to indicate that
			// arguments are needed to create the filter function
			// just as jQuery does
			if ( fn[ expando ] ) {
				return fn( argument );
			}

			// But maintain support for old signatures
			if ( fn.length > 1 ) {
				args = [ pseudo, pseudo, "", argument ];
				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
					markFunction( function( seed, matches ) {
						var idx,
							matched = fn( seed, argument ),
							i = matched.length;
						while ( i-- ) {
							idx = indexOf.call( seed, matched[ i ] );
							seed[ idx ] = !( matches[ idx ] = matched[ i ] );
						}
					} ) :
					function( elem ) {
						return fn( elem, 0, args );
					};
			}

			return fn;
		}
	},

	pseudos: {

		// Potentially complex pseudos
		not: markFunction( function( selector ) {

			// Trim the selector passed to compile
			// to avoid treating leading and trailing
			// spaces as combinators
			var input = [],
				results = [],
				matcher = compile( selector.replace( rtrimCSS, "$1" ) );

			return matcher[ expando ] ?
				markFunction( function( seed, matches, _context, xml ) {
					var elem,
						unmatched = matcher( seed, null, xml, [] ),
						i = seed.length;

					// Match elements unmatched by `matcher`
					while ( i-- ) {
						if ( ( elem = unmatched[ i ] ) ) {
							seed[ i ] = !( matches[ i ] = elem );
						}
					}
				} ) :
				function( elem, _context, xml ) {
					input[ 0 ] = elem;
					matcher( input, null, xml, results );

					// Don't keep the element
					// (see https://github.com/jquery/sizzle/issues/299)
					input[ 0 ] = null;
					return !results.pop();
				};
		} ),

		has: markFunction( function( selector ) {
			return function( elem ) {
				return find( selector, elem ).length > 0;
			};
		} ),

		contains: markFunction( function( text ) {
			text = text.replace( runescape, funescape );
			return function( elem ) {
				return ( elem.textContent || jQuery.text( elem ) ).indexOf( text ) > -1;
			};
		} ),

		// "Whether an element is represented by a :lang() selector
		// is based solely on the element's language value
		// being equal to the identifier C,
		// or beginning with the identifier C immediately followed by "-".
		// The matching of C against the element's language value is performed case-insensitively.
		// The identifier C does not have to be a valid language name."
		// https://www.w3.org/TR/selectors/#lang-pseudo
		lang: markFunction( function( lang ) {

			// lang value must be a valid identifier
			if ( !ridentifier.test( lang || "" ) ) {
				find.error( "unsupported lang: " + lang );
			}
			lang = lang.replace( runescape, funescape ).toLowerCase();
			return function( elem ) {
				var elemLang;
				do {
					if ( ( elemLang = documentIsHTML ?
						elem.lang :
						elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) {

						elemLang = elemLang.toLowerCase();
						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
					}
				} while ( ( elem = elem.parentNode ) && elem.nodeType === 1 );
				return false;
			};
		} ),

		// Miscellaneous
		target: function( elem ) {
			var hash = window.location && window.location.hash;
			return hash && hash.slice( 1 ) === elem.id;
		},

		root: function( elem ) {
			return elem === documentElement;
		},

		focus: function( elem ) {
			return elem === safeActiveElement() &&
				document.hasFocus() &&
				!!( elem.type || elem.href || ~elem.tabIndex );
		},

		// Boolean properties
		enabled: createDisabledPseudo( false ),
		disabled: createDisabledPseudo( true ),

		checked: function( elem ) {

			// In CSS3, :checked should return both checked and selected elements
			// https://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
			return ( nodeName( elem, "input" ) && !!elem.checked ) ||
				( nodeName( elem, "option" ) && !!elem.selected );
		},

		selected: function( elem ) {

			// Support: IE <=11+
			// Accessing the selectedIndex property
			// forces the browser to treat the default option as
			// selected when in an optgroup.
			if ( elem.parentNode ) {
				// eslint-disable-next-line no-unused-expressions
				elem.parentNode.selectedIndex;
			}

			return elem.selected === true;
		},

		// Contents
		empty: function( elem ) {

			// https://www.w3.org/TR/selectors/#empty-pseudo
			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
			//   but not by others (comment: 8; processing instruction: 7; etc.)
			// nodeType < 6 works because attributes (2) do not appear as children
			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
				if ( elem.nodeType < 6 ) {
					return false;
				}
			}
			return true;
		},

		parent: function( elem ) {
			return !Expr.pseudos.empty( elem );
		},

		// Element/input types
		header: function( elem ) {
			return rheader.test( elem.nodeName );
		},

		input: function( elem ) {
			return rinputs.test( elem.nodeName );
		},

		button: function( elem ) {
			return nodeName( elem, "input" ) && elem.type === "button" ||
				nodeName( elem, "button" );
		},

		text: function( elem ) {
			var attr;
			return nodeName( elem, "input" ) && elem.type === "text" &&

				// Support: IE <10 only
				// New HTML5 attribute values (e.g., "search") appear
				// with elem.type === "text"
				( ( attr = elem.getAttribute( "type" ) ) == null ||
					attr.toLowerCase() === "text" );
		},

		// Position-in-collection
		first: createPositionalPseudo( function() {
			return [ 0 ];
		} ),

		last: createPositionalPseudo( function( _matchIndexes, length ) {
			return [ length - 1 ];
		} ),

		eq: createPositionalPseudo( function( _matchIndexes, length, argument ) {
			return [ argument < 0 ? argument + length : argument ];
		} ),

		even: createPositionalPseudo( function( matchIndexes, length ) {
			var i = 0;
			for ( ; i < length; i += 2 ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		} ),

		odd: createPositionalPseudo( function( matchIndexes, length ) {
			var i = 1;
			for ( ; i < length; i += 2 ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		} ),

		lt: createPositionalPseudo( function( matchIndexes, length, argument ) {
			var i;

			if ( argument < 0 ) {
				i = argument + length;
			} else if ( argument > length ) {
				i = length;
			} else {
				i = argument;
			}

			for ( ; --i >= 0; ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		} ),

		gt: createPositionalPseudo( function( matchIndexes, length, argument ) {
			var i = argument < 0 ? argument + length : argument;
			for ( ; ++i < length; ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		} )
	}
};

Expr.pseudos.nth = Expr.pseudos.eq;

// Add button/input type pseudos
for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
	Expr.pseudos[ i ] = createInputPseudo( i );
}
for ( i in { submit: true, reset: true } ) {
	Expr.pseudos[ i ] = createButtonPseudo( i );
}

// Easy API for creating new setFilters
function setFilters() {}
setFilters.prototype = Expr.filters = Expr.pseudos;
Expr.setFilters = new setFilters();

function tokenize( selector, parseOnly ) {
	var matched, match, tokens, type,
		soFar, groups, preFilters,
		cached = tokenCache[ selector + " " ];

	if ( cached ) {
		return parseOnly ? 0 : cached.slice( 0 );
	}

	soFar = selector;
	groups = [];
	preFilters = Expr.preFilter;

	while ( soFar ) {

		// Comma and first run
		if ( !matched || ( match = rcomma.exec( soFar ) ) ) {
			if ( match ) {

				// Don't consume trailing commas as valid
				soFar = soFar.slice( match[ 0 ].length ) || soFar;
			}
			groups.push( ( tokens = [] ) );
		}

		matched = false;

		// Combinators
		if ( ( match = rleadingCombinator.exec( soFar ) ) ) {
			matched = match.shift();
			tokens.push( {
				value: matched,

				// Cast descendant combinators to space
				type: match[ 0 ].replace( rtrimCSS, " " )
			} );
			soFar = soFar.slice( matched.length );
		}

		// Filters
		for ( type in Expr.filter ) {
			if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] ||
				( match = preFilters[ type ]( match ) ) ) ) {
				matched = match.shift();
				tokens.push( {
					value: matched,
					type: type,
					matches: match
				} );
				soFar = soFar.slice( matched.length );
			}
		}

		if ( !matched ) {
			break;
		}
	}

	// Return the length of the invalid excess
	// if we're just parsing
	// Otherwise, throw an error or return tokens
	if ( parseOnly ) {
		return soFar.length;
	}

	return soFar ?
		find.error( selector ) :

		// Cache the tokens
		tokenCache( selector, groups ).slice( 0 );
}

function toSelector( tokens ) {
	var i = 0,
		len = tokens.length,
		selector = "";
	for ( ; i < len; i++ ) {
		selector += tokens[ i ].value;
	}
	return selector;
}

function addCombinator( matcher, combinator, base ) {
	var dir = combinator.dir,
		skip = combinator.next,
		key = skip || dir,
		checkNonElements = base && key === "parentNode",
		doneName = done++;

	return combinator.first ?

		// Check against closest ancestor/preceding element
		function( elem, context, xml ) {
			while ( ( elem = elem[ dir ] ) ) {
				if ( elem.nodeType === 1 || checkNonElements ) {
					return matcher( elem, context, xml );
				}
			}
			return false;
		} :

		// Check against all ancestor/preceding elements
		function( elem, context, xml ) {
			var oldCache, outerCache,
				newCache = [ dirruns, doneName ];

			// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
			if ( xml ) {
				while ( ( elem = elem[ dir ] ) ) {
					if ( elem.nodeType === 1 || checkNonElements ) {
						if ( matcher( elem, context, xml ) ) {
							return true;
						}
					}
				}
			} else {
				while ( ( elem = elem[ dir ] ) ) {
					if ( elem.nodeType === 1 || checkNonElements ) {
						outerCache = elem[ expando ] || ( elem[ expando ] = {} );

						if ( skip && nodeName( elem, skip ) ) {
							elem = elem[ dir ] || elem;
						} else if ( ( oldCache = outerCache[ key ] ) &&
							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {

							// Assign to newCache so results back-propagate to previous elements
							return ( newCache[ 2 ] = oldCache[ 2 ] );
						} else {

							// Reuse newcache so results back-propagate to previous elements
							outerCache[ key ] = newCache;

							// A match means we're done; a fail means we have to keep checking
							if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) {
								return true;
							}
						}
					}
				}
			}
			return false;
		};
}

function elementMatcher( matchers ) {
	return matchers.length > 1 ?
		function( elem, context, xml ) {
			var i = matchers.length;
			while ( i-- ) {
				if ( !matchers[ i ]( elem, context, xml ) ) {
					return false;
				}
			}
			return true;
		} :
		matchers[ 0 ];
}

function multipleContexts( selector, contexts, results ) {
	var i = 0,
		len = contexts.length;
	for ( ; i < len; i++ ) {
		find( selector, contexts[ i ], results );
	}
	return results;
}

function condense( unmatched, map, filter, context, xml ) {
	var elem,
		newUnmatched = [],
		i = 0,
		len = unmatched.length,
		mapped = map != null;

	for ( ; i < len; i++ ) {
		if ( ( elem = unmatched[ i ] ) ) {
			if ( !filter || filter( elem, context, xml ) ) {
				newUnmatched.push( elem );
				if ( mapped ) {
					map.push( i );
				}
			}
		}
	}

	return newUnmatched;
}

function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
	if ( postFilter && !postFilter[ expando ] ) {
		postFilter = setMatcher( postFilter );
	}
	if ( postFinder && !postFinder[ expando ] ) {
		postFinder = setMatcher( postFinder, postSelector );
	}
	return markFunction( function( seed, results, context, xml ) {
		var temp, i, elem, matcherOut,
			preMap = [],
			postMap = [],
			preexisting = results.length,

			// Get initial elements from seed or context
			elems = seed ||
				multipleContexts( selector || "*",
					context.nodeType ? [ context ] : context, [] ),

			// Prefilter to get matcher input, preserving a map for seed-results synchronization
			matcherIn = preFilter && ( seed || !selector ) ?
				condense( elems, preMap, preFilter, context, xml ) :
				elems;

		if ( matcher ) {

			// If we have a postFinder, or filtered seed, or non-seed postFilter
			// or preexisting results,
			matcherOut = postFinder || ( seed ? preFilter : preexisting || postFilter ) ?

				// ...intermediate processing is necessary
				[] :

				// ...otherwise use results directly
				results;

			// Find primary matches
			matcher( matcherIn, matcherOut, context, xml );
		} else {
			matcherOut = matcherIn;
		}

		// Apply postFilter
		if ( postFilter ) {
			temp = condense( matcherOut, postMap );
			postFilter( temp, [], context, xml );

			// Un-match failing elements by moving them back to matcherIn
			i = temp.length;
			while ( i-- ) {
				if ( ( elem = temp[ i ] ) ) {
					matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem );
				}
			}
		}

		if ( seed ) {
			if ( postFinder || preFilter ) {
				if ( postFinder ) {

					// Get the final matcherOut by condensing this intermediate into postFinder contexts
					temp = [];
					i = matcherOut.length;
					while ( i-- ) {
						if ( ( elem = matcherOut[ i ] ) ) {

							// Restore matcherIn since elem is not yet a final match
							temp.push( ( matcherIn[ i ] = elem ) );
						}
					}
					postFinder( null, ( matcherOut = [] ), temp, xml );
				}

				// Move matched elements from seed to results to keep them synchronized
				i = matcherOut.length;
				while ( i-- ) {
					if ( ( elem = matcherOut[ i ] ) &&
						( temp = postFinder ? indexOf.call( seed, elem ) : preMap[ i ] ) > -1 ) {

						seed[ temp ] = !( results[ temp ] = elem );
					}
				}
			}

		// Add elements to results, through postFinder if defined
		} else {
			matcherOut = condense(
				matcherOut === results ?
					matcherOut.splice( preexisting, matcherOut.length ) :
					matcherOut
			);
			if ( postFinder ) {
				postFinder( null, results, matcherOut, xml );
			} else {
				push.apply( results, matcherOut );
			}
		}
	} );
}

function matcherFromTokens( tokens ) {
	var checkContext, matcher, j,
		len = tokens.length,
		leadingRelative = Expr.relative[ tokens[ 0 ].type ],
		implicitRelative = leadingRelative || Expr.relative[ " " ],
		i = leadingRelative ? 1 : 0,

		// The foundational matcher ensures that elements are reachable from top-level context(s)
		matchContext = addCombinator( function( elem ) {
			return elem === checkContext;
		}, implicitRelative, true ),
		matchAnyContext = addCombinator( function( elem ) {
			return indexOf.call( checkContext, elem ) > -1;
		}, implicitRelative, true ),
		matchers = [ function( elem, context, xml ) {

			// Support: IE 11+, Edge 17 - 18+
			// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
			// two documents; shallow comparisons work.
			// eslint-disable-next-line eqeqeq
			var ret = ( !leadingRelative && ( xml || context != outermostContext ) ) || (
				( checkContext = context ).nodeType ?
					matchContext( elem, context, xml ) :
					matchAnyContext( elem, context, xml ) );

			// Avoid hanging onto element
			// (see https://github.com/jquery/sizzle/issues/299)
			checkContext = null;
			return ret;
		} ];

	for ( ; i < len; i++ ) {
		if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) {
			matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];
		} else {
			matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches );

			// Return special upon seeing a positional matcher
			if ( matcher[ expando ] ) {

				// Find the next relative operator (if any) for proper handling
				j = ++i;
				for ( ; j < len; j++ ) {
					if ( Expr.relative[ tokens[ j ].type ] ) {
						break;
					}
				}
				return setMatcher(
					i > 1 && elementMatcher( matchers ),
					i > 1 && toSelector(

						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
						tokens.slice( 0, i - 1 )
							.concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } )
					).replace( rtrimCSS, "$1" ),
					matcher,
					i < j && matcherFromTokens( tokens.slice( i, j ) ),
					j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ),
					j < len && toSelector( tokens )
				);
			}
			matchers.push( matcher );
		}
	}

	return elementMatcher( matchers );
}

function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
	var bySet = setMatchers.length > 0,
		byElement = elementMatchers.length > 0,
		superMatcher = function( seed, context, xml, results, outermost ) {
			var elem, j, matcher,
				matchedCount = 0,
				i = "0",
				unmatched = seed && [],
				setMatched = [],
				contextBackup = outermostContext,

				// We must always have either seed elements or outermost context
				elems = seed || byElement && Expr.find.TAG( "*", outermost ),

				// Use integer dirruns iff this is the outermost matcher
				dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ),
				len = elems.length;

			if ( outermost ) {

				// Support: IE 11+, Edge 17 - 18+
				// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
				// two documents; shallow comparisons work.
				// eslint-disable-next-line eqeqeq
				outermostContext = context == document || context || outermost;
			}

			// Add elements passing elementMatchers directly to results
			// Support: iOS <=7 - 9 only
			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching
			// elements by id. (see trac-14142)
			for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) {
				if ( byElement && elem ) {
					j = 0;

					// Support: IE 11+, Edge 17 - 18+
					// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
					// two documents; shallow comparisons work.
					// eslint-disable-next-line eqeqeq
					if ( !context && elem.ownerDocument != document ) {
						setDocument( elem );
						xml = !documentIsHTML;
					}
					while ( ( matcher = elementMatchers[ j++ ] ) ) {
						if ( matcher( elem, context || document, xml ) ) {
							push.call( results, elem );
							break;
						}
					}
					if ( outermost ) {
						dirruns = dirrunsUnique;
					}
				}

				// Track unmatched elements for set filters
				if ( bySet ) {

					// They will have gone through all possible matchers
					if ( ( elem = !matcher && elem ) ) {
						matchedCount--;
					}

					// Lengthen the array for every element, matched or not
					if ( seed ) {
						unmatched.push( elem );
					}
				}
			}

			// `i` is now the count of elements visited above, and adding it to `matchedCount`
			// makes the latter nonnegative.
			matchedCount += i;

			// Apply set filters to unmatched elements
			// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
			// equals `i`), unless we didn't visit _any_ elements in the above loop because we have
			// no element matchers and no seed.
			// Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
			// case, which will result in a "00" `matchedCount` that differs from `i` but is also
			// numerically zero.
			if ( bySet && i !== matchedCount ) {
				j = 0;
				while ( ( matcher = setMatchers[ j++ ] ) ) {
					matcher( unmatched, setMatched, context, xml );
				}

				if ( seed ) {

					// Reintegrate element matches to eliminate the need for sorting
					if ( matchedCount > 0 ) {
						while ( i-- ) {
							if ( !( unmatched[ i ] || setMatched[ i ] ) ) {
								setMatched[ i ] = pop.call( results );
							}
						}
					}

					// Discard index placeholder values to get only actual matches
					setMatched = condense( setMatched );
				}

				// Add matches to results
				push.apply( results, setMatched );

				// Seedless set matches succeeding multiple successful matchers stipulate sorting
				if ( outermost && !seed && setMatched.length > 0 &&
					( matchedCount + setMatchers.length ) > 1 ) {

					jQuery.uniqueSort( results );
				}
			}

			// Override manipulation of globals by nested matchers
			if ( outermost ) {
				dirruns = dirrunsUnique;
				outermostContext = contextBackup;
			}

			return unmatched;
		};

	return bySet ?
		markFunction( superMatcher ) :
		superMatcher;
}

function compile( selector, match /* Internal Use Only */ ) {
	var i,
		setMatchers = [],
		elementMatchers = [],
		cached = compilerCache[ selector + " " ];

	if ( !cached ) {

		// Generate a function of recursive functions that can be used to check each element
		if ( !match ) {
			match = tokenize( selector );
		}
		i = match.length;
		while ( i-- ) {
			cached = matcherFromTokens( match[ i ] );
			if ( cached[ expando ] ) {
				setMatchers.push( cached );
			} else {
				elementMatchers.push( cached );
			}
		}

		// Cache the compiled function
		cached = compilerCache( selector,
			matcherFromGroupMatchers( elementMatchers, setMatchers ) );

		// Save selector and tokenization
		cached.selector = selector;
	}
	return cached;
}

/**
 * A low-level selection function that works with jQuery's compiled
 *  selector functions
 * @param {String|Function} selector A selector or a pre-compiled
 *  selector function built with jQuery selector compile
 * @param {Element} context
 * @param {Array} [results]
 * @param {Array} [seed] A set of elements to match against
 */
function select( selector, context, results, seed ) {
	var i, tokens, token, type, find,
		compiled = typeof selector === "function" && selector,
		match = !seed && tokenize( ( selector = compiled.selector || selector ) );

	results = results || [];

	// Try to minimize operations if there is only one selector in the list and no seed
	// (the latter of which guarantees us context)
	if ( match.length === 1 ) {

		// Reduce context if the leading compound selector is an ID
		tokens = match[ 0 ] = match[ 0 ].slice( 0 );
		if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" &&
				context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) {

			context = ( Expr.find.ID(
				token.matches[ 0 ].replace( runescape, funescape ),
				context
			) || [] )[ 0 ];
			if ( !context ) {
				return results;

			// Precompiled matchers will still verify ancestry, so step up a level
			} else if ( compiled ) {
				context = context.parentNode;
			}

			selector = selector.slice( tokens.shift().value.length );
		}

		// Fetch a seed set for right-to-left matching
		i = matchExpr.needsContext.test( selector ) ? 0 : tokens.length;
		while ( i-- ) {
			token = tokens[ i ];

			// Abort if we hit a combinator
			if ( Expr.relative[ ( type = token.type ) ] ) {
				break;
			}
			if ( ( find = Expr.find[ type ] ) ) {

				// Search, expanding context for leading sibling combinators
				if ( ( seed = find(
					token.matches[ 0 ].replace( runescape, funescape ),
					rsibling.test( tokens[ 0 ].type ) &&
						testContext( context.parentNode ) || context
				) ) ) {

					// If seed is empty or no tokens remain, we can return early
					tokens.splice( i, 1 );
					selector = seed.length && toSelector( tokens );
					if ( !selector ) {
						push.apply( results, seed );
						return results;
					}

					break;
				}
			}
		}
	}

	// Compile and execute a filtering function if one is not provided
	// Provide `match` to avoid retokenization if we modified the selector above
	( compiled || compile( selector, match ) )(
		seed,
		context,
		!documentIsHTML,
		results,
		!context || rsibling.test( selector ) && testContext( context.parentNode ) || context
	);
	return results;
}

// One-time assignments

// Support: Android <=4.0 - 4.1+
// Sort stability
support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando;

// Initialize against the default document
setDocument();

// Support: Android <=4.0 - 4.1+
// Detached nodes confoundingly follow *each other*
support.sortDetached = assert( function( el ) {

	// Should return 1, but returns 4 (following)
	return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1;
} );

jQuery.find = find;

// Deprecated
jQuery.expr[ ":" ] = jQuery.expr.pseudos;
jQuery.unique = jQuery.uniqueSort;

// These have always been private, but they used to be documented as part of
// Sizzle so let's maintain them for now for backwards compatibility purposes.
find.compile = compile;
find.select = select;
find.setDocument = setDocument;
find.tokenize = tokenize;

find.escape = jQuery.escapeSelector;
find.getText = jQuery.text;
find.isXML = jQuery.isXMLDoc;
find.selectors = jQuery.expr;
find.support = jQuery.support;
find.uniqueSort = jQuery.uniqueSort;

	/* eslint-enable */

} )();


var dir = function( elem, dir, until ) {
	var matched = [],
		truncate = until !== undefined;

	while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
		if ( elem.nodeType === 1 ) {
			if ( truncate && jQuery( elem ).is( until ) ) {
				break;
			}
			matched.push( elem );
		}
	}
	return matched;
};


var siblings = function( n, elem ) {
	var matched = [];

	for ( ; n; n = n.nextSibling ) {
		if ( n.nodeType === 1 && n !== elem ) {
			matched.push( n );
		}
	}

	return matched;
};


var rneedsContext = jQuery.expr.match.needsContext;

var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );



// Implement the identical functionality for filter and not
function winnow( elements, qualifier, not ) {
	if ( isFunction( qualifier ) ) {
		return jQuery.grep( elements, function( elem, i ) {
			return !!qualifier.call( elem, i, elem ) !== not;
		} );
	}

	// Single element
	if ( qualifier.nodeType ) {
		return jQuery.grep( elements, function( elem ) {
			return ( elem === qualifier ) !== not;
		} );
	}

	// Arraylike of elements (jQuery, arguments, Array)
	if ( typeof qualifier !== "string" ) {
		return jQuery.grep( elements, function( elem ) {
			return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
		} );
	}

	// Filtered directly for both simple and complex selectors
	return jQuery.filter( qualifier, elements, not );
}

jQuery.filter = function( expr, elems, not ) {
	var elem = elems[ 0 ];

	if ( not ) {
		expr = ":not(" + expr + ")";
	}

	if ( elems.length === 1 && elem.nodeType === 1 ) {
		return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];
	}

	return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
		return elem.nodeType === 1;
	} ) );
};

jQuery.fn.extend( {
	find: function( selector ) {
		var i, ret,
			len = this.length,
			self = this;

		if ( typeof selector !== "string" ) {
			return this.pushStack( jQuery( selector ).filter( function() {
				for ( i = 0; i < len; i++ ) {
					if ( jQuery.contains( self[ i ], this ) ) {
						return true;
					}
				}
			} ) );
		}

		ret = this.pushStack( [] );

		for ( i = 0; i < len; i++ ) {
			jQuery.find( selector, self[ i ], ret );
		}

		return len > 1 ? jQuery.uniqueSort( ret ) : ret;
	},
	filter: function( selector ) {
		return this.pushStack( winnow( this, selector || [], false ) );
	},
	not: function( selector ) {
		return this.pushStack( winnow( this, selector || [], true ) );
	},
	is: function( selector ) {
		return !!winnow(
			this,

			// If this is a positional/relative selector, check membership in the returned set
			// so $("p:first").is("p:last") won't return true for a doc with two "p".
			typeof selector === "string" && rneedsContext.test( selector ) ?
				jQuery( selector ) :
				selector || [],
			false
		).length;
	}
} );


// Initialize a jQuery object


// A central reference to the root jQuery(document)
var rootjQuery,

	// A simple way to check for HTML strings
	// Prioritize #id over <tag> to avoid XSS via location.hash (trac-9521)
	// Strict HTML recognition (trac-11290: must start with <)
	// Shortcut simple #id case for speed
	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,

	init = jQuery.fn.init = function( selector, context, root ) {
		var match, elem;

		// HANDLE: $(""), $(null), $(undefined), $(false)
		if ( !selector ) {
			return this;
		}

		// Method init() accepts an alternate rootjQuery
		// so migrate can support jQuery.sub (gh-2101)
		root = root || rootjQuery;

		// Handle HTML strings
		if ( typeof selector === "string" ) {
			if ( selector[ 0 ] === "<" &&
				selector[ selector.length - 1 ] === ">" &&
				selector.length >= 3 ) {

				// Assume that strings that start and end with <> are HTML and skip the regex check
				match = [ null, selector, null ];

			} else {
				match = rquickExpr.exec( selector );
			}

			// Match html or make sure no context is specified for #id
			if ( match && ( match[ 1 ] || !context ) ) {

				// HANDLE: $(html) -> $(array)
				if ( match[ 1 ] ) {
					context = context instanceof jQuery ? context[ 0 ] : context;

					// Option to run scripts is true for back-compat
					// Intentionally let the error be thrown if parseHTML is not present
					jQuery.merge( this, jQuery.parseHTML(
						match[ 1 ],
						context && context.nodeType ? context.ownerDocument || context : document,
						true
					) );

					// HANDLE: $(html, props)
					if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
						for ( match in context ) {

							// Properties of context are called as methods if possible
							if ( isFunction( this[ match ] ) ) {
								this[ match ]( context[ match ] );

							// ...and otherwise set as attributes
							} else {
								this.attr( match, context[ match ] );
							}
						}
					}

					return this;

				// HANDLE: $(#id)
				} else {
					elem = document.getElementById( match[ 2 ] );

					if ( elem ) {

						// Inject the element directly into the jQuery object
						this[ 0 ] = elem;
						this.length = 1;
					}
					return this;
				}

			// HANDLE: $(expr, $(...))
			} else if ( !context || context.jquery ) {
				return ( context || root ).find( selector );

			// HANDLE: $(expr, context)
			// (which is just equivalent to: $(context).find(expr)
			} else {
				return this.constructor( context ).find( selector );
			}

		// HANDLE: $(DOMElement)
		} else if ( selector.nodeType ) {
			this[ 0 ] = selector;
			this.length = 1;
			return this;

		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( isFunction( selector ) ) {
			return root.ready !== undefined ?
				root.ready( selector ) :

				// Execute immediately if ready is not present
				selector( jQuery );
		}

		return jQuery.makeArray( selector, this );
	};

// Give the init function the jQuery prototype for later instantiation
init.prototype = jQuery.fn;

// Initialize central reference
rootjQuery = jQuery( document );


var rparentsprev = /^(?:parents|prev(?:Until|All))/,

	// Methods guaranteed to produce a unique set when starting from a unique set
	guaranteedUnique = {
		children: true,
		contents: true,
		next: true,
		prev: true
	};

jQuery.fn.extend( {
	has: function( target ) {
		var targets = jQuery( target, this ),
			l = targets.length;

		return this.filter( function() {
			var i = 0;
			for ( ; i < l; i++ ) {
				if ( jQuery.contains( this, targets[ i ] ) ) {
					return true;
				}
			}
		} );
	},

	closest: function( selectors, context ) {
		var cur,
			i = 0,
			l = this.length,
			matched = [],
			targets = typeof selectors !== "string" && jQuery( selectors );

		// Positional selectors never match, since there's no _selection_ context
		if ( !rneedsContext.test( selectors ) ) {
			for ( ; i < l; i++ ) {
				for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {

					// Always skip document fragments
					if ( cur.nodeType < 11 && ( targets ?
						targets.index( cur ) > -1 :

						// Don't pass non-elements to jQuery#find
						cur.nodeType === 1 &&
							jQuery.find.matchesSelector( cur, selectors ) ) ) {

						matched.push( cur );
						break;
					}
				}
			}
		}

		return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
	},

	// Determine the position of an element within the set
	index: function( elem ) {

		// No argument, return index in parent
		if ( !elem ) {
			return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
		}

		// Index in selector
		if ( typeof elem === "string" ) {
			return indexOf.call( jQuery( elem ), this[ 0 ] );
		}

		// Locate the position of the desired element
		return indexOf.call( this,

			// If it receives a jQuery object, the first element is used
			elem.jquery ? elem[ 0 ] : elem
		);
	},

	add: function( selector, context ) {
		return this.pushStack(
			jQuery.uniqueSort(
				jQuery.merge( this.get(), jQuery( selector, context ) )
			)
		);
	},

	addBack: function( selector ) {
		return this.add( selector == null ?
			this.prevObject : this.prevObject.filter( selector )
		);
	}
} );

function sibling( cur, dir ) {
	while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
	return cur;
}

jQuery.each( {
	parent: function( elem ) {
		var parent = elem.parentNode;
		return parent && parent.nodeType !== 11 ? parent : null;
	},
	parents: function( elem ) {
		return dir( elem, "parentNode" );
	},
	parentsUntil: function( elem, _i, until ) {
		return dir( elem, "parentNode", until );
	},
	next: function( elem ) {
		return sibling( elem, "nextSibling" );
	},
	prev: function( elem ) {
		return sibling( elem, "previousSibling" );
	},
	nextAll: function( elem ) {
		return dir( elem, "nextSibling" );
	},
	prevAll: function( elem ) {
		return dir( elem, "previousSibling" );
	},
	nextUntil: function( elem, _i, until ) {
		return dir( elem, "nextSibling", until );
	},
	prevUntil: function( elem, _i, until ) {
		return dir( elem, "previousSibling", until );
	},
	siblings: function( elem ) {
		return siblings( ( elem.parentNode || {} ).firstChild, elem );
	},
	children: function( elem ) {
		return siblings( elem.firstChild );
	},
	contents: function( elem ) {
		if ( elem.contentDocument != null &&

			// Support: IE 11+
			// <object> elements with no `data` attribute has an object
			// `contentDocument` with a `null` prototype.
			getProto( elem.contentDocument ) ) {

			return elem.contentDocument;
		}

		// Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
		// Treat the template element as a regular one in browsers that
		// don't support it.
		if ( nodeName( elem, "template" ) ) {
			elem = elem.content || elem;
		}

		return jQuery.merge( [], elem.childNodes );
	}
}, function( name, fn ) {
	jQuery.fn[ name ] = function( until, selector ) {
		var matched = jQuery.map( this, fn, until );

		if ( name.slice( -5 ) !== "Until" ) {
			selector = until;
		}

		if ( selector && typeof selector === "string" ) {
			matched = jQuery.filter( selector, matched );
		}

		if ( this.length > 1 ) {

			// Remove duplicates
			if ( !guaranteedUnique[ name ] ) {
				jQuery.uniqueSort( matched );
			}

			// Reverse order for parents* and prev-derivatives
			if ( rparentsprev.test( name ) ) {
				matched.reverse();
			}
		}

		return this.pushStack( matched );
	};
} );
var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g );



// Convert String-formatted options into Object-formatted ones
function createOptions( options ) {
	var object = {};
	jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
		object[ flag ] = true;
	} );
	return object;
}

/*
 * Create a callback list using the following parameters:
 *
 *	options: an optional list of space-separated options that will change how
 *			the callback list behaves or a more traditional option object
 *
 * By default a callback list will act like an event callback list and can be
 * "fired" multiple times.
 *
 * Possible options:
 *
 *	once:			will ensure the callback list can only be fired once (like a Deferred)
 *
 *	memory:			will keep track of previous values and will call any callback added
 *					after the list has been fired right away with the latest "memorized"
 *					values (like a Deferred)
 *
 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
 *
 *	stopOnFalse:	interrupt callings when a callback returns false
 *
 */
jQuery.Callbacks = function( options ) {

	// Convert options from String-formatted to Object-formatted if needed
	// (we check in cache first)
	options = typeof options === "string" ?
		createOptions( options ) :
		jQuery.extend( {}, options );

	var // Flag to know if list is currently firing
		firing,

		// Last fire value for non-forgettable lists
		memory,

		// Flag to know if list was already fired
		fired,

		// Flag to prevent firing
		locked,

		// Actual callback list
		list = [],

		// Queue of execution data for repeatable lists
		queue = [],

		// Index of currently firing callback (modified by add/remove as needed)
		firingIndex = -1,

		// Fire callbacks
		fire = function() {

			// Enforce single-firing
			locked = locked || options.once;

			// Execute callbacks for all pending executions,
			// respecting firingIndex overrides and runtime changes
			fired = firing = true;
			for ( ; queue.length; firingIndex = -1 ) {
				memory = queue.shift();
				while ( ++firingIndex < list.length ) {

					// Run callback and check for early termination
					if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
						options.stopOnFalse ) {

						// Jump to end and forget the data so .add doesn't re-fire
						firingIndex = list.length;
						memory = false;
					}
				}
			}

			// Forget the data if we're done with it
			if ( !options.memory ) {
				memory = false;
			}

			firing = false;

			// Clean up if we're done firing for good
			if ( locked ) {

				// Keep an empty list if we have data for future add calls
				if ( memory ) {
					list = [];

				// Otherwise, this object is spent
				} else {
					list = "";
				}
			}
		},

		// Actual Callbacks object
		self = {

			// Add a callback or a collection of callbacks to the list
			add: function() {
				if ( list ) {

					// If we have memory from a past run, we should fire after adding
					if ( memory && !firing ) {
						firingIndex = list.length - 1;
						queue.push( memory );
					}

					( function add( args ) {
						jQuery.each( args, function( _, arg ) {
							if ( isFunction( arg ) ) {
								if ( !options.unique || !self.has( arg ) ) {
									list.push( arg );
								}
							} else if ( arg && arg.length && toType( arg ) !== "string" ) {

								// Inspect recursively
								add( arg );
							}
						} );
					} )( arguments );

					if ( memory && !firing ) {
						fire();
					}
				}
				return this;
			},

			// Remove a callback from the list
			remove: function() {
				jQuery.each( arguments, function( _, arg ) {
					var index;
					while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
						list.splice( index, 1 );

						// Handle firing indexes
						if ( index <= firingIndex ) {
							firingIndex--;
						}
					}
				} );
				return this;
			},

			// Check if a given callback is in the list.
			// If no argument is given, return whether or not list has callbacks attached.
			has: function( fn ) {
				return fn ?
					jQuery.inArray( fn, list ) > -1 :
					list.length > 0;
			},

			// Remove all callbacks from the list
			empty: function() {
				if ( list ) {
					list = [];
				}
				return this;
			},

			// Disable .fire and .add
			// Abort any current/pending executions
			// Clear all callbacks and values
			disable: function() {
				locked = queue = [];
				list = memory = "";
				return this;
			},
			disabled: function() {
				return !list;
			},

			// Disable .fire
			// Also disable .add unless we have memory (since it would have no effect)
			// Abort any pending executions
			lock: function() {
				locked = queue = [];
				if ( !memory && !firing ) {
					list = memory = "";
				}
				return this;
			},
			locked: function() {
				return !!locked;
			},

			// Call all callbacks with the given context and arguments
			fireWith: function( context, args ) {
				if ( !locked ) {
					args = args || [];
					args = [ context, args.slice ? args.slice() : args ];
					queue.push( args );
					if ( !firing ) {
						fire();
					}
				}
				return this;
			},

			// Call all the callbacks with the given arguments
			fire: function() {
				self.fireWith( this, arguments );
				return this;
			},

			// To know if the callbacks have already been called at least once
			fired: function() {
				return !!fired;
			}
		};

	return self;
};


function Identity( v ) {
	return v;
}
function Thrower( ex ) {
	throw ex;
}

function adoptValue( value, resolve, reject, noValue ) {
	var method;

	try {

		// Check for promise aspect first to privilege synchronous behavior
		if ( value && isFunction( ( method = value.promise ) ) ) {
			method.call( value ).done( resolve ).fail( reject );

		// Other thenables
		} else if ( value && isFunction( ( method = value.then ) ) ) {
			method.call( value, resolve, reject );

		// Other non-thenables
		} else {

			// Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:
			// * false: [ value ].slice( 0 ) => resolve( value )
			// * true: [ value ].slice( 1 ) => resolve()
			resolve.apply( undefined, [ value ].slice( noValue ) );
		}

	// For Promises/A+, convert exceptions into rejections
	// Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
	// Deferred#then to conditionally suppress rejection.
	} catch ( value ) {

		// Support: Android 4.0 only
		// Strict mode functions invoked without .call/.apply get global-object context
		reject.apply( undefined, [ value ] );
	}
}

jQuery.extend( {

	Deferred: function( func ) {
		var tuples = [

				// action, add listener, callbacks,
				// ... .then handlers, argument index, [final state]
				[ "notify", "progress", jQuery.Callbacks( "memory" ),
					jQuery.Callbacks( "memory" ), 2 ],
				[ "resolve", "done", jQuery.Callbacks( "once memory" ),
					jQuery.Callbacks( "once memory" ), 0, "resolved" ],
				[ "reject", "fail", jQuery.Callbacks( "once memory" ),
					jQuery.Callbacks( "once memory" ), 1, "rejected" ]
			],
			state = "pending",
			promise = {
				state: function() {
					return state;
				},
				always: function() {
					deferred.done( arguments ).fail( arguments );
					return this;
				},
				"catch": function( fn ) {
					return promise.then( null, fn );
				},

				// Keep pipe for back-compat
				pipe: function( /* fnDone, fnFail, fnProgress */ ) {
					var fns = arguments;

					return jQuery.Deferred( function( newDefer ) {
						jQuery.each( tuples, function( _i, tuple ) {

							// Map tuples (progress, done, fail) to arguments (done, fail, progress)
							var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];

							// deferred.progress(function() { bind to newDefer or newDefer.notify })
							// deferred.done(function() { bind to newDefer or newDefer.resolve })
							// deferred.fail(function() { bind to newDefer or newDefer.reject })
							deferred[ tuple[ 1 ] ]( function() {
								var returned = fn && fn.apply( this, arguments );
								if ( returned && isFunction( returned.promise ) ) {
									returned.promise()
										.progress( newDefer.notify )
										.done( newDefer.resolve )
										.fail( newDefer.reject );
								} else {
									newDefer[ tuple[ 0 ] + "With" ](
										this,
										fn ? [ returned ] : arguments
									);
								}
							} );
						} );
						fns = null;
					} ).promise();
				},
				then: function( onFulfilled, onRejected, onProgress ) {
					var maxDepth = 0;
					function resolve( depth, deferred, handler, special ) {
						return function() {
							var that = this,
								args = arguments,
								mightThrow = function() {
									var returned, then;

									// Support: Promises/A+ section 2.3.3.3.3
									// https://promisesaplus.com/#point-59
									// Ignore double-resolution attempts
									if ( depth < maxDepth ) {
										return;
									}

									returned = handler.apply( that, args );

									// Support: Promises/A+ section 2.3.1
									// https://promisesaplus.com/#point-48
									if ( returned === deferred.promise() ) {
										throw new TypeError( "Thenable self-resolution" );
									}

									// Support: Promises/A+ sections 2.3.3.1, 3.5
									// https://promisesaplus.com/#point-54
									// https://promisesaplus.com/#point-75
									// Retrieve `then` only once
									then = returned &&

										// Support: Promises/A+ section 2.3.4
										// https://promisesaplus.com/#point-64
										// Only check objects and functions for thenability
										( typeof returned === "object" ||
											typeof returned === "function" ) &&
										returned.then;

									// Handle a returned thenable
									if ( isFunction( then ) ) {

										// Special processors (notify) just wait for resolution
										if ( special ) {
											then.call(
												returned,
												resolve( maxDepth, deferred, Identity, special ),
												resolve( maxDepth, deferred, Thrower, special )
											);

										// Normal processors (resolve) also hook into progress
										} else {

											// ...and disregard older resolution values
											maxDepth++;

											then.call(
												returned,
												resolve( maxDepth, deferred, Identity, special ),
												resolve( maxDepth, deferred, Thrower, special ),
												resolve( maxDepth, deferred, Identity,
													deferred.notifyWith )
											);
										}

									// Handle all other returned values
									} else {

										// Only substitute handlers pass on context
										// and multiple values (non-spec behavior)
										if ( handler !== Identity ) {
											that = undefined;
											args = [ returned ];
										}

										// Process the value(s)
										// Default process is resolve
										( special || deferred.resolveWith )( that, args );
									}
								},

								// Only normal processors (resolve) catch and reject exceptions
								process = special ?
									mightThrow :
									function() {
										try {
											mightThrow();
										} catch ( e ) {

											if ( jQuery.Deferred.exceptionHook ) {
												jQuery.Deferred.exceptionHook( e,
													process.error );
											}

											// Support: Promises/A+ section 2.3.3.3.4.1
											// https://promisesaplus.com/#point-61
											// Ignore post-resolution exceptions
											if ( depth + 1 >= maxDepth ) {

												// Only substitute handlers pass on context
												// and multiple values (non-spec behavior)
												if ( handler !== Thrower ) {
													that = undefined;
													args = [ e ];
												}

												deferred.rejectWith( that, args );
											}
										}
									};

							// Support: Promises/A+ section 2.3.3.3.1
							// https://promisesaplus.com/#point-57
							// Re-resolve promises immediately to dodge false rejection from
							// subsequent errors
							if ( depth ) {
								process();
							} else {

								// Call an optional hook to record the error, in case of exception
								// since it's otherwise lost when execution goes async
								if ( jQuery.Deferred.getErrorHook ) {
									process.error = jQuery.Deferred.getErrorHook();

								// The deprecated alias of the above. While the name suggests
								// returning the stack, not an error instance, jQuery just passes
								// it directly to `console.warn` so both will work; an instance
								// just better cooperates with source maps.
								} else if ( jQuery.Deferred.getStackHook ) {
									process.error = jQuery.Deferred.getStackHook();
								}
								window.setTimeout( process );
							}
						};
					}

					return jQuery.Deferred( function( newDefer ) {

						// progress_handlers.add( ... )
						tuples[ 0 ][ 3 ].add(
							resolve(
								0,
								newDefer,
								isFunction( onProgress ) ?
									onProgress :
									Identity,
								newDefer.notifyWith
							)
						);

						// fulfilled_handlers.add( ... )
						tuples[ 1 ][ 3 ].add(
							resolve(
								0,
								newDefer,
								isFunction( onFulfilled ) ?
									onFulfilled :
									Identity
							)
						);

						// rejected_handlers.add( ... )
						tuples[ 2 ][ 3 ].add(
							resolve(
								0,
								newDefer,
								isFunction( onRejected ) ?
									onRejected :
									Thrower
							)
						);
					} ).promise();
				},

				// Get a promise for this deferred
				// If obj is provided, the promise aspect is added to the object
				promise: function( obj ) {
					return obj != null ? jQuery.extend( obj, promise ) : promise;
				}
			},
			deferred = {};

		// Add list-specific methods
		jQuery.each( tuples, function( i, tuple ) {
			var list = tuple[ 2 ],
				stateString = tuple[ 5 ];

			// promise.progress = list.add
			// promise.done = list.add
			// promise.fail = list.add
			promise[ tuple[ 1 ] ] = list.add;

			// Handle state
			if ( stateString ) {
				list.add(
					function() {

						// state = "resolved" (i.e., fulfilled)
						// state = "rejected"
						state = stateString;
					},

					// rejected_callbacks.disable
					// fulfilled_callbacks.disable
					tuples[ 3 - i ][ 2 ].disable,

					// rejected_handlers.disable
					// fulfilled_handlers.disable
					tuples[ 3 - i ][ 3 ].disable,

					// progress_callbacks.lock
					tuples[ 0 ][ 2 ].lock,

					// progress_handlers.lock
					tuples[ 0 ][ 3 ].lock
				);
			}

			// progress_handlers.fire
			// fulfilled_handlers.fire
			// rejected_handlers.fire
			list.add( tuple[ 3 ].fire );

			// deferred.notify = function() { deferred.notifyWith(...) }
			// deferred.resolve = function() { deferred.resolveWith(...) }
			// deferred.reject = function() { deferred.rejectWith(...) }
			deferred[ tuple[ 0 ] ] = function() {
				deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
				return this;
			};

			// deferred.notifyWith = list.fireWith
			// deferred.resolveWith = list.fireWith
			// deferred.rejectWith = list.fireWith
			deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
		} );

		// Make the deferred a promise
		promise.promise( deferred );

		// Call given func if any
		if ( func ) {
			func.call( deferred, deferred );
		}

		// All done!
		return deferred;
	},

	// Deferred helper
	when: function( singleValue ) {
		var

			// count of uncompleted subordinates
			remaining = arguments.length,

			// count of unprocessed arguments
			i = remaining,

			// subordinate fulfillment data
			resolveContexts = Array( i ),
			resolveValues = slice.call( arguments ),

			// the primary Deferred
			primary = jQuery.Deferred(),

			// subordinate callback factory
			updateFunc = function( i ) {
				return function( value ) {
					resolveContexts[ i ] = this;
					resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
					if ( !( --remaining ) ) {
						primary.resolveWith( resolveContexts, resolveValues );
					}
				};
			};

		// Single- and empty arguments are adopted like Promise.resolve
		if ( remaining <= 1 ) {
			adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject,
				!remaining );

			// Use .then() to unwrap secondary thenables (cf. gh-3000)
			if ( primary.state() === "pending" ||
				isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {

				return primary.then();
			}
		}

		// Multiple arguments are aggregated like Promise.all array elements
		while ( i-- ) {
			adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject );
		}

		return primary.promise();
	}
} );


// These usually indicate a programmer mistake during development,
// warn about them ASAP rather than swallowing them by default.
var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;

// If `jQuery.Deferred.getErrorHook` is defined, `asyncError` is an error
// captured before the async barrier to get the original error cause
// which may otherwise be hidden.
jQuery.Deferred.exceptionHook = function( error, asyncError ) {

	// Support: IE 8 - 9 only
	// Console exists when dev tools are open, which can happen at any time
	if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
		window.console.warn( "jQuery.Deferred exception: " + error.message,
			error.stack, asyncError );
	}
};




jQuery.readyException = function( error ) {
	window.setTimeout( function() {
		throw error;
	} );
};




// The deferred used on DOM ready
var readyList = jQuery.Deferred();

jQuery.fn.ready = function( fn ) {

	readyList
		.then( fn )

		// Wrap jQuery.readyException in a function so that the lookup
		// happens at the time of error handling instead of callback
		// registration.
		.catch( function( error ) {
			jQuery.readyException( error );
		} );

	return this;
};

jQuery.extend( {

	// Is the DOM ready to be used? Set to true once it occurs.
	isReady: false,

	// A counter to track how many items to wait for before
	// the ready event fires. See trac-6781
	readyWait: 1,

	// Handle when the DOM is ready
	ready: function( wait ) {

		// Abort if there are pending holds or we're already ready
		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
			return;
		}

		// Remember that the DOM is ready
		jQuery.isReady = true;

		// If a normal DOM Ready event fired, decrement, and wait if need be
		if ( wait !== true && --jQuery.readyWait > 0 ) {
			return;
		}

		// If there are functions bound, to execute
		readyList.resolveWith( document, [ jQuery ] );
	}
} );

jQuery.ready.then = readyList.then;

// The ready event handler and self cleanup method
function completed() {
	document.removeEventListener( "DOMContentLoaded", completed );
	window.removeEventListener( "load", completed );
	jQuery.ready();
}

// Catch cases where $(document).ready() is called
// after the browser event has already occurred.
// Support: IE <=9 - 10 only
// Older IE sometimes signals "interactive" too soon
if ( document.readyState === "complete" ||
	( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {

	// Handle it asynchronously to allow scripts the opportunity to delay ready
	window.setTimeout( jQuery.ready );

} else {

	// Use the handy event callback
	document.addEventListener( "DOMContentLoaded", completed );

	// A fallback to window.onload, that will always work
	window.addEventListener( "load", completed );
}




// Multifunctional method to get and set values of a collection
// The value/s can optionally be executed if it's a function
var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
	var i = 0,
		len = elems.length,
		bulk = key == null;

	// Sets many values
	if ( toType( key ) === "object" ) {
		chainable = true;
		for ( i in key ) {
			access( elems, fn, i, key[ i ], true, emptyGet, raw );
		}

	// Sets one value
	} else if ( value !== undefined ) {
		chainable = true;

		if ( !isFunction( value ) ) {
			raw = true;
		}

		if ( bulk ) {

			// Bulk operations run against the entire set
			if ( raw ) {
				fn.call( elems, value );
				fn = null;

			// ...except when executing function values
			} else {
				bulk = fn;
				fn = function( elem, _key, value ) {
					return bulk.call( jQuery( elem ), value );
				};
			}
		}

		if ( fn ) {
			for ( ; i < len; i++ ) {
				fn(
					elems[ i ], key, raw ?
						value :
						value.call( elems[ i ], i, fn( elems[ i ], key ) )
				);
			}
		}
	}

	if ( chainable ) {
		return elems;
	}

	// Gets
	if ( bulk ) {
		return fn.call( elems );
	}

	return len ? fn( elems[ 0 ], key ) : emptyGet;
};


// Matches dashed string for camelizing
var rmsPrefix = /^-ms-/,
	rdashAlpha = /-([a-z])/g;

// Used by camelCase as callback to replace()
function fcamelCase( _all, letter ) {
	return letter.toUpperCase();
}

// Convert dashed to camelCase; used by the css and data modules
// Support: IE <=9 - 11, Edge 12 - 15
// Microsoft forgot to hump their vendor prefix (trac-9572)
function camelCase( string ) {
	return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
}
var acceptData = function( owner ) {

	// Accepts only:
	//  - Node
	//    - Node.ELEMENT_NODE
	//    - Node.DOCUMENT_NODE
	//  - Object
	//    - Any
	return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
};




function Data() {
	this.expando = jQuery.expando + Data.uid++;
}

Data.uid = 1;

Data.prototype = {

	cache: function( owner ) {

		// Check if the owner object already has a cache
		var value = owner[ this.expando ];

		// If not, create one
		if ( !value ) {
			value = {};

			// We can accept data for non-element nodes in modern browsers,
			// but we should not, see trac-8335.
			// Always return an empty object.
			if ( acceptData( owner ) ) {

				// If it is a node unlikely to be stringify-ed or looped over
				// use plain assignment
				if ( owner.nodeType ) {
					owner[ this.expando ] = value;

				// Otherwise secure it in a non-enumerable property
				// configurable must be true to allow the property to be
				// deleted when data is removed
				} else {
					Object.defineProperty( owner, this.expando, {
						value: value,
						configurable: true
					} );
				}
			}
		}

		return value;
	},
	set: function( owner, data, value ) {
		var prop,
			cache = this.cache( owner );

		// Handle: [ owner, key, value ] args
		// Always use camelCase key (gh-2257)
		if ( typeof data === "string" ) {
			cache[ camelCase( data ) ] = value;

		// Handle: [ owner, { properties } ] args
		} else {

			// Copy the properties one-by-one to the cache object
			for ( prop in data ) {
				cache[ camelCase( prop ) ] = data[ prop ];
			}
		}
		return cache;
	},
	get: function( owner, key ) {
		return key === undefined ?
			this.cache( owner ) :

			// Always use camelCase key (gh-2257)
			owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];
	},
	access: function( owner, key, value ) {

		// In cases where either:
		//
		//   1. No key was specified
		//   2. A string key was specified, but no value provided
		//
		// Take the "read" path and allow the get method to determine
		// which value to return, respectively either:
		//
		//   1. The entire cache object
		//   2. The data stored at the key
		//
		if ( key === undefined ||
				( ( key && typeof key === "string" ) && value === undefined ) ) {

			return this.get( owner, key );
		}

		// When the key is not a string, or both a key and value
		// are specified, set or extend (existing objects) with either:
		//
		//   1. An object of properties
		//   2. A key and value
		//
		this.set( owner, key, value );

		// Since the "set" path can have two possible entry points
		// return the expected data based on which path was taken[*]
		return value !== undefined ? value : key;
	},
	remove: function( owner, key ) {
		var i,
			cache = owner[ this.expando ];

		if ( cache === undefined ) {
			return;
		}

		if ( key !== undefined ) {

			// Support array or space separated string of keys
			if ( Array.isArray( key ) ) {

				// If key is an array of keys...
				// We always set camelCase keys, so remove that.
				key = key.map( camelCase );
			} else {
				key = camelCase( key );

				// If a key with the spaces exists, use it.
				// Otherwise, create an array by matching non-whitespace
				key = key in cache ?
					[ key ] :
					( key.match( rnothtmlwhite ) || [] );
			}

			i = key.length;

			while ( i-- ) {
				delete cache[ key[ i ] ];
			}
		}

		// Remove the expando if there's no more data
		if ( key === undefined || jQuery.isEmptyObject( cache ) ) {

			// Support: Chrome <=35 - 45
			// Webkit & Blink performance suffers when deleting properties
			// from DOM nodes, so set to undefined instead
			// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
			if ( owner.nodeType ) {
				owner[ this.expando ] = undefined;
			} else {
				delete owner[ this.expando ];
			}
		}
	},
	hasData: function( owner ) {
		var cache = owner[ this.expando ];
		return cache !== undefined && !jQuery.isEmptyObject( cache );
	}
};
var dataPriv = new Data();

var dataUser = new Data();



//	Implementation Summary
//
//	1. Enforce API surface and semantic compatibility with 1.9.x branch
//	2. Improve the module's maintainability by reducing the storage
//		paths to a single mechanism.
//	3. Use the same single mechanism to support "private" and "user" data.
//	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
//	5. Avoid exposing implementation details on user objects (eg. expando properties)
//	6. Provide a clear path for implementation upgrade to WeakMap in 2014

var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
	rmultiDash = /[A-Z]/g;

function getData( data ) {
	if ( data === "true" ) {
		return true;
	}

	if ( data === "false" ) {
		return false;
	}

	if ( data === "null" ) {
		return null;
	}

	// Only convert to a number if it doesn't change the string
	if ( data === +data + "" ) {
		return +data;
	}

	if ( rbrace.test( data ) ) {
		return JSON.parse( data );
	}

	return data;
}

function dataAttr( elem, key, data ) {
	var name;

	// If nothing was found internally, try to fetch any
	// data from the HTML5 data-* attribute
	if ( data === undefined && elem.nodeType === 1 ) {
		name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
		data = elem.getAttribute( name );

		if ( typeof data === "string" ) {
			try {
				data = getData( data );
			} catch ( e ) {}

			// Make sure we set the data so it isn't changed later
			dataUser.set( elem, key, data );
		} else {
			data = undefined;
		}
	}
	return data;
}

jQuery.extend( {
	hasData: function( elem ) {
		return dataUser.hasData( elem ) || dataPriv.hasData( elem );
	},

	data: function( elem, name, data ) {
		return dataUser.access( elem, name, data );
	},

	removeData: function( elem, name ) {
		dataUser.remove( elem, name );
	},

	// TODO: Now that all calls to _data and _removeData have been replaced
	// with direct calls to dataPriv methods, these can be deprecated.
	_data: function( elem, name, data ) {
		return dataPriv.access( elem, name, data );
	},

	_removeData: function( elem, name ) {
		dataPriv.remove( elem, name );
	}
} );

jQuery.fn.extend( {
	data: function( key, value ) {
		var i, name, data,
			elem = this[ 0 ],
			attrs = elem && elem.attributes;

		// Gets all values
		if ( key === undefined ) {
			if ( this.length ) {
				data = dataUser.get( elem );

				if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
					i = attrs.length;
					while ( i-- ) {

						// Support: IE 11 only
						// The attrs elements can be null (trac-14894)
						if ( attrs[ i ] ) {
							name = attrs[ i ].name;
							if ( name.indexOf( "data-" ) === 0 ) {
								name = camelCase( name.slice( 5 ) );
								dataAttr( elem, name, data[ name ] );
							}
						}
					}
					dataPriv.set( elem, "hasDataAttrs", true );
				}
			}

			return data;
		}

		// Sets multiple values
		if ( typeof key === "object" ) {
			return this.each( function() {
				dataUser.set( this, key );
			} );
		}

		return access( this, function( value ) {
			var data;

			// The calling jQuery object (element matches) is not empty
			// (and therefore has an element appears at this[ 0 ]) and the
			// `value` parameter was not undefined. An empty jQuery object
			// will result in `undefined` for elem = this[ 0 ] which will
			// throw an exception if an attempt to read a data cache is made.
			if ( elem && value === undefined ) {

				// Attempt to get data from the cache
				// The key will always be camelCased in Data
				data = dataUser.get( elem, key );
				if ( data !== undefined ) {
					return data;
				}

				// Attempt to "discover" the data in
				// HTML5 custom data-* attrs
				data = dataAttr( elem, key );
				if ( data !== undefined ) {
					return data;
				}

				// We tried really hard, but the data doesn't exist.
				return;
			}

			// Set the data...
			this.each( function() {

				// We always store the camelCased key
				dataUser.set( this, key, value );
			} );
		}, null, value, arguments.length > 1, null, true );
	},

	removeData: function( key ) {
		return this.each( function() {
			dataUser.remove( this, key );
		} );
	}
} );


jQuery.extend( {
	queue: function( elem, type, data ) {
		var queue;

		if ( elem ) {
			type = ( type || "fx" ) + "queue";
			queue = dataPriv.get( elem, type );

			// Speed up dequeue by getting out quickly if this is just a lookup
			if ( data ) {
				if ( !queue || Array.isArray( data ) ) {
					queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
				} else {
					queue.push( data );
				}
			}
			return queue || [];
		}
	},

	dequeue: function( elem, type ) {
		type = type || "fx";

		var queue = jQuery.queue( elem, type ),
			startLength = queue.length,
			fn = queue.shift(),
			hooks = jQuery._queueHooks( elem, type ),
			next = function() {
				jQuery.dequeue( elem, type );
			};

		// If the fx queue is dequeued, always remove the progress sentinel
		if ( fn === "inprogress" ) {
			fn = queue.shift();
			startLength--;
		}

		if ( fn ) {

			// Add a progress sentinel to prevent the fx queue from being
			// automatically dequeued
			if ( type === "fx" ) {
				queue.unshift( "inprogress" );
			}

			// Clear up the last queue stop function
			delete hooks.stop;
			fn.call( elem, next, hooks );
		}

		if ( !startLength && hooks ) {
			hooks.empty.fire();
		}
	},

	// Not public - generate a queueHooks object, or return the current one
	_queueHooks: function( elem, type ) {
		var key = type + "queueHooks";
		return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
			empty: jQuery.Callbacks( "once memory" ).add( function() {
				dataPriv.remove( elem, [ type + "queue", key ] );
			} )
		} );
	}
} );

jQuery.fn.extend( {
	queue: function( type, data ) {
		var setter = 2;

		if ( typeof type !== "string" ) {
			data = type;
			type = "fx";
			setter--;
		}

		if ( arguments.length < setter ) {
			return jQuery.queue( this[ 0 ], type );
		}

		return data === undefined ?
			this :
			this.each( function() {
				var queue = jQuery.queue( this, type, data );

				// Ensure a hooks for this queue
				jQuery._queueHooks( this, type );

				if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
					jQuery.dequeue( this, type );
				}
			} );
	},
	dequeue: function( type ) {
		return this.each( function() {
			jQuery.dequeue( this, type );
		} );
	},
	clearQueue: function( type ) {
		return this.queue( type || "fx", [] );
	},

	// Get a promise resolved when queues of a certain type
	// are emptied (fx is the type by default)
	promise: function( type, obj ) {
		var tmp,
			count = 1,
			defer = jQuery.Deferred(),
			elements = this,
			i = this.length,
			resolve = function() {
				if ( !( --count ) ) {
					defer.resolveWith( elements, [ elements ] );
				}
			};

		if ( typeof type !== "string" ) {
			obj = type;
			type = undefined;
		}
		type = type || "fx";

		while ( i-- ) {
			tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
			if ( tmp && tmp.empty ) {
				count++;
				tmp.empty.add( resolve );
			}
		}
		resolve();
		return defer.promise( obj );
	}
} );
var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;

var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );


var cssExpand = [ "Top", "Right", "Bottom", "Left" ];

var documentElement = document.documentElement;



	var isAttached = function( elem ) {
			return jQuery.contains( elem.ownerDocument, elem );
		},
		composed = { composed: true };

	// Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only
	// Check attachment across shadow DOM boundaries when possible (gh-3504)
	// Support: iOS 10.0-10.2 only
	// Early iOS 10 versions support `attachShadow` but not `getRootNode`,
	// leading to errors. We need to check for `getRootNode`.
	if ( documentElement.getRootNode ) {
		isAttached = function( elem ) {
			return jQuery.contains( elem.ownerDocument, elem ) ||
				elem.getRootNode( composed ) === elem.ownerDocument;
		};
	}
var isHiddenWithinTree = function( elem, el ) {

		// isHiddenWithinTree might be called from jQuery#filter function;
		// in that case, element will be second argument
		elem = el || elem;

		// Inline style trumps all
		return elem.style.display === "none" ||
			elem.style.display === "" &&

			// Otherwise, check computed style
			// Support: Firefox <=43 - 45
			// Disconnected elements can have computed display: none, so first confirm that elem is
			// in the document.
			isAttached( elem ) &&

			jQuery.css( elem, "display" ) === "none";
	};



function adjustCSS( elem, prop, valueParts, tween ) {
	var adjusted, scale,
		maxIterations = 20,
		currentValue = tween ?
			function() {
				return tween.cur();
			} :
			function() {
				return jQuery.css( elem, prop, "" );
			},
		initial = currentValue(),
		unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),

		// Starting value computation is required for potential unit mismatches
		initialInUnit = elem.nodeType &&
			( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
			rcssNum.exec( jQuery.css( elem, prop ) );

	if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {

		// Support: Firefox <=54
		// Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)
		initial = initial / 2;

		// Trust units reported by jQuery.css
		unit = unit || initialInUnit[ 3 ];

		// Iteratively approximate from a nonzero starting point
		initialInUnit = +initial || 1;

		while ( maxIterations-- ) {

			// Evaluate and update our best guess (doubling guesses that zero out).
			// Finish if the scale equals or crosses 1 (making the old*new product non-positive).
			jQuery.style( elem, prop, initialInUnit + unit );
			if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) {
				maxIterations = 0;
			}
			initialInUnit = initialInUnit / scale;

		}

		initialInUnit = initialInUnit * 2;
		jQuery.style( elem, prop, initialInUnit + unit );

		// Make sure we update the tween properties later on
		valueParts = valueParts || [];
	}

	if ( valueParts ) {
		initialInUnit = +initialInUnit || +initial || 0;

		// Apply relative offset (+=/-=) if specified
		adjusted = valueParts[ 1 ] ?
			initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
			+valueParts[ 2 ];
		if ( tween ) {
			tween.unit = unit;
			tween.start = initialInUnit;
			tween.end = adjusted;
		}
	}
	return adjusted;
}


var defaultDisplayMap = {};

function getDefaultDisplay( elem ) {
	var temp,
		doc = elem.ownerDocument,
		nodeName = elem.nodeName,
		display = defaultDisplayMap[ nodeName ];

	if ( display ) {
		return display;
	}

	temp = doc.body.appendChild( doc.createElement( nodeName ) );
	display = jQuery.css( temp, "display" );

	temp.parentNode.removeChild( temp );

	if ( display === "none" ) {
		display = "block";
	}
	defaultDisplayMap[ nodeName ] = display;

	return display;
}

function showHide( elements, show ) {
	var display, elem,
		values = [],
		index = 0,
		length = elements.length;

	// Determine new display value for elements that need to change
	for ( ; index < length; index++ ) {
		elem = elements[ index ];
		if ( !elem.style ) {
			continue;
		}

		display = elem.style.display;
		if ( show ) {

			// Since we force visibility upon cascade-hidden elements, an immediate (and slow)
			// check is required in this first loop unless we have a nonempty display value (either
			// inline or about-to-be-restored)
			if ( display === "none" ) {
				values[ index ] = dataPriv.get( elem, "display" ) || null;
				if ( !values[ index ] ) {
					elem.style.display = "";
				}
			}
			if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
				values[ index ] = getDefaultDisplay( elem );
			}
		} else {
			if ( display !== "none" ) {
				values[ index ] = "none";

				// Remember what we're overwriting
				dataPriv.set( elem, "display", display );
			}
		}
	}

	// Set the display of the elements in a second loop to avoid constant reflow
	for ( index = 0; index < length; index++ ) {
		if ( values[ index ] != null ) {
			elements[ index ].style.display = values[ index ];
		}
	}

	return elements;
}

jQuery.fn.extend( {
	show: function() {
		return showHide( this, true );
	},
	hide: function() {
		return showHide( this );
	},
	toggle: function( state ) {
		if ( typeof state === "boolean" ) {
			return state ? this.show() : this.hide();
		}

		return this.each( function() {
			if ( isHiddenWithinTree( this ) ) {
				jQuery( this ).show();
			} else {
				jQuery( this ).hide();
			}
		} );
	}
} );
var rcheckableType = ( /^(?:checkbox|radio)$/i );

var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i );

var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i );



( function() {
	var fragment = document.createDocumentFragment(),
		div = fragment.appendChild( document.createElement( "div" ) ),
		input = document.createElement( "input" );

	// Support: Android 4.0 - 4.3 only
	// Check state lost if the name is set (trac-11217)
	// Support: Windows Web Apps (WWA)
	// `name` and `type` must use .setAttribute for WWA (trac-14901)
	input.setAttribute( "type", "radio" );
	input.setAttribute( "checked", "checked" );
	input.setAttribute( "name", "t" );

	div.appendChild( input );

	// Support: Android <=4.1 only
	// Older WebKit doesn't clone checked state correctly in fragments
	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;

	// Support: IE <=11 only
	// Make sure textarea (and checkbox) defaultValue is properly cloned
	div.innerHTML = "<textarea>x</textarea>";
	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;

	// Support: IE <=9 only
	// IE <=9 replaces <option> tags with their contents when inserted outside of
	// the select element.
	div.innerHTML = "<option></option>";
	support.option = !!div.lastChild;
} )();


// We have to close these tags to support XHTML (trac-13200)
var wrapMap = {

	// XHTML parsers do not magically insert elements in the
	// same way that tag soup parsers do. So we cannot shorten
	// this by omitting <tbody> or other required elements.
	thead: [ 1, "<table>", "</table>" ],
	col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
	tr: [ 2, "<table><tbody>", "</tbody></table>" ],
	td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],

	_default: [ 0, "", "" ]
};

wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
wrapMap.th = wrapMap.td;

// Support: IE <=9 only
if ( !support.option ) {
	wrapMap.optgroup = wrapMap.option = [ 1, "<select multiple='multiple'>", "</select>" ];
}


function getAll( context, tag ) {

	// Support: IE <=9 - 11 only
	// Use typeof to avoid zero-argument method invocation on host objects (trac-15151)
	var ret;

	if ( typeof context.getElementsByTagName !== "undefined" ) {
		ret = context.getElementsByTagName( tag || "*" );

	} else if ( typeof context.querySelectorAll !== "undefined" ) {
		ret = context.querySelectorAll( tag || "*" );

	} else {
		ret = [];
	}

	if ( tag === undefined || tag && nodeName( context, tag ) ) {
		return jQuery.merge( [ context ], ret );
	}

	return ret;
}


// Mark scripts as having already been evaluated
function setGlobalEval( elems, refElements ) {
	var i = 0,
		l = elems.length;

	for ( ; i < l; i++ ) {
		dataPriv.set(
			elems[ i ],
			"globalEval",
			!refElements || dataPriv.get( refElements[ i ], "globalEval" )
		);
	}
}


var rhtml = /<|&#?\w+;/;

function buildFragment( elems, context, scripts, selection, ignored ) {
	var elem, tmp, tag, wrap, attached, j,
		fragment = context.createDocumentFragment(),
		nodes = [],
		i = 0,
		l = elems.length;

	for ( ; i < l; i++ ) {
		elem = elems[ i ];

		if ( elem || elem === 0 ) {

			// Add nodes directly
			if ( toType( elem ) === "object" ) {

				// Support: Android <=4.0 only, PhantomJS 1 only
				// push.apply(_, arraylike) throws on ancient WebKit
				jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );

			// Convert non-html into a text node
			} else if ( !rhtml.test( elem ) ) {
				nodes.push( context.createTextNode( elem ) );

			// Convert html into DOM nodes
			} else {
				tmp = tmp || fragment.appendChild( context.createElement( "div" ) );

				// Deserialize a standard representation
				tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
				wrap = wrapMap[ tag ] || wrapMap._default;
				tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];

				// Descend through wrappers to the right content
				j = wrap[ 0 ];
				while ( j-- ) {
					tmp = tmp.lastChild;
				}

				// Support: Android <=4.0 only, PhantomJS 1 only
				// push.apply(_, arraylike) throws on ancient WebKit
				jQuery.merge( nodes, tmp.childNodes );

				// Remember the top-level container
				tmp = fragment.firstChild;

				// Ensure the created nodes are orphaned (trac-12392)
				tmp.textContent = "";
			}
		}
	}

	// Remove wrapper from fragment
	fragment.textContent = "";

	i = 0;
	while ( ( elem = nodes[ i++ ] ) ) {

		// Skip elements already in the context collection (trac-4087)
		if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
			if ( ignored ) {
				ignored.push( elem );
			}
			continue;
		}

		attached = isAttached( elem );

		// Append to fragment
		tmp = getAll( fragment.appendChild( elem ), "script" );

		// Preserve script evaluation history
		if ( attached ) {
			setGlobalEval( tmp );
		}

		// Capture executables
		if ( scripts ) {
			j = 0;
			while ( ( elem = tmp[ j++ ] ) ) {
				if ( rscriptType.test( elem.type || "" ) ) {
					scripts.push( elem );
				}
			}
		}
	}

	return fragment;
}


var rtypenamespace = /^([^.]*)(?:\.(.+)|)/;

function returnTrue() {
	return true;
}

function returnFalse() {
	return false;
}

function on( elem, types, selector, data, fn, one ) {
	var origFn, type;

	// Types can be a map of types/handlers
	if ( typeof types === "object" ) {

		// ( types-Object, selector, data )
		if ( typeof selector !== "string" ) {

			// ( types-Object, data )
			data = data || selector;
			selector = undefined;
		}
		for ( type in types ) {
			on( elem, type, selector, data, types[ type ], one );
		}
		return elem;
	}

	if ( data == null && fn == null ) {

		// ( types, fn )
		fn = selector;
		data = selector = undefined;
	} else if ( fn == null ) {
		if ( typeof selector === "string" ) {

			// ( types, selector, fn )
			fn = data;
			data = undefined;
		} else {

			// ( types, data, fn )
			fn = data;
			data = selector;
			selector = undefined;
		}
	}
	if ( fn === false ) {
		fn = returnFalse;
	} else if ( !fn ) {
		return elem;
	}

	if ( one === 1 ) {
		origFn = fn;
		fn = function( event ) {

			// Can use an empty set, since event contains the info
			jQuery().off( event );
			return origFn.apply( this, arguments );
		};

		// Use same guid so caller can remove using origFn
		fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
	}
	return elem.each( function() {
		jQuery.event.add( this, types, fn, data, selector );
	} );
}

/*
 * Helper functions for managing events -- not part of the public interface.
 * Props to Dean Edwards' addEvent library for many of the ideas.
 */
jQuery.event = {

	global: {},

	add: function( elem, types, handler, data, selector ) {

		var handleObjIn, eventHandle, tmp,
			events, t, handleObj,
			special, handlers, type, namespaces, origType,
			elemData = dataPriv.get( elem );

		// Only attach events to objects that accept data
		if ( !acceptData( elem ) ) {
			return;
		}

		// Caller can pass in an object of custom data in lieu of the handler
		if ( handler.handler ) {
			handleObjIn = handler;
			handler = handleObjIn.handler;
			selector = handleObjIn.selector;
		}

		// Ensure that invalid selectors throw exceptions at attach time
		// Evaluate against documentElement in case elem is a non-element node (e.g., document)
		if ( selector ) {
			jQuery.find.matchesSelector( documentElement, selector );
		}

		// Make sure that the handler has a unique ID, used to find/remove it later
		if ( !handler.guid ) {
			handler.guid = jQuery.guid++;
		}

		// Init the element's event structure and main handler, if this is the first
		if ( !( events = elemData.events ) ) {
			events = elemData.events = Object.create( null );
		}
		if ( !( eventHandle = elemData.handle ) ) {
			eventHandle = elemData.handle = function( e ) {

				// Discard the second event of a jQuery.event.trigger() and
				// when an event is called after a page has unloaded
				return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
					jQuery.event.dispatch.apply( elem, arguments ) : undefined;
			};
		}

		// Handle multiple events separated by a space
		types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
		t = types.length;
		while ( t-- ) {
			tmp = rtypenamespace.exec( types[ t ] ) || [];
			type = origType = tmp[ 1 ];
			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();

			// There *must* be a type, no attaching namespace-only handlers
			if ( !type ) {
				continue;
			}

			// If event changes its type, use the special event handlers for the changed type
			special = jQuery.event.special[ type ] || {};

			// If selector defined, determine special event api type, otherwise given type
			type = ( selector ? special.delegateType : special.bindType ) || type;

			// Update special based on newly reset type
			special = jQuery.event.special[ type ] || {};

			// handleObj is passed to all event handlers
			handleObj = jQuery.extend( {
				type: type,
				origType: origType,
				data: data,
				handler: handler,
				guid: handler.guid,
				selector: selector,
				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
				namespace: namespaces.join( "." )
			}, handleObjIn );

			// Init the event handler queue if we're the first
			if ( !( handlers = events[ type ] ) ) {
				handlers = events[ type ] = [];
				handlers.delegateCount = 0;

				// Only use addEventListener if the special events handler returns false
				if ( !special.setup ||
					special.setup.call( elem, data, namespaces, eventHandle ) === false ) {

					if ( elem.addEventListener ) {
						elem.addEventListener( type, eventHandle );
					}
				}
			}

			if ( special.add ) {
				special.add.call( elem, handleObj );

				if ( !handleObj.handler.guid ) {
					handleObj.handler.guid = handler.guid;
				}
			}

			// Add to the element's handler list, delegates in front
			if ( selector ) {
				handlers.splice( handlers.delegateCount++, 0, handleObj );
			} else {
				handlers.push( handleObj );
			}

			// Keep track of which events have ever been used, for event optimization
			jQuery.event.global[ type ] = true;
		}

	},

	// Detach an event or set of events from an element
	remove: function( elem, types, handler, selector, mappedTypes ) {

		var j, origCount, tmp,
			events, t, handleObj,
			special, handlers, type, namespaces, origType,
			elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );

		if ( !elemData || !( events = elemData.events ) ) {
			return;
		}

		// Once for each type.namespace in types; type may be omitted
		types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
		t = types.length;
		while ( t-- ) {
			tmp = rtypenamespace.exec( types[ t ] ) || [];
			type = origType = tmp[ 1 ];
			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();

			// Unbind all events (on this namespace, if provided) for the element
			if ( !type ) {
				for ( type in events ) {
					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
				}
				continue;
			}

			special = jQuery.event.special[ type ] || {};
			type = ( selector ? special.delegateType : special.bindType ) || type;
			handlers = events[ type ] || [];
			tmp = tmp[ 2 ] &&
				new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );

			// Remove matching events
			origCount = j = handlers.length;
			while ( j-- ) {
				handleObj = handlers[ j ];

				if ( ( mappedTypes || origType === handleObj.origType ) &&
					( !handler || handler.guid === handleObj.guid ) &&
					( !tmp || tmp.test( handleObj.namespace ) ) &&
					( !selector || selector === handleObj.selector ||
						selector === "**" && handleObj.selector ) ) {
					handlers.splice( j, 1 );

					if ( handleObj.selector ) {
						handlers.delegateCount--;
					}
					if ( special.remove ) {
						special.remove.call( elem, handleObj );
					}
				}
			}

			// Remove generic event handler if we removed something and no more handlers exist
			// (avoids potential for endless recursion during removal of special event handlers)
			if ( origCount && !handlers.length ) {
				if ( !special.teardown ||
					special.teardown.call( elem, namespaces, elemData.handle ) === false ) {

					jQuery.removeEvent( elem, type, elemData.handle );
				}

				delete events[ type ];
			}
		}

		// Remove data and the expando if it's no longer used
		if ( jQuery.isEmptyObject( events ) ) {
			dataPriv.remove( elem, "handle events" );
		}
	},

	dispatch: function( nativeEvent ) {

		var i, j, ret, matched, handleObj, handlerQueue,
			args = new Array( arguments.length ),

			// Make a writable jQuery.Event from the native event object
			event = jQuery.event.fix( nativeEvent ),

			handlers = (
				dataPriv.get( this, "events" ) || Object.create( null )
			)[ event.type ] || [],
			special = jQuery.event.special[ event.type ] || {};

		// Use the fix-ed jQuery.Event rather than the (read-only) native event
		args[ 0 ] = event;

		for ( i = 1; i < arguments.length; i++ ) {
			args[ i ] = arguments[ i ];
		}

		event.delegateTarget = this;

		// Call the preDispatch hook for the mapped type, and let it bail if desired
		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
			return;
		}

		// Determine handlers
		handlerQueue = jQuery.event.handlers.call( this, event, handlers );

		// Run delegates first; they may want to stop propagation beneath us
		i = 0;
		while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
			event.currentTarget = matched.elem;

			j = 0;
			while ( ( handleObj = matched.handlers[ j++ ] ) &&
				!event.isImmediatePropagationStopped() ) {

				// If the event is namespaced, then each handler is only invoked if it is
				// specially universal or its namespaces are a superset of the event's.
				if ( !event.rnamespace || handleObj.namespace === false ||
					event.rnamespace.test( handleObj.namespace ) ) {

					event.handleObj = handleObj;
					event.data = handleObj.data;

					ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
						handleObj.handler ).apply( matched.elem, args );

					if ( ret !== undefined ) {
						if ( ( event.result = ret ) === false ) {
							event.preventDefault();
							event.stopPropagation();
						}
					}
				}
			}
		}

		// Call the postDispatch hook for the mapped type
		if ( special.postDispatch ) {
			special.postDispatch.call( this, event );
		}

		return event.result;
	},

	handlers: function( event, handlers ) {
		var i, handleObj, sel, matchedHandlers, matchedSelectors,
			handlerQueue = [],
			delegateCount = handlers.delegateCount,
			cur = event.target;

		// Find delegate handlers
		if ( delegateCount &&

			// Support: IE <=9
			// Black-hole SVG <use> instance trees (trac-13180)
			cur.nodeType &&

			// Support: Firefox <=42
			// Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
			// https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
			// Support: IE 11 only
			// ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
			!( event.type === "click" && event.button >= 1 ) ) {

			for ( ; cur !== this; cur = cur.parentNode || this ) {

				// Don't check non-elements (trac-13208)
				// Don't process clicks on disabled elements (trac-6911, trac-8165, trac-11382, trac-11764)
				if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
					matchedHandlers = [];
					matchedSelectors = {};
					for ( i = 0; i < delegateCount; i++ ) {
						handleObj = handlers[ i ];

						// Don't conflict with Object.prototype properties (trac-13203)
						sel = handleObj.selector + " ";

						if ( matchedSelectors[ sel ] === undefined ) {
							matchedSelectors[ sel ] = handleObj.needsContext ?
								jQuery( sel, this ).index( cur ) > -1 :
								jQuery.find( sel, this, null, [ cur ] ).length;
						}
						if ( matchedSelectors[ sel ] ) {
							matchedHandlers.push( handleObj );
						}
					}
					if ( matchedHandlers.length ) {
						handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
					}
				}
			}
		}

		// Add the remaining (directly-bound) handlers
		cur = this;
		if ( delegateCount < handlers.length ) {
			handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
		}

		return handlerQueue;
	},

	addProp: function( name, hook ) {
		Object.defineProperty( jQuery.Event.prototype, name, {
			enumerable: true,
			configurable: true,

			get: isFunction( hook ) ?
				function() {
					if ( this.originalEvent ) {
						return hook( this.originalEvent );
					}
				} :
				function() {
					if ( this.originalEvent ) {
						return this.originalEvent[ name ];
					}
				},

			set: function( value ) {
				Object.defineProperty( this, name, {
					enumerable: true,
					configurable: true,
					writable: true,
					value: value
				} );
			}
		} );
	},

	fix: function( originalEvent ) {
		return originalEvent[ jQuery.expando ] ?
			originalEvent :
			new jQuery.Event( originalEvent );
	},

	special: {
		load: {

			// Prevent triggered image.load events from bubbling to window.load
			noBubble: true
		},
		click: {

			// Utilize native event to ensure correct state for checkable inputs
			setup: function( data ) {

				// For mutual compressibility with _default, replace `this` access with a local var.
				// `|| data` is dead code meant only to preserve the variable through minification.
				var el = this || data;

				// Claim the first handler
				if ( rcheckableType.test( el.type ) &&
					el.click && nodeName( el, "input" ) ) {

					// dataPriv.set( el, "click", ... )
					leverageNative( el, "click", true );
				}

				// Return false to allow normal processing in the caller
				return false;
			},
			trigger: function( data ) {

				// For mutual compressibility with _default, replace `this` access with a local var.
				// `|| data` is dead code meant only to preserve the variable through minification.
				var el = this || data;

				// Force setup before triggering a click
				if ( rcheckableType.test( el.type ) &&
					el.click && nodeName( el, "input" ) ) {

					leverageNative( el, "click" );
				}

				// Return non-false to allow normal event-path propagation
				return true;
			},

			// For cross-browser consistency, suppress native .click() on links
			// Also prevent it if we're currently inside a leveraged native-event stack
			_default: function( event ) {
				var target = event.target;
				return rcheckableType.test( target.type ) &&
					target.click && nodeName( target, "input" ) &&
					dataPriv.get( target, "click" ) ||
					nodeName( target, "a" );
			}
		},

		beforeunload: {
			postDispatch: function( event ) {

				// Support: Firefox 20+
				// Firefox doesn't alert if the returnValue field is not set.
				if ( event.result !== undefined && event.originalEvent ) {
					event.originalEvent.returnValue = event.result;
				}
			}
		}
	}
};

// Ensure the presence of an event listener that handles manually-triggered
// synthetic events by interrupting progress until reinvoked in response to
// *native* events that it fires directly, ensuring that state changes have
// already occurred before other listeners are invoked.
function leverageNative( el, type, isSetup ) {

	// Missing `isSetup` indicates a trigger call, which must force setup through jQuery.event.add
	if ( !isSetup ) {
		if ( dataPriv.get( el, type ) === undefined ) {
			jQuery.event.add( el, type, returnTrue );
		}
		return;
	}

	// Register the controller as a special universal handler for all event namespaces
	dataPriv.set( el, type, false );
	jQuery.event.add( el, type, {
		namespace: false,
		handler: function( event ) {
			var result,
				saved = dataPriv.get( this, type );

			if ( ( event.isTrigger & 1 ) && this[ type ] ) {

				// Interrupt processing of the outer synthetic .trigger()ed event
				if ( !saved ) {

					// Store arguments for use when handling the inner native event
					// There will always be at least one argument (an event object), so this array
					// will not be confused with a leftover capture object.
					saved = slice.call( arguments );
					dataPriv.set( this, type, saved );

					// Trigger the native event and capture its result
					this[ type ]();
					result = dataPriv.get( this, type );
					dataPriv.set( this, type, false );

					if ( saved !== result ) {

						// Cancel the outer synthetic event
						event.stopImmediatePropagation();
						event.preventDefault();

						return result;
					}

				// If this is an inner synthetic event for an event with a bubbling surrogate
				// (focus or blur), assume that the surrogate already propagated from triggering
				// the native event and prevent that from happening again here.
				// This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the
				// bubbling surrogate propagates *after* the non-bubbling base), but that seems
				// less bad than duplication.
				} else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) {
					event.stopPropagation();
				}

			// If this is a native event triggered above, everything is now in order
			// Fire an inner synthetic event with the original arguments
			} else if ( saved ) {

				// ...and capture the result
				dataPriv.set( this, type, jQuery.event.trigger(
					saved[ 0 ],
					saved.slice( 1 ),
					this
				) );

				// Abort handling of the native event by all jQuery handlers while allowing
				// native handlers on the same element to run. On target, this is achieved
				// by stopping immediate propagation just on the jQuery event. However,
				// the native event is re-wrapped by a jQuery one on each level of the
				// propagation so the only way to stop it for jQuery is to stop it for
				// everyone via native `stopPropagation()`. This is not a problem for
				// focus/blur which don't bubble, but it does also stop click on checkboxes
				// and radios. We accept this limitation.
				event.stopPropagation();
				event.isImmediatePropagationStopped = returnTrue;
			}
		}
	} );
}

jQuery.removeEvent = function( elem, type, handle ) {

	// This "if" is needed for plain objects
	if ( elem.removeEventListener ) {
		elem.removeEventListener( type, handle );
	}
};

jQuery.Event = function( src, props ) {

	// Allow instantiation without the 'new' keyword
	if ( !( this instanceof jQuery.Event ) ) {
		return new jQuery.Event( src, props );
	}

	// Event object
	if ( src && src.type ) {
		this.originalEvent = src;
		this.type = src.type;

		// Events bubbling up the document may have been marked as prevented
		// by a handler lower down the tree; reflect the correct value.
		this.isDefaultPrevented = src.defaultPrevented ||
				src.defaultPrevented === undefined &&

				// Support: Android <=2.3 only
				src.returnValue === false ?
			returnTrue :
			returnFalse;

		// Create target properties
		// Support: Safari <=6 - 7 only
		// Target should not be a text node (trac-504, trac-13143)
		this.target = ( src.target && src.target.nodeType === 3 ) ?
			src.target.parentNode :
			src.target;

		this.currentTarget = src.currentTarget;
		this.relatedTarget = src.relatedTarget;

	// Event type
	} else {
		this.type = src;
	}

	// Put explicitly provided properties onto the event object
	if ( props ) {
		jQuery.extend( this, props );
	}

	// Create a timestamp if incoming event doesn't have one
	this.timeStamp = src && src.timeStamp || Date.now();

	// Mark it as fixed
	this[ jQuery.expando ] = true;
};

// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
jQuery.Event.prototype = {
	constructor: jQuery.Event,
	isDefaultPrevented: returnFalse,
	isPropagationStopped: returnFalse,
	isImmediatePropagationStopped: returnFalse,
	isSimulated: false,

	preventDefault: function() {
		var e = this.originalEvent;

		this.isDefaultPrevented = returnTrue;

		if ( e && !this.isSimulated ) {
			e.preventDefault();
		}
	},
	stopPropagation: function() {
		var e = this.originalEvent;

		this.isPropagationStopped = returnTrue;

		if ( e && !this.isSimulated ) {
			e.stopPropagation();
		}
	},
	stopImmediatePropagation: function() {
		var e = this.originalEvent;

		this.isImmediatePropagationStopped = returnTrue;

		if ( e && !this.isSimulated ) {
			e.stopImmediatePropagation();
		}

		this.stopPropagation();
	}
};

// Includes all common event props including KeyEvent and MouseEvent specific props
jQuery.each( {
	altKey: true,
	bubbles: true,
	cancelable: true,
	changedTouches: true,
	ctrlKey: true,
	detail: true,
	eventPhase: true,
	metaKey: true,
	pageX: true,
	pageY: true,
	shiftKey: true,
	view: true,
	"char": true,
	code: true,
	charCode: true,
	key: true,
	keyCode: true,
	button: true,
	buttons: true,
	clientX: true,
	clientY: true,
	offsetX: true,
	offsetY: true,
	pointerId: true,
	pointerType: true,
	screenX: true,
	screenY: true,
	targetTouches: true,
	toElement: true,
	touches: true,
	which: true
}, jQuery.event.addProp );

jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) {

	function focusMappedHandler( nativeEvent ) {
		if ( document.documentMode ) {

			// Support: IE 11+
			// Attach a single focusin/focusout handler on the document while someone wants
			// focus/blur. This is because the former are synchronous in IE while the latter
			// are async. In other browsers, all those handlers are invoked synchronously.

			// `handle` from private data would already wrap the event, but we need
			// to change the `type` here.
			var handle = dataPriv.get( this, "handle" ),
				event = jQuery.event.fix( nativeEvent );
			event.type = nativeEvent.type === "focusin" ? "focus" : "blur";
			event.isSimulated = true;

			// First, handle focusin/focusout
			handle( nativeEvent );

			// ...then, handle focus/blur
			//
			// focus/blur don't bubble while focusin/focusout do; simulate the former by only
			// invoking the handler at the lower level.
			if ( event.target === event.currentTarget ) {

				// The setup part calls `leverageNative`, which, in turn, calls
				// `jQuery.event.add`, so event handle will already have been set
				// by this point.
				handle( event );
			}
		} else {

			// For non-IE browsers, attach a single capturing handler on the document
			// while someone wants focusin/focusout.
			jQuery.event.simulate( delegateType, nativeEvent.target,
				jQuery.event.fix( nativeEvent ) );
		}
	}

	jQuery.event.special[ type ] = {

		// Utilize native event if possible so blur/focus sequence is correct
		setup: function() {

			var attaches;

			// Claim the first handler
			// dataPriv.set( this, "focus", ... )
			// dataPriv.set( this, "blur", ... )
			leverageNative( this, type, true );

			if ( document.documentMode ) {

				// Support: IE 9 - 11+
				// We use the same native handler for focusin & focus (and focusout & blur)
				// so we need to coordinate setup & teardown parts between those events.
				// Use `delegateType` as the key as `type` is already used by `leverageNative`.
				attaches = dataPriv.get( this, delegateType );
				if ( !attaches ) {
					this.addEventListener( delegateType, focusMappedHandler );
				}
				dataPriv.set( this, delegateType, ( attaches || 0 ) + 1 );
			} else {

				// Return false to allow normal processing in the caller
				return false;
			}
		},
		trigger: function() {

			// Force setup before trigger
			leverageNative( this, type );

			// Return non-false to allow normal event-path propagation
			return true;
		},

		teardown: function() {
			var attaches;

			if ( document.documentMode ) {
				attaches = dataPriv.get( this, delegateType ) - 1;
				if ( !attaches ) {
					this.removeEventListener( delegateType, focusMappedHandler );
					dataPriv.remove( this, delegateType );
				} else {
					dataPriv.set( this, delegateType, attaches );
				}
			} else {

				// Return false to indicate standard teardown should be applied
				return false;
			}
		},

		// Suppress native focus or blur if we're currently inside
		// a leveraged native-event stack
		_default: function( event ) {
			return dataPriv.get( event.target, type );
		},

		delegateType: delegateType
	};

	// Support: Firefox <=44
	// Firefox doesn't have focus(in | out) events
	// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
	//
	// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1
	// focus(in | out) events fire after focus & blur events,
	// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
	// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857
	//
	// Support: IE 9 - 11+
	// To preserve relative focusin/focus & focusout/blur event order guaranteed on the 3.x branch,
	// attach a single handler for both events in IE.
	jQuery.event.special[ delegateType ] = {
		setup: function() {

			// Handle: regular nodes (via `this.ownerDocument`), window
			// (via `this.document`) & document (via `this`).
			var doc = this.ownerDocument || this.document || this,
				dataHolder = document.documentMode ? this : doc,
				attaches = dataPriv.get( dataHolder, delegateType );

			// Support: IE 9 - 11+
			// We use the same native handler for focusin & focus (and focusout & blur)
			// so we need to coordinate setup & teardown parts between those events.
			// Use `delegateType` as the key as `type` is already used by `leverageNative`.
			if ( !attaches ) {
				if ( document.documentMode ) {
					this.addEventListener( delegateType, focusMappedHandler );
				} else {
					doc.addEventListener( type, focusMappedHandler, true );
				}
			}
			dataPriv.set( dataHolder, delegateType, ( attaches || 0 ) + 1 );
		},
		teardown: function() {
			var doc = this.ownerDocument || this.document || this,
				dataHolder = document.documentMode ? this : doc,
				attaches = dataPriv.get( dataHolder, delegateType ) - 1;

			if ( !attaches ) {
				if ( document.documentMode ) {
					this.removeEventListener( delegateType, focusMappedHandler );
				} else {
					doc.removeEventListener( type, focusMappedHandler, true );
				}
				dataPriv.remove( dataHolder, delegateType );
			} else {
				dataPriv.set( dataHolder, delegateType, attaches );
			}
		}
	};
} );

// Create mouseenter/leave events using mouseover/out and event-time checks
// so that event delegation works in jQuery.
// Do the same for pointerenter/pointerleave and pointerover/pointerout
//
// Support: Safari 7 only
// Safari sends mouseenter too often; see:
// https://bugs.chromium.org/p/chromium/issues/detail?id=470258
// for the description of the bug (it existed in older Chrome versions as well).
jQuery.each( {
	mouseenter: "mouseover",
	mouseleave: "mouseout",
	pointerenter: "pointerover",
	pointerleave: "pointerout"
}, function( orig, fix ) {
	jQuery.event.special[ orig ] = {
		delegateType: fix,
		bindType: fix,

		handle: function( event ) {
			var ret,
				target = this,
				related = event.relatedTarget,
				handleObj = event.handleObj;

			// For mouseenter/leave call the handler if related is outside the target.
			// NB: No relatedTarget if the mouse left/entered the browser window
			if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
				event.type = handleObj.origType;
				ret = handleObj.handler.apply( this, arguments );
				event.type = fix;
			}
			return ret;
		}
	};
} );

jQuery.fn.extend( {

	on: function( types, selector, data, fn ) {
		return on( this, types, selector, data, fn );
	},
	one: function( types, selector, data, fn ) {
		return on( this, types, selector, data, fn, 1 );
	},
	off: function( types, selector, fn ) {
		var handleObj, type;
		if ( types && types.preventDefault && types.handleObj ) {

			// ( event )  dispatched jQuery.Event
			handleObj = types.handleObj;
			jQuery( types.delegateTarget ).off(
				handleObj.namespace ?
					handleObj.origType + "." + handleObj.namespace :
					handleObj.origType,
				handleObj.selector,
				handleObj.handler
			);
			return this;
		}
		if ( typeof types === "object" ) {

			// ( types-object [, selector] )
			for ( type in types ) {
				this.off( type, selector, types[ type ] );
			}
			return this;
		}
		if ( selector === false || typeof selector === "function" ) {

			// ( types [, fn] )
			fn = selector;
			selector = undefined;
		}
		if ( fn === false ) {
			fn = returnFalse;
		}
		return this.each( function() {
			jQuery.event.remove( this, types, fn, selector );
		} );
	}
} );


var

	// Support: IE <=10 - 11, Edge 12 - 13 only
	// In IE/Edge using regex groups here causes severe slowdowns.
	// See https://connect.microsoft.com/IE/feedback/details/1736512/
	rnoInnerhtml = /<script|<style|<link/i,

	// checked="checked" or checked
	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,

	rcleanScript = /^\s*<!\[CDATA\[|\]\]>\s*$/g;

// Prefer a tbody over its parent table for containing new rows
function manipulationTarget( elem, content ) {
	if ( nodeName( elem, "table" ) &&
		nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {

		return jQuery( elem ).children( "tbody" )[ 0 ] || elem;
	}

	return elem;
}

// Replace/restore the type attribute of script elements for safe DOM manipulation
function disableScript( elem ) {
	elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
	return elem;
}
function restoreScript( elem ) {
	if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) {
		elem.type = elem.type.slice( 5 );
	} else {
		elem.removeAttribute( "type" );
	}

	return elem;
}

function cloneCopyEvent( src, dest ) {
	var i, l, type, pdataOld, udataOld, udataCur, events;

	if ( dest.nodeType !== 1 ) {
		return;
	}

	// 1. Copy private data: events, handlers, etc.
	if ( dataPriv.hasData( src ) ) {
		pdataOld = dataPriv.get( src );
		events = pdataOld.events;

		if ( events ) {
			dataPriv.remove( dest, "handle events" );

			for ( type in events ) {
				for ( i = 0, l = events[ type ].length; i < l; i++ ) {
					jQuery.event.add( dest, type, events[ type ][ i ] );
				}
			}
		}
	}

	// 2. Copy user data
	if ( dataUser.hasData( src ) ) {
		udataOld = dataUser.access( src );
		udataCur = jQuery.extend( {}, udataOld );

		dataUser.set( dest, udataCur );
	}
}

// Fix IE bugs, see support tests
function fixInput( src, dest ) {
	var nodeName = dest.nodeName.toLowerCase();

	// Fails to persist the checked state of a cloned checkbox or radio button.
	if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
		dest.checked = src.checked;

	// Fails to return the selected option to the default selected state when cloning options
	} else if ( nodeName === "input" || nodeName === "textarea" ) {
		dest.defaultValue = src.defaultValue;
	}
}

function domManip( collection, args, callback, ignored ) {

	// Flatten any nested arrays
	args = flat( args );

	var fragment, first, scripts, hasScripts, node, doc,
		i = 0,
		l = collection.length,
		iNoClone = l - 1,
		value = args[ 0 ],
		valueIsFunction = isFunction( value );

	// We can't cloneNode fragments that contain checked, in WebKit
	if ( valueIsFunction ||
			( l > 1 && typeof value === "string" &&
				!support.checkClone && rchecked.test( value ) ) ) {
		return collection.each( function( index ) {
			var self = collection.eq( index );
			if ( valueIsFunction ) {
				args[ 0 ] = value.call( this, index, self.html() );
			}
			domManip( self, args, callback, ignored );
		} );
	}

	if ( l ) {
		fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
		first = fragment.firstChild;

		if ( fragment.childNodes.length === 1 ) {
			fragment = first;
		}

		// Require either new content or an interest in ignored elements to invoke the callback
		if ( first || ignored ) {
			scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
			hasScripts = scripts.length;

			// Use the original fragment for the last item
			// instead of the first because it can end up
			// being emptied incorrectly in certain situations (trac-8070).
			for ( ; i < l; i++ ) {
				node = fragment;

				if ( i !== iNoClone ) {
					node = jQuery.clone( node, true, true );

					// Keep references to cloned scripts for later restoration
					if ( hasScripts ) {

						// Support: Android <=4.0 only, PhantomJS 1 only
						// push.apply(_, arraylike) throws on ancient WebKit
						jQuery.merge( scripts, getAll( node, "script" ) );
					}
				}

				callback.call( collection[ i ], node, i );
			}

			if ( hasScripts ) {
				doc = scripts[ scripts.length - 1 ].ownerDocument;

				// Re-enable scripts
				jQuery.map( scripts, restoreScript );

				// Evaluate executable scripts on first document insertion
				for ( i = 0; i < hasScripts; i++ ) {
					node = scripts[ i ];
					if ( rscriptType.test( node.type || "" ) &&
						!dataPriv.access( node, "globalEval" ) &&
						jQuery.contains( doc, node ) ) {

						if ( node.src && ( node.type || "" ).toLowerCase()  !== "module" ) {

							// Optional AJAX dependency, but won't run scripts if not present
							if ( jQuery._evalUrl && !node.noModule ) {
								jQuery._evalUrl( node.src, {
									nonce: node.nonce || node.getAttribute( "nonce" )
								}, doc );
							}
						} else {

							// Unwrap a CDATA section containing script contents. This shouldn't be
							// needed as in XML documents they're already not visible when
							// inspecting element contents and in HTML documents they have no
							// meaning but we're preserving that logic for backwards compatibility.
							// This will be removed completely in 4.0. See gh-4904.
							DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc );
						}
					}
				}
			}
		}
	}

	return collection;
}

function remove( elem, selector, keepData ) {
	var node,
		nodes = selector ? jQuery.filter( selector, elem ) : elem,
		i = 0;

	for ( ; ( node = nodes[ i ] ) != null; i++ ) {
		if ( !keepData && node.nodeType === 1 ) {
			jQuery.cleanData( getAll( node ) );
		}

		if ( node.parentNode ) {
			if ( keepData && isAttached( node ) ) {
				setGlobalEval( getAll( node, "script" ) );
			}
			node.parentNode.removeChild( node );
		}
	}

	return elem;
}

jQuery.extend( {
	htmlPrefilter: function( html ) {
		return html;
	},

	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
		var i, l, srcElements, destElements,
			clone = elem.cloneNode( true ),
			inPage = isAttached( elem );

		// Fix IE cloning issues
		if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
				!jQuery.isXMLDoc( elem ) ) {

			// We eschew jQuery#find here for performance reasons:
			// https://jsperf.com/getall-vs-sizzle/2
			destElements = getAll( clone );
			srcElements = getAll( elem );

			for ( i = 0, l = srcElements.length; i < l; i++ ) {
				fixInput( srcElements[ i ], destElements[ i ] );
			}
		}

		// Copy the events from the original to the clone
		if ( dataAndEvents ) {
			if ( deepDataAndEvents ) {
				srcElements = srcElements || getAll( elem );
				destElements = destElements || getAll( clone );

				for ( i = 0, l = srcElements.length; i < l; i++ ) {
					cloneCopyEvent( srcElements[ i ], destElements[ i ] );
				}
			} else {
				cloneCopyEvent( elem, clone );
			}
		}

		// Preserve script evaluation history
		destElements = getAll( clone, "script" );
		if ( destElements.length > 0 ) {
			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
		}

		// Return the cloned set
		return clone;
	},

	cleanData: function( elems ) {
		var data, elem, type,
			special = jQuery.event.special,
			i = 0;

		for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
			if ( acceptData( elem ) ) {
				if ( ( data = elem[ dataPriv.expando ] ) ) {
					if ( data.events ) {
						for ( type in data.events ) {
							if ( special[ type ] ) {
								jQuery.event.remove( elem, type );

							// This is a shortcut to avoid jQuery.event.remove's overhead
							} else {
								jQuery.removeEvent( elem, type, data.handle );
							}
						}
					}

					// Support: Chrome <=35 - 45+
					// Assign undefined instead of using delete, see Data#remove
					elem[ dataPriv.expando ] = undefined;
				}
				if ( elem[ dataUser.expando ] ) {

					// Support: Chrome <=35 - 45+
					// Assign undefined instead of using delete, see Data#remove
					elem[ dataUser.expando ] = undefined;
				}
			}
		}
	}
} );

jQuery.fn.extend( {
	detach: function( selector ) {
		return remove( this, selector, true );
	},

	remove: function( selector ) {
		return remove( this, selector );
	},

	text: function( value ) {
		return access( this, function( value ) {
			return value === undefined ?
				jQuery.text( this ) :
				this.empty().each( function() {
					if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
						this.textContent = value;
					}
				} );
		}, null, value, arguments.length );
	},

	append: function() {
		return domManip( this, arguments, function( elem ) {
			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
				var target = manipulationTarget( this, elem );
				target.appendChild( elem );
			}
		} );
	},

	prepend: function() {
		return domManip( this, arguments, function( elem ) {
			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
				var target = manipulationTarget( this, elem );
				target.insertBefore( elem, target.firstChild );
			}
		} );
	},

	before: function() {
		return domManip( this, arguments, function( elem ) {
			if ( this.parentNode ) {
				this.parentNode.insertBefore( elem, this );
			}
		} );
	},

	after: function() {
		return domManip( this, arguments, function( elem ) {
			if ( this.parentNode ) {
				this.parentNode.insertBefore( elem, this.nextSibling );
			}
		} );
	},

	empty: function() {
		var elem,
			i = 0;

		for ( ; ( elem = this[ i ] ) != null; i++ ) {
			if ( elem.nodeType === 1 ) {

				// Prevent memory leaks
				jQuery.cleanData( getAll( elem, false ) );

				// Remove any remaining nodes
				elem.textContent = "";
			}
		}

		return this;
	},

	clone: function( dataAndEvents, deepDataAndEvents ) {
		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;

		return this.map( function() {
			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
		} );
	},

	html: function( value ) {
		return access( this, function( value ) {
			var elem = this[ 0 ] || {},
				i = 0,
				l = this.length;

			if ( value === undefined && elem.nodeType === 1 ) {
				return elem.innerHTML;
			}

			// See if we can take a shortcut and just use innerHTML
			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
				!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {

				value = jQuery.htmlPrefilter( value );

				try {
					for ( ; i < l; i++ ) {
						elem = this[ i ] || {};

						// Remove element nodes and prevent memory leaks
						if ( elem.nodeType === 1 ) {
							jQuery.cleanData( getAll( elem, false ) );
							elem.innerHTML = value;
						}
					}

					elem = 0;

				// If using innerHTML throws an exception, use the fallback method
				} catch ( e ) {}
			}

			if ( elem ) {
				this.empty().append( value );
			}
		}, null, value, arguments.length );
	},

	replaceWith: function() {
		var ignored = [];

		// Make the changes, replacing each non-ignored context element with the new content
		return domManip( this, arguments, function( elem ) {
			var parent = this.parentNode;

			if ( jQuery.inArray( this, ignored ) < 0 ) {
				jQuery.cleanData( getAll( this ) );
				if ( parent ) {
					parent.replaceChild( elem, this );
				}
			}

		// Force callback invocation
		}, ignored );
	}
} );

jQuery.each( {
	appendTo: "append",
	prependTo: "prepend",
	insertBefore: "before",
	insertAfter: "after",
	replaceAll: "replaceWith"
}, function( name, original ) {
	jQuery.fn[ name ] = function( selector ) {
		var elems,
			ret = [],
			insert = jQuery( selector ),
			last = insert.length - 1,
			i = 0;

		for ( ; i <= last; i++ ) {
			elems = i === last ? this : this.clone( true );
			jQuery( insert[ i ] )[ original ]( elems );

			// Support: Android <=4.0 only, PhantomJS 1 only
			// .get() because push.apply(_, arraylike) throws on ancient WebKit
			push.apply( ret, elems.get() );
		}

		return this.pushStack( ret );
	};
} );
var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );

var rcustomProp = /^--/;


var getStyles = function( elem ) {

		// Support: IE <=11 only, Firefox <=30 (trac-15098, trac-14150)
		// IE throws on elements created in popups
		// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
		var view = elem.ownerDocument.defaultView;

		if ( !view || !view.opener ) {
			view = window;
		}

		return view.getComputedStyle( elem );
	};

var swap = function( elem, options, callback ) {
	var ret, name,
		old = {};

	// Remember the old values, and insert the new ones
	for ( name in options ) {
		old[ name ] = elem.style[ name ];
		elem.style[ name ] = options[ name ];
	}

	ret = callback.call( elem );

	// Revert the old values
	for ( name in options ) {
		elem.style[ name ] = old[ name ];
	}

	return ret;
};


var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" );



( function() {

	// Executing both pixelPosition & boxSizingReliable tests require only one layout
	// so they're executed at the same time to save the second computation.
	function computeStyleTests() {

		// This is a singleton, we need to execute it only once
		if ( !div ) {
			return;
		}

		container.style.cssText = "position:absolute;left:-11111px;width:60px;" +
			"margin-top:1px;padding:0;border:0";
		div.style.cssText =
			"position:relative;display:block;box-sizing:border-box;overflow:scroll;" +
			"margin:auto;border:1px;padding:1px;" +
			"width:60%;top:1%";
		documentElement.appendChild( container ).appendChild( div );

		var divStyle = window.getComputedStyle( div );
		pixelPositionVal = divStyle.top !== "1%";

		// Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
		reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12;

		// Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3
		// Some styles come back with percentage values, even though they shouldn't
		div.style.right = "60%";
		pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36;

		// Support: IE 9 - 11 only
		// Detect misreporting of content dimensions for box-sizing:border-box elements
		boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36;

		// Support: IE 9 only
		// Detect overflow:scroll screwiness (gh-3699)
		// Support: Chrome <=64
		// Don't get tricked when zoom affects offsetWidth (gh-4029)
		div.style.position = "absolute";
		scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12;

		documentElement.removeChild( container );

		// Nullify the div so it wouldn't be stored in the memory and
		// it will also be a sign that checks already performed
		div = null;
	}

	function roundPixelMeasures( measure ) {
		return Math.round( parseFloat( measure ) );
	}

	var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal,
		reliableTrDimensionsVal, reliableMarginLeftVal,
		container = document.createElement( "div" ),
		div = document.createElement( "div" );

	// Finish early in limited (non-browser) environments
	if ( !div.style ) {
		return;
	}

	// Support: IE <=9 - 11 only
	// Style of cloned element affects source element cloned (trac-8908)
	div.style.backgroundClip = "content-box";
	div.cloneNode( true ).style.backgroundClip = "";
	support.clearCloneStyle = div.style.backgroundClip === "content-box";

	jQuery.extend( support, {
		boxSizingReliable: function() {
			computeStyleTests();
			return boxSizingReliableVal;
		},
		pixelBoxStyles: function() {
			computeStyleTests();
			return pixelBoxStylesVal;
		},
		pixelPosition: function() {
			computeStyleTests();
			return pixelPositionVal;
		},
		reliableMarginLeft: function() {
			computeStyleTests();
			return reliableMarginLeftVal;
		},
		scrollboxSize: function() {
			computeStyleTests();
			return scrollboxSizeVal;
		},

		// Support: IE 9 - 11+, Edge 15 - 18+
		// IE/Edge misreport `getComputedStyle` of table rows with width/height
		// set in CSS while `offset*` properties report correct values.
		// Behavior in IE 9 is more subtle than in newer versions & it passes
		// some versions of this test; make sure not to make it pass there!
		//
		// Support: Firefox 70+
		// Only Firefox includes border widths
		// in computed dimensions. (gh-4529)
		reliableTrDimensions: function() {
			var table, tr, trChild, trStyle;
			if ( reliableTrDimensionsVal == null ) {
				table = document.createElement( "table" );
				tr = document.createElement( "tr" );
				trChild = document.createElement( "div" );

				table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate";
				tr.style.cssText = "box-sizing:content-box;border:1px solid";

				// Support: Chrome 86+
				// Height set through cssText does not get applied.
				// Computed height then comes back as 0.
				tr.style.height = "1px";
				trChild.style.height = "9px";

				// Support: Android 8 Chrome 86+
				// In our bodyBackground.html iframe,
				// display for all div elements is set to "inline",
				// which causes a problem only in Android 8 Chrome 86.
				// Ensuring the div is `display: block`
				// gets around this issue.
				trChild.style.display = "block";

				documentElement
					.appendChild( table )
					.appendChild( tr )
					.appendChild( trChild );

				trStyle = window.getComputedStyle( tr );
				reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) +
					parseInt( trStyle.borderTopWidth, 10 ) +
					parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight;

				documentElement.removeChild( table );
			}
			return reliableTrDimensionsVal;
		}
	} );
} )();


function curCSS( elem, name, computed ) {
	var width, minWidth, maxWidth, ret,
		isCustomProp = rcustomProp.test( name ),

		// Support: Firefox 51+
		// Retrieving style before computed somehow
		// fixes an issue with getting wrong values
		// on detached elements
		style = elem.style;

	computed = computed || getStyles( elem );

	// getPropertyValue is needed for:
	//   .css('filter') (IE 9 only, trac-12537)
	//   .css('--customProperty) (gh-3144)
	if ( computed ) {

		// Support: IE <=9 - 11+
		// IE only supports `"float"` in `getPropertyValue`; in computed styles
		// it's only available as `"cssFloat"`. We no longer modify properties
		// sent to `.css()` apart from camelCasing, so we need to check both.
		// Normally, this would create difference in behavior: if
		// `getPropertyValue` returns an empty string, the value returned
		// by `.css()` would be `undefined`. This is usually the case for
		// disconnected elements. However, in IE even disconnected elements
		// with no styles return `"none"` for `getPropertyValue( "float" )`
		ret = computed.getPropertyValue( name ) || computed[ name ];

		if ( isCustomProp && ret ) {

			// Support: Firefox 105+, Chrome <=105+
			// Spec requires trimming whitespace for custom properties (gh-4926).
			// Firefox only trims leading whitespace. Chrome just collapses
			// both leading & trailing whitespace to a single space.
			//
			// Fall back to `undefined` if empty string returned.
			// This collapses a missing definition with property defined
			// and set to an empty string but there's no standard API
			// allowing us to differentiate them without a performance penalty
			// and returning `undefined` aligns with older jQuery.
			//
			// rtrimCSS treats U+000D CARRIAGE RETURN and U+000C FORM FEED
			// as whitespace while CSS does not, but this is not a problem
			// because CSS preprocessing replaces them with U+000A LINE FEED
			// (which *is* CSS whitespace)
			// https://www.w3.org/TR/css-syntax-3/#input-preprocessing
			ret = ret.replace( rtrimCSS, "$1" ) || undefined;
		}

		if ( ret === "" && !isAttached( elem ) ) {
			ret = jQuery.style( elem, name );
		}

		// A tribute to the "awesome hack by Dean Edwards"
		// Android Browser returns percentage for some values,
		// but width seems to be reliably pixels.
		// This is against the CSSOM draft spec:
		// https://drafts.csswg.org/cssom/#resolved-values
		if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) {

			// Remember the original values
			width = style.width;
			minWidth = style.minWidth;
			maxWidth = style.maxWidth;

			// Put in the new values to get a computed value out
			style.minWidth = style.maxWidth = style.width = ret;
			ret = computed.width;

			// Revert the changed values
			style.width = width;
			style.minWidth = minWidth;
			style.maxWidth = maxWidth;
		}
	}

	return ret !== undefined ?

		// Support: IE <=9 - 11 only
		// IE returns zIndex value as an integer.
		ret + "" :
		ret;
}


function addGetHookIf( conditionFn, hookFn ) {

	// Define the hook, we'll check on the first run if it's really needed.
	return {
		get: function() {
			if ( conditionFn() ) {

				// Hook not needed (or it's not possible to use it due
				// to missing dependency), remove it.
				delete this.get;
				return;
			}

			// Hook needed; redefine it so that the support test is not executed again.
			return ( this.get = hookFn ).apply( this, arguments );
		}
	};
}


var cssPrefixes = [ "Webkit", "Moz", "ms" ],
	emptyStyle = document.createElement( "div" ).style,
	vendorProps = {};

// Return a vendor-prefixed property or undefined
function vendorPropName( name ) {

	// Check for vendor prefixed names
	var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
		i = cssPrefixes.length;

	while ( i-- ) {
		name = cssPrefixes[ i ] + capName;
		if ( name in emptyStyle ) {
			return name;
		}
	}
}

// Return a potentially-mapped jQuery.cssProps or vendor prefixed property
function finalPropName( name ) {
	var final = jQuery.cssProps[ name ] || vendorProps[ name ];

	if ( final ) {
		return final;
	}
	if ( name in emptyStyle ) {
		return name;
	}
	return vendorProps[ name ] = vendorPropName( name ) || name;
}


var

	// Swappable if display is none or starts with table
	// except "table", "table-cell", or "table-caption"
	// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
	cssNormalTransform = {
		letterSpacing: "0",
		fontWeight: "400"
	};

function setPositiveNumber( _elem, value, subtract ) {

	// Any relative (+/-) values have already been
	// normalized at this point
	var matches = rcssNum.exec( value );
	return matches ?

		// Guard against undefined "subtract", e.g., when used as in cssHooks
		Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
		value;
}

function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) {
	var i = dimension === "width" ? 1 : 0,
		extra = 0,
		delta = 0,
		marginDelta = 0;

	// Adjustment may not be necessary
	if ( box === ( isBorderBox ? "border" : "content" ) ) {
		return 0;
	}

	for ( ; i < 4; i += 2 ) {

		// Both box models exclude margin
		// Count margin delta separately to only add it after scroll gutter adjustment.
		// This is needed to make negative margins work with `outerHeight( true )` (gh-3982).
		if ( box === "margin" ) {
			marginDelta += jQuery.css( elem, box + cssExpand[ i ], true, styles );
		}

		// If we get here with a content-box, we're seeking "padding" or "border" or "margin"
		if ( !isBorderBox ) {

			// Add padding
			delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );

			// For "border" or "margin", add border
			if ( box !== "padding" ) {
				delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );

			// But still keep track of it otherwise
			} else {
				extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
			}

		// If we get here with a border-box (content + padding + border), we're seeking "content" or
		// "padding" or "margin"
		} else {

			// For "content", subtract padding
			if ( box === "content" ) {
				delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
			}

			// For "content" or "padding", subtract border
			if ( box !== "margin" ) {
				delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
			}
		}
	}

	// Account for positive content-box scroll gutter when requested by providing computedVal
	if ( !isBorderBox && computedVal >= 0 ) {

		// offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border
		// Assuming integer scroll gutter, subtract the rest and round down
		delta += Math.max( 0, Math.ceil(
			elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
			computedVal -
			delta -
			extra -
			0.5

		// If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter
		// Use an explicit zero to avoid NaN (gh-3964)
		) ) || 0;
	}

	return delta + marginDelta;
}

function getWidthOrHeight( elem, dimension, extra ) {

	// Start with computed style
	var styles = getStyles( elem ),

		// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322).
		// Fake content-box until we know it's needed to know the true value.
		boxSizingNeeded = !support.boxSizingReliable() || extra,
		isBorderBox = boxSizingNeeded &&
			jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
		valueIsBorderBox = isBorderBox,

		val = curCSS( elem, dimension, styles ),
		offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 );

	// Support: Firefox <=54
	// Return a confounding non-pixel value or feign ignorance, as appropriate.
	if ( rnumnonpx.test( val ) ) {
		if ( !extra ) {
			return val;
		}
		val = "auto";
	}


	// Support: IE 9 - 11 only
	// Use offsetWidth/offsetHeight for when box sizing is unreliable.
	// In those cases, the computed value can be trusted to be border-box.
	if ( ( !support.boxSizingReliable() && isBorderBox ||

		// Support: IE 10 - 11+, Edge 15 - 18+
		// IE/Edge misreport `getComputedStyle` of table rows with width/height
		// set in CSS while `offset*` properties report correct values.
		// Interestingly, in some cases IE 9 doesn't suffer from this issue.
		!support.reliableTrDimensions() && nodeName( elem, "tr" ) ||

		// Fall back to offsetWidth/offsetHeight when value is "auto"
		// This happens for inline elements with no explicit setting (gh-3571)
		val === "auto" ||

		// Support: Android <=4.1 - 4.3 only
		// Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602)
		!parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) &&

		// Make sure the element is visible & connected
		elem.getClientRects().length ) {

		isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";

		// Where available, offsetWidth/offsetHeight approximate border box dimensions.
		// Where not available (e.g., SVG), assume unreliable box-sizing and interpret the
		// retrieved value as a content box dimension.
		valueIsBorderBox = offsetProp in elem;
		if ( valueIsBorderBox ) {
			val = elem[ offsetProp ];
		}
	}

	// Normalize "" and auto
	val = parseFloat( val ) || 0;

	// Adjust for the element's box model
	return ( val +
		boxModelAdjustment(
			elem,
			dimension,
			extra || ( isBorderBox ? "border" : "content" ),
			valueIsBorderBox,
			styles,

			// Provide the current computed size to request scroll gutter calculation (gh-3589)
			val
		)
	) + "px";
}

jQuery.extend( {

	// Add in style property hooks for overriding the default
	// behavior of getting and setting a style property
	cssHooks: {
		opacity: {
			get: function( elem, computed ) {
				if ( computed ) {

					// We should always get a number back from opacity
					var ret = curCSS( elem, "opacity" );
					return ret === "" ? "1" : ret;
				}
			}
		}
	},

	// Don't automatically add "px" to these possibly-unitless properties
	cssNumber: {
		animationIterationCount: true,
		aspectRatio: true,
		borderImageSlice: true,
		columnCount: true,
		flexGrow: true,
		flexShrink: true,
		fontWeight: true,
		gridArea: true,
		gridColumn: true,
		gridColumnEnd: true,
		gridColumnStart: true,
		gridRow: true,
		gridRowEnd: true,
		gridRowStart: true,
		lineHeight: true,
		opacity: true,
		order: true,
		orphans: true,
		scale: true,
		widows: true,
		zIndex: true,
		zoom: true,

		// SVG-related
		fillOpacity: true,
		floodOpacity: true,
		stopOpacity: true,
		strokeMiterlimit: true,
		strokeOpacity: true
	},

	// Add in properties whose names you wish to fix before
	// setting or getting the value
	cssProps: {},

	// Get and set the style property on a DOM Node
	style: function( elem, name, value, extra ) {

		// Don't set styles on text and comment nodes
		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
			return;
		}

		// Make sure that we're working with the right name
		var ret, type, hooks,
			origName = camelCase( name ),
			isCustomProp = rcustomProp.test( name ),
			style = elem.style;

		// Make sure that we're working with the right name. We don't
		// want to query the value if it is a CSS custom property
		// since they are user-defined.
		if ( !isCustomProp ) {
			name = finalPropName( origName );
		}

		// Gets hook for the prefixed version, then unprefixed version
		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];

		// Check if we're setting a value
		if ( value !== undefined ) {
			type = typeof value;

			// Convert "+=" or "-=" to relative numbers (trac-7345)
			if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
				value = adjustCSS( elem, name, ret );

				// Fixes bug trac-9237
				type = "number";
			}

			// Make sure that null and NaN values aren't set (trac-7116)
			if ( value == null || value !== value ) {
				return;
			}

			// If a number was passed in, add the unit (except for certain CSS properties)
			// The isCustomProp check can be removed in jQuery 4.0 when we only auto-append
			// "px" to a few hardcoded values.
			if ( type === "number" && !isCustomProp ) {
				value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
			}

			// background-* props affect original clone's values
			if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
				style[ name ] = "inherit";
			}

			// If a hook was provided, use that value, otherwise just set the specified value
			if ( !hooks || !( "set" in hooks ) ||
				( value = hooks.set( elem, value, extra ) ) !== undefined ) {

				if ( isCustomProp ) {
					style.setProperty( name, value );
				} else {
					style[ name ] = value;
				}
			}

		} else {

			// If a hook was provided get the non-computed value from there
			if ( hooks && "get" in hooks &&
				( ret = hooks.get( elem, false, extra ) ) !== undefined ) {

				return ret;
			}

			// Otherwise just get the value from the style object
			return style[ name ];
		}
	},

	css: function( elem, name, extra, styles ) {
		var val, num, hooks,
			origName = camelCase( name ),
			isCustomProp = rcustomProp.test( name );

		// Make sure that we're working with the right name. We don't
		// want to modify the value if it is a CSS custom property
		// since they are user-defined.
		if ( !isCustomProp ) {
			name = finalPropName( origName );
		}

		// Try prefixed name followed by the unprefixed name
		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];

		// If a hook was provided get the computed value from there
		if ( hooks && "get" in hooks ) {
			val = hooks.get( elem, true, extra );
		}

		// Otherwise, if a way to get the computed value exists, use that
		if ( val === undefined ) {
			val = curCSS( elem, name, styles );
		}

		// Convert "normal" to computed value
		if ( val === "normal" && name in cssNormalTransform ) {
			val = cssNormalTransform[ name ];
		}

		// Make numeric if forced or a qualifier was provided and val looks numeric
		if ( extra === "" || extra ) {
			num = parseFloat( val );
			return extra === true || isFinite( num ) ? num || 0 : val;
		}

		return val;
	}
} );

jQuery.each( [ "height", "width" ], function( _i, dimension ) {
	jQuery.cssHooks[ dimension ] = {
		get: function( elem, computed, extra ) {
			if ( computed ) {

				// Certain elements can have dimension info if we invisibly show them
				// but it must have a current display style that would benefit
				return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&

					// Support: Safari 8+
					// Table columns in Safari have non-zero offsetWidth & zero
					// getBoundingClientRect().width unless display is changed.
					// Support: IE <=11 only
					// Running getBoundingClientRect on a disconnected node
					// in IE throws an error.
					( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
					swap( elem, cssShow, function() {
						return getWidthOrHeight( elem, dimension, extra );
					} ) :
					getWidthOrHeight( elem, dimension, extra );
			}
		},

		set: function( elem, value, extra ) {
			var matches,
				styles = getStyles( elem ),

				// Only read styles.position if the test has a chance to fail
				// to avoid forcing a reflow.
				scrollboxSizeBuggy = !support.scrollboxSize() &&
					styles.position === "absolute",

				// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991)
				boxSizingNeeded = scrollboxSizeBuggy || extra,
				isBorderBox = boxSizingNeeded &&
					jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
				subtract = extra ?
					boxModelAdjustment(
						elem,
						dimension,
						extra,
						isBorderBox,
						styles
					) :
					0;

			// Account for unreliable border-box dimensions by comparing offset* to computed and
			// faking a content-box to get border and padding (gh-3699)
			if ( isBorderBox && scrollboxSizeBuggy ) {
				subtract -= Math.ceil(
					elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
					parseFloat( styles[ dimension ] ) -
					boxModelAdjustment( elem, dimension, "border", false, styles ) -
					0.5
				);
			}

			// Convert to pixels if value adjustment is needed
			if ( subtract && ( matches = rcssNum.exec( value ) ) &&
				( matches[ 3 ] || "px" ) !== "px" ) {

				elem.style[ dimension ] = value;
				value = jQuery.css( elem, dimension );
			}

			return setPositiveNumber( elem, value, subtract );
		}
	};
} );

jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
	function( elem, computed ) {
		if ( computed ) {
			return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
				elem.getBoundingClientRect().left -
					swap( elem, { marginLeft: 0 }, function() {
						return elem.getBoundingClientRect().left;
					} )
			) + "px";
		}
	}
);

// These hooks are used by animate to expand properties
jQuery.each( {
	margin: "",
	padding: "",
	border: "Width"
}, function( prefix, suffix ) {
	jQuery.cssHooks[ prefix + suffix ] = {
		expand: function( value ) {
			var i = 0,
				expanded = {},

				// Assumes a single number if not a string
				parts = typeof value === "string" ? value.split( " " ) : [ value ];

			for ( ; i < 4; i++ ) {
				expanded[ prefix + cssExpand[ i ] + suffix ] =
					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
			}

			return expanded;
		}
	};

	if ( prefix !== "margin" ) {
		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
	}
} );

jQuery.fn.extend( {
	css: function( name, value ) {
		return access( this, function( elem, name, value ) {
			var styles, len,
				map = {},
				i = 0;

			if ( Array.isArray( name ) ) {
				styles = getStyles( elem );
				len = name.length;

				for ( ; i < len; i++ ) {
					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
				}

				return map;
			}

			return value !== undefined ?
				jQuery.style( elem, name, value ) :
				jQuery.css( elem, name );
		}, name, value, arguments.length > 1 );
	}
} );


function Tween( elem, options, prop, end, easing ) {
	return new Tween.prototype.init( elem, options, prop, end, easing );
}
jQuery.Tween = Tween;

Tween.prototype = {
	constructor: Tween,
	init: function( elem, options, prop, end, easing, unit ) {
		this.elem = elem;
		this.prop = prop;
		this.easing = easing || jQuery.easing._default;
		this.options = options;
		this.start = this.now = this.cur();
		this.end = end;
		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
	},
	cur: function() {
		var hooks = Tween.propHooks[ this.prop ];

		return hooks && hooks.get ?
			hooks.get( this ) :
			Tween.propHooks._default.get( this );
	},
	run: function( percent ) {
		var eased,
			hooks = Tween.propHooks[ this.prop ];

		if ( this.options.duration ) {
			this.pos = eased = jQuery.easing[ this.easing ](
				percent, this.options.duration * percent, 0, 1, this.options.duration
			);
		} else {
			this.pos = eased = percent;
		}
		this.now = ( this.end - this.start ) * eased + this.start;

		if ( this.options.step ) {
			this.options.step.call( this.elem, this.now, this );
		}

		if ( hooks && hooks.set ) {
			hooks.set( this );
		} else {
			Tween.propHooks._default.set( this );
		}
		return this;
	}
};

Tween.prototype.init.prototype = Tween.prototype;

Tween.propHooks = {
	_default: {
		get: function( tween ) {
			var result;

			// Use a property on the element directly when it is not a DOM element,
			// or when there is no matching style property that exists.
			if ( tween.elem.nodeType !== 1 ||
				tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
				return tween.elem[ tween.prop ];
			}

			// Passing an empty string as a 3rd parameter to .css will automatically
			// attempt a parseFloat and fallback to a string if the parse fails.
			// Simple values such as "10px" are parsed to Float;
			// complex values such as "rotate(1rad)" are returned as-is.
			result = jQuery.css( tween.elem, tween.prop, "" );

			// Empty strings, null, undefined and "auto" are converted to 0.
			return !result || result === "auto" ? 0 : result;
		},
		set: function( tween ) {

			// Use step hook for back compat.
			// Use cssHook if its there.
			// Use .style if available and use plain properties where available.
			if ( jQuery.fx.step[ tween.prop ] ) {
				jQuery.fx.step[ tween.prop ]( tween );
			} else if ( tween.elem.nodeType === 1 && (
				jQuery.cssHooks[ tween.prop ] ||
					tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) {
				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
			} else {
				tween.elem[ tween.prop ] = tween.now;
			}
		}
	}
};

// Support: IE <=9 only
// Panic based approach to setting things on disconnected nodes
Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
	set: function( tween ) {
		if ( tween.elem.nodeType && tween.elem.parentNode ) {
			tween.elem[ tween.prop ] = tween.now;
		}
	}
};

jQuery.easing = {
	linear: function( p ) {
		return p;
	},
	swing: function( p ) {
		return 0.5 - Math.cos( p * Math.PI ) / 2;
	},
	_default: "swing"
};

jQuery.fx = Tween.prototype.init;

// Back compat <1.8 extension point
jQuery.fx.step = {};




var
	fxNow, inProgress,
	rfxtypes = /^(?:toggle|show|hide)$/,
	rrun = /queueHooks$/;

function schedule() {
	if ( inProgress ) {
		if ( document.hidden === false && window.requestAnimationFrame ) {
			window.requestAnimationFrame( schedule );
		} else {
			window.setTimeout( schedule, jQuery.fx.interval );
		}

		jQuery.fx.tick();
	}
}

// Animations created synchronously will run synchronously
function createFxNow() {
	window.setTimeout( function() {
		fxNow = undefined;
	} );
	return ( fxNow = Date.now() );
}

// Generate parameters to create a standard animation
function genFx( type, includeWidth ) {
	var which,
		i = 0,
		attrs = { height: type };

	// If we include width, step value is 1 to do all cssExpand values,
	// otherwise step value is 2 to skip over Left and Right
	includeWidth = includeWidth ? 1 : 0;
	for ( ; i < 4; i += 2 - includeWidth ) {
		which = cssExpand[ i ];
		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
	}

	if ( includeWidth ) {
		attrs.opacity = attrs.width = type;
	}

	return attrs;
}

function createTween( value, prop, animation ) {
	var tween,
		collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
		index = 0,
		length = collection.length;
	for ( ; index < length; index++ ) {
		if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {

			// We're done with this property
			return tween;
		}
	}
}

function defaultPrefilter( elem, props, opts ) {
	var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
		isBox = "width" in props || "height" in props,
		anim = this,
		orig = {},
		style = elem.style,
		hidden = elem.nodeType && isHiddenWithinTree( elem ),
		dataShow = dataPriv.get( elem, "fxshow" );

	// Queue-skipping animations hijack the fx hooks
	if ( !opts.queue ) {
		hooks = jQuery._queueHooks( elem, "fx" );
		if ( hooks.unqueued == null ) {
			hooks.unqueued = 0;
			oldfire = hooks.empty.fire;
			hooks.empty.fire = function() {
				if ( !hooks.unqueued ) {
					oldfire();
				}
			};
		}
		hooks.unqueued++;

		anim.always( function() {

			// Ensure the complete handler is called before this completes
			anim.always( function() {
				hooks.unqueued--;
				if ( !jQuery.queue( elem, "fx" ).length ) {
					hooks.empty.fire();
				}
			} );
		} );
	}

	// Detect show/hide animations
	for ( prop in props ) {
		value = props[ prop ];
		if ( rfxtypes.test( value ) ) {
			delete props[ prop ];
			toggle = toggle || value === "toggle";
			if ( value === ( hidden ? "hide" : "show" ) ) {

				// Pretend to be hidden if this is a "show" and
				// there is still data from a stopped show/hide
				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
					hidden = true;

				// Ignore all other no-op show/hide data
				} else {
					continue;
				}
			}
			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
		}
	}

	// Bail out if this is a no-op like .hide().hide()
	propTween = !jQuery.isEmptyObject( props );
	if ( !propTween && jQuery.isEmptyObject( orig ) ) {
		return;
	}

	// Restrict "overflow" and "display" styles during box animations
	if ( isBox && elem.nodeType === 1 ) {

		// Support: IE <=9 - 11, Edge 12 - 15
		// Record all 3 overflow attributes because IE does not infer the shorthand
		// from identically-valued overflowX and overflowY and Edge just mirrors
		// the overflowX value there.
		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];

		// Identify a display type, preferring old show/hide data over the CSS cascade
		restoreDisplay = dataShow && dataShow.display;
		if ( restoreDisplay == null ) {
			restoreDisplay = dataPriv.get( elem, "display" );
		}
		display = jQuery.css( elem, "display" );
		if ( display === "none" ) {
			if ( restoreDisplay ) {
				display = restoreDisplay;
			} else {

				// Get nonempty value(s) by temporarily forcing visibility
				showHide( [ elem ], true );
				restoreDisplay = elem.style.display || restoreDisplay;
				display = jQuery.css( elem, "display" );
				showHide( [ elem ] );
			}
		}

		// Animate inline elements as inline-block
		if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
			if ( jQuery.css( elem, "float" ) === "none" ) {

				// Restore the original display value at the end of pure show/hide animations
				if ( !propTween ) {
					anim.done( function() {
						style.display = restoreDisplay;
					} );
					if ( restoreDisplay == null ) {
						display = style.display;
						restoreDisplay = display === "none" ? "" : display;
					}
				}
				style.display = "inline-block";
			}
		}
	}

	if ( opts.overflow ) {
		style.overflow = "hidden";
		anim.always( function() {
			style.overflow = opts.overflow[ 0 ];
			style.overflowX = opts.overflow[ 1 ];
			style.overflowY = opts.overflow[ 2 ];
		} );
	}

	// Implement show/hide animations
	propTween = false;
	for ( prop in orig ) {

		// General show/hide setup for this element animation
		if ( !propTween ) {
			if ( dataShow ) {
				if ( "hidden" in dataShow ) {
					hidden = dataShow.hidden;
				}
			} else {
				dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
			}

			// Store hidden/visible for toggle so `.stop().toggle()` "reverses"
			if ( toggle ) {
				dataShow.hidden = !hidden;
			}

			// Show elements before animating them
			if ( hidden ) {
				showHide( [ elem ], true );
			}

			/* eslint-disable no-loop-func */

			anim.done( function() {

				/* eslint-enable no-loop-func */

				// The final step of a "hide" animation is actually hiding the element
				if ( !hidden ) {
					showHide( [ elem ] );
				}
				dataPriv.remove( elem, "fxshow" );
				for ( prop in orig ) {
					jQuery.style( elem, prop, orig[ prop ] );
				}
			} );
		}

		// Per-property setup
		propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
		if ( !( prop in dataShow ) ) {
			dataShow[ prop ] = propTween.start;
			if ( hidden ) {
				propTween.end = propTween.start;
				propTween.start = 0;
			}
		}
	}
}

function propFilter( props, specialEasing ) {
	var index, name, easing, value, hooks;

	// camelCase, specialEasing and expand cssHook pass
	for ( index in props ) {
		name = camelCase( index );
		easing = specialEasing[ name ];
		value = props[ index ];
		if ( Array.isArray( value ) ) {
			easing = value[ 1 ];
			value = props[ index ] = value[ 0 ];
		}

		if ( index !== name ) {
			props[ name ] = value;
			delete props[ index ];
		}

		hooks = jQuery.cssHooks[ name ];
		if ( hooks && "expand" in hooks ) {
			value = hooks.expand( value );
			delete props[ name ];

			// Not quite $.extend, this won't overwrite existing keys.
			// Reusing 'index' because we have the correct "name"
			for ( index in value ) {
				if ( !( index in props ) ) {
					props[ index ] = value[ index ];
					specialEasing[ index ] = easing;
				}
			}
		} else {
			specialEasing[ name ] = easing;
		}
	}
}

function Animation( elem, properties, options ) {
	var result,
		stopped,
		index = 0,
		length = Animation.prefilters.length,
		deferred = jQuery.Deferred().always( function() {

			// Don't match elem in the :animated selector
			delete tick.elem;
		} ),
		tick = function() {
			if ( stopped ) {
				return false;
			}
			var currentTime = fxNow || createFxNow(),
				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),

				// Support: Android 2.3 only
				// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (trac-12497)
				temp = remaining / animation.duration || 0,
				percent = 1 - temp,
				index = 0,
				length = animation.tweens.length;

			for ( ; index < length; index++ ) {
				animation.tweens[ index ].run( percent );
			}

			deferred.notifyWith( elem, [ animation, percent, remaining ] );

			// If there's more to do, yield
			if ( percent < 1 && length ) {
				return remaining;
			}

			// If this was an empty animation, synthesize a final progress notification
			if ( !length ) {
				deferred.notifyWith( elem, [ animation, 1, 0 ] );
			}

			// Resolve the animation and report its conclusion
			deferred.resolveWith( elem, [ animation ] );
			return false;
		},
		animation = deferred.promise( {
			elem: elem,
			props: jQuery.extend( {}, properties ),
			opts: jQuery.extend( true, {
				specialEasing: {},
				easing: jQuery.easing._default
			}, options ),
			originalProperties: properties,
			originalOptions: options,
			startTime: fxNow || createFxNow(),
			duration: options.duration,
			tweens: [],
			createTween: function( prop, end ) {
				var tween = jQuery.Tween( elem, animation.opts, prop, end,
					animation.opts.specialEasing[ prop ] || animation.opts.easing );
				animation.tweens.push( tween );
				return tween;
			},
			stop: function( gotoEnd ) {
				var index = 0,

					// If we are going to the end, we want to run all the tweens
					// otherwise we skip this part
					length = gotoEnd ? animation.tweens.length : 0;
				if ( stopped ) {
					return this;
				}
				stopped = true;
				for ( ; index < length; index++ ) {
					animation.tweens[ index ].run( 1 );
				}

				// Resolve when we played the last frame; otherwise, reject
				if ( gotoEnd ) {
					deferred.notifyWith( elem, [ animation, 1, 0 ] );
					deferred.resolveWith( elem, [ animation, gotoEnd ] );
				} else {
					deferred.rejectWith( elem, [ animation, gotoEnd ] );
				}
				return this;
			}
		} ),
		props = animation.props;

	propFilter( props, animation.opts.specialEasing );

	for ( ; index < length; index++ ) {
		result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
		if ( result ) {
			if ( isFunction( result.stop ) ) {
				jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
					result.stop.bind( result );
			}
			return result;
		}
	}

	jQuery.map( props, createTween, animation );

	if ( isFunction( animation.opts.start ) ) {
		animation.opts.start.call( elem, animation );
	}

	// Attach callbacks from options
	animation
		.progress( animation.opts.progress )
		.done( animation.opts.done, animation.opts.complete )
		.fail( animation.opts.fail )
		.always( animation.opts.always );

	jQuery.fx.timer(
		jQuery.extend( tick, {
			elem: elem,
			anim: animation,
			queue: animation.opts.queue
		} )
	);

	return animation;
}

jQuery.Animation = jQuery.extend( Animation, {

	tweeners: {
		"*": [ function( prop, value ) {
			var tween = this.createTween( prop, value );
			adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
			return tween;
		} ]
	},

	tweener: function( props, callback ) {
		if ( isFunction( props ) ) {
			callback = props;
			props = [ "*" ];
		} else {
			props = props.match( rnothtmlwhite );
		}

		var prop,
			index = 0,
			length = props.length;

		for ( ; index < length; index++ ) {
			prop = props[ index ];
			Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
			Animation.tweeners[ prop ].unshift( callback );
		}
	},

	prefilters: [ defaultPrefilter ],

	prefilter: function( callback, prepend ) {
		if ( prepend ) {
			Animation.prefilters.unshift( callback );
		} else {
			Animation.prefilters.push( callback );
		}
	}
} );

jQuery.speed = function( speed, easing, fn ) {
	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
		complete: fn || !fn && easing ||
			isFunction( speed ) && speed,
		duration: speed,
		easing: fn && easing || easing && !isFunction( easing ) && easing
	};

	// Go to the end state if fx are off
	if ( jQuery.fx.off ) {
		opt.duration = 0;

	} else {
		if ( typeof opt.duration !== "number" ) {
			if ( opt.duration in jQuery.fx.speeds ) {
				opt.duration = jQuery.fx.speeds[ opt.duration ];

			} else {
				opt.duration = jQuery.fx.speeds._default;
			}
		}
	}

	// Normalize opt.queue - true/undefined/null -> "fx"
	if ( opt.queue == null || opt.queue === true ) {
		opt.queue = "fx";
	}

	// Queueing
	opt.old = opt.complete;

	opt.complete = function() {
		if ( isFunction( opt.old ) ) {
			opt.old.call( this );
		}

		if ( opt.queue ) {
			jQuery.dequeue( this, opt.queue );
		}
	};

	return opt;
};

jQuery.fn.extend( {
	fadeTo: function( speed, to, easing, callback ) {

		// Show any hidden elements after setting opacity to 0
		return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()

			// Animate to the value specified
			.end().animate( { opacity: to }, speed, easing, callback );
	},
	animate: function( prop, speed, easing, callback ) {
		var empty = jQuery.isEmptyObject( prop ),
			optall = jQuery.speed( speed, easing, callback ),
			doAnimation = function() {

				// Operate on a copy of prop so per-property easing won't be lost
				var anim = Animation( this, jQuery.extend( {}, prop ), optall );

				// Empty animations, or finishing resolves immediately
				if ( empty || dataPriv.get( this, "finish" ) ) {
					anim.stop( true );
				}
			};

		doAnimation.finish = doAnimation;

		return empty || optall.queue === false ?
			this.each( doAnimation ) :
			this.queue( optall.queue, doAnimation );
	},
	stop: function( type, clearQueue, gotoEnd ) {
		var stopQueue = function( hooks ) {
			var stop = hooks.stop;
			delete hooks.stop;
			stop( gotoEnd );
		};

		if ( typeof type !== "string" ) {
			gotoEnd = clearQueue;
			clearQueue = type;
			type = undefined;
		}
		if ( clearQueue ) {
			this.queue( type || "fx", [] );
		}

		return this.each( function() {
			var dequeue = true,
				index = type != null && type + "queueHooks",
				timers = jQuery.timers,
				data = dataPriv.get( this );

			if ( index ) {
				if ( data[ index ] && data[ index ].stop ) {
					stopQueue( data[ index ] );
				}
			} else {
				for ( index in data ) {
					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
						stopQueue( data[ index ] );
					}
				}
			}

			for ( index = timers.length; index--; ) {
				if ( timers[ index ].elem === this &&
					( type == null || timers[ index ].queue === type ) ) {

					timers[ index ].anim.stop( gotoEnd );
					dequeue = false;
					timers.splice( index, 1 );
				}
			}

			// Start the next in the queue if the last step wasn't forced.
			// Timers currently will call their complete callbacks, which
			// will dequeue but only if they were gotoEnd.
			if ( dequeue || !gotoEnd ) {
				jQuery.dequeue( this, type );
			}
		} );
	},
	finish: function( type ) {
		if ( type !== false ) {
			type = type || "fx";
		}
		return this.each( function() {
			var index,
				data = dataPriv.get( this ),
				queue = data[ type + "queue" ],
				hooks = data[ type + "queueHooks" ],
				timers = jQuery.timers,
				length = queue ? queue.length : 0;

			// Enable finishing flag on private data
			data.finish = true;

			// Empty the queue first
			jQuery.queue( this, type, [] );

			if ( hooks && hooks.stop ) {
				hooks.stop.call( this, true );
			}

			// Look for any active animations, and finish them
			for ( index = timers.length; index--; ) {
				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
					timers[ index ].anim.stop( true );
					timers.splice( index, 1 );
				}
			}

			// Look for any animations in the old queue and finish them
			for ( index = 0; index < length; index++ ) {
				if ( queue[ index ] && queue[ index ].finish ) {
					queue[ index ].finish.call( this );
				}
			}

			// Turn off finishing flag
			delete data.finish;
		} );
	}
} );

jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) {
	var cssFn = jQuery.fn[ name ];
	jQuery.fn[ name ] = function( speed, easing, callback ) {
		return speed == null || typeof speed === "boolean" ?
			cssFn.apply( this, arguments ) :
			this.animate( genFx( name, true ), speed, easing, callback );
	};
} );

// Generate shortcuts for custom animations
jQuery.each( {
	slideDown: genFx( "show" ),
	slideUp: genFx( "hide" ),
	slideToggle: genFx( "toggle" ),
	fadeIn: { opacity: "show" },
	fadeOut: { opacity: "hide" },
	fadeToggle: { opacity: "toggle" }
}, function( name, props ) {
	jQuery.fn[ name ] = function( speed, easing, callback ) {
		return this.animate( props, speed, easing, callback );
	};
} );

jQuery.timers = [];
jQuery.fx.tick = function() {
	var timer,
		i = 0,
		timers = jQuery.timers;

	fxNow = Date.now();

	for ( ; i < timers.length; i++ ) {
		timer = timers[ i ];

		// Run the timer and safely remove it when done (allowing for external removal)
		if ( !timer() && timers[ i ] === timer ) {
			timers.splice( i--, 1 );
		}
	}

	if ( !timers.length ) {
		jQuery.fx.stop();
	}
	fxNow = undefined;
};

jQuery.fx.timer = function( timer ) {
	jQuery.timers.push( timer );
	jQuery.fx.start();
};

jQuery.fx.interval = 13;
jQuery.fx.start = function() {
	if ( inProgress ) {
		return;
	}

	inProgress = true;
	schedule();
};

jQuery.fx.stop = function() {
	inProgress = null;
};

jQuery.fx.speeds = {
	slow: 600,
	fast: 200,

	// Default speed
	_default: 400
};


// Based off of the plugin by Clint Helfers, with permission.
jQuery.fn.delay = function( time, type ) {
	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
	type = type || "fx";

	return this.queue( type, function( next, hooks ) {
		var timeout = window.setTimeout( next, time );
		hooks.stop = function() {
			window.clearTimeout( timeout );
		};
	} );
};


( function() {
	var input = document.createElement( "input" ),
		select = document.createElement( "select" ),
		opt = select.appendChild( document.createElement( "option" ) );

	input.type = "checkbox";

	// Support: Android <=4.3 only
	// Default value for a checkbox should be "on"
	support.checkOn = input.value !== "";

	// Support: IE <=11 only
	// Must access selectedIndex to make default options select
	support.optSelected = opt.selected;

	// Support: IE <=11 only
	// An input loses its value after becoming a radio
	input = document.createElement( "input" );
	input.value = "t";
	input.type = "radio";
	support.radioValue = input.value === "t";
} )();


var boolHook,
	attrHandle = jQuery.expr.attrHandle;

jQuery.fn.extend( {
	attr: function( name, value ) {
		return access( this, jQuery.attr, name, value, arguments.length > 1 );
	},

	removeAttr: function( name ) {
		return this.each( function() {
			jQuery.removeAttr( this, name );
		} );
	}
} );

jQuery.extend( {
	attr: function( elem, name, value ) {
		var ret, hooks,
			nType = elem.nodeType;

		// Don't get/set attributes on text, comment and attribute nodes
		if ( nType === 3 || nType === 8 || nType === 2 ) {
			return;
		}

		// Fallback to prop when attributes are not supported
		if ( typeof elem.getAttribute === "undefined" ) {
			return jQuery.prop( elem, name, value );
		}

		// Attribute hooks are determined by the lowercase version
		// Grab necessary hook if one is defined
		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
			hooks = jQuery.attrHooks[ name.toLowerCase() ] ||
				( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
		}

		if ( value !== undefined ) {
			if ( value === null ) {
				jQuery.removeAttr( elem, name );
				return;
			}

			if ( hooks && "set" in hooks &&
				( ret = hooks.set( elem, value, name ) ) !== undefined ) {
				return ret;
			}

			elem.setAttribute( name, value + "" );
			return value;
		}

		if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
			return ret;
		}

		ret = jQuery.find.attr( elem, name );

		// Non-existent attributes return null, we normalize to undefined
		return ret == null ? undefined : ret;
	},

	attrHooks: {
		type: {
			set: function( elem, value ) {
				if ( !support.radioValue && value === "radio" &&
					nodeName( elem, "input" ) ) {
					var val = elem.value;
					elem.setAttribute( "type", value );
					if ( val ) {
						elem.value = val;
					}
					return value;
				}
			}
		}
	},

	removeAttr: function( elem, value ) {
		var name,
			i = 0,

			// Attribute names can contain non-HTML whitespace characters
			// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
			attrNames = value && value.match( rnothtmlwhite );

		if ( attrNames && elem.nodeType === 1 ) {
			while ( ( name = attrNames[ i++ ] ) ) {
				elem.removeAttribute( name );
			}
		}
	}
} );

// Hooks for boolean attributes
boolHook = {
	set: function( elem, value, name ) {
		if ( value === false ) {

			// Remove boolean attributes when set to false
			jQuery.removeAttr( elem, name );
		} else {
			elem.setAttribute( name, name );
		}
		return name;
	}
};

jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) {
	var getter = attrHandle[ name ] || jQuery.find.attr;

	attrHandle[ name ] = function( elem, name, isXML ) {
		var ret, handle,
			lowercaseName = name.toLowerCase();

		if ( !isXML ) {

			// Avoid an infinite loop by temporarily removing this function from the getter
			handle = attrHandle[ lowercaseName ];
			attrHandle[ lowercaseName ] = ret;
			ret = getter( elem, name, isXML ) != null ?
				lowercaseName :
				null;
			attrHandle[ lowercaseName ] = handle;
		}
		return ret;
	};
} );




var rfocusable = /^(?:input|select|textarea|button)$/i,
	rclickable = /^(?:a|area)$/i;

jQuery.fn.extend( {
	prop: function( name, value ) {
		return access( this, jQuery.prop, name, value, arguments.length > 1 );
	},

	removeProp: function( name ) {
		return this.each( function() {
			delete this[ jQuery.propFix[ name ] || name ];
		} );
	}
} );

jQuery.extend( {
	prop: function( elem, name, value ) {
		var ret, hooks,
			nType = elem.nodeType;

		// Don't get/set properties on text, comment and attribute nodes
		if ( nType === 3 || nType === 8 || nType === 2 ) {
			return;
		}

		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {

			// Fix name and attach hooks
			name = jQuery.propFix[ name ] || name;
			hooks = jQuery.propHooks[ name ];
		}

		if ( value !== undefined ) {
			if ( hooks && "set" in hooks &&
				( ret = hooks.set( elem, value, name ) ) !== undefined ) {
				return ret;
			}

			return ( elem[ name ] = value );
		}

		if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
			return ret;
		}

		return elem[ name ];
	},

	propHooks: {
		tabIndex: {
			get: function( elem ) {

				// Support: IE <=9 - 11 only
				// elem.tabIndex doesn't always return the
				// correct value when it hasn't been explicitly set
				// Use proper attribute retrieval (trac-12072)
				var tabindex = jQuery.find.attr( elem, "tabindex" );

				if ( tabindex ) {
					return parseInt( tabindex, 10 );
				}

				if (
					rfocusable.test( elem.nodeName ) ||
					rclickable.test( elem.nodeName ) &&
					elem.href
				) {
					return 0;
				}

				return -1;
			}
		}
	},

	propFix: {
		"for": "htmlFor",
		"class": "className"
	}
} );

// Support: IE <=11 only
// Accessing the selectedIndex property
// forces the browser to respect setting selected
// on the option
// The getter ensures a default option is selected
// when in an optgroup
// eslint rule "no-unused-expressions" is disabled for this code
// since it considers such accessions noop
if ( !support.optSelected ) {
	jQuery.propHooks.selected = {
		get: function( elem ) {

			/* eslint no-unused-expressions: "off" */

			var parent = elem.parentNode;
			if ( parent && parent.parentNode ) {
				parent.parentNode.selectedIndex;
			}
			return null;
		},
		set: function( elem ) {

			/* eslint no-unused-expressions: "off" */

			var parent = elem.parentNode;
			if ( parent ) {
				parent.selectedIndex;

				if ( parent.parentNode ) {
					parent.parentNode.selectedIndex;
				}
			}
		}
	};
}

jQuery.each( [
	"tabIndex",
	"readOnly",
	"maxLength",
	"cellSpacing",
	"cellPadding",
	"rowSpan",
	"colSpan",
	"useMap",
	"frameBorder",
	"contentEditable"
], function() {
	jQuery.propFix[ this.toLowerCase() ] = this;
} );




	// Strip and collapse whitespace according to HTML spec
	// https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace
	function stripAndCollapse( value ) {
		var tokens = value.match( rnothtmlwhite ) || [];
		return tokens.join( " " );
	}


function getClass( elem ) {
	return elem.getAttribute && elem.getAttribute( "class" ) || "";
}

function classesToArray( value ) {
	if ( Array.isArray( value ) ) {
		return value;
	}
	if ( typeof value === "string" ) {
		return value.match( rnothtmlwhite ) || [];
	}
	return [];
}

jQuery.fn.extend( {
	addClass: function( value ) {
		var classNames, cur, curValue, className, i, finalValue;

		if ( isFunction( value ) ) {
			return this.each( function( j ) {
				jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
			} );
		}

		classNames = classesToArray( value );

		if ( classNames.length ) {
			return this.each( function() {
				curValue = getClass( this );
				cur = this.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );

				if ( cur ) {
					for ( i = 0; i < classNames.length; i++ ) {
						className = classNames[ i ];
						if ( cur.indexOf( " " + className + " " ) < 0 ) {
							cur += className + " ";
						}
					}

					// Only assign if different to avoid unneeded rendering.
					finalValue = stripAndCollapse( cur );
					if ( curValue !== finalValue ) {
						this.setAttribute( "class", finalValue );
					}
				}
			} );
		}

		return this;
	},

	removeClass: function( value ) {
		var classNames, cur, curValue, className, i, finalValue;

		if ( isFunction( value ) ) {
			return this.each( function( j ) {
				jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
			} );
		}

		if ( !arguments.length ) {
			return this.attr( "class", "" );
		}

		classNames = classesToArray( value );

		if ( classNames.length ) {
			return this.each( function() {
				curValue = getClass( this );

				// This expression is here for better compressibility (see addClass)
				cur = this.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );

				if ( cur ) {
					for ( i = 0; i < classNames.length; i++ ) {
						className = classNames[ i ];

						// Remove *all* instances
						while ( cur.indexOf( " " + className + " " ) > -1 ) {
							cur = cur.replace( " " + className + " ", " " );
						}
					}

					// Only assign if different to avoid unneeded rendering.
					finalValue = stripAndCollapse( cur );
					if ( curValue !== finalValue ) {
						this.setAttribute( "class", finalValue );
					}
				}
			} );
		}

		return this;
	},

	toggleClass: function( value, stateVal ) {
		var classNames, className, i, self,
			type = typeof value,
			isValidValue = type === "string" || Array.isArray( value );

		if ( isFunction( value ) ) {
			return this.each( function( i ) {
				jQuery( this ).toggleClass(
					value.call( this, i, getClass( this ), stateVal ),
					stateVal
				);
			} );
		}

		if ( typeof stateVal === "boolean" && isValidValue ) {
			return stateVal ? this.addClass( value ) : this.removeClass( value );
		}

		classNames = classesToArray( value );

		return this.each( function() {
			if ( isValidValue ) {

				// Toggle individual class names
				self = jQuery( this );

				for ( i = 0; i < classNames.length; i++ ) {
					className = classNames[ i ];

					// Check each className given, space separated list
					if ( self.hasClass( className ) ) {
						self.removeClass( className );
					} else {
						self.addClass( className );
					}
				}

			// Toggle whole class name
			} else if ( value === undefined || type === "boolean" ) {
				className = getClass( this );
				if ( className ) {

					// Store className if set
					dataPriv.set( this, "__className__", className );
				}

				// If the element has a class name or if we're passed `false`,
				// then remove the whole classname (if there was one, the above saved it).
				// Otherwise bring back whatever was previously saved (if anything),
				// falling back to the empty string if nothing was stored.
				if ( this.setAttribute ) {
					this.setAttribute( "class",
						className || value === false ?
							"" :
							dataPriv.get( this, "__className__" ) || ""
					);
				}
			}
		} );
	},

	hasClass: function( selector ) {
		var className, elem,
			i = 0;

		className = " " + selector + " ";
		while ( ( elem = this[ i++ ] ) ) {
			if ( elem.nodeType === 1 &&
				( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
				return true;
			}
		}

		return false;
	}
} );




var rreturn = /\r/g;

jQuery.fn.extend( {
	val: function( value ) {
		var hooks, ret, valueIsFunction,
			elem = this[ 0 ];

		if ( !arguments.length ) {
			if ( elem ) {
				hooks = jQuery.valHooks[ elem.type ] ||
					jQuery.valHooks[ elem.nodeName.toLowerCase() ];

				if ( hooks &&
					"get" in hooks &&
					( ret = hooks.get( elem, "value" ) ) !== undefined
				) {
					return ret;
				}

				ret = elem.value;

				// Handle most common string cases
				if ( typeof ret === "string" ) {
					return ret.replace( rreturn, "" );
				}

				// Handle cases where value is null/undef or number
				return ret == null ? "" : ret;
			}

			return;
		}

		valueIsFunction = isFunction( value );

		return this.each( function( i ) {
			var val;

			if ( this.nodeType !== 1 ) {
				return;
			}

			if ( valueIsFunction ) {
				val = value.call( this, i, jQuery( this ).val() );
			} else {
				val = value;
			}

			// Treat null/undefined as ""; convert numbers to string
			if ( val == null ) {
				val = "";

			} else if ( typeof val === "number" ) {
				val += "";

			} else if ( Array.isArray( val ) ) {
				val = jQuery.map( val, function( value ) {
					return value == null ? "" : value + "";
				} );
			}

			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];

			// If set returns undefined, fall back to normal setting
			if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
				this.value = val;
			}
		} );
	}
} );

jQuery.extend( {
	valHooks: {
		option: {
			get: function( elem ) {

				var val = jQuery.find.attr( elem, "value" );
				return val != null ?
					val :

					// Support: IE <=10 - 11 only
					// option.text throws exceptions (trac-14686, trac-14858)
					// Strip and collapse whitespace
					// https://html.spec.whatwg.org/#strip-and-collapse-whitespace
					stripAndCollapse( jQuery.text( elem ) );
			}
		},
		select: {
			get: function( elem ) {
				var value, option, i,
					options = elem.options,
					index = elem.selectedIndex,
					one = elem.type === "select-one",
					values = one ? null : [],
					max = one ? index + 1 : options.length;

				if ( index < 0 ) {
					i = max;

				} else {
					i = one ? index : 0;
				}

				// Loop through all the selected options
				for ( ; i < max; i++ ) {
					option = options[ i ];

					// Support: IE <=9 only
					// IE8-9 doesn't update selected after form reset (trac-2551)
					if ( ( option.selected || i === index ) &&

							// Don't return options that are disabled or in a disabled optgroup
							!option.disabled &&
							( !option.parentNode.disabled ||
								!nodeName( option.parentNode, "optgroup" ) ) ) {

						// Get the specific value for the option
						value = jQuery( option ).val();

						// We don't need an array for one selects
						if ( one ) {
							return value;
						}

						// Multi-Selects return an array
						values.push( value );
					}
				}

				return values;
			},

			set: function( elem, value ) {
				var optionSet, option,
					options = elem.options,
					values = jQuery.makeArray( value ),
					i = options.length;

				while ( i-- ) {
					option = options[ i ];

					/* eslint-disable no-cond-assign */

					if ( option.selected =
						jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
					) {
						optionSet = true;
					}

					/* eslint-enable no-cond-assign */
				}

				// Force browsers to behave consistently when non-matching value is set
				if ( !optionSet ) {
					elem.selectedIndex = -1;
				}
				return values;
			}
		}
	}
} );

// Radios and checkboxes getter/setter
jQuery.each( [ "radio", "checkbox" ], function() {
	jQuery.valHooks[ this ] = {
		set: function( elem, value ) {
			if ( Array.isArray( value ) ) {
				return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
			}
		}
	};
	if ( !support.checkOn ) {
		jQuery.valHooks[ this ].get = function( elem ) {
			return elem.getAttribute( "value" ) === null ? "on" : elem.value;
		};
	}
} );




// Return jQuery for attributes-only inclusion
var location = window.location;

var nonce = { guid: Date.now() };

var rquery = ( /\?/ );



// Cross-browser xml parsing
jQuery.parseXML = function( data ) {
	var xml, parserErrorElem;
	if ( !data || typeof data !== "string" ) {
		return null;
	}

	// Support: IE 9 - 11 only
	// IE throws on parseFromString with invalid input.
	try {
		xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
	} catch ( e ) {}

	parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ];
	if ( !xml || parserErrorElem ) {
		jQuery.error( "Invalid XML: " + (
			parserErrorElem ?
				jQuery.map( parserErrorElem.childNodes, function( el ) {
					return el.textContent;
				} ).join( "\n" ) :
				data
		) );
	}
	return xml;
};


var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
	stopPropagationCallback = function( e ) {
		e.stopPropagation();
	};

jQuery.extend( jQuery.event, {

	trigger: function( event, data, elem, onlyHandlers ) {

		var i, cur, tmp, bubbleType, ontype, handle, special, lastElement,
			eventPath = [ elem || document ],
			type = hasOwn.call( event, "type" ) ? event.type : event,
			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];

		cur = lastElement = tmp = elem = elem || document;

		// Don't do events on text and comment nodes
		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
			return;
		}

		// focus/blur morphs to focusin/out; ensure we're not firing them right now
		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
			return;
		}

		if ( type.indexOf( "." ) > -1 ) {

			// Namespaced trigger; create a regexp to match event type in handle()
			namespaces = type.split( "." );
			type = namespaces.shift();
			namespaces.sort();
		}
		ontype = type.indexOf( ":" ) < 0 && "on" + type;

		// Caller can pass in a jQuery.Event object, Object, or just an event type string
		event = event[ jQuery.expando ] ?
			event :
			new jQuery.Event( type, typeof event === "object" && event );

		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
		event.isTrigger = onlyHandlers ? 2 : 3;
		event.namespace = namespaces.join( "." );
		event.rnamespace = event.namespace ?
			new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
			null;

		// Clean up the event in case it is being reused
		event.result = undefined;
		if ( !event.target ) {
			event.target = elem;
		}

		// Clone any incoming data and prepend the event, creating the handler arg list
		data = data == null ?
			[ event ] :
			jQuery.makeArray( data, [ event ] );

		// Allow special events to draw outside the lines
		special = jQuery.event.special[ type ] || {};
		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
			return;
		}

		// Determine event propagation path in advance, per W3C events spec (trac-9951)
		// Bubble up to document, then to window; watch for a global ownerDocument var (trac-9724)
		if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) {

			bubbleType = special.delegateType || type;
			if ( !rfocusMorph.test( bubbleType + type ) ) {
				cur = cur.parentNode;
			}
			for ( ; cur; cur = cur.parentNode ) {
				eventPath.push( cur );
				tmp = cur;
			}

			// Only add window if we got to document (e.g., not plain obj or detached DOM)
			if ( tmp === ( elem.ownerDocument || document ) ) {
				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
			}
		}

		// Fire handlers on the event path
		i = 0;
		while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
			lastElement = cur;
			event.type = i > 1 ?
				bubbleType :
				special.bindType || type;

			// jQuery handler
			handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] &&
				dataPriv.get( cur, "handle" );
			if ( handle ) {
				handle.apply( cur, data );
			}

			// Native handler
			handle = ontype && cur[ ontype ];
			if ( handle && handle.apply && acceptData( cur ) ) {
				event.result = handle.apply( cur, data );
				if ( event.result === false ) {
					event.preventDefault();
				}
			}
		}
		event.type = type;

		// If nobody prevented the default action, do it now
		if ( !onlyHandlers && !event.isDefaultPrevented() ) {

			if ( ( !special._default ||
				special._default.apply( eventPath.pop(), data ) === false ) &&
				acceptData( elem ) ) {

				// Call a native DOM method on the target with the same name as the event.
				// Don't do default actions on window, that's where global variables be (trac-6170)
				if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) {

					// Don't re-trigger an onFOO event when we call its FOO() method
					tmp = elem[ ontype ];

					if ( tmp ) {
						elem[ ontype ] = null;
					}

					// Prevent re-triggering of the same event, since we already bubbled it above
					jQuery.event.triggered = type;

					if ( event.isPropagationStopped() ) {
						lastElement.addEventListener( type, stopPropagationCallback );
					}

					elem[ type ]();

					if ( event.isPropagationStopped() ) {
						lastElement.removeEventListener( type, stopPropagationCallback );
					}

					jQuery.event.triggered = undefined;

					if ( tmp ) {
						elem[ ontype ] = tmp;
					}
				}
			}
		}

		return event.result;
	},

	// Piggyback on a donor event to simulate a different one
	// Used only for `focus(in | out)` events
	simulate: function( type, elem, event ) {
		var e = jQuery.extend(
			new jQuery.Event(),
			event,
			{
				type: type,
				isSimulated: true
			}
		);

		jQuery.event.trigger( e, null, elem );
	}

} );

jQuery.fn.extend( {

	trigger: function( type, data ) {
		return this.each( function() {
			jQuery.event.trigger( type, data, this );
		} );
	},
	triggerHandler: function( type, data ) {
		var elem = this[ 0 ];
		if ( elem ) {
			return jQuery.event.trigger( type, data, elem, true );
		}
	}
} );


var
	rbracket = /\[\]$/,
	rCRLF = /\r?\n/g,
	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
	rsubmittable = /^(?:input|select|textarea|keygen)/i;

function buildParams( prefix, obj, traditional, add ) {
	var name;

	if ( Array.isArray( obj ) ) {

		// Serialize array item.
		jQuery.each( obj, function( i, v ) {
			if ( traditional || rbracket.test( prefix ) ) {

				// Treat each array item as a scalar.
				add( prefix, v );

			} else {

				// Item is non-scalar (array or object), encode its numeric index.
				buildParams(
					prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
					v,
					traditional,
					add
				);
			}
		} );

	} else if ( !traditional && toType( obj ) === "object" ) {

		// Serialize object item.
		for ( name in obj ) {
			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
		}

	} else {

		// Serialize scalar item.
		add( prefix, obj );
	}
}

// Serialize an array of form elements or a set of
// key/values into a query string
jQuery.param = function( a, traditional ) {
	var prefix,
		s = [],
		add = function( key, valueOrFunction ) {

			// If value is a function, invoke it and use its return value
			var value = isFunction( valueOrFunction ) ?
				valueOrFunction() :
				valueOrFunction;

			s[ s.length ] = encodeURIComponent( key ) + "=" +
				encodeURIComponent( value == null ? "" : value );
		};

	if ( a == null ) {
		return "";
	}

	// If an array was passed in, assume that it is an array of form elements.
	if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {

		// Serialize the form elements
		jQuery.each( a, function() {
			add( this.name, this.value );
		} );

	} else {

		// If traditional, encode the "old" way (the way 1.3.2 or older
		// did it), otherwise encode params recursively.
		for ( prefix in a ) {
			buildParams( prefix, a[ prefix ], traditional, add );
		}
	}

	// Return the resulting serialization
	return s.join( "&" );
};

jQuery.fn.extend( {
	serialize: function() {
		return jQuery.param( this.serializeArray() );
	},
	serializeArray: function() {
		return this.map( function() {

			// Can add propHook for "elements" to filter or add form elements
			var elements = jQuery.prop( this, "elements" );
			return elements ? jQuery.makeArray( elements ) : this;
		} ).filter( function() {
			var type = this.type;

			// Use .is( ":disabled" ) so that fieldset[disabled] works
			return this.name && !jQuery( this ).is( ":disabled" ) &&
				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
				( this.checked || !rcheckableType.test( type ) );
		} ).map( function( _i, elem ) {
			var val = jQuery( this ).val();

			if ( val == null ) {
				return null;
			}

			if ( Array.isArray( val ) ) {
				return jQuery.map( val, function( val ) {
					return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
				} );
			}

			return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
		} ).get();
	}
} );


var
	r20 = /%20/g,
	rhash = /#.*$/,
	rantiCache = /([?&])_=[^&]*/,
	rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,

	// trac-7653, trac-8125, trac-8152: local protocol detection
	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
	rnoContent = /^(?:GET|HEAD)$/,
	rprotocol = /^\/\//,

	/* Prefilters
	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
	 * 2) These are called:
	 *    - BEFORE asking for a transport
	 *    - AFTER param serialization (s.data is a string if s.processData is true)
	 * 3) key is the dataType
	 * 4) the catchall symbol "*" can be used
	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
	 */
	prefilters = {},

	/* Transports bindings
	 * 1) key is the dataType
	 * 2) the catchall symbol "*" can be used
	 * 3) selection will start with transport dataType and THEN go to "*" if needed
	 */
	transports = {},

	// Avoid comment-prolog char sequence (trac-10098); must appease lint and evade compression
	allTypes = "*/".concat( "*" ),

	// Anchor tag for parsing the document origin
	originAnchor = document.createElement( "a" );

originAnchor.href = location.href;

// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
function addToPrefiltersOrTransports( structure ) {

	// dataTypeExpression is optional and defaults to "*"
	return function( dataTypeExpression, func ) {

		if ( typeof dataTypeExpression !== "string" ) {
			func = dataTypeExpression;
			dataTypeExpression = "*";
		}

		var dataType,
			i = 0,
			dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];

		if ( isFunction( func ) ) {

			// For each dataType in the dataTypeExpression
			while ( ( dataType = dataTypes[ i++ ] ) ) {

				// Prepend if requested
				if ( dataType[ 0 ] === "+" ) {
					dataType = dataType.slice( 1 ) || "*";
					( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );

				// Otherwise append
				} else {
					( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
				}
			}
		}
	};
}

// Base inspection function for prefilters and transports
function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {

	var inspected = {},
		seekingTransport = ( structure === transports );

	function inspect( dataType ) {
		var selected;
		inspected[ dataType ] = true;
		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
			if ( typeof dataTypeOrTransport === "string" &&
				!seekingTransport && !inspected[ dataTypeOrTransport ] ) {

				options.dataTypes.unshift( dataTypeOrTransport );
				inspect( dataTypeOrTransport );
				return false;
			} else if ( seekingTransport ) {
				return !( selected = dataTypeOrTransport );
			}
		} );
		return selected;
	}

	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
}

// A special extend for ajax options
// that takes "flat" options (not to be deep extended)
// Fixes trac-9887
function ajaxExtend( target, src ) {
	var key, deep,
		flatOptions = jQuery.ajaxSettings.flatOptions || {};

	for ( key in src ) {
		if ( src[ key ] !== undefined ) {
			( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
		}
	}
	if ( deep ) {
		jQuery.extend( true, target, deep );
	}

	return target;
}

/* Handles responses to an ajax request:
 * - finds the right dataType (mediates between content-type and expected dataType)
 * - returns the corresponding response
 */
function ajaxHandleResponses( s, jqXHR, responses ) {

	var ct, type, finalDataType, firstDataType,
		contents = s.contents,
		dataTypes = s.dataTypes;

	// Remove auto dataType and get content-type in the process
	while ( dataTypes[ 0 ] === "*" ) {
		dataTypes.shift();
		if ( ct === undefined ) {
			ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
		}
	}

	// Check if we're dealing with a known content-type
	if ( ct ) {
		for ( type in contents ) {
			if ( contents[ type ] && contents[ type ].test( ct ) ) {
				dataTypes.unshift( type );
				break;
			}
		}
	}

	// Check to see if we have a response for the expected dataType
	if ( dataTypes[ 0 ] in responses ) {
		finalDataType = dataTypes[ 0 ];
	} else {

		// Try convertible dataTypes
		for ( type in responses ) {
			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
				finalDataType = type;
				break;
			}
			if ( !firstDataType ) {
				firstDataType = type;
			}
		}

		// Or just use first one
		finalDataType = finalDataType || firstDataType;
	}

	// If we found a dataType
	// We add the dataType to the list if needed
	// and return the corresponding response
	if ( finalDataType ) {
		if ( finalDataType !== dataTypes[ 0 ] ) {
			dataTypes.unshift( finalDataType );
		}
		return responses[ finalDataType ];
	}
}

/* Chain conversions given the request and the original response
 * Also sets the responseXXX fields on the jqXHR instance
 */
function ajaxConvert( s, response, jqXHR, isSuccess ) {
	var conv2, current, conv, tmp, prev,
		converters = {},

		// Work with a copy of dataTypes in case we need to modify it for conversion
		dataTypes = s.dataTypes.slice();

	// Create converters map with lowercased keys
	if ( dataTypes[ 1 ] ) {
		for ( conv in s.converters ) {
			converters[ conv.toLowerCase() ] = s.converters[ conv ];
		}
	}

	current = dataTypes.shift();

	// Convert to each sequential dataType
	while ( current ) {

		if ( s.responseFields[ current ] ) {
			jqXHR[ s.responseFields[ current ] ] = response;
		}

		// Apply the dataFilter if provided
		if ( !prev && isSuccess && s.dataFilter ) {
			response = s.dataFilter( response, s.dataType );
		}

		prev = current;
		current = dataTypes.shift();

		if ( current ) {

			// There's only work to do if current dataType is non-auto
			if ( current === "*" ) {

				current = prev;

			// Convert response if prev dataType is non-auto and differs from current
			} else if ( prev !== "*" && prev !== current ) {

				// Seek a direct converter
				conv = converters[ prev + " " + current ] || converters[ "* " + current ];

				// If none found, seek a pair
				if ( !conv ) {
					for ( conv2 in converters ) {

						// If conv2 outputs current
						tmp = conv2.split( " " );
						if ( tmp[ 1 ] === current ) {

							// If prev can be converted to accepted input
							conv = converters[ prev + " " + tmp[ 0 ] ] ||
								converters[ "* " + tmp[ 0 ] ];
							if ( conv ) {

								// Condense equivalence converters
								if ( conv === true ) {
									conv = converters[ conv2 ];

								// Otherwise, insert the intermediate dataType
								} else if ( converters[ conv2 ] !== true ) {
									current = tmp[ 0 ];
									dataTypes.unshift( tmp[ 1 ] );
								}
								break;
							}
						}
					}
				}

				// Apply converter (if not an equivalence)
				if ( conv !== true ) {

					// Unless errors are allowed to bubble, catch and return them
					if ( conv && s.throws ) {
						response = conv( response );
					} else {
						try {
							response = conv( response );
						} catch ( e ) {
							return {
								state: "parsererror",
								error: conv ? e : "No conversion from " + prev + " to " + current
							};
						}
					}
				}
			}
		}
	}

	return { state: "success", data: response };
}

jQuery.extend( {

	// Counter for holding the number of active queries
	active: 0,

	// Last-Modified header cache for next request
	lastModified: {},
	etag: {},

	ajaxSettings: {
		url: location.href,
		type: "GET",
		isLocal: rlocalProtocol.test( location.protocol ),
		global: true,
		processData: true,
		async: true,
		contentType: "application/x-www-form-urlencoded; charset=UTF-8",

		/*
		timeout: 0,
		data: null,
		dataType: null,
		username: null,
		password: null,
		cache: null,
		throws: false,
		traditional: false,
		headers: {},
		*/

		accepts: {
			"*": allTypes,
			text: "text/plain",
			html: "text/html",
			xml: "application/xml, text/xml",
			json: "application/json, text/javascript"
		},

		contents: {
			xml: /\bxml\b/,
			html: /\bhtml/,
			json: /\bjson\b/
		},

		responseFields: {
			xml: "responseXML",
			text: "responseText",
			json: "responseJSON"
		},

		// Data converters
		// Keys separate source (or catchall "*") and destination types with a single space
		converters: {

			// Convert anything to text
			"* text": String,

			// Text to html (true = no transformation)
			"text html": true,

			// Evaluate text as a json expression
			"text json": JSON.parse,

			// Parse text as xml
			"text xml": jQuery.parseXML
		},

		// For options that shouldn't be deep extended:
		// you can add your own custom options here if
		// and when you create one that shouldn't be
		// deep extended (see ajaxExtend)
		flatOptions: {
			url: true,
			context: true
		}
	},

	// Creates a full fledged settings object into target
	// with both ajaxSettings and settings fields.
	// If target is omitted, writes into ajaxSettings.
	ajaxSetup: function( target, settings ) {
		return settings ?

			// Building a settings object
			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :

			// Extending ajaxSettings
			ajaxExtend( jQuery.ajaxSettings, target );
	},

	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
	ajaxTransport: addToPrefiltersOrTransports( transports ),

	// Main method
	ajax: function( url, options ) {

		// If url is an object, simulate pre-1.5 signature
		if ( typeof url === "object" ) {
			options = url;
			url = undefined;
		}

		// Force options to be an object
		options = options || {};

		var transport,

			// URL without anti-cache param
			cacheURL,

			// Response headers
			responseHeadersString,
			responseHeaders,

			// timeout handle
			timeoutTimer,

			// Url cleanup var
			urlAnchor,

			// Request state (becomes false upon send and true upon completion)
			completed,

			// To know if global events are to be dispatched
			fireGlobals,

			// Loop variable
			i,

			// uncached part of the url
			uncached,

			// Create the final options object
			s = jQuery.ajaxSetup( {}, options ),

			// Callbacks context
			callbackContext = s.context || s,

			// Context for global events is callbackContext if it is a DOM node or jQuery collection
			globalEventContext = s.context &&
				( callbackContext.nodeType || callbackContext.jquery ) ?
				jQuery( callbackContext ) :
				jQuery.event,

			// Deferreds
			deferred = jQuery.Deferred(),
			completeDeferred = jQuery.Callbacks( "once memory" ),

			// Status-dependent callbacks
			statusCode = s.statusCode || {},

			// Headers (they are sent all at once)
			requestHeaders = {},
			requestHeadersNames = {},

			// Default abort message
			strAbort = "canceled",

			// Fake xhr
			jqXHR = {
				readyState: 0,

				// Builds headers hashtable if needed
				getResponseHeader: function( key ) {
					var match;
					if ( completed ) {
						if ( !responseHeaders ) {
							responseHeaders = {};
							while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
								responseHeaders[ match[ 1 ].toLowerCase() + " " ] =
									( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] )
										.concat( match[ 2 ] );
							}
						}
						match = responseHeaders[ key.toLowerCase() + " " ];
					}
					return match == null ? null : match.join( ", " );
				},

				// Raw string
				getAllResponseHeaders: function() {
					return completed ? responseHeadersString : null;
				},

				// Caches the header
				setRequestHeader: function( name, value ) {
					if ( completed == null ) {
						name = requestHeadersNames[ name.toLowerCase() ] =
							requestHeadersNames[ name.toLowerCase() ] || name;
						requestHeaders[ name ] = value;
					}
					return this;
				},

				// Overrides response content-type header
				overrideMimeType: function( type ) {
					if ( completed == null ) {
						s.mimeType = type;
					}
					return this;
				},

				// Status-dependent callbacks
				statusCode: function( map ) {
					var code;
					if ( map ) {
						if ( completed ) {

							// Execute the appropriate callbacks
							jqXHR.always( map[ jqXHR.status ] );
						} else {

							// Lazy-add the new callbacks in a way that preserves old ones
							for ( code in map ) {
								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
							}
						}
					}
					return this;
				},

				// Cancel the request
				abort: function( statusText ) {
					var finalText = statusText || strAbort;
					if ( transport ) {
						transport.abort( finalText );
					}
					done( 0, finalText );
					return this;
				}
			};

		// Attach deferreds
		deferred.promise( jqXHR );

		// Add protocol if not provided (prefilters might expect it)
		// Handle falsy url in the settings object (trac-10093: consistency with old signature)
		// We also use the url parameter if available
		s.url = ( ( url || s.url || location.href ) + "" )
			.replace( rprotocol, location.protocol + "//" );

		// Alias method option to type as per ticket trac-12004
		s.type = options.method || options.type || s.method || s.type;

		// Extract dataTypes list
		s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ];

		// A cross-domain request is in order when the origin doesn't match the current origin.
		if ( s.crossDomain == null ) {
			urlAnchor = document.createElement( "a" );

			// Support: IE <=8 - 11, Edge 12 - 15
			// IE throws exception on accessing the href property if url is malformed,
			// e.g. http://example.com:80x/
			try {
				urlAnchor.href = s.url;

				// Support: IE <=8 - 11 only
				// Anchor's host property isn't correctly set when s.url is relative
				urlAnchor.href = urlAnchor.href;
				s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
					urlAnchor.protocol + "//" + urlAnchor.host;
			} catch ( e ) {

				// If there is an error parsing the URL, assume it is crossDomain,
				// it can be rejected by the transport if it is invalid
				s.crossDomain = true;
			}
		}

		// Convert data if not already a string
		if ( s.data && s.processData && typeof s.data !== "string" ) {
			s.data = jQuery.param( s.data, s.traditional );
		}

		// Apply prefilters
		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );

		// If request was aborted inside a prefilter, stop there
		if ( completed ) {
			return jqXHR;
		}

		// We can fire global events as of now if asked to
		// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (trac-15118)
		fireGlobals = jQuery.event && s.global;

		// Watch for a new set of requests
		if ( fireGlobals && jQuery.active++ === 0 ) {
			jQuery.event.trigger( "ajaxStart" );
		}

		// Uppercase the type
		s.type = s.type.toUpperCase();

		// Determine if request has content
		s.hasContent = !rnoContent.test( s.type );

		// Save the URL in case we're toying with the If-Modified-Since
		// and/or If-None-Match header later on
		// Remove hash to simplify url manipulation
		cacheURL = s.url.replace( rhash, "" );

		// More options handling for requests with no content
		if ( !s.hasContent ) {

			// Remember the hash so we can put it back
			uncached = s.url.slice( cacheURL.length );

			// If data is available and should be processed, append data to url
			if ( s.data && ( s.processData || typeof s.data === "string" ) ) {
				cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;

				// trac-9682: remove data so that it's not used in an eventual retry
				delete s.data;
			}

			// Add or update anti-cache param if needed
			if ( s.cache === false ) {
				cacheURL = cacheURL.replace( rantiCache, "$1" );
				uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) +
					uncached;
			}

			// Put hash and anti-cache on the URL that will be requested (gh-1732)
			s.url = cacheURL + uncached;

		// Change '%20' to '+' if this is encoded form body content (gh-2658)
		} else if ( s.data && s.processData &&
			( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
			s.data = s.data.replace( r20, "+" );
		}

		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
		if ( s.ifModified ) {
			if ( jQuery.lastModified[ cacheURL ] ) {
				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
			}
			if ( jQuery.etag[ cacheURL ] ) {
				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
			}
		}

		// Set the correct header, if data is being sent
		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
			jqXHR.setRequestHeader( "Content-Type", s.contentType );
		}

		// Set the Accepts header for the server, depending on the dataType
		jqXHR.setRequestHeader(
			"Accept",
			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
				s.accepts[ s.dataTypes[ 0 ] ] +
					( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
				s.accepts[ "*" ]
		);

		// Check for headers option
		for ( i in s.headers ) {
			jqXHR.setRequestHeader( i, s.headers[ i ] );
		}

		// Allow custom headers/mimetypes and early abort
		if ( s.beforeSend &&
			( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {

			// Abort if not done already and return
			return jqXHR.abort();
		}

		// Aborting is no longer a cancellation
		strAbort = "abort";

		// Install callbacks on deferreds
		completeDeferred.add( s.complete );
		jqXHR.done( s.success );
		jqXHR.fail( s.error );

		// Get transport
		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );

		// If no transport, we auto-abort
		if ( !transport ) {
			done( -1, "No Transport" );
		} else {
			jqXHR.readyState = 1;

			// Send global event
			if ( fireGlobals ) {
				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
			}

			// If request was aborted inside ajaxSend, stop there
			if ( completed ) {
				return jqXHR;
			}

			// Timeout
			if ( s.async && s.timeout > 0 ) {
				timeoutTimer = window.setTimeout( function() {
					jqXHR.abort( "timeout" );
				}, s.timeout );
			}

			try {
				completed = false;
				transport.send( requestHeaders, done );
			} catch ( e ) {

				// Rethrow post-completion exceptions
				if ( completed ) {
					throw e;
				}

				// Propagate others as results
				done( -1, e );
			}
		}

		// Callback for when everything is done
		function done( status, nativeStatusText, responses, headers ) {
			var isSuccess, success, error, response, modified,
				statusText = nativeStatusText;

			// Ignore repeat invocations
			if ( completed ) {
				return;
			}

			completed = true;

			// Clear timeout if it exists
			if ( timeoutTimer ) {
				window.clearTimeout( timeoutTimer );
			}

			// Dereference transport for early garbage collection
			// (no matter how long the jqXHR object will be used)
			transport = undefined;

			// Cache response headers
			responseHeadersString = headers || "";

			// Set readyState
			jqXHR.readyState = status > 0 ? 4 : 0;

			// Determine if successful
			isSuccess = status >= 200 && status < 300 || status === 304;

			// Get response data
			if ( responses ) {
				response = ajaxHandleResponses( s, jqXHR, responses );
			}

			// Use a noop converter for missing script but not if jsonp
			if ( !isSuccess &&
				jQuery.inArray( "script", s.dataTypes ) > -1 &&
				jQuery.inArray( "json", s.dataTypes ) < 0 ) {
				s.converters[ "text script" ] = function() {};
			}

			// Convert no matter what (that way responseXXX fields are always set)
			response = ajaxConvert( s, response, jqXHR, isSuccess );

			// If successful, handle type chaining
			if ( isSuccess ) {

				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
				if ( s.ifModified ) {
					modified = jqXHR.getResponseHeader( "Last-Modified" );
					if ( modified ) {
						jQuery.lastModified[ cacheURL ] = modified;
					}
					modified = jqXHR.getResponseHeader( "etag" );
					if ( modified ) {
						jQuery.etag[ cacheURL ] = modified;
					}
				}

				// if no content
				if ( status === 204 || s.type === "HEAD" ) {
					statusText = "nocontent";

				// if not modified
				} else if ( status === 304 ) {
					statusText = "notmodified";

				// If we have data, let's convert it
				} else {
					statusText = response.state;
					success = response.data;
					error = response.error;
					isSuccess = !error;
				}
			} else {

				// Extract error from statusText and normalize for non-aborts
				error = statusText;
				if ( status || !statusText ) {
					statusText = "error";
					if ( status < 0 ) {
						status = 0;
					}
				}
			}

			// Set data for the fake xhr object
			jqXHR.status = status;
			jqXHR.statusText = ( nativeStatusText || statusText ) + "";

			// Success/Error
			if ( isSuccess ) {
				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
			} else {
				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
			}

			// Status-dependent callbacks
			jqXHR.statusCode( statusCode );
			statusCode = undefined;

			if ( fireGlobals ) {
				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
					[ jqXHR, s, isSuccess ? success : error ] );
			}

			// Complete
			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );

			if ( fireGlobals ) {
				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );

				// Handle the global AJAX counter
				if ( !( --jQuery.active ) ) {
					jQuery.event.trigger( "ajaxStop" );
				}
			}
		}

		return jqXHR;
	},

	getJSON: function( url, data, callback ) {
		return jQuery.get( url, data, callback, "json" );
	},

	getScript: function( url, callback ) {
		return jQuery.get( url, undefined, callback, "script" );
	}
} );

jQuery.each( [ "get", "post" ], function( _i, method ) {
	jQuery[ method ] = function( url, data, callback, type ) {

		// Shift arguments if data argument was omitted
		if ( isFunction( data ) ) {
			type = type || callback;
			callback = data;
			data = undefined;
		}

		// The url can be an options object (which then must have .url)
		return jQuery.ajax( jQuery.extend( {
			url: url,
			type: method,
			dataType: type,
			data: data,
			success: callback
		}, jQuery.isPlainObject( url ) && url ) );
	};
} );

jQuery.ajaxPrefilter( function( s ) {
	var i;
	for ( i in s.headers ) {
		if ( i.toLowerCase() === "content-type" ) {
			s.contentType = s.headers[ i ] || "";
		}
	}
} );


jQuery._evalUrl = function( url, options, doc ) {
	return jQuery.ajax( {
		url: url,

		// Make this explicit, since user can override this through ajaxSetup (trac-11264)
		type: "GET",
		dataType: "script",
		cache: true,
		async: false,
		global: false,

		// Only evaluate the response if it is successful (gh-4126)
		// dataFilter is not invoked for failure responses, so using it instead
		// of the default converter is kludgy but it works.
		converters: {
			"text script": function() {}
		},
		dataFilter: function( response ) {
			jQuery.globalEval( response, options, doc );
		}
	} );
};


jQuery.fn.extend( {
	wrapAll: function( html ) {
		var wrap;

		if ( this[ 0 ] ) {
			if ( isFunction( html ) ) {
				html = html.call( this[ 0 ] );
			}

			// The elements to wrap the target around
			wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );

			if ( this[ 0 ].parentNode ) {
				wrap.insertBefore( this[ 0 ] );
			}

			wrap.map( function() {
				var elem = this;

				while ( elem.firstElementChild ) {
					elem = elem.firstElementChild;
				}

				return elem;
			} ).append( this );
		}

		return this;
	},

	wrapInner: function( html ) {
		if ( isFunction( html ) ) {
			return this.each( function( i ) {
				jQuery( this ).wrapInner( html.call( this, i ) );
			} );
		}

		return this.each( function() {
			var self = jQuery( this ),
				contents = self.contents();

			if ( contents.length ) {
				contents.wrapAll( html );

			} else {
				self.append( html );
			}
		} );
	},

	wrap: function( html ) {
		var htmlIsFunction = isFunction( html );

		return this.each( function( i ) {
			jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html );
		} );
	},

	unwrap: function( selector ) {
		this.parent( selector ).not( "body" ).each( function() {
			jQuery( this ).replaceWith( this.childNodes );
		} );
		return this;
	}
} );


jQuery.expr.pseudos.hidden = function( elem ) {
	return !jQuery.expr.pseudos.visible( elem );
};
jQuery.expr.pseudos.visible = function( elem ) {
	return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
};




jQuery.ajaxSettings.xhr = function() {
	try {
		return new window.XMLHttpRequest();
	} catch ( e ) {}
};

var xhrSuccessStatus = {

		// File protocol always yields status code 0, assume 200
		0: 200,

		// Support: IE <=9 only
		// trac-1450: sometimes IE returns 1223 when it should be 204
		1223: 204
	},
	xhrSupported = jQuery.ajaxSettings.xhr();

support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
support.ajax = xhrSupported = !!xhrSupported;

jQuery.ajaxTransport( function( options ) {
	var callback, errorCallback;

	// Cross domain only allowed if supported through XMLHttpRequest
	if ( support.cors || xhrSupported && !options.crossDomain ) {
		return {
			send: function( headers, complete ) {
				var i,
					xhr = options.xhr();

				xhr.open(
					options.type,
					options.url,
					options.async,
					options.username,
					options.password
				);

				// Apply custom fields if provided
				if ( options.xhrFields ) {
					for ( i in options.xhrFields ) {
						xhr[ i ] = options.xhrFields[ i ];
					}
				}

				// Override mime type if needed
				if ( options.mimeType && xhr.overrideMimeType ) {
					xhr.overrideMimeType( options.mimeType );
				}

				// X-Requested-With header
				// For cross-domain requests, seeing as conditions for a preflight are
				// akin to a jigsaw puzzle, we simply never set it to be sure.
				// (it can always be set on a per-request basis or even using ajaxSetup)
				// For same-domain requests, won't change header if already provided.
				if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
					headers[ "X-Requested-With" ] = "XMLHttpRequest";
				}

				// Set headers
				for ( i in headers ) {
					xhr.setRequestHeader( i, headers[ i ] );
				}

				// Callback
				callback = function( type ) {
					return function() {
						if ( callback ) {
							callback = errorCallback = xhr.onload =
								xhr.onerror = xhr.onabort = xhr.ontimeout =
									xhr.onreadystatechange = null;

							if ( type === "abort" ) {
								xhr.abort();
							} else if ( type === "error" ) {

								// Support: IE <=9 only
								// On a manual native abort, IE9 throws
								// errors on any property access that is not readyState
								if ( typeof xhr.status !== "number" ) {
									complete( 0, "error" );
								} else {
									complete(

										// File: protocol always yields status 0; see trac-8605, trac-14207
										xhr.status,
										xhr.statusText
									);
								}
							} else {
								complete(
									xhrSuccessStatus[ xhr.status ] || xhr.status,
									xhr.statusText,

									// Support: IE <=9 only
									// IE9 has no XHR2 but throws on binary (trac-11426)
									// For XHR2 non-text, let the caller handle it (gh-2498)
									( xhr.responseType || "text" ) !== "text"  ||
									typeof xhr.responseText !== "string" ?
										{ binary: xhr.response } :
										{ text: xhr.responseText },
									xhr.getAllResponseHeaders()
								);
							}
						}
					};
				};

				// Listen to events
				xhr.onload = callback();
				errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" );

				// Support: IE 9 only
				// Use onreadystatechange to replace onabort
				// to handle uncaught aborts
				if ( xhr.onabort !== undefined ) {
					xhr.onabort = errorCallback;
				} else {
					xhr.onreadystatechange = function() {

						// Check readyState before timeout as it changes
						if ( xhr.readyState === 4 ) {

							// Allow onerror to be called first,
							// but that will not handle a native abort
							// Also, save errorCallback to a variable
							// as xhr.onerror cannot be accessed
							window.setTimeout( function() {
								if ( callback ) {
									errorCallback();
								}
							} );
						}
					};
				}

				// Create the abort callback
				callback = callback( "abort" );

				try {

					// Do send the request (this may raise an exception)
					xhr.send( options.hasContent && options.data || null );
				} catch ( e ) {

					// trac-14683: Only rethrow if this hasn't been notified as an error yet
					if ( callback ) {
						throw e;
					}
				}
			},

			abort: function() {
				if ( callback ) {
					callback();
				}
			}
		};
	}
} );




// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
jQuery.ajaxPrefilter( function( s ) {
	if ( s.crossDomain ) {
		s.contents.script = false;
	}
} );

// Install script dataType
jQuery.ajaxSetup( {
	accepts: {
		script: "text/javascript, application/javascript, " +
			"application/ecmascript, application/x-ecmascript"
	},
	contents: {
		script: /\b(?:java|ecma)script\b/
	},
	converters: {
		"text script": function( text ) {
			jQuery.globalEval( text );
			return text;
		}
	}
} );

// Handle cache's special case and crossDomain
jQuery.ajaxPrefilter( "script", function( s ) {
	if ( s.cache === undefined ) {
		s.cache = false;
	}
	if ( s.crossDomain ) {
		s.type = "GET";
	}
} );

// Bind script tag hack transport
jQuery.ajaxTransport( "script", function( s ) {

	// This transport only deals with cross domain or forced-by-attrs requests
	if ( s.crossDomain || s.scriptAttrs ) {
		var script, callback;
		return {
			send: function( _, complete ) {
				script = jQuery( "<script>" )
					.attr( s.scriptAttrs || {} )
					.prop( { charset: s.scriptCharset, src: s.url } )
					.on( "load error", callback = function( evt ) {
						script.remove();
						callback = null;
						if ( evt ) {
							complete( evt.type === "error" ? 404 : 200, evt.type );
						}
					} );

				// Use native DOM manipulation to avoid our domManip AJAX trickery
				document.head.appendChild( script[ 0 ] );
			},
			abort: function() {
				if ( callback ) {
					callback();
				}
			}
		};
	}
} );




var oldCallbacks = [],
	rjsonp = /(=)\?(?=&|$)|\?\?/;

// Default jsonp settings
jQuery.ajaxSetup( {
	jsonp: "callback",
	jsonpCallback: function() {
		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce.guid++ ) );
		this[ callback ] = true;
		return callback;
	}
} );

// Detect, normalize options and install callbacks for jsonp requests
jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {

	var callbackName, overwritten, responseContainer,
		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
			"url" :
			typeof s.data === "string" &&
				( s.contentType || "" )
					.indexOf( "application/x-www-form-urlencoded" ) === 0 &&
				rjsonp.test( s.data ) && "data"
		);

	// Handle iff the expected data type is "jsonp" or we have a parameter to set
	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {

		// Get callback name, remembering preexisting value associated with it
		callbackName = s.jsonpCallback = isFunction( s.jsonpCallback ) ?
			s.jsonpCallback() :
			s.jsonpCallback;

		// Insert callback into url or form data
		if ( jsonProp ) {
			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
		} else if ( s.jsonp !== false ) {
			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
		}

		// Use data converter to retrieve json after script execution
		s.converters[ "script json" ] = function() {
			if ( !responseContainer ) {
				jQuery.error( callbackName + " was not called" );
			}
			return responseContainer[ 0 ];
		};

		// Force json dataType
		s.dataTypes[ 0 ] = "json";

		// Install callback
		overwritten = window[ callbackName ];
		window[ callbackName ] = function() {
			responseContainer = arguments;
		};

		// Clean-up function (fires after converters)
		jqXHR.always( function() {

			// If previous value didn't exist - remove it
			if ( overwritten === undefined ) {
				jQuery( window ).removeProp( callbackName );

			// Otherwise restore preexisting value
			} else {
				window[ callbackName ] = overwritten;
			}

			// Save back as free
			if ( s[ callbackName ] ) {

				// Make sure that re-using the options doesn't screw things around
				s.jsonpCallback = originalSettings.jsonpCallback;

				// Save the callback name for future use
				oldCallbacks.push( callbackName );
			}

			// Call if it was a function and we have a response
			if ( responseContainer && isFunction( overwritten ) ) {
				overwritten( responseContainer[ 0 ] );
			}

			responseContainer = overwritten = undefined;
		} );

		// Delegate to script
		return "script";
	}
} );




// Support: Safari 8 only
// In Safari 8 documents created via document.implementation.createHTMLDocument
// collapse sibling forms: the second one becomes a child of the first one.
// Because of that, this security measure has to be disabled in Safari 8.
// https://bugs.webkit.org/show_bug.cgi?id=137337
support.createHTMLDocument = ( function() {
	var body = document.implementation.createHTMLDocument( "" ).body;
	body.innerHTML = "<form></form><form></form>";
	return body.childNodes.length === 2;
} )();


// Argument "data" should be string of html
// context (optional): If specified, the fragment will be created in this context,
// defaults to document
// keepScripts (optional): If true, will include scripts passed in the html string
jQuery.parseHTML = function( data, context, keepScripts ) {
	if ( typeof data !== "string" ) {
		return [];
	}
	if ( typeof context === "boolean" ) {
		keepScripts = context;
		context = false;
	}

	var base, parsed, scripts;

	if ( !context ) {

		// Stop scripts or inline event handlers from being executed immediately
		// by using document.implementation
		if ( support.createHTMLDocument ) {
			context = document.implementation.createHTMLDocument( "" );

			// Set the base href for the created document
			// so any parsed elements with URLs
			// are based on the document's URL (gh-2965)
			base = context.createElement( "base" );
			base.href = document.location.href;
			context.head.appendChild( base );
		} else {
			context = document;
		}
	}

	parsed = rsingleTag.exec( data );
	scripts = !keepScripts && [];

	// Single tag
	if ( parsed ) {
		return [ context.createElement( parsed[ 1 ] ) ];
	}

	parsed = buildFragment( [ data ], context, scripts );

	if ( scripts && scripts.length ) {
		jQuery( scripts ).remove();
	}

	return jQuery.merge( [], parsed.childNodes );
};


/**
 * Load a url into a page
 */
jQuery.fn.load = function( url, params, callback ) {
	var selector, type, response,
		self = this,
		off = url.indexOf( " " );

	if ( off > -1 ) {
		selector = stripAndCollapse( url.slice( off ) );
		url = url.slice( 0, off );
	}

	// If it's a function
	if ( isFunction( params ) ) {

		// We assume that it's the callback
		callback = params;
		params = undefined;

	// Otherwise, build a param string
	} else if ( params && typeof params === "object" ) {
		type = "POST";
	}

	// If we have elements to modify, make the request
	if ( self.length > 0 ) {
		jQuery.ajax( {
			url: url,

			// If "type" variable is undefined, then "GET" method will be used.
			// Make value of this field explicit since
			// user can override it through ajaxSetup method
			type: type || "GET",
			dataType: "html",
			data: params
		} ).done( function( responseText ) {

			// Save response for use in complete callback
			response = arguments;

			self.html( selector ?

				// If a selector was specified, locate the right elements in a dummy div
				// Exclude scripts to avoid IE 'Permission Denied' errors
				jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :

				// Otherwise use the full result
				responseText );

		// If the request succeeds, this function gets "data", "status", "jqXHR"
		// but they are ignored because response was set above.
		// If it fails, this function gets "jqXHR", "status", "error"
		} ).always( callback && function( jqXHR, status ) {
			self.each( function() {
				callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
			} );
		} );
	}

	return this;
};




jQuery.expr.pseudos.animated = function( elem ) {
	return jQuery.grep( jQuery.timers, function( fn ) {
		return elem === fn.elem;
	} ).length;
};




jQuery.offset = {
	setOffset: function( elem, options, i ) {
		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
			position = jQuery.css( elem, "position" ),
			curElem = jQuery( elem ),
			props = {};

		// Set position first, in-case top/left are set even on static elem
		if ( position === "static" ) {
			elem.style.position = "relative";
		}

		curOffset = curElem.offset();
		curCSSTop = jQuery.css( elem, "top" );
		curCSSLeft = jQuery.css( elem, "left" );
		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
			( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;

		// Need to be able to calculate position if either
		// top or left is auto and position is either absolute or fixed
		if ( calculatePosition ) {
			curPosition = curElem.position();
			curTop = curPosition.top;
			curLeft = curPosition.left;

		} else {
			curTop = parseFloat( curCSSTop ) || 0;
			curLeft = parseFloat( curCSSLeft ) || 0;
		}

		if ( isFunction( options ) ) {

			// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
			options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
		}

		if ( options.top != null ) {
			props.top = ( options.top - curOffset.top ) + curTop;
		}
		if ( options.left != null ) {
			props.left = ( options.left - curOffset.left ) + curLeft;
		}

		if ( "using" in options ) {
			options.using.call( elem, props );

		} else {
			curElem.css( props );
		}
	}
};

jQuery.fn.extend( {

	// offset() relates an element's border box to the document origin
	offset: function( options ) {

		// Preserve chaining for setter
		if ( arguments.length ) {
			return options === undefined ?
				this :
				this.each( function( i ) {
					jQuery.offset.setOffset( this, options, i );
				} );
		}

		var rect, win,
			elem = this[ 0 ];

		if ( !elem ) {
			return;
		}

		// Return zeros for disconnected and hidden (display: none) elements (gh-2310)
		// Support: IE <=11 only
		// Running getBoundingClientRect on a
		// disconnected node in IE throws an error
		if ( !elem.getClientRects().length ) {
			return { top: 0, left: 0 };
		}

		// Get document-relative position by adding viewport scroll to viewport-relative gBCR
		rect = elem.getBoundingClientRect();
		win = elem.ownerDocument.defaultView;
		return {
			top: rect.top + win.pageYOffset,
			left: rect.left + win.pageXOffset
		};
	},

	// position() relates an element's margin box to its offset parent's padding box
	// This corresponds to the behavior of CSS absolute positioning
	position: function() {
		if ( !this[ 0 ] ) {
			return;
		}

		var offsetParent, offset, doc,
			elem = this[ 0 ],
			parentOffset = { top: 0, left: 0 };

		// position:fixed elements are offset from the viewport, which itself always has zero offset
		if ( jQuery.css( elem, "position" ) === "fixed" ) {

			// Assume position:fixed implies availability of getBoundingClientRect
			offset = elem.getBoundingClientRect();

		} else {
			offset = this.offset();

			// Account for the *real* offset parent, which can be the document or its root element
			// when a statically positioned element is identified
			doc = elem.ownerDocument;
			offsetParent = elem.offsetParent || doc.documentElement;
			while ( offsetParent &&
				( offsetParent === doc.body || offsetParent === doc.documentElement ) &&
				jQuery.css( offsetParent, "position" ) === "static" ) {

				offsetParent = offsetParent.parentNode;
			}
			if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) {

				// Incorporate borders into its offset, since they are outside its content origin
				parentOffset = jQuery( offsetParent ).offset();
				parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true );
				parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true );
			}
		}

		// Subtract parent offsets and element margins
		return {
			top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
		};
	},

	// This method will return documentElement in the following cases:
	// 1) For the element inside the iframe without offsetParent, this method will return
	//    documentElement of the parent window
	// 2) For the hidden or detached element
	// 3) For body or html element, i.e. in case of the html node - it will return itself
	//
	// but those exceptions were never presented as a real life use-cases
	// and might be considered as more preferable results.
	//
	// This logic, however, is not guaranteed and can change at any point in the future
	offsetParent: function() {
		return this.map( function() {
			var offsetParent = this.offsetParent;

			while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
				offsetParent = offsetParent.offsetParent;
			}

			return offsetParent || documentElement;
		} );
	}
} );

// Create scrollLeft and scrollTop methods
jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
	var top = "pageYOffset" === prop;

	jQuery.fn[ method ] = function( val ) {
		return access( this, function( elem, method, val ) {

			// Coalesce documents and windows
			var win;
			if ( isWindow( elem ) ) {
				win = elem;
			} else if ( elem.nodeType === 9 ) {
				win = elem.defaultView;
			}

			if ( val === undefined ) {
				return win ? win[ prop ] : elem[ method ];
			}

			if ( win ) {
				win.scrollTo(
					!top ? val : win.pageXOffset,
					top ? val : win.pageYOffset
				);

			} else {
				elem[ method ] = val;
			}
		}, method, val, arguments.length );
	};
} );

// Support: Safari <=7 - 9.1, Chrome <=37 - 49
// Add the top/left cssHooks using jQuery.fn.position
// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
// getComputedStyle returns percent when specified for top/left/bottom/right;
// rather than make the css module depend on the offset module, just check for it here
jQuery.each( [ "top", "left" ], function( _i, prop ) {
	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
		function( elem, computed ) {
			if ( computed ) {
				computed = curCSS( elem, prop );

				// If curCSS returns percentage, fallback to offset
				return rnumnonpx.test( computed ) ?
					jQuery( elem ).position()[ prop ] + "px" :
					computed;
			}
		}
	);
} );


// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
	jQuery.each( {
		padding: "inner" + name,
		content: type,
		"": "outer" + name
	}, function( defaultExtra, funcName ) {

		// Margin is only for outerHeight, outerWidth
		jQuery.fn[ funcName ] = function( margin, value ) {
			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );

			return access( this, function( elem, type, value ) {
				var doc;

				if ( isWindow( elem ) ) {

					// $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)
					return funcName.indexOf( "outer" ) === 0 ?
						elem[ "inner" + name ] :
						elem.document.documentElement[ "client" + name ];
				}

				// Get document width or height
				if ( elem.nodeType === 9 ) {
					doc = elem.documentElement;

					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
					// whichever is greatest
					return Math.max(
						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
						elem.body[ "offset" + name ], doc[ "offset" + name ],
						doc[ "client" + name ]
					);
				}

				return value === undefined ?

					// Get width or height on the element, requesting but not forcing parseFloat
					jQuery.css( elem, type, extra ) :

					// Set width or height on the element
					jQuery.style( elem, type, value, extra );
			}, type, chainable ? margin : undefined, chainable );
		};
	} );
} );


jQuery.each( [
	"ajaxStart",
	"ajaxStop",
	"ajaxComplete",
	"ajaxError",
	"ajaxSuccess",
	"ajaxSend"
], function( _i, type ) {
	jQuery.fn[ type ] = function( fn ) {
		return this.on( type, fn );
	};
} );




jQuery.fn.extend( {

	bind: function( types, data, fn ) {
		return this.on( types, null, data, fn );
	},
	unbind: function( types, fn ) {
		return this.off( types, null, fn );
	},

	delegate: function( selector, types, data, fn ) {
		return this.on( types, selector, data, fn );
	},
	undelegate: function( selector, types, fn ) {

		// ( namespace ) or ( selector, types [, fn] )
		return arguments.length === 1 ?
			this.off( selector, "**" ) :
			this.off( types, selector || "**", fn );
	},

	hover: function( fnOver, fnOut ) {
		return this
			.on( "mouseenter", fnOver )
			.on( "mouseleave", fnOut || fnOver );
	}
} );

jQuery.each(
	( "blur focus focusin focusout resize scroll click dblclick " +
	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
	"change select submit keydown keypress keyup contextmenu" ).split( " " ),
	function( _i, name ) {

		// Handle event binding
		jQuery.fn[ name ] = function( data, fn ) {
			return arguments.length > 0 ?
				this.on( name, null, data, fn ) :
				this.trigger( name );
		};
	}
);




// Support: Android <=4.0 only
// Make sure we trim BOM and NBSP
// Require that the "whitespace run" starts from a non-whitespace
// to avoid O(N^2) behavior when the engine would try matching "\s+$" at each space position.
var rtrim = /^[\s\uFEFF\xA0]+|([^\s\uFEFF\xA0])[\s\uFEFF\xA0]+$/g;

// Bind a function to a context, optionally partially applying any
// arguments.
// jQuery.proxy is deprecated to promote standards (specifically Function#bind)
// However, it is not slated for removal any time soon
jQuery.proxy = function( fn, context ) {
	var tmp, args, proxy;

	if ( typeof context === "string" ) {
		tmp = fn[ context ];
		context = fn;
		fn = tmp;
	}

	// Quick check to determine if target is callable, in the spec
	// this throws a TypeError, but we will just return undefined.
	if ( !isFunction( fn ) ) {
		return undefined;
	}

	// Simulated bind
	args = slice.call( arguments, 2 );
	proxy = function() {
		return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
	};

	// Set the guid of unique handler to the same of original handler, so it can be removed
	proxy.guid = fn.guid = fn.guid || jQuery.guid++;

	return proxy;
};

jQuery.holdReady = function( hold ) {
	if ( hold ) {
		jQuery.readyWait++;
	} else {
		jQuery.ready( true );
	}
};
jQuery.isArray = Array.isArray;
jQuery.parseJSON = JSON.parse;
jQuery.nodeName = nodeName;
jQuery.isFunction = isFunction;
jQuery.isWindow = isWindow;
jQuery.camelCase = camelCase;
jQuery.type = toType;

jQuery.now = Date.now;

jQuery.isNumeric = function( obj ) {

	// As of jQuery 3.0, isNumeric is limited to
	// strings and numbers (primitives or objects)
	// that can be coerced to finite numbers (gh-2662)
	var type = jQuery.type( obj );
	return ( type === "number" || type === "string" ) &&

		// parseFloat NaNs numeric-cast false positives ("")
		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
		// subtraction forces infinities to NaN
		!isNaN( obj - parseFloat( obj ) );
};

jQuery.trim = function( text ) {
	return text == null ?
		"" :
		( text + "" ).replace( rtrim, "$1" );
};



// Register as a named AMD module, since jQuery can be concatenated with other
// files that may use define, but not via a proper concatenation script that
// understands anonymous AMD modules. A named AMD is safest and most robust
// way to register. Lowercase jquery is used because AMD module names are
// derived from file names, and jQuery is normally delivered in a lowercase
// file name. Do this after creating the global so that if an AMD module wants
// to call noConflict to hide this version of jQuery, it will work.

// Note that for maximum portability, libraries that are not jQuery should
// declare themselves as anonymous modules, and avoid setting a global if an
// AMD loader is present. jQuery is a special case. For more information, see
// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon

if ( true ) {
	!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function() {
		return jQuery;
	}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
		__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
}




var

	// Map over jQuery in case of overwrite
	_jQuery = window.jQuery,

	// Map over the $ in case of overwrite
	_$ = window.$;

jQuery.noConflict = function( deep ) {
	if ( window.$ === jQuery ) {
		window.$ = _$;
	}

	if ( deep && window.jQuery === jQuery ) {
		window.jQuery = _jQuery;
	}

	return jQuery;
};

// Expose jQuery and $ identifiers, even in AMD
// (trac-7102#comment:10, https://github.com/jquery/jquery/pull/557)
// and CommonJS for browser emulators (trac-13566)
if ( typeof noGlobal === "undefined" ) {
	window.jQuery = window.$ = jQuery;
}




return jQuery;
} );


/***/ }),

/***/ 793:
/***/ ((module) => {

/**
 * @license
 * Copyright 2000, Silicon Graphics, Inc. All Rights Reserved.
 * Copyright 2015, Google Inc. All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice including the dates of first publication and
 * either this permission notice or a reference to http://oss.sgi.com/projects/FreeB/
 * shall be included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
 * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Original Code. The Original Code is: OpenGL Sample Implementation,
 * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
 * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
 * Copyright in any portions created by third parties is as indicated
 * elsewhere herein. All Rights Reserved.
 */
/**
 * @author ericv@cs.stanford.edu (Eric Veach)
 * @author bckenny@google.com (Brendan Kenny)
 */

/**
 * Base namespace.
 * @const
 */
var libtess = {};

/**
 * Whether to run asserts and extra debug checks.
 * @define {boolean}
 */
libtess.DEBUG = false;

/**
 * Checks if the condition evaluates to true if libtess.DEBUG is true.
 * @param {*} condition The condition to check.
 * @param {string=} opt_message Error message in case of failure.
 * @throws {Error} Assertion failed, the condition evaluates to false.
 */
libtess.assert = function(condition, opt_message) {
  if (libtess.DEBUG && !condition) {
    throw new Error('Assertion failed' +
        (opt_message ? ': ' + opt_message : ''));
  }
};

/**
 * The maximum vertex coordinate size, 1e150. Anything larger will trigger a
 * GLU_TESS_COORD_TOO_LARGE error callback and the vertex will be clamped to
 * this value for all tessellation calculations.
 * @const {number}
 */
libtess.GLU_TESS_MAX_COORD = 1e150;
// NOTE(bckenny): value from glu.pl generator

/**
 * Normally the polygon is projected to a plane perpendicular to one of the
 * three coordinate axes before tessellating in 2d. This helps numerical
 * accuracy by forgoing a transformation step by simply dropping one coordinate
 * dimension.
 *
 * However, this can affect the placement of intersection points for non-axis-
 * aligned polygons. Setting TRUE_PROJECT to true will instead project onto a
 * plane actually perpendicular to the polygon's normal.
 *
 * NOTE(bckenny): I can find no instances on the internet in which this mode has
 * been used, but it's difficult to search for. This was a compile-time setting
 * in the original, so setting this as constant. If this is exposed in the
 * public API, remove the ignore coverage directives on
 * libtess.normal.projectPolygon and libtess.normal.normalize_.
 * @const {boolean}
 */
libtess.TRUE_PROJECT = false;

/**
 * The default tolerance for merging features, 0, meaning vertices are only
 * merged if they are exactly coincident
 * If a higher tolerance is needed, significant rewriting will need to occur.
 * See libtess.sweep.TOLERANCE_NONZERO_ as a starting place.
 * @const {number}
 */
libtess.GLU_TESS_DEFAULT_TOLERANCE = 0;

/**
 * The input contours parition the plane into regions. A winding
 * rule determines which of these regions are inside the polygon.
 *
 * For a single contour C, the winding number of a point x is simply
 * the signed number of revolutions we make around x as we travel
 * once around C (where CCW is positive). When there are several
 * contours, the individual winding numbers are summed. This
 * procedure associates a signed integer value with each point x in
 * the plane. Note that the winding number is the same for all
 * points in a single region.
 *
 * The winding rule classifies a region as "inside" if its winding
 * number belongs to the chosen category (odd, nonzero, positive,
 * negative, or absolute value of at least two). The current GLU
 * tesselator implements the "odd" rule. The "nonzero" rule is another
 * common way to define the interior. The other three rules are
 * useful for polygon CSG operations.
 * @enum {number}
 */
libtess.windingRule = {
  // NOTE(bckenny): values from enumglu.spec
  GLU_TESS_WINDING_ODD: 100130,
  GLU_TESS_WINDING_NONZERO: 100131,
  GLU_TESS_WINDING_POSITIVE: 100132,
  GLU_TESS_WINDING_NEGATIVE: 100133,
  GLU_TESS_WINDING_ABS_GEQ_TWO: 100134
};

/**
 * The type of primitive return from a "begin" callback. GL_LINE_LOOP is only
 * returned when GLU_TESS_BOUNDARY_ONLY is true. GL_TRIANGLE_STRIP and
 * GL_TRIANGLE_FAN are no longer returned since 1.1.0 (see release notes).
 * @enum {number}
 */
libtess.primitiveType = {
  GL_LINE_LOOP: 2,
  GL_TRIANGLES: 4,
  GL_TRIANGLE_STRIP: 5,
  GL_TRIANGLE_FAN: 6
};

/**
 * The types of errors provided in the error callback.
 * @enum {number}
 */
libtess.errorType = {
  // TODO(bckenny) doc types
  // NOTE(bckenny): values from enumglu.spec
  GLU_TESS_MISSING_BEGIN_POLYGON: 100151,
  GLU_TESS_MISSING_END_POLYGON: 100153,
  GLU_TESS_MISSING_BEGIN_CONTOUR: 100152,
  GLU_TESS_MISSING_END_CONTOUR: 100154,
  GLU_TESS_COORD_TOO_LARGE: 100155,
  GLU_TESS_NEED_COMBINE_CALLBACK: 100156
};

/**
 * Enum values necessary for providing settings and callbacks. See the readme
 * for details.
 * @enum {number}
 */
libtess.gluEnum = {
  // TODO(bckenny): rename so not always typing libtess.gluEnum.*?

  // NOTE(bckenny): values from enumglu.spec
  GLU_TESS_BEGIN: 100100,
  GLU_TESS_VERTEX: 100101,
  GLU_TESS_END: 100102,
  GLU_TESS_ERROR: 100103,
  GLU_TESS_EDGE_FLAG: 100104,
  GLU_TESS_COMBINE: 100105,
  GLU_TESS_BEGIN_DATA: 100106,
  GLU_TESS_VERTEX_DATA: 100107,
  GLU_TESS_END_DATA: 100108,
  GLU_TESS_ERROR_DATA: 100109,
  GLU_TESS_EDGE_FLAG_DATA: 100110,
  GLU_TESS_COMBINE_DATA: 100111,

  GLU_TESS_MESH: 100112,  //  NOTE(bckenny): from tess.c
  GLU_TESS_TOLERANCE: 100142,
  GLU_TESS_WINDING_RULE: 100140,
  GLU_TESS_BOUNDARY_ONLY: 100141,

  // TODO(bckenny): move this to libtess.errorType?
  GLU_INVALID_ENUM: 100900,
  GLU_INVALID_VALUE: 100901
};

/** @typedef {number} */
libtess.PQHandle;

/* global libtess */

/** @const */
libtess.geom = {};

/**
 * Returns whether vertex u and vertex v are equal.
 * @param {libtess.GluVertex} u
 * @param {libtess.GluVertex} v
 * @return {boolean}
 */
libtess.geom.vertEq = function(u, v) {
  return u.s === v.s && u.t === v.t;
};

/**
 * Returns whether vertex u is lexicographically less than or equal to vertex v.
 * @param {libtess.GluVertex} u
 * @param {libtess.GluVertex} v
 * @return {boolean}
 */
libtess.geom.vertLeq = function(u, v) {
  return (u.s < v.s) || (u.s === v.s && u.t <= v.t);
};

/**
 * Given three vertices u,v,w such that geom.vertLeq(u,v) && geom.vertLeq(v,w),
 * evaluates the t-coord of the edge uw at the s-coord of the vertex v.
 * Returns v.t - (uw)(v.s), ie. the signed distance from uw to v.
 * If uw is vertical (and thus passes thru v), the result is zero.
 *
 * The calculation is extremely accurate and stable, even when v
 * is very close to u or w.  In particular if we set v.t = 0 and
 * let r be the negated result (this evaluates (uw)(v.s)), then
 * r is guaranteed to satisfy MIN(u.t,w.t) <= r <= MAX(u.t,w.t).
 * @param {libtess.GluVertex} u
 * @param {libtess.GluVertex} v
 * @param {libtess.GluVertex} w
 * @return {number}
 */
libtess.geom.edgeEval = function(u, v, w) {

  var gapL = v.s - u.s;
  var gapR = w.s - v.s;

  if (gapL + gapR > 0) {
    if (gapL < gapR) {
      return (v.t - u.t) + (u.t - w.t) * (gapL / (gapL + gapR));
    } else {
      return (v.t - w.t) + (w.t - u.t) * (gapR / (gapL + gapR));
    }
  }

  // vertical line
  return 0;
};

/**
 * Returns a number whose sign matches geom.edgeEval(u,v,w) but which
 * is cheaper to evaluate.  Returns > 0, == 0 , or < 0
 * as v is above, on, or below the edge uw.
 * @param {libtess.GluVertex} u
 * @param {libtess.GluVertex} v
 * @param {libtess.GluVertex} w
 * @return {number}
 */
libtess.geom.edgeSign = function(u, v, w) {

  var gapL = v.s - u.s;
  var gapR = w.s - v.s;

  if (gapL + gapR > 0) {
    return (v.t - w.t) * gapL + (v.t - u.t) * gapR;
  }

  // vertical line
  return 0;
};

/**
 * Version of VertLeq with s and t transposed.
 * Returns whether vertex u is lexicographically less than or equal to vertex v.
 * @param {libtess.GluVertex} u
 * @param {libtess.GluVertex} v
 * @return {boolean}
 */
libtess.geom.transLeq = function(u, v) {
  return (u.t < v.t) || (u.t === v.t && u.s <= v.s);
};

/**
 * Version of geom.edgeEval with s and t transposed.
 * Given three vertices u,v,w such that geom.transLeq(u,v) &&
 * geom.transLeq(v,w), evaluates the t-coord of the edge uw at the s-coord of
 * the vertex v. Returns v.s - (uw)(v.t), ie. the signed distance from uw to v.
 * If uw is vertical (and thus passes thru v), the result is zero.
 *
 * The calculation is extremely accurate and stable, even when v
 * is very close to u or w.  In particular if we set v.s = 0 and
 * let r be the negated result (this evaluates (uw)(v.t)), then
 * r is guaranteed to satisfy MIN(u.s,w.s) <= r <= MAX(u.s,w.s).
 * @param {libtess.GluVertex} u
 * @param {libtess.GluVertex} v
 * @param {libtess.GluVertex} w
 * @return {number}
 */
libtess.geom.transEval = function(u, v, w) {

  var gapL = v.t - u.t;
  var gapR = w.t - v.t;

  if (gapL + gapR > 0) {
    if (gapL < gapR) {
      return (v.s - u.s) + (u.s - w.s) * (gapL / (gapL + gapR));
    } else {
      return (v.s - w.s) + (w.s - u.s) * (gapR / (gapL + gapR));
    }
  }

  // vertical line
  return 0;
};

/**
 * Version of geom.edgeSign with s and t transposed.
 * Returns a number whose sign matches geom.transEval(u,v,w) but which
 * is cheaper to evaluate.  Returns > 0, == 0 , or < 0
 * as v is above, on, or below the edge uw.
 * @param {libtess.GluVertex} u
 * @param {libtess.GluVertex} v
 * @param {libtess.GluVertex} w
 * @return {number}
 */
libtess.geom.transSign = function(u, v, w) {

  var gapL = v.t - u.t;
  var gapR = w.t - v.t;

  if (gapL + gapR > 0) {
    return (v.s - w.s) * gapL + (v.s - u.s) * gapR;
  }

  // vertical line
  return 0;
};

/**
 * Returns whether edge is directed from right to left.
 * @param {libtess.GluHalfEdge} e
 * @return {boolean}
 */
libtess.geom.edgeGoesLeft = function(e) {
  return libtess.geom.vertLeq(e.dst(), e.org);
};

/**
 * Returns whether edge is directed from left to right.
 * @param {libtess.GluHalfEdge} e
 * @return {boolean}
 */
libtess.geom.edgeGoesRight = function(e) {
  return libtess.geom.vertLeq(e.org, e.dst());
};

/**
 * Calculates the L1 distance between vertices u and v.
 * @param {libtess.GluVertex} u
 * @param {libtess.GluVertex} v
 * @return {number}
 */
libtess.geom.vertL1dist = function(u, v) {
  return Math.abs(u.s - v.s) + Math.abs(u.t - v.t);
};

// NOTE(bckenny): vertCCW is called nowhere in libtess and isn't part of the
// public API.
/* istanbul ignore next */
/**
 * For almost-degenerate situations, the results are not reliable.
 * Unless the floating-point arithmetic can be performed without
 * rounding errors, *any* implementation will give incorrect results
 * on some degenerate inputs, so the client must have some way to
 * handle this situation.
 * @param {!libtess.GluVertex} u
 * @param {!libtess.GluVertex} v
 * @param {!libtess.GluVertex} w
 * @return {boolean}
 */
libtess.geom.vertCCW = function(u, v, w) {
  return (u.s * (v.t - w.t) + v.s * (w.t - u.t) + w.s * (u.t - v.t)) >= 0;
};

/**
 * Given parameters a,x,b,y returns the value (b*x+a*y)/(a+b),
 * or (x+y)/2 if a==b==0. It requires that a,b >= 0, and enforces
 * this in the rare case that one argument is slightly negative.
 * The implementation is extremely stable numerically.
 * In particular it guarantees that the result r satisfies
 * MIN(x,y) <= r <= MAX(x,y), and the results are very accurate
 * even when a and b differ greatly in magnitude.
 * @private
 * @param {number} a
 * @param {number} x
 * @param {number} b
 * @param {number} y
 * @return {number}
 */
libtess.geom.interpolate_ = function(a, x, b, y) {
  // from Macro RealInterpolate:
  //(a = (a < 0) ? 0 : a, b = (b < 0) ? 0 : b, ((a <= b) ? ((b == 0) ? ((x+y) / 2) : (x + (y-x) * (a/(a+b)))) : (y + (x-y) * (b/(a+b)))))
  a = (a < 0) ? 0 : a;
  b = (b < 0) ? 0 : b;

  if (a <= b) {
    if (b === 0) {
      return (x + y) / 2;
    } else {
      return x + (y - x) * (a / (a + b));
    }
  } else {
    return y + (x - y) * (b / (a + b));
  }
};

/**
 * Given edges (o1,d1) and (o2,d2), compute their point of intersection.
 * The computed point is guaranteed to lie in the intersection of the
 * bounding rectangles defined by each edge.
 * @param {!libtess.GluVertex} o1
 * @param {!libtess.GluVertex} d1
 * @param {!libtess.GluVertex} o2
 * @param {!libtess.GluVertex} d2
 * @param {!libtess.GluVertex} v
 */
libtess.geom.edgeIntersect = function(o1, d1, o2, d2, v) {
  // This is certainly not the most efficient way to find the intersection
  // of two line segments, but it is very numerically stable.

  // Strategy: find the two middle vertices in the VertLeq ordering,
  // and interpolate the intersection s-value from these. Then repeat
  // using the TransLeq ordering to find the intersection t-value.
  var z1;
  var z2;
  var tmp;
  if (!libtess.geom.vertLeq(o1, d1)) {
    // Swap(o1, d1);
    tmp = o1;
    o1 = d1;
    d1 = tmp;
  }
  if (!libtess.geom.vertLeq(o2, d2)) {
    // Swap(o2, d2);
    tmp = o2;
    o2 = d2;
    d2 = tmp;
  }
  if (!libtess.geom.vertLeq(o1, o2)) {
    // Swap(o1, o2);
    tmp = o1;
    o1 = o2;
    o2 = tmp;
    // Swap(d1, d2);
    tmp = d1;
    d1 = d2;
    d2 = tmp;
  }

  if (!libtess.geom.vertLeq(o2, d1)) {
    // Technically, no intersection -- do our best
    v.s = (o2.s + d1.s) / 2;

  } else if (libtess.geom.vertLeq(d1, d2)) {
    // Interpolate between o2 and d1
    z1 = libtess.geom.edgeEval(o1, o2, d1);
    z2 = libtess.geom.edgeEval(o2, d1, d2);
    if (z1 + z2 < 0) { z1 = -z1; z2 = -z2; }
    v.s = libtess.geom.interpolate_(z1, o2.s, z2, d1.s);

  } else {
    // Interpolate between o2 and d2
    z1 = libtess.geom.edgeSign(o1, o2, d1);
    z2 = -libtess.geom.edgeSign(o1, d2, d1);
    if (z1 + z2 < 0) { z1 = -z1; z2 = -z2; }
    v.s = libtess.geom.interpolate_(z1, o2.s, z2, d2.s);
  }

  // Now repeat the process for t
  if (!libtess.geom.transLeq(o1, d1)) {
    // Swap(o1, d1);
    tmp = o1;
    o1 = d1;
    d1 = tmp;
  }
  if (!libtess.geom.transLeq(o2, d2)) {
    // Swap(o2, d2);
    tmp = o2;
    o2 = d2;
    d2 = tmp;
  }
  if (!libtess.geom.transLeq(o1, o2)) {
    // Swap(o1, o2);
    tmp = o1;
    o1 = o2;
    o2 = tmp;
    // Swap(d1, d2);
    tmp = d1;
    d1 = d2;
    d2 = tmp;
  }

  if (!libtess.geom.transLeq(o2, d1)) {
    // Technically, no intersection -- do our best
    v.t = (o2.t + d1.t) / 2;

  } else if (libtess.geom.transLeq(d1, d2)) {
    // Interpolate between o2 and d1
    z1 = libtess.geom.transEval(o1, o2, d1);
    z2 = libtess.geom.transEval(o2, d1, d2);
    if (z1 + z2 < 0) { z1 = -z1; z2 = -z2; }
    v.t = libtess.geom.interpolate_(z1, o2.t, z2, d1.t);

  } else {
    // Interpolate between o2 and d2
    z1 = libtess.geom.transSign(o1, o2, d1);
    z2 = -libtess.geom.transSign(o1, d2, d1);
    if (z1 + z2 < 0) { z1 = -z1; z2 = -z2; }
    v.t = libtess.geom.interpolate_(z1, o2.t, z2, d2.t);
  }
};

/* global libtess */

// TODO(bckenny): could maybe merge GluMesh and mesh.js since these are
// operations on the mesh

/** @const */
libtess.mesh = {};

/****************** Basic Edge Operations **********************/


/**
 * makeEdge creates one edge, two vertices, and a loop (face).
 * The loop consists of the two new half-edges.
 *
 * @param {libtess.GluMesh} mesh [description].
 * @return {libtess.GluHalfEdge} [description].
 */
libtess.mesh.makeEdge = function(mesh) {
  // TODO(bckenny): probably move to GluMesh, but needs Make* methods with it

  var e = libtess.mesh.makeEdgePair_(mesh.eHead);

  // complete edge with vertices and face (see mesh.makeEdgePair_)
  libtess.mesh.makeVertex_(e, mesh.vHead);
  libtess.mesh.makeVertex_(e.sym, mesh.vHead);
  libtess.mesh.makeFace_(e, mesh.fHead);

  return e;
};


/**
 * meshSplice(eOrg, eDst) is the basic operation for changing the
 * mesh connectivity and topology. It changes the mesh so that
 *  eOrg.oNext <- OLD( eDst.oNext )
 *  eDst.oNext <- OLD( eOrg.oNext )
 * where OLD(...) means the value before the meshSplice operation.
 *
 * This can have two effects on the vertex structure:
 *  - if eOrg.org != eDst.org, the two vertices are merged together
 *  - if eOrg.org == eDst.org, the origin is split into two vertices
 * In both cases, eDst.org is changed and eOrg.org is untouched.
 *
 * Similarly (and independently) for the face structure,
 *  - if eOrg.lFace == eDst.lFace, one loop is split into two
 *  - if eOrg.lFace != eDst.lFace, two distinct loops are joined into one
 * In both cases, eDst.lFace is changed and eOrg.lFace is unaffected.
 *
 * Some special cases:
 * If eDst == eOrg, the operation has no effect.
 * If eDst == eOrg.lNext, the new face will have a single edge.
 * If eDst == eOrg.lPrev(), the old face will have a single edge.
 * If eDst == eOrg.oNext, the new vertex will have a single edge.
 * If eDst == eOrg.oPrev(), the old vertex will have a single edge.
 *
 * @param {libtess.GluHalfEdge} eOrg [description].
 * @param {libtess.GluHalfEdge} eDst [description].
 */
libtess.mesh.meshSplice = function(eOrg, eDst) {
  // TODO: more descriptive name?

  var joiningLoops = false;
  var joiningVertices = false;

  if (eOrg === eDst) {
    return;
  }

  if (eDst.org !== eOrg.org) {
    // We are merging two disjoint vertices -- destroy eDst.org
    joiningVertices = true;
    libtess.mesh.killVertex_(eDst.org, eOrg.org);
  }

  if (eDst.lFace !== eOrg.lFace) {
    // We are connecting two disjoint loops -- destroy eDst.lFace
    joiningLoops = true;
    libtess.mesh.killFace_(eDst.lFace, eOrg.lFace);
  }

  // Change the edge structure
  libtess.mesh.splice_(eDst, eOrg);

  if (!joiningVertices) {
    // We split one vertex into two -- the new vertex is eDst.org.
    // Make sure the old vertex points to a valid half-edge.
    libtess.mesh.makeVertex_(eDst, eOrg.org);
    eOrg.org.anEdge = eOrg;
  }

  if (!joiningLoops) {
    // We split one loop into two -- the new loop is eDst.lFace.
    // Make sure the old face points to a valid half-edge.
    libtess.mesh.makeFace_(eDst, eOrg.lFace);
    eOrg.lFace.anEdge = eOrg;
  }
};


/**
 * deleteEdge(eDel) removes the edge eDel. There are several cases:
 * if (eDel.lFace != eDel.rFace()), we join two loops into one; the loop
 * eDel.lFace is deleted. Otherwise, we are splitting one loop into two;
 * the newly created loop will contain eDel.dst(). If the deletion of eDel
 * would create isolated vertices, those are deleted as well.
 *
 * This function could be implemented as two calls to __gl_meshSplice
 * plus a few calls to memFree, but this would allocate and delete
 * unnecessary vertices and faces.
 *
 * @param {libtess.GluHalfEdge} eDel [description].
 */
libtess.mesh.deleteEdge = function(eDel) {
  var eDelSym = eDel.sym;
  var joiningLoops = false;

  // First step: disconnect the origin vertex eDel.org.  We make all
  // changes to get a consistent mesh in this "intermediate" state.
  if (eDel.lFace !== eDel.rFace()) {
    // We are joining two loops into one -- remove the left face
    joiningLoops = true;
    libtess.mesh.killFace_(eDel.lFace, eDel.rFace());
  }

  if (eDel.oNext === eDel) {
    libtess.mesh.killVertex_(eDel.org, null);

  } else {
    // Make sure that eDel.org and eDel.rFace() point to valid half-edges
    eDel.rFace().anEdge = eDel.oPrev();
    eDel.org.anEdge = eDel.oNext;

    libtess.mesh.splice_(eDel, eDel.oPrev());

    if (!joiningLoops) {
      // We are splitting one loop into two -- create a new loop for eDel.
      libtess.mesh.makeFace_(eDel, eDel.lFace);
    }
  }

  // Claim: the mesh is now in a consistent state, except that eDel.org
  // may have been deleted.  Now we disconnect eDel.dst().
  if (eDelSym.oNext === eDelSym) {
    libtess.mesh.killVertex_(eDelSym.org, null);
    libtess.mesh.killFace_(eDelSym.lFace, null);

  } else {
    // Make sure that eDel.dst() and eDel.lFace point to valid half-edges
    eDel.lFace.anEdge = eDelSym.oPrev();
    eDelSym.org.anEdge = eDelSym.oNext;
    libtess.mesh.splice_(eDelSym, eDelSym.oPrev());
  }

  // Any isolated vertices or faces have already been freed.
  libtess.mesh.killEdge_(eDel);
};

/******************** Other Edge Operations **********************/

/* All these routines can be implemented with the basic edge
 * operations above.  They are provided for convenience and efficiency.
 */


/**
 * addEdgeVertex(eOrg) creates a new edge eNew such that
 * eNew == eOrg.lNext, and eNew.dst() is a newly created vertex.
 * eOrg and eNew will have the same left face.
 *
 * @param {libtess.GluHalfEdge} eOrg [description].
 * @return {libtess.GluHalfEdge} [description].
 */
libtess.mesh.addEdgeVertex = function(eOrg) {
  // TODO(bckenny): why is it named this?

  var eNew = libtess.mesh.makeEdgePair_(eOrg);
  var eNewSym = eNew.sym;

  // Connect the new edge appropriately
  libtess.mesh.splice_(eNew, eOrg.lNext);

  // Set the vertex and face information
  eNew.org = eOrg.dst();

  libtess.mesh.makeVertex_(eNewSym, eNew.org);

  eNew.lFace = eNewSym.lFace = eOrg.lFace;

  return eNew;
};


/**
 * splitEdge(eOrg) splits eOrg into two edges eOrg and eNew,
 * such that eNew == eOrg.lNext. The new vertex is eOrg.dst() == eNew.org.
 * eOrg and eNew will have the same left face.
 *
 * @param {libtess.GluHalfEdge} eOrg [description].
 * @return {!libtess.GluHalfEdge} [description].
 */
libtess.mesh.splitEdge = function(eOrg) {
  var tempHalfEdge = libtess.mesh.addEdgeVertex(eOrg);
  var eNew = tempHalfEdge.sym;

  // Disconnect eOrg from eOrg.dst() and connect it to eNew.org
  libtess.mesh.splice_(eOrg.sym, eOrg.sym.oPrev());
  libtess.mesh.splice_(eOrg.sym, eNew);

  // Set the vertex and face information
  eOrg.sym.org = eNew.org; // NOTE(bckenny): assignment to dst
  eNew.dst().anEdge = eNew.sym;  // may have pointed to eOrg.sym
  eNew.sym.lFace = eOrg.rFace(); // NOTE(bckenny): assignment to rFace
  eNew.winding = eOrg.winding;  // copy old winding information
  eNew.sym.winding = eOrg.sym.winding;

  return eNew;
};


/**
 * connect(eOrg, eDst) creates a new edge from eOrg.dst()
 * to eDst.org, and returns the corresponding half-edge eNew.
 * If eOrg.lFace == eDst.lFace, this splits one loop into two,
 * and the newly created loop is eNew.lFace. Otherwise, two disjoint
 * loops are merged into one, and the loop eDst.lFace is destroyed.
 *
 * If (eOrg == eDst), the new face will have only two edges.
 * If (eOrg.lNext == eDst), the old face is reduced to a single edge.
 * If (eOrg.lNext.lNext == eDst), the old face is reduced to two edges.
 *
 * @param {libtess.GluHalfEdge} eOrg [description].
 * @param {libtess.GluHalfEdge} eDst [description].
 * @return {!libtess.GluHalfEdge} [description].
 */
libtess.mesh.connect = function(eOrg, eDst) {
  var joiningLoops = false;
  var eNew = libtess.mesh.makeEdgePair_(eOrg);
  var eNewSym = eNew.sym;

  if (eDst.lFace !== eOrg.lFace) {
    // We are connecting two disjoint loops -- destroy eDst.lFace
    joiningLoops = true;
    libtess.mesh.killFace_(eDst.lFace, eOrg.lFace);
  }

  // Connect the new edge appropriately
  libtess.mesh.splice_(eNew, eOrg.lNext);
  libtess.mesh.splice_(eNewSym, eDst);

  // Set the vertex and face information
  eNew.org = eOrg.dst();
  eNewSym.org = eDst.org;
  eNew.lFace = eNewSym.lFace = eOrg.lFace;

  // Make sure the old face points to a valid half-edge
  eOrg.lFace.anEdge = eNewSym;

  if (!joiningLoops) {
    // We split one loop into two -- the new loop is eNew.lFace
    libtess.mesh.makeFace_(eNew, eOrg.lFace);
  }
  return eNew;
};

/******************** Other Operations **********************/


/**
 * zapFace(fZap) destroys a face and removes it from the
 * global face list. All edges of fZap will have a null pointer as their
 * left face. Any edges which also have a null pointer as their right face
 * are deleted entirely (along with any isolated vertices this produces).
 * An entire mesh can be deleted by zapping its faces, one at a time,
 * in any order. Zapped faces cannot be used in further mesh operations!
 *
 * @param {libtess.GluFace} fZap [description].
 */
libtess.mesh.zapFace = function(fZap) {
  var eStart = fZap.anEdge;

  // walk around face, deleting edges whose right face is also NULL
  var eNext = eStart.lNext;
  var e;
  do {
    e = eNext;
    eNext = e.lNext;

    e.lFace = null;
    if (e.rFace() === null) {
      // delete the edge -- see mesh.deleteEdge above
      if (e.oNext === e) {
        libtess.mesh.killVertex_(e.org, null);

      } else {
        // Make sure that e.org points to a valid half-edge
        e.org.anEdge = e.oNext;
        libtess.mesh.splice_(e, e.oPrev());
      }

      var eSym = e.sym;

      if (eSym.oNext === eSym) {
        libtess.mesh.killVertex_(eSym.org, null);

      } else {
        // Make sure that eSym.org points to a valid half-edge
        eSym.org.anEdge = eSym.oNext;
        libtess.mesh.splice_(eSym, eSym.oPrev());
      }
      libtess.mesh.killEdge_(e);
    }
  } while (e !== eStart);

  // delete from circular doubly-linked list
  var fPrev = fZap.prev;
  var fNext = fZap.next;
  fNext.prev = fPrev;
  fPrev.next = fNext;

  // TODO(bckenny): memFree( fZap );
  // TODO(bckenny): probably null at callsite
};

// TODO(bckenny): meshUnion isn't called within libtess and isn't part of the
// public API. Could be useful if more mesh manipulation functions are exposed.
/* istanbul ignore next */
/**
 * meshUnion() forms the union of all structures in
 * both meshes, and returns the new mesh (the old meshes are destroyed).
 *
 * @param {!libtess.GluMesh} mesh1
 * @param {!libtess.GluMesh} mesh2
 * @return {!libtess.GluMesh}
 */
libtess.mesh.meshUnion = function(mesh1, mesh2) {
  // TODO(bceknny): probably move to GluMesh method
  var f1 = mesh1.fHead;
  var v1 = mesh1.vHead;
  var e1 = mesh1.eHead;

  var f2 = mesh2.fHead;
  var v2 = mesh2.vHead;
  var e2 = mesh2.eHead;

  // Add the faces, vertices, and edges of mesh2 to those of mesh1
  if (f2.next !== f2) {
    f1.prev.next = f2.next;
    f2.next.prev = f1.prev;
    f2.prev.next = f1;
    f1.prev = f2.prev;
  }

  if (v2.next !== v2) {
    v1.prev.next = v2.next;
    v2.next.prev = v1.prev;
    v2.prev.next = v1;
    v1.prev = v2.prev;
  }

  if (e2.next !== e2) {
    e1.sym.next.sym.next = e2.next;
    e2.next.sym.next = e1.sym.next;
    e2.sym.next.sym.next = e1;
    e1.sym.next = e2.sym.next;
  }

  // TODO(bckenny): memFree(mesh2);
  // TODO(bckenny): If function is kept, remove mesh2's data to enforce.
  return mesh1;
};


/**
 * deleteMesh(mesh) will free all storage for any valid mesh.
 * @param {libtess.GluMesh} mesh [description].
 */
libtess.mesh.deleteMesh = function(mesh) {
  // TODO(bckenny): unnecessary, I think.
  // TODO(bckenny): might want to explicitly null at callsite
  // lots of memFrees. see also DELETE_BY_ZAPPING
};

/************************ Utility Routines ************************/


/**
 * Creates a new pair of half-edges which form their own loop.
 * No vertex or face structures are allocated, but these must be assigned
 * before the current edge operation is completed.
 *
 * TODO(bckenny): warning about eNext strictly being first of pair? (see code)
 *
 * @private
 * @param {libtess.GluHalfEdge} eNext [description].
 * @return {libtess.GluHalfEdge} [description].
 */
libtess.mesh.makeEdgePair_ = function(eNext) {
  var e = new libtess.GluHalfEdge();
  var eSym = new libtess.GluHalfEdge();

  // TODO(bckenny): how do we ensure this? see above comment in jsdoc
  // Make sure eNext points to the first edge of the edge pair
  // if (eNext->Sym < eNext ) { eNext = eNext->Sym; }

  // NOTE(bckenny): check this for bugs in current implementation!

  // Insert in circular doubly-linked list before eNext.
  // Note that the prev pointer is stored in sym.next.
  var ePrev = eNext.sym.next;
  eSym.next = ePrev;
  ePrev.sym.next = e;
  e.next = eNext;
  eNext.sym.next = eSym;

  e.sym = eSym;
  e.oNext = e;
  e.lNext = eSym;

  eSym.sym = e;
  eSym.oNext = eSym;
  eSym.lNext = e;

  return e;
};


/**
 * splice_ is best described by the Guibas/Stolfi paper or the
 * CS348a notes. Basically, it modifies the mesh so that
 * a.oNext and b.oNext are exchanged. This can have various effects
 * depending on whether a and b belong to different face or vertex rings.
 * For more explanation see mesh.meshSplice below.
 *
 * @private
 * @param {libtess.GluHalfEdge} a [description].
 * @param {libtess.GluHalfEdge} b [description].
 */
libtess.mesh.splice_ = function(a, b) {
  var aONext = a.oNext;
  var bONext = b.oNext;

  aONext.sym.lNext = b;
  bONext.sym.lNext = a;
  a.oNext = bONext;
  b.oNext = aONext;
};


/**
 * makeVertex_(eOrig, vNext) attaches a new vertex and makes it the
 * origin of all edges in the vertex loop to which eOrig belongs. "vNext" gives
 * a place to insert the new vertex in the global vertex list.  We insert
 * the new vertex *before* vNext so that algorithms which walk the vertex
 * list will not see the newly created vertices.
 *
 * NOTE: unlike original, acutally allocates new vertex.
 *
 * @private
 * @param {libtess.GluHalfEdge} eOrig [description].
 * @param {libtess.GluVertex} vNext [description].
 */
libtess.mesh.makeVertex_ = function(eOrig, vNext) {
  // insert in circular doubly-linked list before vNext
  var vPrev = vNext.prev;
  var vNew = new libtess.GluVertex(vNext, vPrev);
  vPrev.next = vNew;
  vNext.prev = vNew;

  vNew.anEdge = eOrig;
  // leave coords, s, t undefined
  // TODO(bckenny): does above line mean 0 specifically, or does it matter?

  // fix other edges on this vertex loop
  var e = eOrig;
  do {
    e.org = vNew;
    e = e.oNext;
  } while (e !== eOrig);
};


/**
 * makeFace_(eOrig, fNext) attaches a new face and makes it the left
 * face of all edges in the face loop to which eOrig belongs. "fNext" gives
 * a place to insert the new face in the global face list.  We insert
 * the new face *before* fNext so that algorithms which walk the face
 * list will not see the newly created faces.
 *
 * NOTE: unlike original, acutally allocates new face.
 *
 * @private
 * @param {libtess.GluHalfEdge} eOrig [description].
 * @param {libtess.GluFace} fNext [description].
 */
libtess.mesh.makeFace_ = function(eOrig, fNext) {
  // insert in circular doubly-linked list before fNext
  var fPrev = fNext.prev;
  var fNew = new libtess.GluFace(fNext, fPrev);
  fPrev.next = fNew;
  fNext.prev = fNew;

  fNew.anEdge = eOrig;

  // The new face is marked "inside" if the old one was.  This is a
  // convenience for the common case where a face has been split in two.
  fNew.inside = fNext.inside;

  // fix other edges on this face loop
  var e = eOrig;
  do {
    e.lFace = fNew;
    e = e.lNext;
  } while (e !== eOrig);
};


/**
 * killEdge_ destroys an edge (the half-edges eDel and eDel.sym),
 * and removes from the global edge list.
 *
 * @private
 * @param {libtess.GluHalfEdge} eDel [description].
 */
libtess.mesh.killEdge_ = function(eDel) {
  // TODO(bckenny): in this case, no need to worry(?), but check when checking mesh.makeEdgePair_
  // Half-edges are allocated in pairs, see EdgePair above
  // if (eDel->Sym < eDel ) { eDel = eDel->Sym; }

  // delete from circular doubly-linked list
  var eNext = eDel.next;
  var ePrev = eDel.sym.next;
  eNext.sym.next = ePrev;
  ePrev.sym.next = eNext;

  // TODO(bckenny): memFree( eDel ); (which also frees eDel.sym)
  // TODO(bckenny): need to null at callsites?
};


/**
 * killVertex_ destroys a vertex and removes it from the global
 * vertex list. It updates the vertex loop to point to a given new vertex.
 *
 * @private
 * @param {libtess.GluVertex} vDel [description].
 * @param {libtess.GluVertex} newOrg [description].
 */
libtess.mesh.killVertex_ = function(vDel, newOrg) {
  var eStart = vDel.anEdge;

  // change the origin of all affected edges
  var e = eStart;
  do {
    e.org = newOrg;
    e = e.oNext;
  } while (e !== eStart);

  // delete from circular doubly-linked list
  var vPrev = vDel.prev;
  var vNext = vDel.next;
  vNext.prev = vPrev;
  vPrev.next = vNext;

  // TODO(bckenny): memFree( vDel );
  // TODO(bckenny): need to null at callsites?
};


/**
 * killFace_ destroys a face and removes it from the global face
 * list. It updates the face loop to point to a given new face.
 *
 * @private
 * @param {libtess.GluFace} fDel [description].
 * @param {libtess.GluFace} newLFace [description].
 */
libtess.mesh.killFace_ = function(fDel, newLFace) {
  var eStart = fDel.anEdge;

  // change the left face of all affected edges
  var e = eStart;
  do {
    e.lFace = newLFace;
    e = e.lNext;
  } while (e !== eStart);

  // delete from circular doubly-linked list
  var fPrev = fDel.prev;
  var fNext = fDel.next;
  fNext.prev = fPrev;
  fPrev.next = fNext;

  // TODO(bckenny): memFree( fDel );
  // TODO(bckenny): need to null at callsites?
};

/* global libtess */

/** @const */
libtess.normal = {};

// TODO(bckenny): Integrate SLANTED_SWEEP somehow?
/* The "feature merging" is not intended to be complete. There are
 * special cases where edges are nearly parallel to the sweep line
 * which are not implemented. The algorithm should still behave
 * robustly (ie. produce a reasonable tesselation) in the presence
 * of such edges, however it may miss features which could have been
 * merged. We could minimize this effect by choosing the sweep line
 * direction to be something unusual (ie. not parallel to one of the
 * coordinate axes).
 * #if defined(SLANTED_SWEEP)
 * #define S_UNIT_X  0.50941539564955385 // Pre-normalized
 * #define S_UNIT_Y  0.86052074622010633
 * #endif
 */

/**
 * X coordinate of local basis for polygon projection.
 * @private {number}
 * @const
 */
libtess.normal.S_UNIT_X_ = 1.0;

/**
 * Y coordinate of local basis for polygon projection.
 * @private {number}
 * @const
 */
libtess.normal.S_UNIT_Y_ = 0.0;

/**
 * Determines a polygon normal and projects vertices onto the plane of the
 * polygon. A pre-computed normal for the data may be provided, or set to the
 * zero vector if one should be computed from it.
 * @param {!libtess.GluTesselator} tess
 * @param {number} normalX
 * @param {number} normalY
 * @param {number} normalZ
 */
libtess.normal.projectPolygon = function(tess, normalX, normalY, normalZ) {
  var computedNormal = false;

  var norm = [
    normalX,
    normalY,
    normalZ
  ];
  if (normalX === 0 && normalY === 0 && normalZ === 0) {
    libtess.normal.computeNormal_(tess, norm);
    computedNormal = true;
  }

  var i = libtess.normal.longAxis_(norm);
  var vHead = tess.mesh.vHead;
  var v;

  // NOTE(bckenny): This branch is never taken. See comment on
  // libtess.TRUE_PROJECT.
  /* istanbul ignore if */
  if (libtess.TRUE_PROJECT) {
    // Choose the initial sUnit vector to be approximately perpendicular
    // to the normal.
    libtess.normal.normalize_(norm);

    var sUnit = [0, 0, 0];
    var tUnit = [0, 0, 0];

    sUnit[i] = 0;
    sUnit[(i + 1) % 3] = libtess.normal.S_UNIT_X_;
    sUnit[(i + 2) % 3] = libtess.normal.S_UNIT_Y_;

    // Now make it exactly perpendicular
    var w = libtess.normal.dot_(sUnit, norm);
    sUnit[0] -= w * norm[0];
    sUnit[1] -= w * norm[1];
    sUnit[2] -= w * norm[2];
    libtess.normal.normalize_(sUnit);

    // Choose tUnit so that (sUnit,tUnit,norm) form a right-handed frame
    tUnit[0] = norm[1] * sUnit[2] - norm[2] * sUnit[1];
    tUnit[1] = norm[2] * sUnit[0] - norm[0] * sUnit[2];
    tUnit[2] = norm[0] * sUnit[1] - norm[1] * sUnit[0];
    libtess.normal.normalize_(tUnit);

    // Project the vertices onto the sweep plane
    for (v = vHead.next; v !== vHead; v = v.next) {
      v.s = libtess.normal.dot_(v.coords, sUnit);
      v.t = libtess.normal.dot_(v.coords, tUnit);
    }

  } else {
    // Project perpendicular to a coordinate axis -- better numerically
    var sAxis = (i + 1) % 3;
    var tAxis = (i + 2) % 3;
    var tNegate = norm[i] > 0 ? 1 : -1;

    // Project the vertices onto the sweep plane
    for (v = vHead.next; v !== vHead; v = v.next) {
      v.s = v.coords[sAxis];
      v.t = tNegate * v.coords[tAxis];
    }
  }

  if (computedNormal) {
    libtess.normal.checkOrientation_(tess);
  }
};

// NOTE(bckenny): libtess.normal.dot_ is no longer called in code without
// libtess.TRUE_PROJECT defined.
/* istanbul ignore next */
/**
 * Computes the dot product of vectors u and v.
 * @private
 * @param {!Array<number>} u
 * @param {!Array<number>} v
 * @return {number}
 */
libtess.normal.dot_ = function(u, v) {
  return u[0] * v[0] + u[1] * v[1] + u[2] * v[2];
};

// NOTE(bckenny): only called from within libtess.normal.projectPolygon's
// TRUE_PROJECT branch, so ignoring for code coverage.
/* istanbul ignore next */
/**
 * Normalize vector v.
 * @private
 * @param {!Array<number>} v
 */
libtess.normal.normalize_ = function(v) {
  var len = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];

  len = Math.sqrt(len);
  v[0] /= len;
  v[1] /= len;
  v[2] /= len;
};

/**
 * Returns the index of the longest component of vector v.
 * @private
 * @param {!Array<number>} v
 * @return {number}
 */
libtess.normal.longAxis_ = function(v) {
  var i = 0;

  if (Math.abs(v[1]) > Math.abs(v[0])) {
    i = 1;
  }
  if (Math.abs(v[2]) > Math.abs(v[i])) {
    i = 2;
  }

  return i;
};

/**
 * Compute an approximate normal of the polygon from the vertices themselves.
 * Result returned in norm.
 * @private
 * @param {!libtess.GluTesselator} tess
 * @param {!Array<number>} norm
 */
libtess.normal.computeNormal_ = function(tess, norm) {
  var maxVal = [
    -2 * libtess.GLU_TESS_MAX_COORD,
    -2 * libtess.GLU_TESS_MAX_COORD,
    -2 * libtess.GLU_TESS_MAX_COORD
  ];
  var minVal = [
    2 * libtess.GLU_TESS_MAX_COORD,
    2 * libtess.GLU_TESS_MAX_COORD,
    2 * libtess.GLU_TESS_MAX_COORD
  ];
  var maxVert = [];
  var minVert = [];

  var v;
  var vHead = tess.mesh.vHead;
  for (v = vHead.next; v !== vHead; v = v.next) {
    for (var i = 0; i < 3; ++i) {
      var c = v.coords[i];
      if (c < minVal[i]) { minVal[i] = c; minVert[i] = v; }
      if (c > maxVal[i]) { maxVal[i] = c; maxVert[i] = v; }
    }
  }

  // Find two vertices separated by at least 1/sqrt(3) of the maximum
  // distance between any two vertices
  var index = 0;
  if (maxVal[1] - minVal[1] > maxVal[0] - minVal[0]) { index = 1; }
  if (maxVal[2] - minVal[2] > maxVal[index] - minVal[index]) { index = 2; }
  if (minVal[index] >= maxVal[index]) {
    // All vertices are the same -- normal doesn't matter
    norm[0] = 0; norm[1] = 0; norm[2] = 1;
    return;
  }

  // Look for a third vertex which forms the triangle with maximum area
  // (Length of normal == twice the triangle area)
  var maxLen2 = 0;
  var v1 = minVert[index];
  var v2 = maxVert[index];
  var tNorm = [0, 0, 0];
  var d1 = [
    v1.coords[0] - v2.coords[0],
    v1.coords[1] - v2.coords[1],
    v1.coords[2] - v2.coords[2]
  ];
  var d2 = [0, 0, 0];
  for (v = vHead.next; v !== vHead; v = v.next) {
    d2[0] = v.coords[0] - v2.coords[0];
    d2[1] = v.coords[1] - v2.coords[1];
    d2[2] = v.coords[2] - v2.coords[2];
    tNorm[0] = d1[1] * d2[2] - d1[2] * d2[1];
    tNorm[1] = d1[2] * d2[0] - d1[0] * d2[2];
    tNorm[2] = d1[0] * d2[1] - d1[1] * d2[0];
    var tLen2 = tNorm[0] * tNorm[0] + tNorm[1] * tNorm[1] + tNorm[2] * tNorm[2];
    if (tLen2 > maxLen2) {
      maxLen2 = tLen2;
      norm[0] = tNorm[0];
      norm[1] = tNorm[1];
      norm[2] = tNorm[2];
    }
  }

  if (maxLen2 <= 0) {
    // All points lie on a single line -- any decent normal will do
    norm[0] = norm[1] = norm[2] = 0;
    norm[libtess.normal.longAxis_(d1)] = 1;
  }
};

/**
 * Check that the sum of the signed area of all projected contours is
 * non-negative. If not, negate the t-coordinates to reverse the orientation and
 * make it so.
 * @private
 * @param {!libtess.GluTesselator} tess
 */
libtess.normal.checkOrientation_ = function(tess) {
  var area = 0;
  var fHead = tess.mesh.fHead;
  for (var f = fHead.next; f !== fHead; f = f.next) {
    var e = f.anEdge;
    if (e.winding <= 0) { continue; }
    do {
      area += (e.org.s - e.dst().s) * (e.org.t + e.dst().t);
      e = e.lNext;
    } while (e !== f.anEdge);
  }

  if (area < 0) {
    // Reverse the orientation by flipping all the t-coordinates
    var vHead = tess.mesh.vHead;
    for (var v = vHead.next; v !== vHead; v = v.next) {
      v.t = -v.t;
    }
  }
};

/* global libtess */

/** @const */
libtess.render = {};

/**
 * Takes a mesh, breaks it into separate triangles, and renders them. The
 * rendering output is provided as callbacks (see the API). Set flagEdges to
 * true to get edgeFlag callbacks (tess.flagBoundary in original libtess).
 * @param {!libtess.GluTesselator} tess
 * @param {!libtess.GluMesh} mesh
 * @param {boolean} flagEdges
 */
libtess.render.renderMesh = function(tess, mesh, flagEdges) {
  var beginCallbackCalled = false;

  // TODO(bckenny): edgeState needs to be boolean, but !== on first call
  // force edge state output for first vertex
  var edgeState = -1;

  // We examine all faces in an arbitrary order. Whenever we find
  // an inside triangle f, we render f.
  // NOTE(bckenny): go backwards through face list to match original libtess
  // triangle order
  for (var f = mesh.fHead.prev; f !== mesh.fHead; f = f.prev) {
    if (f.inside) {
      // We're going to emit a triangle, so call begin callback once
      if (!beginCallbackCalled) {
        tess.callBeginCallback(libtess.primitiveType.GL_TRIANGLES);
        beginCallbackCalled = true;
      }

      // check that face has only three edges
      var e = f.anEdge;
      // Loop once for each edge (there will always be 3 edges)
      do {
        if (flagEdges) {
          // Set the "edge state" to true just before we output the
          // first vertex of each edge on the polygon boundary.
          var newState = !e.rFace().inside ? 1 : 0; // TODO(bckenny): total hack to get edgeState working. fix me.
          if (edgeState !== newState) {
            edgeState = newState;
            // TODO(bckenny): edgeState should be boolean now
            tess.callEdgeFlagCallback(!!edgeState);
          }
        }

        // emit vertex
        tess.callVertexCallback(e.org.data);

        e = e.lNext;
      } while (e !== f.anEdge);
    }
  }

  // only call end callback if begin was called
  if (beginCallbackCalled) {
    tess.callEndCallback();
  }
};

/**
 * Takes a mesh, and outputs one contour for each face marked "inside". The
 * rendering output is provided as callbacks (see the API).
 * @param {!libtess.GluTesselator} tess
 * @param {!libtess.GluMesh} mesh
 */
libtess.render.renderBoundary = function(tess, mesh) {
  for (var f = mesh.fHead.next; f !== mesh.fHead; f = f.next) {
    if (f.inside) {
      tess.callBeginCallback(libtess.primitiveType.GL_LINE_LOOP);

      var e = f.anEdge;
      do {
        tess.callVertexCallback(e.org.data);
        e = e.lNext;
      } while (e !== f.anEdge);

      tess.callEndCallback();
    }
  }
};

/* global libtess */

// TODO(bckenny): a number of these never return null (as opposed to original) and should be typed appropriately

/*
 * Invariants for the Edge Dictionary.
 * - each pair of adjacent edges e2=succ(e1) satisfies edgeLeq_(e1,e2)
 *   at any valid location of the sweep event
 * - if edgeLeq_(e2,e1) as well (at any valid sweep event), then e1 and e2
 *   share a common endpoint
 * - for each e, e.dst() has been processed, but not e.org
 * - each edge e satisfies vertLeq(e.dst(),event) && vertLeq(event,e.org)
 *   where "event" is the current sweep line event.
 * - no edge e has zero length
 *
 * Invariants for the Mesh (the processed portion).
 * - the portion of the mesh left of the sweep line is a planar graph,
 *   ie. there is *some* way to embed it in the plane
 * - no processed edge has zero length
 * - no two processed vertices have identical coordinates
 * - each "inside" region is monotone, ie. can be broken into two chains
 *   of monotonically increasing vertices according to VertLeq(v1,v2)
 *   - a non-invariant: these chains may intersect (very slightly)
 *
 * Invariants for the Sweep.
 * - if none of the edges incident to the event vertex have an activeRegion
 *   (ie. none of these edges are in the edge dictionary), then the vertex
 *   has only right-going edges.
 * - if an edge is marked "fixUpperEdge" (it is a temporary edge introduced
 *   by ConnectRightVertex), then it is the only right-going edge from
 *   its associated vertex.  (This says that these edges exist only
 *   when it is necessary.)
 */

/** @const */
libtess.sweep = {};


/**
 * Make the sentinel coordinates big enough that they will never be
 * merged with real input features.  (Even with the largest possible
 * input contour and the maximum tolerance of 1.0, no merging will be
 * done with coordinates larger than 3 * libtess.GLU_TESS_MAX_COORD).
 * @private
 * @const
 * @type {number}
 */
libtess.sweep.SENTINEL_COORD_ = 4 * libtess.GLU_TESS_MAX_COORD;


/**
 * Because vertices at exactly the same location are merged together
 * before we process the sweep event, some degenerate cases can't occur.
 * However if someone eventually makes the modifications required to
 * merge features which are close together, the cases below marked
 * TOLERANCE_NONZERO will be useful.  They were debugged before the
 * code to merge identical vertices in the main loop was added.
 * @private
 * @const
 * @type {boolean}
 */
libtess.sweep.TOLERANCE_NONZERO_ = false;


/**
 * computeInterior(tess) computes the planar arrangement specified
 * by the given contours, and further subdivides this arrangement
 * into regions. Each region is marked "inside" if it belongs
 * to the polygon, according to the rule given by tess.windingRule.
 * Each interior region is guaranteed be monotone.
 *
 * @param {libtess.GluTesselator} tess [description].
 */
libtess.sweep.computeInterior = function(tess) {
  tess.fatalError = false;

  // Each vertex defines an event for our sweep line. Start by inserting
  // all the vertices in a priority queue. Events are processed in
  // lexicographic order, ie.
  // e1 < e2  iff  e1.x < e2.x || (e1.x == e2.x && e1.y < e2.y)
  libtess.sweep.removeDegenerateEdges_(tess);
  libtess.sweep.initPriorityQ_(tess);
  libtess.sweep.initEdgeDict_(tess);

  var v;
  while ((v = tess.pq.extractMin()) !== null) {
    for (;;) {
      var vNext = tess.pq.minimum();
      if (vNext === null || !libtess.geom.vertEq(vNext, v)) {
        break;
      }

      /* Merge together all vertices at exactly the same location.
       * This is more efficient than processing them one at a time,
       * simplifies the code (see connectLeftDegenerate), and is also
       * important for correct handling of certain degenerate cases.
       * For example, suppose there are two identical edges A and B
       * that belong to different contours (so without this code they would
       * be processed by separate sweep events).  Suppose another edge C
       * crosses A and B from above.  When A is processed, we split it
       * at its intersection point with C.  However this also splits C,
       * so when we insert B we may compute a slightly different
       * intersection point.  This might leave two edges with a small
       * gap between them.  This kind of error is especially obvious
       * when using boundary extraction (GLU_TESS_BOUNDARY_ONLY).
       */
      vNext = tess.pq.extractMin();
      libtess.sweep.spliceMergeVertices_(tess, v.anEdge, vNext.anEdge);
    }
    libtess.sweep.sweepEvent_(tess, v);
  }

  // TODO(bckenny): what does the next comment mean? can we eliminate event except when debugging?
  // Set tess.event for debugging purposes
  var minRegion = tess.dict.getMin().getKey();
  tess.event = minRegion.eUp.org;
  libtess.sweep.doneEdgeDict_(tess);
  libtess.sweep.donePriorityQ_(tess);

  libtess.sweep.removeDegenerateFaces_(tess.mesh);
  tess.mesh.checkMesh();
};


/**
 * When we merge two edges into one, we need to compute the combined
 * winding of the new edge.
 * @private
 * @param {libtess.GluHalfEdge} eDst [description].
 * @param {libtess.GluHalfEdge} eSrc [description].
 */
libtess.sweep.addWinding_ = function(eDst, eSrc) {
  // NOTE(bckenny): from AddWinding macro
  eDst.winding += eSrc.winding;
  eDst.sym.winding += eSrc.sym.winding;
};


/**
 * Both edges must be directed from right to left (this is the canonical
 * direction for the upper edge of each region).
 *
 * The strategy is to evaluate a "t" value for each edge at the
 * current sweep line position, given by tess.event.  The calculations
 * are designed to be very stable, but of course they are not perfect.
 *
 * Special case: if both edge destinations are at the sweep event,
 * we sort the edges by slope (they would otherwise compare equally).
 *
 * @private
 * @param {!libtess.GluTesselator} tess
 * @param {!libtess.ActiveRegion} reg1
 * @param {!libtess.ActiveRegion} reg2
 * @return {boolean}
 */
libtess.sweep.edgeLeq_ = function(tess, reg1, reg2) {
  var event = tess.event;
  var e1 = reg1.eUp;
  var e2 = reg2.eUp;

  if (e1.dst() === event) {
    if (e2.dst() === event) {
      // Two edges right of the sweep line which meet at the sweep event.
      // Sort them by slope.
      if (libtess.geom.vertLeq(e1.org, e2.org)) {
        return libtess.geom.edgeSign(e2.dst(), e1.org, e2.org) <= 0;
      }

      return libtess.geom.edgeSign(e1.dst(), e2.org, e1.org) >= 0;
    }

    return libtess.geom.edgeSign(e2.dst(), event, e2.org) <= 0;
  }

  if (e2.dst() === event) {
    return libtess.geom.edgeSign(e1.dst(), event, e1.org) >= 0;
  }

  // General case - compute signed distance *from* e1, e2 to event
  var t1 = libtess.geom.edgeEval(e1.dst(), event, e1.org);
  var t2 = libtess.geom.edgeEval(e2.dst(), event, e2.org);
  return (t1 >= t2);
};


/**
 * [deleteRegion_ description]
 * @private
 * @param {libtess.GluTesselator} tess [description].
 * @param {libtess.ActiveRegion} reg [description].
 */
libtess.sweep.deleteRegion_ = function(tess, reg) {
  if (reg.fixUpperEdge) {
    // It was created with zero winding number, so it better be
    // deleted with zero winding number (ie. it better not get merged
    // with a real edge).
  }

  reg.eUp.activeRegion = null;

  tess.dict.deleteNode(reg.nodeUp);
  reg.nodeUp = null;

  // memFree( reg ); TODO(bckenny)
  // TODO(bckenny): may need to null at callsite
};


/**
 * Replace an upper edge which needs fixing (see connectRightVertex).
 * @private
 * @param {libtess.ActiveRegion} reg [description].
 * @param {libtess.GluHalfEdge} newEdge [description].
 */
libtess.sweep.fixUpperEdge_ = function(reg, newEdge) {
  libtess.mesh.deleteEdge(reg.eUp);

  reg.fixUpperEdge = false;
  reg.eUp = newEdge;
  newEdge.activeRegion = reg;
};


/**
 * Find the region above the uppermost edge with the same origin.
 * @private
 * @param {libtess.ActiveRegion} reg [description].
 * @return {libtess.ActiveRegion} [description].
 */
libtess.sweep.topLeftRegion_ = function(reg) {
  var org = reg.eUp.org;

  // Find the region above the uppermost edge with the same origin
  do {
    reg = reg.regionAbove();
  } while (reg.eUp.org === org);

  // If the edge above was a temporary edge introduced by connectRightVertex,
  // now is the time to fix it.
  if (reg.fixUpperEdge) {
    var e = libtess.mesh.connect(reg.regionBelow().eUp.sym, reg.eUp.lNext);
    libtess.sweep.fixUpperEdge_(reg, e);
    reg = reg.regionAbove();
  }

  return reg;
};


/**
 * Find the region above the uppermost edge with the same destination.
 * @private
 * @param {libtess.ActiveRegion} reg [description].
 * @return {libtess.ActiveRegion} [description].
 */
libtess.sweep.topRightRegion_ = function(reg) {
  var dst = reg.eUp.dst();

  do {
    reg = reg.regionAbove();
  } while (reg.eUp.dst() === dst);

  return reg;
};


/**
 * Add a new active region to the sweep line, *somewhere* below "regAbove"
 * (according to where the new edge belongs in the sweep-line dictionary).
 * The upper edge of the new region will be "eNewUp".
 * Winding number and "inside" flag are not updated.
 *
 * @private
 * @param {libtess.GluTesselator} tess [description].
 * @param {libtess.ActiveRegion} regAbove [description].
 * @param {libtess.GluHalfEdge} eNewUp [description].
 * @return {libtess.ActiveRegion} regNew.
 */
libtess.sweep.addRegionBelow_ = function(tess, regAbove, eNewUp) {
  var regNew = new libtess.ActiveRegion();

  regNew.eUp = eNewUp;
  regNew.nodeUp = tess.dict.insertBefore(regAbove.nodeUp, regNew);
  eNewUp.activeRegion = regNew;

  return regNew;
};


/**
 * [isWindingInside_ description]
 * @private
 * @param {libtess.GluTesselator} tess [description].
 * @param {number} n int.
 * @return {boolean} [description].
 */
libtess.sweep.isWindingInside_ = function(tess, n) {
  switch (tess.windingRule) {
    case libtess.windingRule.GLU_TESS_WINDING_ODD:
      return ((n & 1) !== 0);
    case libtess.windingRule.GLU_TESS_WINDING_NONZERO:
      return (n !== 0);
    case libtess.windingRule.GLU_TESS_WINDING_POSITIVE:
      return (n > 0);
    case libtess.windingRule.GLU_TESS_WINDING_NEGATIVE:
      return (n < 0);
    case libtess.windingRule.GLU_TESS_WINDING_ABS_GEQ_TWO:
      return (n >= 2) || (n <= -2);
  }

  // TODO(bckenny): not reached
  return false;
};


/**
 * [computeWinding_ description]
 * @private
 * @param {libtess.GluTesselator} tess [description].
 * @param {libtess.ActiveRegion} reg [description].
 */
libtess.sweep.computeWinding_ = function(tess, reg) {
  reg.windingNumber = reg.regionAbove().windingNumber + reg.eUp.winding;
  reg.inside = libtess.sweep.isWindingInside_(tess, reg.windingNumber);
};


/**
 * Delete a region from the sweep line. This happens when the upper
 * and lower chains of a region meet (at a vertex on the sweep line).
 * The "inside" flag is copied to the appropriate mesh face (we could
 * not do this before -- since the structure of the mesh is always
 * changing, this face may not have even existed until now).
 *
 * @private
 * @param {libtess.GluTesselator} tess [description].
 * @param {libtess.ActiveRegion} reg [description].
 */
libtess.sweep.finishRegion_ = function(tess, reg) {
  // TODO(bckenny): may need to null reg at callsite

  var e = reg.eUp;
  var f = e.lFace;

  f.inside = reg.inside;
  f.anEdge = e;   // optimization for tessmono.tessellateMonoRegion() // TODO(bckenny): how so?
  libtess.sweep.deleteRegion_(tess, reg);
};


/**
 * We are given a vertex with one or more left-going edges. All affected
 * edges should be in the edge dictionary. Starting at regFirst.eUp,
 * we walk down deleting all regions where both edges have the same
 * origin vOrg. At the same time we copy the "inside" flag from the
 * active region to the face, since at this point each face will belong
 * to at most one region (this was not necessarily true until this point
 * in the sweep). The walk stops at the region above regLast; if regLast
 * is null we walk as far as possible. At the same time we relink the
 * mesh if necessary, so that the ordering of edges around vOrg is the
 * same as in the dictionary.
 *
 * @private
 * @param {libtess.GluTesselator} tess [description].
 * @param {libtess.ActiveRegion} regFirst [description].
 * @param {libtess.ActiveRegion} regLast [description].
 * @return {libtess.GluHalfEdge} [description].
 */
libtess.sweep.finishLeftRegions_ = function(tess, regFirst, regLast) {
  var regPrev = regFirst;
  var ePrev = regFirst.eUp;
  while (regPrev !== regLast) {
    // placement was OK
    regPrev.fixUpperEdge = false;
    var reg = regPrev.regionBelow();
    var e = reg.eUp;
    if (e.org !== ePrev.org) {
      if (!reg.fixUpperEdge) {
        /* Remove the last left-going edge. Even though there are no further
         * edges in the dictionary with this origin, there may be further
         * such edges in the mesh (if we are adding left edges to a vertex
         * that has already been processed). Thus it is important to call
         * finishRegion rather than just deleteRegion.
         */
        libtess.sweep.finishRegion_(tess, regPrev);
        break;
      }

      // If the edge below was a temporary edge introduced by
      // connectRightVertex, now is the time to fix it.
      e = libtess.mesh.connect(ePrev.lPrev(), e.sym);
      libtess.sweep.fixUpperEdge_(reg, e);
    }

    // Relink edges so that ePrev.oNext === e
    if (ePrev.oNext !== e) {
      libtess.mesh.meshSplice(e.oPrev(), e);
      libtess.mesh.meshSplice(ePrev, e);
    }

    // may change reg.eUp
    libtess.sweep.finishRegion_(tess, regPrev);
    ePrev = reg.eUp;
    regPrev = reg;
  }

  return ePrev;
};


/**
 * Purpose: insert right-going edges into the edge dictionary, and update
 * winding numbers and mesh connectivity appropriately. All right-going
 * edges share a common origin vOrg. Edges are inserted CCW starting at
 * eFirst; the last edge inserted is eLast.oPrev. If vOrg has any
 * left-going edges already processed, then eTopLeft must be the edge
 * such that an imaginary upward vertical segment from vOrg would be
 * contained between eTopLeft.oPrev and eTopLeft; otherwise eTopLeft
 * should be null.
 *
 * @private
 * @param {libtess.GluTesselator} tess [description].
 * @param {libtess.ActiveRegion} regUp [description].
 * @param {libtess.GluHalfEdge} eFirst [description].
 * @param {libtess.GluHalfEdge} eLast [description].
 * @param {libtess.GluHalfEdge} eTopLeft [description].
 * @param {boolean} cleanUp [description].
 */
libtess.sweep.addRightEdges_ = function(tess, regUp, eFirst, eLast, eTopLeft,
    cleanUp) {

  var firstTime = true;

  // Insert the new right-going edges in the dictionary
  var e = eFirst;
  do {
    libtess.sweep.addRegionBelow_(tess, regUp, e.sym);
    e = e.oNext;
  } while (e !== eLast);

  // Walk *all* right-going edges from e.org, in the dictionary order,
  // updating the winding numbers of each region, and re-linking the mesh
  // edges to match the dictionary ordering (if necessary).
  if (eTopLeft === null) {
    eTopLeft = regUp.regionBelow().eUp.rPrev();
  }
  var regPrev = regUp;
  var ePrev = eTopLeft;
  var reg;
  for (;;) {
    reg = regPrev.regionBelow();
    e = reg.eUp.sym;
    if (e.org !== ePrev.org) {
      break;
    }

    if (e.oNext !== ePrev) {
      // Unlink e from its current position, and relink below ePrev
      libtess.mesh.meshSplice(e.oPrev(), e);
      libtess.mesh.meshSplice(ePrev.oPrev(), e);
    }
    // Compute the winding number and "inside" flag for the new regions
    reg.windingNumber = regPrev.windingNumber - e.winding;
    reg.inside = libtess.sweep.isWindingInside_(tess, reg.windingNumber);

    // Check for two outgoing edges with same slope -- process these
    // before any intersection tests (see example in libtess.sweep.computeInterior).
    regPrev.dirty = true;
    if (!firstTime && libtess.sweep.checkForRightSplice_(tess, regPrev)) {
      libtess.sweep.addWinding_(e, ePrev);
      libtess.sweep.deleteRegion_(tess, regPrev); // TODO(bckenny): need to null regPrev anywhere else?
      libtess.mesh.deleteEdge(ePrev);
    }
    firstTime = false;
    regPrev = reg;
    ePrev = e;
  }

  regPrev.dirty = true;

  if (cleanUp) {
    // Check for intersections between newly adjacent edges.
    libtess.sweep.walkDirtyRegions_(tess, regPrev);
  }
};


/**
 * Set up data for and call GLU_TESS_COMBINE callback on GluTesselator.
 * @private
 * @param {!libtess.GluTesselator} tess
 * @param {!libtess.GluVertex} isect A raw vertex at the intersection.
 * @param {!Array<Object>} data The vertices of the intersecting edges.
 * @param {!Array<number>} weights The linear combination coefficients for this intersection.
 * @param {boolean} needed Whether a returned vertex is necessary in this case.
 */
libtess.sweep.callCombine_ = function(tess, isect, data, weights, needed) {
  // Copy coord data in case the callback changes it.
  var coords = [
    isect.coords[0],
    isect.coords[1],
    isect.coords[2]
  ];

  isect.data = null;
  isect.data = tess.callCombineCallback(coords, data, weights);
  if (isect.data === null) {
    if (!needed) {
      // not needed, so just use data from first vertex
      isect.data = data[0];

    } else if (!tess.fatalError) {
      // The only way fatal error is when two edges are found to intersect,
      // but the user has not provided the callback necessary to handle
      // generated intersection points.
      tess.callErrorCallback(libtess.errorType.GLU_TESS_NEED_COMBINE_CALLBACK);
      tess.fatalError = true;
    }
  }
};


/**
 * Two vertices with idential coordinates are combined into one.
 * e1.org is kept, while e2.org is discarded.
 * @private
 * @param {!libtess.GluTesselator} tess
 * @param {libtess.GluHalfEdge} e1 [description].
 * @param {libtess.GluHalfEdge} e2 [description].
 */
libtess.sweep.spliceMergeVertices_ = function(tess, e1, e2) {
  // TODO(bckenny): better way to init these? save them?
  var data = [null, null, null, null];
  var weights = [0.5, 0.5, 0, 0];

  data[0] = e1.org.data;
  data[1] = e2.org.data;
  libtess.sweep.callCombine_(tess, e1.org, data, weights, false);
  libtess.mesh.meshSplice(e1, e2);
};


/**
 * Find some weights which describe how the intersection vertex is
 * a linear combination of org and dst. Each of the two edges
 * which generated "isect" is allocated 50% of the weight; each edge
 * splits the weight between its org and dst according to the
 * relative distance to "isect".
 *
 * @private
 * @param {libtess.GluVertex} isect [description].
 * @param {libtess.GluVertex} org [description].
 * @param {libtess.GluVertex} dst [description].
 * @param {Array.<number>} weights [description].
 * @param {number} weightIndex Index into weights for first weight to supply.
 */
libtess.sweep.vertexWeights_ = function(isect, org, dst, weights, weightIndex) {
  // TODO(bckenny): think through how we can use L1dist here and be correct for coords
  var t1 = libtess.geom.vertL1dist(org, isect);
  var t2 = libtess.geom.vertL1dist(dst, isect);

  // TODO(bckenny): introduced weightIndex to mimic addressing in original
  // 1) document (though it is private and only used from getIntersectData)
  // 2) better way? manually inline into getIntersectData? supply two two-length tmp arrays?
  var i0 = weightIndex;
  var i1 = weightIndex + 1;
  weights[i0] = 0.5 * t2 / (t1 + t2);
  weights[i1] = 0.5 * t1 / (t1 + t2);
  isect.coords[0] += weights[i0] * org.coords[0] + weights[i1] * dst.coords[0];
  isect.coords[1] += weights[i0] * org.coords[1] + weights[i1] * dst.coords[1];
  isect.coords[2] += weights[i0] * org.coords[2] + weights[i1] * dst.coords[2];
};


/**
 * We've computed a new intersection point, now we need a "data" pointer
 * from the user so that we can refer to this new vertex in the
 * rendering callbacks.
 * @private
 * @param {!libtess.GluTesselator} tess
 * @param {libtess.GluVertex} isect [description].
 * @param {libtess.GluVertex} orgUp [description].
 * @param {libtess.GluVertex} dstUp [description].
 * @param {libtess.GluVertex} orgLo [description].
 * @param {libtess.GluVertex} dstLo [description].
 */
libtess.sweep.getIntersectData_ = function(tess, isect, orgUp, dstUp, orgLo,
    dstLo) {

  // TODO(bckenny): called for every intersection event, should these be from a pool?
  // TODO(bckenny): better way to init these?
  var weights = [0, 0, 0, 0];
  var data = [
    orgUp.data,
    dstUp.data,
    orgLo.data,
    dstLo.data
  ];

  // TODO(bckenny): it appears isect is a reappropriated vertex, so does need to be zeroed.
  // double check this.
  isect.coords[0] = isect.coords[1] = isect.coords[2] = 0;

  // TODO(bckenny): see note in libtess.sweep.vertexWeights_ for explanation of weightIndex. fix?
  libtess.sweep.vertexWeights_(isect, orgUp, dstUp, weights, 0);
  libtess.sweep.vertexWeights_(isect, orgLo, dstLo, weights, 2);

  libtess.sweep.callCombine_(tess, isect, data, weights, true);
};


/**
 * Check the upper and lower edge of regUp, to make sure that the
 * eUp.org is above eLo, or eLo.org is below eUp (depending on which
 * origin is leftmost).
 *
 * The main purpose is to splice right-going edges with the same
 * dest vertex and nearly identical slopes (ie. we can't distinguish
 * the slopes numerically). However the splicing can also help us
 * to recover from numerical errors. For example, suppose at one
 * point we checked eUp and eLo, and decided that eUp.org is barely
 * above eLo. Then later, we split eLo into two edges (eg. from
 * a splice operation like this one). This can change the result of
 * our test so that now eUp.org is incident to eLo, or barely below it.
 * We must correct this condition to maintain the dictionary invariants.
 *
 * One possibility is to check these edges for intersection again
 * (i.e. checkForIntersect). This is what we do if possible. However
 * checkForIntersect requires that tess.event lies between eUp and eLo,
 * so that it has something to fall back on when the intersection
 * calculation gives us an unusable answer. So, for those cases where
 * we can't check for intersection, this routine fixes the problem
 * by just splicing the offending vertex into the other edge.
 * This is a guaranteed solution, no matter how degenerate things get.
 * Basically this is a combinatorial solution to a numerical problem.
 *
 * @private
 * @param {libtess.GluTesselator} tess [description].
 * @param {libtess.ActiveRegion} regUp [description].
 * @return {boolean} [description].
 */
libtess.sweep.checkForRightSplice_ = function(tess, regUp) {
  // TODO(bckenny): fully learn how these two checks work

  var regLo = regUp.regionBelow();
  var eUp = regUp.eUp;
  var eLo = regLo.eUp;

  if (libtess.geom.vertLeq(eUp.org, eLo.org)) {
    if (libtess.geom.edgeSign(eLo.dst(), eUp.org, eLo.org) > 0) {
      return false;
    }

    // eUp.org appears to be below eLo
    if (!libtess.geom.vertEq(eUp.org, eLo.org)) {
      // Splice eUp.org into eLo
      libtess.mesh.splitEdge(eLo.sym);
      libtess.mesh.meshSplice(eUp, eLo.oPrev());
      regUp.dirty = regLo.dirty = true;

    } else if (eUp.org !== eLo.org) {
      // merge the two vertices, discarding eUp.org
      tess.pq.remove(eUp.org.pqHandle);
      libtess.sweep.spliceMergeVertices_(tess, eLo.oPrev(), eUp);
    }

  } else {
    if (libtess.geom.edgeSign(eUp.dst(), eLo.org, eUp.org) < 0) {
      return false;
    }

    // eLo.org appears to be above eUp, so splice eLo.org into eUp
    regUp.regionAbove().dirty = regUp.dirty = true;
    libtess.mesh.splitEdge(eUp.sym);
    libtess.mesh.meshSplice(eLo.oPrev(), eUp);
  }

  return true;
};


/**
 * Check the upper and lower edge of regUp to make sure that the
 * eUp.dst() is above eLo, or eLo.dst() is below eUp (depending on which
 * destination is rightmost).
 *
 * Theoretically, this should always be true. However, splitting an edge
 * into two pieces can change the results of previous tests. For example,
 * suppose at one point we checked eUp and eLo, and decided that eUp.dst()
 * is barely above eLo. Then later, we split eLo into two edges (eg. from
 * a splice operation like this one). This can change the result of
 * the test so that now eUp.dst() is incident to eLo, or barely below it.
 * We must correct this condition to maintain the dictionary invariants
 * (otherwise new edges might get inserted in the wrong place in the
 * dictionary, and bad stuff will happen).
 *
 * We fix the problem by just splicing the offending vertex into the
 * other edge.
 *
 * @private
 * @param {libtess.GluTesselator} tess description].
 * @param {libtess.ActiveRegion} regUp [description].
 * @return {boolean} [description].
 */
libtess.sweep.checkForLeftSplice_ = function(tess, regUp) {
  var regLo = regUp.regionBelow();
  var eUp = regUp.eUp;
  var eLo = regLo.eUp;
  var e;

  if (libtess.geom.vertLeq(eUp.dst(), eLo.dst())) {
    if (libtess.geom.edgeSign(eUp.dst(), eLo.dst(), eUp.org) < 0) {
      return false;
    }

    // eLo.dst() is above eUp, so splice eLo.dst() into eUp
    regUp.regionAbove().dirty = regUp.dirty = true;
    e = libtess.mesh.splitEdge(eUp);
    libtess.mesh.meshSplice(eLo.sym, e);
    e.lFace.inside = regUp.inside;

  } else {
    if (libtess.geom.edgeSign(eLo.dst(), eUp.dst(), eLo.org) > 0) {
      return false;
    }

    // eUp.dst() is below eLo, so splice eUp.dst() into eLo
    regUp.dirty = regLo.dirty = true;
    e = libtess.mesh.splitEdge(eLo);
    libtess.mesh.meshSplice(eUp.lNext, eLo.sym);
    e.rFace().inside = regUp.inside;
  }

  return true;
};


/**
 * Check the upper and lower edges of the given region to see if
 * they intersect. If so, create the intersection and add it
 * to the data structures.
 *
 * Returns true if adding the new intersection resulted in a recursive
 * call to addRightEdges_(); in this case all "dirty" regions have been
 * checked for intersections, and possibly regUp has been deleted.
 *
 * @private
 * @param {libtess.GluTesselator} tess [description].
 * @param {libtess.ActiveRegion} regUp [description].
 * @return {boolean} [description].
 */
libtess.sweep.checkForIntersect_ = function(tess, regUp) {
  var regLo = regUp.regionBelow();
  var eUp = regUp.eUp;
  var eLo = regLo.eUp;
  var orgUp = eUp.org;
  var orgLo = eLo.org;
  var dstUp = eUp.dst();
  var dstLo = eLo.dst();

  var isect = new libtess.GluVertex();

  if (orgUp === orgLo) {
    // right endpoints are the same
    return false;
  }

  var tMinUp = Math.min(orgUp.t, dstUp.t);
  var tMaxLo = Math.max(orgLo.t, dstLo.t);
  if (tMinUp > tMaxLo) {
    // t ranges do not overlap
    return false;
  }

  if (libtess.geom.vertLeq(orgUp, orgLo)) {
    if (libtess.geom.edgeSign(dstLo, orgUp, orgLo) > 0) {
      return false;
    }
  } else {
    if (libtess.geom.edgeSign(dstUp, orgLo, orgUp) < 0) {
      return false;
    }
  }

  // At this point the edges intersect, at least marginally
  libtess.geom.edgeIntersect(dstUp, orgUp, dstLo, orgLo, isect);

  // The following properties are guaranteed:

  if (libtess.geom.vertLeq(isect, tess.event)) {
    /* The intersection point lies slightly to the left of the sweep line,
     * so move it until it's slightly to the right of the sweep line.
     * (If we had perfect numerical precision, this would never happen
     * in the first place). The easiest and safest thing to do is
     * replace the intersection by tess.event.
     */
    isect.s = tess.event.s;
    isect.t = tess.event.t;
  }

  // TODO(bckenny): try to find test54.d
  /* Similarly, if the computed intersection lies to the right of the
   * rightmost origin (which should rarely happen), it can cause
   * unbelievable inefficiency on sufficiently degenerate inputs.
   * (If you have the test program, try running test54.d with the
   * "X zoom" option turned on).
   */
  var orgMin = libtess.geom.vertLeq(orgUp, orgLo) ? orgUp : orgLo;
  if (libtess.geom.vertLeq(orgMin, isect)) {
    isect.s = orgMin.s;
    isect.t = orgMin.t;
  }

  if (libtess.geom.vertEq(isect, orgUp) || libtess.geom.vertEq(isect, orgLo)) {
    // Easy case -- intersection at one of the right endpoints
    libtess.sweep.checkForRightSplice_(tess, regUp);
    return false;
  }

  // TODO(bckenny): clean this up; length is distracting
  if ((!libtess.geom.vertEq(dstUp, tess.event) &&
      libtess.geom.edgeSign(dstUp, tess.event, isect) >= 0) ||
      (!libtess.geom.vertEq(dstLo, tess.event) &&
      libtess.geom.edgeSign(dstLo, tess.event, isect) <= 0)) {

    /* Very unusual -- the new upper or lower edge would pass on the
     * wrong side of the sweep event, or through it. This can happen
     * due to very small numerical errors in the intersection calculation.
     */
    if (dstLo === tess.event) {
      // Splice dstLo into eUp, and process the new region(s)
      libtess.mesh.splitEdge(eUp.sym);
      libtess.mesh.meshSplice(eLo.sym, eUp);
      regUp = libtess.sweep.topLeftRegion_(regUp);
      eUp = regUp.regionBelow().eUp;
      libtess.sweep.finishLeftRegions_(tess, regUp.regionBelow(), regLo);
      libtess.sweep.addRightEdges_(tess, regUp, eUp.oPrev(), eUp, eUp, true);
      return true;
    }

    if (dstUp === tess.event) {
      // Splice dstUp into eLo, and process the new region(s)
      libtess.mesh.splitEdge(eLo.sym);
      libtess.mesh.meshSplice(eUp.lNext, eLo.oPrev());
      regLo = regUp;
      regUp = libtess.sweep.topRightRegion_(regUp);
      var e = regUp.regionBelow().eUp.rPrev();
      regLo.eUp = eLo.oPrev();
      eLo = libtess.sweep.finishLeftRegions_(tess, regLo, null);
      libtess.sweep.addRightEdges_(tess, regUp, eLo.oNext, eUp.rPrev(), e,
          true);
      return true;
    }

    /* Special case: called from connectRightVertex. If either
     * edge passes on the wrong side of tess.event, split it
     * (and wait for connectRightVertex to splice it appropriately).
     */
    if (libtess.geom.edgeSign(dstUp, tess.event, isect) >= 0) {
      regUp.regionAbove().dirty = regUp.dirty = true;
      libtess.mesh.splitEdge(eUp.sym);
      eUp.org.s = tess.event.s;
      eUp.org.t = tess.event.t;
    }

    if (libtess.geom.edgeSign(dstLo, tess.event, isect) <= 0) {
      regUp.dirty = regLo.dirty = true;
      libtess.mesh.splitEdge(eLo.sym);
      eLo.org.s = tess.event.s;
      eLo.org.t = tess.event.t;
    }

    // leave the rest for connectRightVertex
    return false;
  }

  /* General case -- split both edges, splice into new vertex.
   * When we do the splice operation, the order of the arguments is
   * arbitrary as far as correctness goes. However, when the operation
   * creates a new face, the work done is proportional to the size of
   * the new face. We expect the faces in the processed part of
   * the mesh (ie. eUp.lFace) to be smaller than the faces in the
   * unprocessed original contours (which will be eLo.oPrev.lFace).
   */
  libtess.mesh.splitEdge(eUp.sym);
  libtess.mesh.splitEdge(eLo.sym);
  libtess.mesh.meshSplice(eLo.oPrev(), eUp);
  eUp.org.s = isect.s;
  eUp.org.t = isect.t;
  eUp.org.pqHandle = tess.pq.insert(eUp.org);
  libtess.sweep.getIntersectData_(tess, eUp.org, orgUp, dstUp, orgLo, dstLo);
  regUp.regionAbove().dirty = regUp.dirty = regLo.dirty = true;

  return false;
};


/**
 * When the upper or lower edge of any region changes, the region is
 * marked "dirty". This routine walks through all the dirty regions
 * and makes sure that the dictionary invariants are satisfied
 * (see the comments at the beginning of this file). Of course,
 * new dirty regions can be created as we make changes to restore
 * the invariants.
 * @private
 * @param {libtess.GluTesselator} tess [description].
 * @param {libtess.ActiveRegion} regUp [description].
 */
libtess.sweep.walkDirtyRegions_ = function(tess, regUp) {
  var regLo = regUp.regionBelow();

  for (;;) {
    // Find the lowest dirty region (we walk from the bottom up).
    while (regLo.dirty) {
      regUp = regLo;
      regLo = regLo.regionBelow();
    }
    if (!regUp.dirty) {
      regLo = regUp;
      regUp = regUp.regionAbove();
      if (regUp === null || !regUp.dirty) {
        // We've walked all the dirty regions
        return;
      }
    }

    regUp.dirty = false;
    var eUp = regUp.eUp;
    var eLo = regLo.eUp;

    if (eUp.dst() !== eLo.dst()) {
      // Check that the edge ordering is obeyed at the dst vertices.
      if (libtess.sweep.checkForLeftSplice_(tess, regUp)) {
        // If the upper or lower edge was marked fixUpperEdge, then
        // we no longer need it (since these edges are needed only for
        // vertices which otherwise have no right-going edges).
        if (regLo.fixUpperEdge) {
          libtess.sweep.deleteRegion_(tess, regLo);
          libtess.mesh.deleteEdge(eLo);
          regLo = regUp.regionBelow();
          eLo = regLo.eUp;

        } else if (regUp.fixUpperEdge) {
          libtess.sweep.deleteRegion_(tess, regUp);
          libtess.mesh.deleteEdge(eUp);
          regUp = regLo.regionAbove();
          eUp = regUp.eUp;
        }
      }
    }

    if (eUp.org !== eLo.org) {
      if (eUp.dst() !== eLo.dst() && !regUp.fixUpperEdge &&
          !regLo.fixUpperEdge &&
          (eUp.dst() === tess.event || eLo.dst() === tess.event)) {
        /* When all else fails in checkForIntersect(), it uses tess.event
         * as the intersection location. To make this possible, it requires
         * that tess.event lie between the upper and lower edges, and also
         * that neither of these is marked fixUpperEdge (since in the worst
         * case it might splice one of these edges into tess.event, and
         * violate the invariant that fixable edges are the only right-going
         * edge from their associated vertex).
         */
        if (libtess.sweep.checkForIntersect_(tess, regUp)) {
          // walkDirtyRegions() was called recursively; we're done
          return;
        }

      } else {
        // Even though we can't use checkForIntersect(), the org vertices
        // may violate the dictionary edge ordering. Check and correct this.
        libtess.sweep.checkForRightSplice_(tess, regUp);
      }
    }

    if (eUp.org === eLo.org && eUp.dst() === eLo.dst()) {
      // A degenerate loop consisting of only two edges -- delete it.
      libtess.sweep.addWinding_(eLo, eUp);
      libtess.sweep.deleteRegion_(tess, regUp);
      libtess.mesh.deleteEdge(eUp);
      regUp = regLo.regionAbove();
    }
  }
};


/**
 * Purpose: connect a "right" vertex vEvent (one where all edges go left)
 * to the unprocessed portion of the mesh. Since there are no right-going
 * edges, two regions (one above vEvent and one below) are being merged
 * into one. regUp is the upper of these two regions.
 *
 * There are two reasons for doing this (adding a right-going edge):
 *  - if the two regions being merged are "inside", we must add an edge
 *    to keep them separated (the combined region would not be monotone).
 *  - in any case, we must leave some record of vEvent in the dictionary,
 *    so that we can merge vEvent with features that we have not seen yet.
 *    For example, maybe there is a vertical edge which passes just to
 *    the right of vEvent; we would like to splice vEvent into this edge.
 *
 * However, we don't want to connect vEvent to just any vertex. We don't
 * want the new edge to cross any other edges; otherwise we will create
 * intersection vertices even when the input data had no self-intersections.
 * (This is a bad thing; if the user's input data has no intersections,
 * we don't want to generate any false intersections ourselves.)
 *
 * Our eventual goal is to connect vEvent to the leftmost unprocessed
 * vertex of the combined region (the union of regUp and regLo).
 * But because of unseen vertices with all right-going edges, and also
 * new vertices which may be created by edge intersections, we don't
 * know where that leftmost unprocessed vertex is. In the meantime, we
 * connect vEvent to the closest vertex of either chain, and mark the region
 * as "fixUpperEdge". This flag says to delete and reconnect this edge
 * to the next processed vertex on the boundary of the combined region.
 * Quite possibly the vertex we connected to will turn out to be the
 * closest one, in which case we won't need to make any changes.
 *
 * @private
 * @param {libtess.GluTesselator} tess [description].
 * @param {libtess.ActiveRegion} regUp [description].
 * @param {libtess.GluHalfEdge} eBottomLeft [description].
 */
libtess.sweep.connectRightVertex_ = function(tess, regUp, eBottomLeft) {
  var eTopLeft = eBottomLeft.oNext;
  var regLo = regUp.regionBelow();
  var eUp = regUp.eUp;
  var eLo = regLo.eUp;
  var degenerate = false;

  if (eUp.dst() !== eLo.dst()) {
    libtess.sweep.checkForIntersect_(tess, regUp);
  }

  // Possible new degeneracies: upper or lower edge of regUp may pass
  // through vEvent, or may coincide with new intersection vertex
  if (libtess.geom.vertEq(eUp.org, tess.event)) {
    libtess.mesh.meshSplice(eTopLeft.oPrev(), eUp);
    regUp = libtess.sweep.topLeftRegion_(regUp);
    eTopLeft = regUp.regionBelow().eUp;
    libtess.sweep.finishLeftRegions_(tess, regUp.regionBelow(), regLo);
    degenerate = true;
  }
  if (libtess.geom.vertEq(eLo.org, tess.event)) {
    libtess.mesh.meshSplice(eBottomLeft, eLo.oPrev());
    eBottomLeft = libtess.sweep.finishLeftRegions_(tess, regLo, null);
    degenerate = true;
  }
  if (degenerate) {
    libtess.sweep.addRightEdges_(tess, regUp, eBottomLeft.oNext, eTopLeft,
        eTopLeft, true);
    return;
  }

  // Non-degenerate situation -- need to add a temporary, fixable edge.
  // Connect to the closer of eLo.org, eUp.org.
  var eNew;
  if (libtess.geom.vertLeq(eLo.org, eUp.org)) {
    eNew = eLo.oPrev();
  } else {
    eNew = eUp;
  }
  eNew = libtess.mesh.connect(eBottomLeft.lPrev(), eNew);

  // Prevent cleanup, otherwise eNew might disappear before we've even
  // had a chance to mark it as a temporary edge.
  libtess.sweep.addRightEdges_(tess, regUp, eNew, eNew.oNext, eNew.oNext,
      false);
  eNew.sym.activeRegion.fixUpperEdge = true;
  libtess.sweep.walkDirtyRegions_(tess, regUp);
};


/**
 * The event vertex lies exacty on an already-processed edge or vertex.
 * Adding the new vertex involves splicing it into the already-processed
 * part of the mesh.
 * @private
 * @param {!libtess.GluTesselator} tess
 * @param {libtess.ActiveRegion} regUp [description].
 * @param {libtess.GluVertex} vEvent [description].
 */
libtess.sweep.connectLeftDegenerate_ = function(tess, regUp, vEvent) {
  var e = regUp.eUp;
  /* istanbul ignore if */
  if (libtess.geom.vertEq(e.org, vEvent)) {
    // NOTE(bckenny): this code is unreachable but remains for a hypothetical
    // future extension of libtess. See docs on libtess.sweep.TOLERANCE_NONZERO_
    // for more information. Conditional on TOLERANCE_NONZERO_ to help Closure
    // Compiler eliminate dead code.
    // e.org is an unprocessed vertex - just combine them, and wait
    // for e.org to be pulled from the queue
    if (libtess.sweep.TOLERANCE_NONZERO_) {
      libtess.sweep.spliceMergeVertices_(tess, e, vEvent.anEdge);
    }
    return;
  }

  if (!libtess.geom.vertEq(e.dst(), vEvent)) {
    // General case -- splice vEvent into edge e which passes through it
    libtess.mesh.splitEdge(e.sym);

    if (regUp.fixUpperEdge) {
      // This edge was fixable -- delete unused portion of original edge
      libtess.mesh.deleteEdge(e.oNext);
      regUp.fixUpperEdge = false;
    }

    libtess.mesh.meshSplice(vEvent.anEdge, e);

    // recurse
    libtess.sweep.sweepEvent_(tess, vEvent);
    return;
  }

  // NOTE(bckenny): this code is unreachable but remains for a hypothetical
  // future extension of libtess. See docs on libtess.sweep.TOLERANCE_NONZERO_
  // for more information. Conditional on TOLERANCE_NONZERO_ to help Closure
  // Compiler eliminate dead code.
  // vEvent coincides with e.dst(), which has already been processed.
  // Splice in the additional right-going edges.
  /* istanbul ignore next */

  /* istanbul ignore next */
  if (libtess.sweep.TOLERANCE_NONZERO_) {
    regUp = libtess.sweep.topRightRegion_(regUp);
    var reg = regUp.regionBelow();
    var eTopRight = reg.eUp.sym;
    var eTopLeft = eTopRight.oNext;
    var eLast = eTopLeft;

    if (reg.fixUpperEdge) {
      // Here e.dst() has only a single fixable edge going right.
      // We can delete it since now we have some real right-going edges.

      // there are some left edges too
      libtess.sweep.deleteRegion_(tess, reg); // TODO(bckenny): something to null?
      libtess.mesh.deleteEdge(eTopRight);
      eTopRight = eTopLeft.oPrev();
    }

    libtess.mesh.meshSplice(vEvent.anEdge, eTopRight);
    if (!libtess.geom.edgeGoesLeft(eTopLeft)) {
      // e.dst() had no left-going edges -- indicate this to addRightEdges()
      eTopLeft = null;
    }

    libtess.sweep.addRightEdges_(tess, regUp, eTopRight.oNext, eLast, eTopLeft,
        true);
  }
};


/**
 * Connect a "left" vertex (one where both edges go right)
 * to the processed portion of the mesh. Let R be the active region
 * containing vEvent, and let U and L be the upper and lower edge
 * chains of R. There are two possibilities:
 *
 * - the normal case: split R into two regions, by connecting vEvent to
 *   the rightmost vertex of U or L lying to the left of the sweep line
 *
 * - the degenerate case: if vEvent is close enough to U or L, we
 *   merge vEvent into that edge chain. The subcases are:
 *  - merging with the rightmost vertex of U or L
 *  - merging with the active edge of U or L
 *  - merging with an already-processed portion of U or L
 *
 * @private
 * @param {libtess.GluTesselator} tess   [description].
 * @param {libtess.GluVertex} vEvent [description].
 */
libtess.sweep.connectLeftVertex_ = function(tess, vEvent) {
  // TODO(bckenny): tmp only used for sweep. better to keep tmp across calls?
  var tmp = new libtess.ActiveRegion();

  // NOTE(bckenny): this was commented out in the original
  // libtess.assert(vEvent.anEdge.oNext.oNext === vEvent.anEdge);

  // Get a pointer to the active region containing vEvent
  tmp.eUp = vEvent.anEdge.sym;
  var regUp = tess.dict.search(tmp).getKey();
  var regLo = regUp.regionBelow();
  var eUp = regUp.eUp;
  var eLo = regLo.eUp;

  // try merging with U or L first
  if (libtess.geom.edgeSign(eUp.dst(), vEvent, eUp.org) === 0) {
    libtess.sweep.connectLeftDegenerate_(tess, regUp, vEvent);
    return;
  }

  // Connect vEvent to rightmost processed vertex of either chain.
  // e.dst() is the vertex that we will connect to vEvent.
  var reg = libtess.geom.vertLeq(eLo.dst(), eUp.dst()) ? regUp : regLo;
  var eNew;
  if (regUp.inside || reg.fixUpperEdge) {
    if (reg === regUp) {
      eNew = libtess.mesh.connect(vEvent.anEdge.sym, eUp.lNext);

    } else {
      var tempHalfEdge = libtess.mesh.connect(eLo.dNext(), vEvent.anEdge);
      eNew = tempHalfEdge.sym;
    }

    if (reg.fixUpperEdge) {
      libtess.sweep.fixUpperEdge_(reg, eNew);

    } else {
      libtess.sweep.computeWinding_(tess,
          libtess.sweep.addRegionBelow_(tess, regUp, eNew));
    }
    libtess.sweep.sweepEvent_(tess, vEvent);

  } else {
    // The new vertex is in a region which does not belong to the polygon.
    // We don''t need to connect this vertex to the rest of the mesh.
    libtess.sweep.addRightEdges_(tess, regUp, vEvent.anEdge, vEvent.anEdge,
        null, true);
  }
};


/**
 * Does everything necessary when the sweep line crosses a vertex.
 * Updates the mesh and the edge dictionary.
 * @private
 * @param {libtess.GluTesselator} tess [description].
 * @param {libtess.GluVertex} vEvent [description].
 */
libtess.sweep.sweepEvent_ = function(tess, vEvent) {
  tess.event = vEvent; // for access in edgeLeq_ // TODO(bckenny): wuh?

  /* Check if this vertex is the right endpoint of an edge that is
   * already in the dictionary.  In this case we don't need to waste
   * time searching for the location to insert new edges.
   */
  var e = vEvent.anEdge;
  while (e.activeRegion === null) {
    e = e.oNext;
    if (e === vEvent.anEdge) {
      // All edges go right -- not incident to any processed edges
      libtess.sweep.connectLeftVertex_(tess, vEvent);
      return;
    }
  }

  /* Processing consists of two phases: first we "finish" all the
   * active regions where both the upper and lower edges terminate
   * at vEvent (ie. vEvent is closing off these regions).
   * We mark these faces "inside" or "outside" the polygon according
   * to their winding number, and delete the edges from the dictionary.
   * This takes care of all the left-going edges from vEvent.
   */
  var regUp = libtess.sweep.topLeftRegion_(e.activeRegion);
  var reg = regUp.regionBelow();
  var eTopLeft = reg.eUp;
  var eBottomLeft = libtess.sweep.finishLeftRegions_(tess, reg, null);

  /* Next we process all the right-going edges from vEvent. This
   * involves adding the edges to the dictionary, and creating the
   * associated "active regions" which record information about the
   * regions between adjacent dictionary edges.
   */
  if (eBottomLeft.oNext === eTopLeft) {
    // No right-going edges -- add a temporary "fixable" edge
    libtess.sweep.connectRightVertex_(tess, regUp, eBottomLeft);

  } else {
    libtess.sweep.addRightEdges_(tess, regUp, eBottomLeft.oNext, eTopLeft,
        eTopLeft, true);
  }
};


/**
 * We add two sentinel edges above and below all other edges,
 * to avoid special cases at the top and bottom.
 * @private
 * @param {libtess.GluTesselator} tess [description].
 * @param {number} t [description].
 */
libtess.sweep.addSentinel_ = function(tess, t) {
  var reg = new libtess.ActiveRegion();

  var e = libtess.mesh.makeEdge(tess.mesh);

  e.org.s = libtess.sweep.SENTINEL_COORD_;
  e.org.t = t;
  e.dst().s = -libtess.sweep.SENTINEL_COORD_;
  e.dst().t = t;
  tess.event = e.dst(); //initialize it

  reg.eUp = e;
  reg.windingNumber = 0;
  reg.inside = false;
  reg.fixUpperEdge = false;
  reg.sentinel = true;
  reg.dirty = false;
  reg.nodeUp = tess.dict.insert(reg);
};


/**
 * We maintain an ordering of edge intersections with the sweep line.
 * This order is maintained in a dynamic dictionary.
 * @private
 * @param {libtess.GluTesselator} tess [description].
 */
libtess.sweep.initEdgeDict_ = function(tess) {
  tess.dict = new libtess.Dict(tess, libtess.sweep.edgeLeq_);

  libtess.sweep.addSentinel_(tess, -libtess.sweep.SENTINEL_COORD_);
  libtess.sweep.addSentinel_(tess, libtess.sweep.SENTINEL_COORD_);
};


/**
 * [doneEdgeDict_ description]
 * @private
 * @param {libtess.GluTesselator} tess [description].
 */
libtess.sweep.doneEdgeDict_ = function(tess) {
  // NOTE(bckenny): fixedEdges is only used in the assert below, so ignore so
  // when asserts are removed jshint won't error.
  /* jshint unused:false */
  var fixedEdges = 0;

  var reg;
  while ((reg = tess.dict.getMin().getKey()) !== null) {
    // At the end of all processing, the dictionary should contain
    // only the two sentinel edges, plus at most one "fixable" edge
    // created by connectRightVertex().
    if (!reg.sentinel) {
    }
    libtess.sweep.deleteRegion_(tess, reg);
  }

  // NOTE(bckenny): see tess.dict.deleteDict_() for old delete dict function
  tess.dict = null;
};


/**
 * Remove zero-length edges, and contours with fewer than 3 vertices.
 * @private
 * @param {libtess.GluTesselator} tess [description].
 */
libtess.sweep.removeDegenerateEdges_ = function(tess) {
  var eHead = tess.mesh.eHead;

  var eNext;
  for (var e = eHead.next; e !== eHead; e = eNext) {
    eNext = e.next;
    var eLNext = e.lNext;

    if (libtess.geom.vertEq(e.org, e.dst()) && e.lNext.lNext !== e) {
      // Zero-length edge, contour has at least 3 edges
      libtess.sweep.spliceMergeVertices_(tess, eLNext, e); // deletes e.org
      libtess.mesh.deleteEdge(e); // e is a self-loop TODO(bckenny): does this comment really apply here?
      e = eLNext;
      eLNext = e.lNext;
    }

    if (eLNext.lNext === e) {
      // Degenerate contour (one or two edges)
      if (eLNext !== e) {
        if (eLNext === eNext || eLNext === eNext.sym) {
          eNext = eNext.next;
        }
        libtess.mesh.deleteEdge(eLNext);
      }

      if (e === eNext || e === eNext.sym) {
        eNext = eNext.next;
      }
      libtess.mesh.deleteEdge(e);
    }
  }
};


/**
 * Construct priority queue and insert all vertices into it, which determines
 * the order in which vertices cross the sweep line.
 * @private
 * @param {libtess.GluTesselator} tess [description].
 */
libtess.sweep.initPriorityQ_ = function(tess) {
  var pq = new libtess.PriorityQ();
  tess.pq = pq;

  var vHead = tess.mesh.vHead;
  var v;
  for (v = vHead.next; v !== vHead; v = v.next) {
    v.pqHandle = pq.insert(v);
  }

  pq.init();
};


/**
 * [donePriorityQ_ description]
 * @private
 * @param {libtess.GluTesselator} tess [description].
 */
libtess.sweep.donePriorityQ_ = function(tess) {
  // TODO(bckenny): probably don't need deleteQ. check that function for comment
  tess.pq.deleteQ();
  tess.pq = null;
};


/**
 * Delete any degenerate faces with only two edges. walkDirtyRegions()
 * will catch almost all of these, but it won't catch degenerate faces
 * produced by splice operations on already-processed edges.
 * The two places this can happen are in finishLeftRegions(), when
 * we splice in a "temporary" edge produced by connectRightVertex(),
 * and in checkForLeftSplice(), where we splice already-processed
 * edges to ensure that our dictionary invariants are not violated
 * by numerical errors.
 *
 * In both these cases it is *very* dangerous to delete the offending
 * edge at the time, since one of the routines further up the stack
 * will sometimes be keeping a pointer to that edge.
 *
 * @private
 * @param {libtess.GluMesh} mesh [description].
 */
libtess.sweep.removeDegenerateFaces_ = function(mesh) {
  var fNext;
  for (var f = mesh.fHead.next; f !== mesh.fHead; f = fNext) {
    fNext = f.next;
    var e = f.anEdge;

    if (e.lNext.lNext === e) {
      // A face with only two edges
      libtess.sweep.addWinding_(e.oNext, e);
      libtess.mesh.deleteEdge(e);
    }
  }
};

/* global libtess */

/** @const */
libtess.tessmono = {};

/**
 * Tessellates a monotone region (what else would it do??). The region must
 * consist of a single loop of half-edges (see mesh.js) oriented CCW. "Monotone"
 * in this case means that any vertical line intersects the interior of the
 * region in a single interval.
 *
 * Tessellation consists of adding interior edges (actually pairs of
 * half-edges), to split the region into non-overlapping triangles.
 * @private
 * @param {!libtess.GluFace} face
 */
libtess.tessmono.tessellateMonoRegion_ = function(face) {
  /* The basic idea is explained in Preparata and Shamos (which I don't
   * have handy right now), although their implementation is more
   * complicated than this one. The are two edge chains, an upper chain
   * and a lower chain. We process all vertices from both chains in order,
   * from right to left.
   *
   * The algorithm ensures that the following invariant holds after each
   * vertex is processed: the untessellated region consists of two
   * chains, where one chain (say the upper) is a single edge, and
   * the other chain is concave. The left vertex of the single edge
   * is always to the left of all vertices in the concave chain.
   *
   * Each step consists of adding the rightmost unprocessed vertex to one
   * of the two chains, and forming a fan of triangles from the rightmost
   * of two chain endpoints. Determining whether we can add each triangle
   * to the fan is a simple orientation test. By making the fan as large
   * as possible, we restore the invariant (check it yourself).
   *
   * All edges are oriented CCW around the boundary of the region.
   * First, find the half-edge whose origin vertex is rightmost.
   * Since the sweep goes from left to right, face.anEdge should
   * be close to the edge we want.
   */
  var up = face.anEdge;

  for (; libtess.geom.vertLeq(up.dst(), up.org); up = up.lPrev()) { }
  for (; libtess.geom.vertLeq(up.org, up.dst()); up = up.lNext) { }

  var lo = up.lPrev();

  var tempHalfEdge;
  while (up.lNext !== lo) {
    if (libtess.geom.vertLeq(up.dst(), lo.org)) {
      // up.dst() is on the left. It is safe to form triangles from lo.org.
      // The edgeGoesLeft test guarantees progress even when some triangles
      // are CW, given that the upper and lower chains are truly monotone.
      while (lo.lNext !== up && (libtess.geom.edgeGoesLeft(lo.lNext) ||
          libtess.geom.edgeSign(lo.org, lo.dst(), lo.lNext.dst()) <= 0)) {

        tempHalfEdge = libtess.mesh.connect(lo.lNext, lo);
        lo = tempHalfEdge.sym;
      }
      lo = lo.lPrev();

    } else {
      // lo.org is on the left. We can make CCW triangles from up.dst().
      while (lo.lNext !== up && (libtess.geom.edgeGoesRight(up.lPrev()) ||
          libtess.geom.edgeSign(up.dst(), up.org, up.lPrev().org) >= 0)) {

        tempHalfEdge = libtess.mesh.connect(up, up.lPrev());
        up = tempHalfEdge.sym;
      }
      up = up.lNext;
    }
  }

  // Now lo.org == up.dst() == the leftmost vertex. The remaining region
  // can be tessellated in a fan from this leftmost vertex.
  while (lo.lNext.lNext !== up) {
    tempHalfEdge = libtess.mesh.connect(lo.lNext, lo);
    lo = tempHalfEdge.sym;
  }
};

/**
 * Tessellates each region of the mesh which is marked "inside" the polygon.
 * Each such region must be monotone.
 * @param {!libtess.GluMesh} mesh
 */
libtess.tessmono.tessellateInterior = function(mesh) {
  var next;
  for (var f = mesh.fHead.next; f !== mesh.fHead; f = next) {
    // Make sure we don't try to tessellate the new triangles.
    next = f.next;
    if (f.inside) {
      libtess.tessmono.tessellateMonoRegion_(f);
    }
  }
};

/**
 * Zaps (i.e. sets to null) all faces which are not marked "inside" the polygon.
 * Since further mesh operations on null faces are not allowed, the main purpose
 * is to clean up the mesh so that exterior loops are not represented in the
 * data structure.
 * @param {!libtess.GluMesh} mesh
 */
libtess.tessmono.discardExterior = function(mesh) {
  var next;
  for (var f = mesh.fHead.next; f !== mesh.fHead; f = next) {
    // Since f will be destroyed, save its next pointer.
    next = f.next;
    if (!f.inside) {
      libtess.mesh.zapFace(f);
    }
  }
};

/**
 * Resets the winding numbers on all edges so that regions marked "inside" the
 * polygon have a winding number of "value", and regions outside have a winding
 * number of 0.
 *
 * If keepOnlyBoundary is true, it also deletes all edges which do not separate
 * an interior region from an exterior one.
 *
 * @param {!libtess.GluMesh} mesh
 * @param {number} value
 * @param {boolean} keepOnlyBoundary
 */
libtess.tessmono.setWindingNumber = function(mesh, value, keepOnlyBoundary) {
  var eNext;
  for (var e = mesh.eHead.next; e !== mesh.eHead; e = eNext) {
    eNext = e.next;

    if (e.rFace().inside !== e.lFace.inside) {
      // This is a boundary edge (one side is interior, one is exterior).
      e.winding = (e.lFace.inside) ? value : -value;

    } else {
      // Both regions are interior, or both are exterior.
      if (!keepOnlyBoundary) {
        e.winding = 0;

      } else {
        libtess.mesh.deleteEdge(e);
      }
    }
  }
};

/* global libtess */

/**
 * A list of edges crossing the sweep line, sorted from top to bottom.
 * Implementation is a doubly-linked list, sorted by the injected edgeLeq
 * comparator function. Here it is a simple ordering, but see libtess.sweep for
 * the list of invariants on the edge dictionary this ordering creates.
 * @constructor
 * @struct
 * @param {!libtess.GluTesselator} frame
 * @param {function(!libtess.GluTesselator, !libtess.ActiveRegion, !libtess.ActiveRegion): boolean} leq
 */
libtess.Dict = function(frame, leq) {

  /**
   * The head of the doubly-linked DictNode list. At creation time, links back
   * and forward only to itself.
   * @private {!libtess.DictNode}
   */
  this.head_ = new libtess.DictNode();

  /**
   * The GluTesselator used as the frame for edge/event comparisons.
   * @private {!libtess.GluTesselator}
   */
  this.frame_ = frame;

  /**
   * Comparison function to maintain the invariants of the Dict. See
   * libtess.sweep.edgeLeq_ for source.
   * @private
   * @type {function(!libtess.GluTesselator, !libtess.ActiveRegion, !libtess.ActiveRegion): boolean}
   */
  this.leq_ = leq;
};

/* istanbul ignore next */
/**
 * Formerly used to delete the dict.
 * NOTE(bckenny): No longer called but left for memFree documentation. Nulled at
 * former callsite instead (sweep.doneEdgeDict_)
 * @private
 */
libtess.Dict.prototype.deleteDict_ = function() {
  // for (var node = this.head_.next; node !== this.head_; node = node.next) {
  //   memFree(node);
  // }
  // memFree(dict);
};

/**
 * Insert the supplied key into the edge list and return its new node.
 * @param {libtess.DictNode} node
 * @param {!libtess.ActiveRegion} key
 * @return {!libtess.DictNode}
 */
libtess.Dict.prototype.insertBefore = function(node, key) {
  do {
    node = node.prev;
  } while (node.key !== null && !this.leq_(this.frame_, node.key, key));

  // insert the new node and update the surrounding nodes to point to it
  var newNode = new libtess.DictNode(key, node.next, node);
  node.next.prev = newNode;
  node.next = newNode;

  return newNode;
};

/**
 * Insert key into the dict and return the new node that contains it.
 * @param {!libtess.ActiveRegion} key
 * @return {!libtess.DictNode}
 */
libtess.Dict.prototype.insert = function(key) {
  // NOTE(bckenny): from a macro in dict.h/dict-list.h
  return this.insertBefore(this.head_, key);
};

/**
 * Remove node from the list.
 * @param {libtess.DictNode} node
 */
libtess.Dict.prototype.deleteNode = function(node) {
  node.next.prev = node.prev;
  node.prev.next = node.next;

  // NOTE(bckenny): nulled at callsite (sweep.deleteRegion_)
  // memFree( node );
};

/**
 * Search returns the node with the smallest key greater than or equal
 * to the given key. If there is no such key, returns a node whose
 * key is null. Similarly, max(d).getSuccessor() has a null key, etc.
 * @param {!libtess.ActiveRegion} key
 * @return {!libtess.DictNode}
 */
libtess.Dict.prototype.search = function(key) {
  var node = this.head_;

  do {
    node = node.next;
  } while (node.key !== null && !this.leq_(this.frame_, key, node.key));

  return node;
};

/**
 * Return the node with the smallest key.
 * @return {!libtess.DictNode}
 */
libtess.Dict.prototype.getMin = function() {
  // NOTE(bckenny): from a macro in dict.h/dict-list.h
  return this.head_.next;
};

// NOTE(bckenny): libtess.Dict.getMax isn't called within libtess and isn't part
// of the public API. For now, leaving in but ignoring for coverage.
/* istanbul ignore next */
/**
 * Returns the node with the greatest key.
 * @return {!libtess.DictNode}
 */
libtess.Dict.prototype.getMax = function() {
  // NOTE(bckenny): from a macro in dict.h/dict-list.h
  return this.head_.prev;
};

/* global libtess */

/**
 * A doubly-linked-list node with a libtess.ActiveRegion payload.
 * The key for this node and the next and previous nodes in the parent Dict list
 * can be provided to insert it into an existing list (or all can be omitted if
 * this is to be the founding node of the list).
 * @param {!libtess.ActiveRegion=} opt_key
 * @param {!libtess.DictNode=} opt_nextNode
 * @param {!libtess.DictNode=} opt_prevNode
 * @constructor
 * @struct
 */
libtess.DictNode = function(opt_key, opt_nextNode, opt_prevNode) {
  /**
   * The ActiveRegion key for this node, or null if the head of the list.
   * @type {libtess.ActiveRegion}
   */
  this.key = opt_key || null;

  /**
   * Link to next DictNode in parent list or to self if this is the first node.
   * @type {!libtess.DictNode}
   */
  this.next = opt_nextNode || this;

  /**
   * Link to previous DictNode in parent list or to self if this is the first
   * node.
   * @type {!libtess.DictNode}
   */
  this.prev = opt_prevNode || this;
};

/**
 * Get the key from this node.
 * @return {libtess.ActiveRegion}
 */
libtess.DictNode.prototype.getKey = function() {
  return this.key;
};

/**
 * Get the successor node to this one.
 * @return {!libtess.DictNode}
 */
libtess.DictNode.prototype.getSuccessor = function() {
  return this.next;
};

/**
 * Get the predecessor node to this one.
 * @return {!libtess.DictNode}
 */
libtess.DictNode.prototype.getPredecessor = function() {
  return this.prev;
};

/* global libtess */

// TODO(bckenny): create more javascript-y API, e.g. make gluTessEndPolygon
// async, don't require so many temp objects created

/**
 * The tesselator main class, providing the public API.
 * @constructor
 * @struct
 */
libtess.GluTesselator = function() {
  // Only initialize fields which can be changed by the api. Other fields
  // are initialized where they are used.

  /*** state needed for collecting the input data ***/

  /**
   * Tesselator state, tracking what begin/end calls have been seen.
   * @private {libtess.GluTesselator.tessState_}
   */
  this.state_ = libtess.GluTesselator.tessState_.T_DORMANT;

  /**
   * lastEdge_.org is the most recent vertex
   * @private {libtess.GluHalfEdge}
   */
  this.lastEdge_ = null;

  /**
   * stores the input contours, and eventually the tessellation itself
   * @type {libtess.GluMesh}
   */
  this.mesh = null;

  /**
   * Error callback.
   * @private {?function((libtess.errorType|libtess.gluEnum), Object=)}
   */
  this.errorCallback_ = null;

  /*** state needed for projecting onto the sweep plane ***/

  /**
   * user-specified normal (if provided)
   * @private {!Array<number>}
   */
  this.normal_ = [0, 0, 0];

  /*** state needed for the line sweep ***/

  /**
   * rule for determining polygon interior
   * @type {libtess.windingRule}
   */
  this.windingRule = libtess.windingRule.GLU_TESS_WINDING_ODD;

  /**
   * fatal error: needed combine callback
   * @type {boolean}
   */
  this.fatalError = false;

  /**
   * edge dictionary for sweep line
   * @type {libtess.Dict}
   */
  this.dict = null;
  // NOTE(bckenny): dict initialized in sweep.initEdgeDict_, removed in sweep.doneEdgeDict_

  /**
   * priority queue of vertex events
   * @type {libtess.PriorityQ}
   */
  this.pq = null;
  // NOTE(bckenny): pq initialized in sweep.initPriorityQ

  /**
   * current sweep event being processed
   * @type {libtess.GluVertex}
   */
  this.event = null;

  /**
   * Combine callback.
   * @private {?function(Array<number>, Array<Object>, Array<number>, Object=): Object}
   */
  this.combineCallback_ = null;

  /*** state needed for rendering callbacks (see render.js) ***/

  /**
   * Extract contours, not triangles
   * @private {boolean}
   */
  this.boundaryOnly_ = false;

  /**
   * Begin callback.
   * @private {?function(libtess.primitiveType, Object=)}
   */
  this.beginCallback_ = null;

  /**
   * Edge flag callback.
   * @private {?function(boolean, Object=)}
   */
  this.edgeFlagCallback_ = null;

  /**
   * Vertex callback.
   * @private {?function(Object, Object=)}
   */
  this.vertexCallback_ = null;

  /**
   * End callback.
   * @private {?function(Object=)}
   */
  this.endCallback_ = null;

  /**
   * Mesh callback.
   * @private {?function(libtess.GluMesh)}
   */
  this.meshCallback_ = null;

  /**
   * client data for current polygon
   * @private {Object}
   */
  this.polygonData_ = null;
};

/**
 * The begin/end calls must be properly nested. We keep track of the current
 * state to enforce the ordering.
 * @enum {number}
 * @private
 */
libtess.GluTesselator.tessState_ = {
  T_DORMANT: 0,
  T_IN_POLYGON: 1,
  T_IN_CONTOUR: 2
};

/**
 * Destory the tesselator object. See README.
 */
libtess.GluTesselator.prototype.gluDeleteTess = function() {
  // TODO(bckenny): This does nothing but assert that it isn't called while
  // building the polygon since we rely on GC to handle memory. *If* the public
  // API changes, this should go.
  this.requireState_(libtess.GluTesselator.tessState_.T_DORMANT);
  // memFree(tess); TODO(bckenny)
};

/**
 * Set properties for control over tesselation. See README.
 * @param {libtess.gluEnum} which [description].
 * @param {number|boolean} value [description].
 */
libtess.GluTesselator.prototype.gluTessProperty = function(which, value) {
  // TODO(bckenny): split into more setters?
  // TODO(bckenny): in any case, we can do better than this switch statement

  switch (which) {
    case libtess.gluEnum.GLU_TESS_TOLERANCE:
      // NOTE(bckenny): libtess has never supported any tolerance but 0.
      return;

    case libtess.gluEnum.GLU_TESS_WINDING_RULE:
      var windingRule = /** @type {libtess.windingRule} */(value);

      switch (windingRule) {
        case libtess.windingRule.GLU_TESS_WINDING_ODD:
        case libtess.windingRule.GLU_TESS_WINDING_NONZERO:
        case libtess.windingRule.GLU_TESS_WINDING_POSITIVE:
        case libtess.windingRule.GLU_TESS_WINDING_NEGATIVE:
        case libtess.windingRule.GLU_TESS_WINDING_ABS_GEQ_TWO:
          this.windingRule = windingRule;
          return;
        default:
      }
      break;

    case libtess.gluEnum.GLU_TESS_BOUNDARY_ONLY:
      this.boundaryOnly_ = !!value;
      return;

    default:
      this.callErrorCallback(libtess.gluEnum.GLU_INVALID_ENUM);
      return;
  }
  this.callErrorCallback(libtess.gluEnum.GLU_INVALID_VALUE);
};

/**
 * Returns tessellator property
 * @param {libtess.gluEnum} which [description].
 * @return {number|boolean} [description].
 */
libtess.GluTesselator.prototype.gluGetTessProperty = function(which) {
  // TODO(bckenny): as above, split into more getters? and improve on switch statement
  // why are these being asserted in getter but not setter?

  switch (which) {
    case libtess.gluEnum.GLU_TESS_TOLERANCE:
      return 0;

    case libtess.gluEnum.GLU_TESS_WINDING_RULE:
      var rule = this.windingRule;
      return rule;

    case libtess.gluEnum.GLU_TESS_BOUNDARY_ONLY:
      return this.boundaryOnly_;

    default:
      this.callErrorCallback(libtess.gluEnum.GLU_INVALID_ENUM);
      break;
  }
  return false;
};

/**
 * Lets the user supply the polygon normal, if known. All input data is
 * projected into a plane perpendicular to the normal before tesselation. All
 * output triangles are oriented CCW with respect to the normal (CW orientation
 * can be obtained by reversing the sign of the supplied normal). For example,
 * if you know that all polygons lie in the x-y plane, call
 * `tess.gluTessNormal(0.0, 0.0, 1.0)` before rendering any polygons.
 * @param {number} x
 * @param {number} y
 * @param {number} z
 */
libtess.GluTesselator.prototype.gluTessNormal = function(x, y, z) {
  this.normal_[0] = x;
  this.normal_[1] = y;
  this.normal_[2] = z;
};

/**
 * Specify callbacks. See README for callback descriptions. A null or undefined
 * opt_fn removes current callback.
 * @param {libtess.gluEnum} which The callback-type gluEnum value.
 * @param {?Function=} opt_fn
 */
libtess.GluTesselator.prototype.gluTessCallback = function(which, opt_fn) {
  var fn = !opt_fn ? null : opt_fn;
  // TODO(bckenny): better opt_fn typing?
  // TODO(bckenny): should add documentation that references in callback are volatile (or make a copy)

  switch (which) {
    case libtess.gluEnum.GLU_TESS_BEGIN:
    case libtess.gluEnum.GLU_TESS_BEGIN_DATA:
      this.beginCallback_ = /** @type {?function(libtess.primitiveType, Object=)} */ (fn);
      return;

    case libtess.gluEnum.GLU_TESS_EDGE_FLAG:
    case libtess.gluEnum.GLU_TESS_EDGE_FLAG_DATA:
      this.edgeFlagCallback_ = /** @type {?function(boolean, Object=)} */ (fn);
      return;

    case libtess.gluEnum.GLU_TESS_VERTEX:
    case libtess.gluEnum.GLU_TESS_VERTEX_DATA:
      this.vertexCallback_ = /** @type {?function(Object, Object=)} */ (fn);
      return;

    case libtess.gluEnum.GLU_TESS_END:
    case libtess.gluEnum.GLU_TESS_END_DATA:
      this.endCallback_ = /** @type {?function(Object=)} */ (fn);
      return;

    case libtess.gluEnum.GLU_TESS_ERROR:
    case libtess.gluEnum.GLU_TESS_ERROR_DATA:
      this.errorCallback_ = /** @type {?function((libtess.errorType|libtess.gluEnum), Object=)} */ (fn);
      return;

    case libtess.gluEnum.GLU_TESS_COMBINE:
    case libtess.gluEnum.GLU_TESS_COMBINE_DATA:
      this.combineCallback_ = /** @type {?function(Array<number>, Array<Object>, Array<number>, Object=): Object} */ (fn);
      return;

    case libtess.gluEnum.GLU_TESS_MESH:
      this.meshCallback_ = /** @type {?function(libtess.GluMesh)} */ (fn);
      return;

    default:
      this.callErrorCallback(libtess.gluEnum.GLU_INVALID_ENUM);
      return;
  }
};

/**
 * Specify a vertex and associated data. Must be within calls to
 * beginContour/endContour. See README.
 * @param {!Array<number>} coords
 * @param {Object} data
 */
libtess.GluTesselator.prototype.gluTessVertex = function(coords, data) {
  var tooLarge = false;

  // TODO(bckenny): pool allocation?
  var clamped = [0, 0, 0];

  this.requireState_(libtess.GluTesselator.tessState_.T_IN_CONTOUR);

  for (var i = 0; i < 3; ++i) {
    var x = coords[i];
    if (x < -libtess.GLU_TESS_MAX_COORD) {
      x = -libtess.GLU_TESS_MAX_COORD;
      tooLarge = true;
    }
    if (x > libtess.GLU_TESS_MAX_COORD) {
      x = libtess.GLU_TESS_MAX_COORD;
      tooLarge = true;
    }
    clamped[i] = x;
  }

  if (tooLarge) {
    this.callErrorCallback(libtess.errorType.GLU_TESS_COORD_TOO_LARGE);
  }

  this.addVertex_(clamped, data);
};

/**
 * [gluTessBeginPolygon description]
 * @param {Object} data Client data for current polygon.
 */
libtess.GluTesselator.prototype.gluTessBeginPolygon = function(data) {
  this.requireState_(libtess.GluTesselator.tessState_.T_DORMANT);

  this.state_ = libtess.GluTesselator.tessState_.T_IN_POLYGON;

  this.mesh = new libtess.GluMesh();

  this.polygonData_ = data;
};

/**
 * [gluTessBeginContour description]
 */
libtess.GluTesselator.prototype.gluTessBeginContour = function() {
  this.requireState_(libtess.GluTesselator.tessState_.T_IN_POLYGON);

  this.state_ = libtess.GluTesselator.tessState_.T_IN_CONTOUR;
  this.lastEdge_ = null;
};

/**
 * [gluTessEndContour description]
 */
libtess.GluTesselator.prototype.gluTessEndContour = function() {
  this.requireState_(libtess.GluTesselator.tessState_.T_IN_CONTOUR);
  this.state_ = libtess.GluTesselator.tessState_.T_IN_POLYGON;
};

/**
 * [gluTessEndPolygon description]
 */
libtess.GluTesselator.prototype.gluTessEndPolygon = function() {
  this.requireState_(libtess.GluTesselator.tessState_.T_IN_POLYGON);
  this.state_ = libtess.GluTesselator.tessState_.T_DORMANT;

  // Determine the polygon normal and project vertices onto the plane
  // of the polygon.
  libtess.normal.projectPolygon(this, this.normal_[0], this.normal_[1],
      this.normal_[2]);

  // computeInterior(tess) computes the planar arrangement specified
  // by the given contours, and further subdivides this arrangement
  // into regions. Each region is marked "inside" if it belongs
  // to the polygon, according to the rule given by this.windingRule.
  // Each interior region is guaranteed be monotone.
  libtess.sweep.computeInterior(this);

  if (!this.fatalError) {
    // If the user wants only the boundary contours, we throw away all edges
    // except those which separate the interior from the exterior.
    // Otherwise we tessellate all the regions marked "inside".
    // NOTE(bckenny): we know this.mesh has been initialized, so help closure out.
    var mesh = /** @type {!libtess.GluMesh} */(this.mesh);
    if (this.boundaryOnly_) {
      libtess.tessmono.setWindingNumber(mesh, 1, true);
    } else {
      libtess.tessmono.tessellateInterior(mesh);
    }

    this.mesh.checkMesh();

    if (this.beginCallback_ || this.endCallback_ || this.vertexCallback_ ||
        this.edgeFlagCallback_) {

      if (this.boundaryOnly_) {
        // output boundary contours
        libtess.render.renderBoundary(this, this.mesh);

      } else {
        // output triangles (with edge callback if one is set)
        var flagEdges = !!this.edgeFlagCallback_;
        libtess.render.renderMesh(this, this.mesh, flagEdges);
      }
    }

    if (this.meshCallback_) {
      // Throw away the exterior faces, so that all faces are interior.
      // This way the user doesn't have to check the "inside" flag,
      // and we don't need to even reveal its existence. It also leaves
      // the freedom for an implementation to not generate the exterior
      // faces in the first place.
      libtess.tessmono.discardExterior(this.mesh);
      // user wants the mesh itself
      this.meshCallback_(this.mesh);

      this.mesh = null;
      this.polygonData_ = null;
      return;
    }
  }

  libtess.mesh.deleteMesh(this.mesh);
  this.polygonData_ = null;
  this.mesh = null;
};

/**
 * Change the tesselator state.
 * @private
 * @param {libtess.GluTesselator.tessState_} state
 */
libtess.GluTesselator.prototype.requireState_ = function(state) {
  if (this.state_ !== state) {
    this.gotoState_(state);
  }
};

/**
 * Change the current tesselator state one level at a time to get to the
 * desired state. Only triggered when the API is not called in the correct order
 * so an error callback is made, however the tesselator will always attempt to
 * recover afterwards (see README).
 * @private
 * @param {libtess.GluTesselator.tessState_} newState
 */
libtess.GluTesselator.prototype.gotoState_ = function(newState) {
  while (this.state_ !== newState) {
    if (this.state_ < newState) {
      switch (this.state_) {
        case libtess.GluTesselator.tessState_.T_DORMANT:
          this.callErrorCallback(
              libtess.errorType.GLU_TESS_MISSING_BEGIN_POLYGON);
          this.gluTessBeginPolygon(null);
          break;

        case libtess.GluTesselator.tessState_.T_IN_POLYGON:
          this.callErrorCallback(
              libtess.errorType.GLU_TESS_MISSING_BEGIN_CONTOUR);
          this.gluTessBeginContour();
          break;
      }

    } else {
      switch (this.state_) {
        case libtess.GluTesselator.tessState_.T_IN_CONTOUR:
          this.callErrorCallback(
              libtess.errorType.GLU_TESS_MISSING_END_CONTOUR);
          this.gluTessEndContour();
          break;

        case libtess.GluTesselator.tessState_.T_IN_POLYGON:
          this.callErrorCallback(
              libtess.errorType.GLU_TESS_MISSING_END_POLYGON);
          // NOTE(bckenny): libtess originally reset the tesselator, even though
          // the README claims it should spit out the tessellated results at
          // this point.
          // (see http://cgit.freedesktop.org/mesa/glu/tree/src/libtess/tess.c#n180)
          this.gluTessEndPolygon();
          break;
      }
    }
  }
};

/**
 * [addVertex_ description]
 * @private
 * @param {!Array<number>} coords [description].
 * @param {Object} data [description].
 */
libtess.GluTesselator.prototype.addVertex_ = function(coords, data) {
  var e = this.lastEdge_;
  if (e === null) {
    // Make a self-loop (one vertex, one edge).
    e = libtess.mesh.makeEdge(this.mesh);
    libtess.mesh.meshSplice(e, e.sym);

  } else {
    // Create a new vertex and edge which immediately follow e
    // in the ordering around the left face.
    libtess.mesh.splitEdge(e);
    e = e.lNext;
  }

  // The new vertex is now e.org.
  e.org.data = data;
  e.org.coords[0] = coords[0];
  e.org.coords[1] = coords[1];
  e.org.coords[2] = coords[2];

  // The winding of an edge says how the winding number changes as we
  // cross from the edge''s right face to its left face.  We add the
  // vertices in such an order that a CCW contour will add +1 to
  // the winding number of the region inside the contour.
  e.winding = 1;
  e.sym.winding = -1;

  this.lastEdge_ = e;
};

/**
 * Call callback to indicate the start of a primitive, to be followed by emitted
 * vertices, if any. In libtess.js, `type` will always be `GL_TRIANGLES`.
 * @param {libtess.primitiveType} type
 */
libtess.GluTesselator.prototype.callBeginCallback = function(type) {
  if (this.beginCallback_) {
    this.beginCallback_(type, this.polygonData_);
  }
};

/**
 * Call callback to emit a vertex of the tessellated polygon.
 * @param {Object} data
 */
libtess.GluTesselator.prototype.callVertexCallback = function(data) {
  if (this.vertexCallback_) {
    this.vertexCallback_(data, this.polygonData_);
  }
};

/**
 * Call callback to indicate whether the vertices to follow begin edges which
 * lie on a polygon boundary.
 * @param {boolean} flag
 */
libtess.GluTesselator.prototype.callEdgeFlagCallback = function(flag) {
  if (this.edgeFlagCallback_) {
    this.edgeFlagCallback_(flag, this.polygonData_);
  }
};

/**
 * Call callback to indicate the end of tessellation.
 */
libtess.GluTesselator.prototype.callEndCallback = function() {
  if (this.endCallback_) {
    this.endCallback_(this.polygonData_);
  }
};

/* jscs:disable maximumLineLength */
/**
 * Call callback for combining vertices at edge intersection requiring the
 * creation of a new vertex.
 * @param {!Array<number>} coords Intersection coordinates.
 * @param {!Array<Object>} data Array of vertex data, one per edge vertices.
 * @param {!Array<number>} weight Coefficients used for the linear combination of vertex coordinates that gives coords.
 * @return {?Object} Interpolated vertex.
 */
libtess.GluTesselator.prototype.callCombineCallback = function(coords, data, weight) {
  if (this.combineCallback_) {
    return this.combineCallback_(coords, data, weight, this.polygonData_) ||
        null;
  }

  return null;
};
/* jscs:enable maximumLineLength */

/**
 * Call error callback, if specified, with errno.
 * @param {(libtess.errorType|libtess.gluEnum)} errno
 */
libtess.GluTesselator.prototype.callErrorCallback = function(errno) {
  if (this.errorCallback_) {
    this.errorCallback_(errno, this.polygonData_);
  }
};

/* global libtess */

/**
 * Each face has a pointer to the next and previous faces in the
 * circular list, and a pointer to a half-edge with this face as
 * the left face (null if this is the dummy header). There is also
 * a field "data" for client data.
 *
 * @param {libtess.GluFace=} opt_nextFace
 * @param {libtess.GluFace=} opt_prevFace
 * @constructor
 * @struct
 */
libtess.GluFace = function(opt_nextFace, opt_prevFace) {
  // TODO(bckenny): reverse order of params?

  /**
   * next face (never null)
   * @type {!libtess.GluFace}
   */
  this.next = opt_nextFace || this;

  /**
   * previous face (never NULL)
   * @type {!libtess.GluFace}
   */
  this.prev = opt_prevFace || this;

  /**
   * A half edge with this left face.
   * @type {libtess.GluHalfEdge}
   */
  this.anEdge = null;

  /**
   * room for client's data
   * @type {Object}
   */
  this.data = null;

  /**
   * This face is in the polygon interior.
   * @type {boolean}
   */
  this.inside = false;
};

/* global libtess */

/**
 * The fundamental data structure is the "half-edge". Two half-edges
 * go together to make an edge, but they point in opposite directions.
 * Each half-edge has a pointer to its mate (the "symmetric" half-edge sym),
 * its origin vertex (org), the face on its left side (lFace), and the
 * adjacent half-edges in the CCW direction around the origin vertex
 * (oNext) and around the left face (lNext). There is also a "next"
 * pointer for the global edge list (see below).
 *
 * The notation used for mesh navigation:
 *  sym   = the mate of a half-edge (same edge, but opposite direction)
 *  oNext = edge CCW around origin vertex (keep same origin)
 *  dNext = edge CCW around destination vertex (keep same dest)
 *  lNext = edge CCW around left face (dest becomes new origin)
 *  rNext = edge CCW around right face (origin becomes new dest)
 *
 * "prev" means to substitute CW for CCW in the definitions above.
 *
 * The circular edge list is special; since half-edges always occur
 * in pairs (e and e.sym), each half-edge stores a pointer in only
 * one direction. Starting at eHead and following the e.next pointers
 * will visit each *edge* once (ie. e or e.sym, but not both).
 * e.sym stores a pointer in the opposite direction, thus it is
 * always true that e.sym.next.sym.next === e.
 *
 * @param {libtess.GluHalfEdge=} opt_nextEdge
 * @constructor
 * @struct
 */
libtess.GluHalfEdge = function(opt_nextEdge) {
  // TODO(bckenny): are these the right defaults? (from gl_meshNewMesh requirements)

  /**
   * doubly-linked list (prev==sym->next)
   * @type {!libtess.GluHalfEdge}
   */
  this.next = opt_nextEdge || this;

  // TODO(bckenny): how can this be required if created in pairs? move to factory creation only?
  /**
   * same edge, opposite direction
   * @type {libtess.GluHalfEdge}
   */
  this.sym = null;

  /**
   * next edge CCW around origin
   * @type {libtess.GluHalfEdge}
   */
  this.oNext = null;

  /**
   * next edge CCW around left face
   * @type {libtess.GluHalfEdge}
   */
  this.lNext = null;

  /**
   * origin vertex (oVertex too long)
   * @type {libtess.GluVertex}
   */
  this.org = null;

  /**
   * left face
   * @type {libtess.GluFace}
   */
  this.lFace = null;

  // Internal data (keep hidden)
  // NOTE(bckenny): can't be private, though...

  /**
   * a region with this upper edge (see sweep.js)
   * @type {libtess.ActiveRegion}
   */
  this.activeRegion = null;

  /**
   * change in winding number when crossing from the right face to the left face
   * @type {number}
   */
  this.winding = 0;
};

// NOTE(bckenny): the following came from macros in mesh
// TODO(bckenny): using methods as aliases for sym connections for now.
// not sure about this approach. getters? renames?


/**
 * [rFace description]
 * @return {libtess.GluFace} [description].
 */
libtess.GluHalfEdge.prototype.rFace = function() {
  return this.sym.lFace;
};


/**
 * [dst description]
 * @return {libtess.GluVertex} [description].
 */
libtess.GluHalfEdge.prototype.dst = function() {
  return this.sym.org;
};


/**
 * [oPrev description]
 * @return {libtess.GluHalfEdge} [description].
 */
libtess.GluHalfEdge.prototype.oPrev = function() {
  return this.sym.lNext;
};


/**
 * [lPrev description]
 * @return {libtess.GluHalfEdge} [description].
 */
libtess.GluHalfEdge.prototype.lPrev = function() {
  return this.oNext.sym;
};

// NOTE(bckenny): libtess.GluHalfEdge.dPrev is called nowhere in libtess and
// isn't part of the current public API. It could be useful for mesh traversal
// and manipulation if made public, however.
/* istanbul ignore next */
/**
 * The edge clockwise around destination vertex (keep same dest).
 * @return {libtess.GluHalfEdge}
 */
libtess.GluHalfEdge.prototype.dPrev = function() {
  return this.lNext.sym;
};


/**
 * [rPrev description]
 * @return {libtess.GluHalfEdge} [description].
 */
libtess.GluHalfEdge.prototype.rPrev = function() {
  return this.sym.oNext;
};


/**
 * [dNext description]
 * @return {libtess.GluHalfEdge} [description].
 */
libtess.GluHalfEdge.prototype.dNext = function() {
  return this.rPrev().sym;
};


// NOTE(bckenny): libtess.GluHalfEdge.rNext is called nowhere in libtess and
// isn't part of the current public API. It could be useful for mesh traversal
// and manipulation if made public, however.
/* istanbul ignore next */
/**
 * The edge CCW around the right face (origin of this becomes new dest).
 * @return {libtess.GluHalfEdge}
 */
libtess.GluHalfEdge.prototype.rNext = function() {
  return this.oPrev().sym;
};

/* global libtess */

/**
 * Creates a new mesh with no edges, no vertices,
 * and no loops (what we usually call a "face").
 *
 * @constructor
 * @struct
 */
libtess.GluMesh = function() {
  /**
   * dummy header for vertex list
   * @type {libtess.GluVertex}
   */
  this.vHead = new libtess.GluVertex();

  /**
   * dummy header for face list
   * @type {libtess.GluFace}
   */
  this.fHead = new libtess.GluFace();

  /**
   * dummy header for edge list
   * @type {libtess.GluHalfEdge}
   */
  this.eHead = new libtess.GluHalfEdge();

  /**
   * and its symmetric counterpart
   * @type {libtess.GluHalfEdge}
   */
  this.eHeadSym = new libtess.GluHalfEdge();

  // TODO(bckenny): better way to pair these?
  this.eHead.sym = this.eHeadSym;
  this.eHeadSym.sym = this.eHead;
};


// TODO(bckenny): #ifndef NDEBUG
/**
 * Checks mesh for self-consistency.
 */
libtess.GluMesh.prototype.checkMesh = function() {
  if (!libtess.DEBUG) {
    return;
  }

  var fHead = this.fHead;
  var vHead = this.vHead;
  var eHead = this.eHead;

  var e;

  // faces
  var f;
  var fPrev = fHead;
  for (fPrev = fHead; (f = fPrev.next) !== fHead; fPrev = f) {
    e = f.anEdge;
    do {
      e = e.lNext;
    } while (e !== f.anEdge);
  }

  // vertices
  var v;
  var vPrev = vHead;
  for (vPrev = vHead; (v = vPrev.next) !== vHead; vPrev = v) {
    e = v.anEdge;
    do {
      e = e.oNext;
    } while (e !== v.anEdge);
  }

  // edges
  var ePrev = eHead;
  for (ePrev = eHead; (e = ePrev.next) !== eHead; ePrev = e) {
  }
};

/* global libtess */

/**
 * Each vertex has a pointer to next and previous vertices in the
 * circular list, and a pointer to a half-edge with this vertex as
 * the origin (null if this is the dummy header). There is also a
 * field "data" for client data.
 * @param {libtess.GluVertex=} opt_nextVertex Optional reference to next vertex in the vertex list.
 * @param {libtess.GluVertex=} opt_prevVertex Optional reference to previous vertex in the vertex list.
 * @constructor
 * @struct
 */
libtess.GluVertex = function(opt_nextVertex, opt_prevVertex) {
  /**
   * Next vertex (never null).
   * @type {!libtess.GluVertex}
   */
  this.next = opt_nextVertex || this;

  /**
   * Previous vertex (never null).
   * @type {!libtess.GluVertex}
   */
  this.prev = opt_prevVertex || this;

  /**
   * A half-edge with this origin.
   * @type {libtess.GluHalfEdge}
   */
  this.anEdge = null;

  /**
   * The client's data.
   * @type {Object}
   */
  this.data = null;

  /**
   * The vertex location in 3D.
   * @type {!Array.<number>}
   */
  this.coords = [0, 0, 0];
  // TODO(bckenny): we may want to rethink coords, either eliminate (using s
  // and t and user data) or index into contiguous storage?

  /**
   * Component of projection onto the sweep plane.
   * @type {number}
   */
  this.s = 0;

  /**
   * Component of projection onto the sweep plane.
   * @type {number}
   */
  this.t = 0;

  /**
   * Handle to allow deletion from priority queue, or 0 if not yet inserted into
   * queue.
   * @type {libtess.PQHandle}
   */
  this.pqHandle = 0;
};

/* global libtess */

/**
 * A priority queue of vertices, ordered by libtess.geom.vertLeq, implemented
 * with a sorted array. Used for initial insertion of vertices (see
 * libtess.sweep.initPriorityQ_), sorted once, then it uses an internal
 * libtess.PriorityQHeap for any subsequently created vertices from
 * intersections.
 * @constructor
 * @struct
 */
libtess.PriorityQ = function() {
  /**
   * An unordered list of vertices that have been inserted in the queue, with
   * null in empty slots.
   * @private {Array<libtess.GluVertex>}
   */
  this.verts_ = [];

  /**
   * Array of indices into this.verts_, sorted by vertLeq over the addressed
   * vertices.
   * @private {Array<number>}
   */
  this.order_ = null;

  /**
   * The size of this queue, not counting any vertices stored in heap_.
   * @private {number}
   */
  this.size_ = 0;

  /**
   * Indicates that the queue has been initialized via init. If false, inserts
   * are fast insertions at the end of the verts_ array. If true, the verts_
   * array is sorted and subsequent inserts are done in the heap.
   * @private {boolean}
   */
  this.initialized_ = false;

  /**
   * A priority queue heap, used for faster insertions of vertices after verts_
   * has been sorted.
   * @private {libtess.PriorityQHeap}
   */
  this.heap_ = new libtess.PriorityQHeap();
};

/**
 * Release major storage memory used by priority queue.
 */
libtess.PriorityQ.prototype.deleteQ = function() {
  // TODO(bckenny): could instead clear most of these.
  this.heap_ = null;
  this.order_ = null;
  this.verts_ = null;
  // NOTE(bckenny): nulled at callsite (sweep.donePriorityQ_)
};

/**
 * Sort vertices by libtess.geom.vertLeq. Must be called before any method other
 * than insert is called to ensure correctness when removing or querying.
 */
libtess.PriorityQ.prototype.init = function() {
  // TODO(bckenny): reuse. in theory, we don't have to empty this, as access is
  // dictated by this.size_, but array.sort doesn't know that
  this.order_ = [];

  // Create an array of indirect pointers to the verts, so that
  // the handles we have returned are still valid.
  // TODO(bckenny): valid for when? it appears we can just store indexes into
  // verts_, but what did this mean?
  for (var i = 0; i < this.size_; i++) {
    this.order_[i] = i;
  }

  // sort the indirect pointers in descending order of the verts themselves
  // TODO(bckenny): make sure it's ok that verts[a] === verts[b] returns 1
  // TODO(bckenny): unstable sort means we may get slightly different polys in
  // different browsers, but only when passing in equal points
  // TODO(bckenny): make less awkward closure?
  var comparator = (function(verts) {
    return function(a, b) {
      return libtess.geom.vertLeq(verts[a], verts[b]) ? 1 : -1;
    };
  })(this.verts_);
  this.order_.sort(comparator);

  this.initialized_ = true;
  this.heap_.init();

  // NOTE(bckenny): debug assert of ordering of the verts_ array.
  if (libtess.DEBUG) {
    var p = 0;
    var r = p + this.size_ - 1;
    for (i = p; i < r; ++i) {
    }
  }
};

/**
 * Insert a vertex into the priority queue. Returns a PQHandle to refer to it,
 * which will never be 0.
 * @param {libtess.GluVertex} vert
 * @return {libtess.PQHandle}
 */
libtess.PriorityQ.prototype.insert = function(vert) {
  // NOTE(bckenny): originally returned LONG_MAX as alloc failure signal. no
  // longer does.
  if (this.initialized_) {
    return this.heap_.insert(vert);
  }

  var curr = this.size_++;

  this.verts_[curr] = vert;

  // Negative handles index the sorted array.
  return -(curr + 1);
};

/**
 * Removes the minimum vertex from the queue and returns it. If the queue is
 * empty, null will be returned.
 * @return {libtess.GluVertex}
 */
libtess.PriorityQ.prototype.extractMin = function() {
  if (this.size_ === 0) {
    return this.heap_.extractMin();
  }

  var sortMin = this.verts_[this.order_[this.size_ - 1]];
  if (!this.heap_.isEmpty()) {
    var heapMin = this.heap_.minimum();
    if (libtess.geom.vertLeq(heapMin, sortMin)) {
      return this.heap_.extractMin();
    }
  }

  do {
    --this.size_;
  } while (this.size_ > 0 && this.verts_[this.order_[this.size_ - 1]] === null);

  return sortMin;
};

/**
 * Returns the minimum vertex in the queue. If the queue is empty, null will be
 * returned.
 * @return {libtess.GluVertex}
 */
libtess.PriorityQ.prototype.minimum = function() {
  if (this.size_ === 0) {
    return this.heap_.minimum();
  }

  var sortMin = this.verts_[this.order_[this.size_ - 1]];
  if (!this.heap_.isEmpty()) {
    var heapMin = this.heap_.minimum();
    if (libtess.geom.vertLeq(heapMin, sortMin)) {
      return heapMin;
    }
  }

  return sortMin;
};

/**
 * Remove vertex with handle removeHandle from queue.
 * @param {libtess.PQHandle} removeHandle
 */
libtess.PriorityQ.prototype.remove = function(removeHandle) {
  if (removeHandle >= 0) {
    this.heap_.remove(removeHandle);
    return;
  }
  removeHandle = -(removeHandle + 1);

  this.verts_[removeHandle] = null;
  while (this.size_ > 0 && this.verts_[this.order_[this.size_ - 1]] === null) {
    --this.size_;
  }
};

/* global libtess */

/**
 * A priority queue of vertices, ordered by libtess.geom.vertLeq, implemented
 * with a binary heap. Used only within libtess.PriorityQ for prioritizing
 * vertices created by intersections (see libtess.sweep.checkForIntersect_).
 * @constructor
 * @struct
 */
libtess.PriorityQHeap = function() {
  /**
   * The heap itself. Active nodes are stored in the range 1..size, with the
   * minimum at 1. Each node stores only an index into verts_ and handles_.
   * @private {!Array<number>}
   */
  this.heap_ = libtess.PriorityQHeap.reallocNumeric_([0],
      libtess.PriorityQHeap.INIT_SIZE_ + 1);

  /**
   * An unordered list of vertices in the heap, with null in empty slots.
   * @private {!Array<libtess.GluVertex>}
   */
  this.verts_ = [null, null];

  /**
   * An unordered list of indices mapping vertex handles into the heap. An entry
   * at index i will map the vertex at i in verts_ to its place in the heap
   * (i.e. heap_[handles_[i]] === i).
   * Empty slots below size_ are a free list chain starting at freeList_.
   * @private {!Array<number>}
   */
  this.handles_ = [0, 0];

  /**
   * The size of the queue.
   * @private {number}
   */
  this.size_ = 0;

  /**
   * The queue's current allocated space.
   * @private {number}
   */
  this.max_ = libtess.PriorityQHeap.INIT_SIZE_;

  /**
   * The index of the next free hole in the verts_ array. That slot in handles_
   * has the next index in the free list. If there are no holes, freeList_ === 0
   * and a new vertex must be appended to the list.
   * @private {libtess.PQHandle}
   */
  this.freeList_ = 0;

  /**
   * Indicates that the heap has been initialized via init. If false, inserts
   * are fast insertions at the end of a list. If true, all inserts will now be
   * correctly ordered in the queue before returning.
   * @private {boolean}
   */
  this.initialized_ = false;

  // Point the first index at the first (currently null) vertex.
  this.heap_[1] = 1;
};

/**
 * The initial allocated space for the queue.
 * @const
 * @private {number}
 */
libtess.PriorityQHeap.INIT_SIZE_ = 32;

/**
 * Allocate a numeric index array of size size. oldArray's contents are copied
 * to the beginning of the new array. The rest of the array is filled with
 * zeroes.
 * @private
 * @param {!Array<number>} oldArray
 * @param {number} size
 * @return {!Array<number>}
 */
libtess.PriorityQHeap.reallocNumeric_ = function(oldArray, size) {
  var newArray = new Array(size);

  // NOTE(bckenny): V8 likes this significantly more than simply growing the
  // array element-by-element or expanding the existing array all at once, so,
  // for now, emulating realloc.
  for (var index = 0; index < oldArray.length; index++) {
    newArray[index] = oldArray[index];
  }

  for (; index < size; index++) {
    newArray[index] = 0;
  }

  return newArray;
};

/**
 * Initializing ordering of the heap. Must be called before any method other
 * than insert is called to ensure correctness when removing or querying.
 */
libtess.PriorityQHeap.prototype.init = function() {
  // This method of building a heap is O(n), rather than O(n lg n).
  for (var i = this.size_; i >= 1; --i) {
    // TODO(bckenny): since init is called before anything is inserted (see
    // PriorityQ.init), this will always be empty. Better to lazily init?
    this.floatDown_(i);
  }

  this.initialized_ = true;
};

/**
 * Insert a new vertex into the heap.
 * @param {libtess.GluVertex} vert The vertex to insert.
 * @return {libtess.PQHandle} A handle that can be used to remove the vertex.
 */
libtess.PriorityQHeap.prototype.insert = function(vert) {
  var endIndex = ++this.size_;

  // If the heap overflows, double its size.
  if ((endIndex * 2) > this.max_) {
    this.max_ *= 2;

    this.handles_ = libtess.PriorityQHeap.reallocNumeric_(this.handles_,
        this.max_ + 1);
  }

  var newVertSlot;
  if (this.freeList_ === 0) {
    // No free slots, append vertex.
    newVertSlot = endIndex;
  } else {
    // Put vertex in free slot, update freeList_ to next free slot.
    newVertSlot = this.freeList_;
    this.freeList_ = this.handles_[this.freeList_];
  }

  this.verts_[newVertSlot] = vert;
  this.handles_[newVertSlot] = endIndex;
  this.heap_[endIndex] = newVertSlot;

  if (this.initialized_) {
    this.floatUp_(endIndex);
  }
  return newVertSlot;
};

/**
 * @return {boolean} Whether the heap is empty.
 */
libtess.PriorityQHeap.prototype.isEmpty = function() {
  return this.size_ === 0;
};

/**
 * Returns the minimum vertex in the heap. If the heap is empty, null will be
 * returned.
 * @return {libtess.GluVertex}
 */
libtess.PriorityQHeap.prototype.minimum = function() {
  return this.verts_[this.heap_[1]];
};

/**
 * Removes the minimum vertex from the heap and returns it. If the heap is
 * empty, null will be returned.
 * @return {libtess.GluVertex}
 */
libtess.PriorityQHeap.prototype.extractMin = function() {
  var heap = this.heap_;
  var verts = this.verts_;
  var handles = this.handles_;

  var minHandle = heap[1];
  var minVertex = verts[minHandle];

  if (this.size_ > 0) {
    // Replace min with last vertex.
    heap[1] = heap[this.size_];
    handles[heap[1]] = 1;

    // Clear min vertex and put slot at front of freeList_.
    verts[minHandle] = null;
    handles[minHandle] = this.freeList_;
    this.freeList_ = minHandle;

    // Restore heap.
    if (--this.size_ > 0) {
      this.floatDown_(1);
    }
  }

  return minVertex;
};

/**
 * Remove vertex with handle removeHandle from heap.
 * @param {libtess.PQHandle} removeHandle
 */
libtess.PriorityQHeap.prototype.remove = function(removeHandle) {
  var heap = this.heap_;
  var verts = this.verts_;
  var handles = this.handles_;

  var heapIndex = handles[removeHandle];

  // Replace with last vertex.
  heap[heapIndex] = heap[this.size_];
  handles[heap[heapIndex]] = heapIndex;

  // Restore heap.
  if (heapIndex <= --this.size_) {
    if (heapIndex <= 1) {
      this.floatDown_(heapIndex);
    } else {
      var vert = verts[heap[heapIndex]];
      var parentVert = verts[heap[heapIndex >> 1]];
      if (libtess.geom.vertLeq(parentVert, vert)) {
        this.floatDown_(heapIndex);
      } else {
        this.floatUp_(heapIndex);
      }
    }
  }

  // Clear vertex and put slot at front of freeList_.
  verts[removeHandle] = null;
  handles[removeHandle] = this.freeList_;
  this.freeList_ = removeHandle;
};

/**
 * Restore heap by moving the vertex at index in the heap downwards to a valid
 * slot.
 * @private
 * @param {libtess.PQHandle} index
 */
libtess.PriorityQHeap.prototype.floatDown_ = function(index) {
  var heap = this.heap_;
  var verts = this.verts_;
  var handles = this.handles_;

  var currIndex = index;
  var currHandle = heap[currIndex];
  for (;;) {
    // The children of node i are nodes 2i and 2i+1.
    var childIndex = currIndex << 1;
    if (childIndex < this.size_) {
      // Set child to the index of the child with the minimum vertex.
      if (libtess.geom.vertLeq(verts[heap[childIndex + 1]],
          verts[heap[childIndex]])) {
        childIndex = childIndex + 1;
      }
    }

    var childHandle = heap[childIndex];
    if (childIndex > this.size_ ||
        libtess.geom.vertLeq(verts[currHandle], verts[childHandle])) {
      // Heap restored.
      heap[currIndex] = currHandle;
      handles[currHandle] = currIndex;
      return;
    }

    // Swap current node and child; repeat from childIndex.
    heap[currIndex] = childHandle;
    handles[childHandle] = currIndex;
    currIndex = childIndex;
  }
};

/**
 * Restore heap by moving the vertex at index in the heap upwards to a valid
 * slot.
 * @private
 * @param {libtess.PQHandle} index
 */
libtess.PriorityQHeap.prototype.floatUp_ = function(index) {
  var heap = this.heap_;
  var verts = this.verts_;
  var handles = this.handles_;

  var currIndex = index;
  var currHandle = heap[currIndex];
  for (;;) {
    // The parent of node i is node floor(i/2).
    var parentIndex = currIndex >> 1;
    var parentHandle = heap[parentIndex];

    if (parentIndex === 0 ||
        libtess.geom.vertLeq(verts[parentHandle], verts[currHandle])) {
      // Heap restored.
      heap[currIndex] = currHandle;
      handles[currHandle] = currIndex;
      return;
    }

    // Swap current node and parent; repeat from parentIndex.
    heap[currIndex] = parentHandle;
    handles[parentHandle] = currIndex;
    currIndex = parentIndex;
  }
};

/* global libtess */

// TODO(bckenny): apparently only visible outside of sweep for debugging routines.
// find out if we can hide

/**
 * For each pair of adjacent edges crossing the sweep line, there is
 * an ActiveRegion to represent the region between them. The active
 * regions are kept in sorted order in a dynamic dictionary. As the
 * sweep line crosses each vertex, we update the affected regions.
 * @constructor
 * @struct
 */
libtess.ActiveRegion = function() {
  // TODO(bckenny): I *think* eUp and nodeUp could be passed in as constructor params

  /**
   * The upper edge of the region, directed right to left
   * @type {libtess.GluHalfEdge}
   */
  this.eUp = null;

  /**
   * Dictionary node corresponding to eUp edge.
   * @type {libtess.DictNode}
   */
  this.nodeUp = null;

  /**
   * Used to determine which regions are inside the polygon.
   * @type {number}
   */
  this.windingNumber = 0;

  /**
   * Whether this region is inside the polygon.
   * @type {boolean}
   */
  this.inside = false;

  /**
   * Marks fake edges at t = +/-infinity.
   * @type {boolean}
   */
  this.sentinel = false;

  /**
   * Marks regions where the upper or lower edge has changed, but we haven't
   * checked whether they intersect yet.
   * @type {boolean}
   */
  this.dirty = false;

  /**
   * marks temporary edges introduced when we process a "right vertex" (one
   * without any edges leaving to the right)
   * @type {boolean}
   */
  this.fixUpperEdge = false;
};

/**
 * Returns the ActiveRegion below this one.
 * @return {libtess.ActiveRegion}
 */
libtess.ActiveRegion.prototype.regionBelow = function() {
  return this.nodeUp.getPredecessor().getKey();
};

/**
 * Returns the ActiveRegion above this one.
 * @return {libtess.ActiveRegion}
 */
libtess.ActiveRegion.prototype.regionAbove = function() {
  return this.nodeUp.getSuccessor().getKey();
};

/* global libtess, module */

/**
 * node.js export for non-compiled source
 */
if (true) {
  module.exports = libtess;
}


/***/ }),

/***/ 822:
/***/ (function(__unused_webpack_module, exports) {


/*! pako 2.1.0 https://github.com/nodeca/pako @license (MIT AND Zlib) */
(function (global, factory) {
   true ? factory(exports) :
  0;
})(this, (function (exports) { 'use strict';

  // Note: adler32 takes 12% for level 0 and 2% for level 6.
  // It isn't worth it to make additional optimizations as in original.
  // Small size is preferable.

  // (C) 1995-2013 Jean-loup Gailly and Mark Adler
  // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
  //
  // This software is provided 'as-is', without any express or implied
  // warranty. In no event will the authors be held liable for any damages
  // arising from the use of this software.
  //
  // Permission is granted to anyone to use this software for any purpose,
  // including commercial applications, and to alter it and redistribute it
  // freely, subject to the following restrictions:
  //
  // 1. The origin of this software must not be misrepresented; you must not
  //   claim that you wrote the original software. If you use this software
  //   in a product, an acknowledgment in the product documentation would be
  //   appreciated but is not required.
  // 2. Altered source versions must be plainly marked as such, and must not be
  //   misrepresented as being the original software.
  // 3. This notice may not be removed or altered from any source distribution.

  const adler32 = (adler, buf, len, pos) => {
    let s1 = (adler & 0xffff) |0,
        s2 = ((adler >>> 16) & 0xffff) |0,
        n = 0;

    while (len !== 0) {
      // Set limit ~ twice less than 5552, to keep
      // s2 in 31-bits, because we force signed ints.
      // in other case %= will fail.
      n = len > 2000 ? 2000 : len;
      len -= n;

      do {
        s1 = (s1 + buf[pos++]) |0;
        s2 = (s2 + s1) |0;
      } while (--n);

      s1 %= 65521;
      s2 %= 65521;
    }

    return (s1 | (s2 << 16)) |0;
  };


  var adler32_1 = adler32;

  // Note: we can't get significant speed boost here.
  // So write code to minimize size - no pregenerated tables
  // and array tools dependencies.

  // (C) 1995-2013 Jean-loup Gailly and Mark Adler
  // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
  //
  // This software is provided 'as-is', without any express or implied
  // warranty. In no event will the authors be held liable for any damages
  // arising from the use of this software.
  //
  // Permission is granted to anyone to use this software for any purpose,
  // including commercial applications, and to alter it and redistribute it
  // freely, subject to the following restrictions:
  //
  // 1. The origin of this software must not be misrepresented; you must not
  //   claim that you wrote the original software. If you use this software
  //   in a product, an acknowledgment in the product documentation would be
  //   appreciated but is not required.
  // 2. Altered source versions must be plainly marked as such, and must not be
  //   misrepresented as being the original software.
  // 3. This notice may not be removed or altered from any source distribution.

  // Use ordinary array, since untyped makes no boost here
  const makeTable = () => {
    let c, table = [];

    for (var n = 0; n < 256; n++) {
      c = n;
      for (var k = 0; k < 8; k++) {
        c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
      }
      table[n] = c;
    }

    return table;
  };

  // Create table on load. Just 255 signed longs. Not a problem.
  const crcTable = new Uint32Array(makeTable());


  const crc32 = (crc, buf, len, pos) => {
    const t = crcTable;
    const end = pos + len;

    crc ^= -1;

    for (let i = pos; i < end; i++) {
      crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF];
    }

    return (crc ^ (-1)); // >>> 0;
  };


  var crc32_1 = crc32;

  // (C) 1995-2013 Jean-loup Gailly and Mark Adler
  // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
  //
  // This software is provided 'as-is', without any express or implied
  // warranty. In no event will the authors be held liable for any damages
  // arising from the use of this software.
  //
  // Permission is granted to anyone to use this software for any purpose,
  // including commercial applications, and to alter it and redistribute it
  // freely, subject to the following restrictions:
  //
  // 1. The origin of this software must not be misrepresented; you must not
  //   claim that you wrote the original software. If you use this software
  //   in a product, an acknowledgment in the product documentation would be
  //   appreciated but is not required.
  // 2. Altered source versions must be plainly marked as such, and must not be
  //   misrepresented as being the original software.
  // 3. This notice may not be removed or altered from any source distribution.

  // See state defs from inflate.js
  const BAD$1 = 16209;       /* got a data error -- remain here until reset */
  const TYPE$1 = 16191;      /* i: waiting for type bits, including last-flag bit */

  /*
     Decode literal, length, and distance codes and write out the resulting
     literal and match bytes until either not enough input or output is
     available, an end-of-block is encountered, or a data error is encountered.
     When large enough input and output buffers are supplied to inflate(), for
     example, a 16K input buffer and a 64K output buffer, more than 95% of the
     inflate execution time is spent in this routine.

     Entry assumptions:

          state.mode === LEN
          strm.avail_in >= 6
          strm.avail_out >= 258
          start >= strm.avail_out
          state.bits < 8

     On return, state.mode is one of:

          LEN -- ran out of enough output space or enough available input
          TYPE -- reached end of block code, inflate() to interpret next block
          BAD -- error in block data

     Notes:

      - The maximum input bits used by a length/distance pair is 15 bits for the
        length code, 5 bits for the length extra, 15 bits for the distance code,
        and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
        Therefore if strm.avail_in >= 6, then there is enough input to avoid
        checking for available input while decoding.

      - The maximum bytes that a single length/distance pair can output is 258
        bytes, which is the maximum length that can be coded.  inflate_fast()
        requires strm.avail_out >= 258 for each loop to avoid checking for
        output space.
   */
  var inffast = function inflate_fast(strm, start) {
    let _in;                    /* local strm.input */
    let last;                   /* have enough input while in < last */
    let _out;                   /* local strm.output */
    let beg;                    /* inflate()'s initial strm.output */
    let end;                    /* while out < end, enough space available */
  //#ifdef INFLATE_STRICT
    let dmax;                   /* maximum distance from zlib header */
  //#endif
    let wsize;                  /* window size or zero if not using window */
    let whave;                  /* valid bytes in the window */
    let wnext;                  /* window write index */
    // Use `s_window` instead `window`, avoid conflict with instrumentation tools
    let s_window;               /* allocated sliding window, if wsize != 0 */
    let hold;                   /* local strm.hold */
    let bits;                   /* local strm.bits */
    let lcode;                  /* local strm.lencode */
    let dcode;                  /* local strm.distcode */
    let lmask;                  /* mask for first level of length codes */
    let dmask;                  /* mask for first level of distance codes */
    let here;                   /* retrieved table entry */
    let op;                     /* code bits, operation, extra bits, or */
                                /*  window position, window bytes to copy */
    let len;                    /* match length, unused bytes */
    let dist;                   /* match distance */
    let from;                   /* where to copy match from */
    let from_source;


    let input, output; // JS specific, because we have no pointers

    /* copy state to local variables */
    const state = strm.state;
    //here = state.here;
    _in = strm.next_in;
    input = strm.input;
    last = _in + (strm.avail_in - 5);
    _out = strm.next_out;
    output = strm.output;
    beg = _out - (start - strm.avail_out);
    end = _out + (strm.avail_out - 257);
  //#ifdef INFLATE_STRICT
    dmax = state.dmax;
  //#endif
    wsize = state.wsize;
    whave = state.whave;
    wnext = state.wnext;
    s_window = state.window;
    hold = state.hold;
    bits = state.bits;
    lcode = state.lencode;
    dcode = state.distcode;
    lmask = (1 << state.lenbits) - 1;
    dmask = (1 << state.distbits) - 1;


    /* decode literals and length/distances until end-of-block or not enough
       input data or output space */

    top:
    do {
      if (bits < 15) {
        hold += input[_in++] << bits;
        bits += 8;
        hold += input[_in++] << bits;
        bits += 8;
      }

      here = lcode[hold & lmask];

      dolen:
      for (;;) { // Goto emulation
        op = here >>> 24/*here.bits*/;
        hold >>>= op;
        bits -= op;
        op = (here >>> 16) & 0xff/*here.op*/;
        if (op === 0) {                          /* literal */
          //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
          //        "inflate:         literal '%c'\n" :
          //        "inflate:         literal 0x%02x\n", here.val));
          output[_out++] = here & 0xffff/*here.val*/;
        }
        else if (op & 16) {                     /* length base */
          len = here & 0xffff/*here.val*/;
          op &= 15;                           /* number of extra bits */
          if (op) {
            if (bits < op) {
              hold += input[_in++] << bits;
              bits += 8;
            }
            len += hold & ((1 << op) - 1);
            hold >>>= op;
            bits -= op;
          }
          //Tracevv((stderr, "inflate:         length %u\n", len));
          if (bits < 15) {
            hold += input[_in++] << bits;
            bits += 8;
            hold += input[_in++] << bits;
            bits += 8;
          }
          here = dcode[hold & dmask];

          dodist:
          for (;;) { // goto emulation
            op = here >>> 24/*here.bits*/;
            hold >>>= op;
            bits -= op;
            op = (here >>> 16) & 0xff/*here.op*/;

            if (op & 16) {                      /* distance base */
              dist = here & 0xffff/*here.val*/;
              op &= 15;                       /* number of extra bits */
              if (bits < op) {
                hold += input[_in++] << bits;
                bits += 8;
                if (bits < op) {
                  hold += input[_in++] << bits;
                  bits += 8;
                }
              }
              dist += hold & ((1 << op) - 1);
  //#ifdef INFLATE_STRICT
              if (dist > dmax) {
                strm.msg = 'invalid distance too far back';
                state.mode = BAD$1;
                break top;
              }
  //#endif
              hold >>>= op;
              bits -= op;
              //Tracevv((stderr, "inflate:         distance %u\n", dist));
              op = _out - beg;                /* max distance in output */
              if (dist > op) {                /* see if copy from window */
                op = dist - op;               /* distance back in window */
                if (op > whave) {
                  if (state.sane) {
                    strm.msg = 'invalid distance too far back';
                    state.mode = BAD$1;
                    break top;
                  }

  // (!) This block is disabled in zlib defaults,
  // don't enable it for binary compatibility
  //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
  //                if (len <= op - whave) {
  //                  do {
  //                    output[_out++] = 0;
  //                  } while (--len);
  //                  continue top;
  //                }
  //                len -= op - whave;
  //                do {
  //                  output[_out++] = 0;
  //                } while (--op > whave);
  //                if (op === 0) {
  //                  from = _out - dist;
  //                  do {
  //                    output[_out++] = output[from++];
  //                  } while (--len);
  //                  continue top;
  //                }
  //#endif
                }
                from = 0; // window index
                from_source = s_window;
                if (wnext === 0) {           /* very common case */
                  from += wsize - op;
                  if (op < len) {         /* some from window */
                    len -= op;
                    do {
                      output[_out++] = s_window[from++];
                    } while (--op);
                    from = _out - dist;  /* rest from output */
                    from_source = output;
                  }
                }
                else if (wnext < op) {      /* wrap around window */
                  from += wsize + wnext - op;
                  op -= wnext;
                  if (op < len) {         /* some from end of window */
                    len -= op;
                    do {
                      output[_out++] = s_window[from++];
                    } while (--op);
                    from = 0;
                    if (wnext < len) {  /* some from start of window */
                      op = wnext;
                      len -= op;
                      do {
                        output[_out++] = s_window[from++];
                      } while (--op);
                      from = _out - dist;      /* rest from output */
                      from_source = output;
                    }
                  }
                }
                else {                      /* contiguous in window */
                  from += wnext - op;
                  if (op < len) {         /* some from window */
                    len -= op;
                    do {
                      output[_out++] = s_window[from++];
                    } while (--op);
                    from = _out - dist;  /* rest from output */
                    from_source = output;
                  }
                }
                while (len > 2) {
                  output[_out++] = from_source[from++];
                  output[_out++] = from_source[from++];
                  output[_out++] = from_source[from++];
                  len -= 3;
                }
                if (len) {
                  output[_out++] = from_source[from++];
                  if (len > 1) {
                    output[_out++] = from_source[from++];
                  }
                }
              }
              else {
                from = _out - dist;          /* copy direct from output */
                do {                        /* minimum length is three */
                  output[_out++] = output[from++];
                  output[_out++] = output[from++];
                  output[_out++] = output[from++];
                  len -= 3;
                } while (len > 2);
                if (len) {
                  output[_out++] = output[from++];
                  if (len > 1) {
                    output[_out++] = output[from++];
                  }
                }
              }
            }
            else if ((op & 64) === 0) {          /* 2nd level distance code */
              here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
              continue dodist;
            }
            else {
              strm.msg = 'invalid distance code';
              state.mode = BAD$1;
              break top;
            }

            break; // need to emulate goto via "continue"
          }
        }
        else if ((op & 64) === 0) {              /* 2nd level length code */
          here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
          continue dolen;
        }
        else if (op & 32) {                     /* end-of-block */
          //Tracevv((stderr, "inflate:         end of block\n"));
          state.mode = TYPE$1;
          break top;
        }
        else {
          strm.msg = 'invalid literal/length code';
          state.mode = BAD$1;
          break top;
        }

        break; // need to emulate goto via "continue"
      }
    } while (_in < last && _out < end);

    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
    len = bits >> 3;
    _in -= len;
    bits -= len << 3;
    hold &= (1 << bits) - 1;

    /* update state and return */
    strm.next_in = _in;
    strm.next_out = _out;
    strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last));
    strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end));
    state.hold = hold;
    state.bits = bits;
    return;
  };

  // (C) 1995-2013 Jean-loup Gailly and Mark Adler
  // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
  //
  // This software is provided 'as-is', without any express or implied
  // warranty. In no event will the authors be held liable for any damages
  // arising from the use of this software.
  //
  // Permission is granted to anyone to use this software for any purpose,
  // including commercial applications, and to alter it and redistribute it
  // freely, subject to the following restrictions:
  //
  // 1. The origin of this software must not be misrepresented; you must not
  //   claim that you wrote the original software. If you use this software
  //   in a product, an acknowledgment in the product documentation would be
  //   appreciated but is not required.
  // 2. Altered source versions must be plainly marked as such, and must not be
  //   misrepresented as being the original software.
  // 3. This notice may not be removed or altered from any source distribution.

  const MAXBITS = 15;
  const ENOUGH_LENS$1 = 852;
  const ENOUGH_DISTS$1 = 592;
  //const ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);

  const CODES$1 = 0;
  const LENS$1 = 1;
  const DISTS$1 = 2;

  const lbase = new Uint16Array([ /* Length codes 257..285 base */
    3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
    35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
  ]);

  const lext = new Uint8Array([ /* Length codes 257..285 extra */
    16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
    19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78
  ]);

  const dbase = new Uint16Array([ /* Distance codes 0..29 base */
    1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
    257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
    8193, 12289, 16385, 24577, 0, 0
  ]);

  const dext = new Uint8Array([ /* Distance codes 0..29 extra */
    16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
    23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
    28, 28, 29, 29, 64, 64
  ]);

  const inflate_table = (type, lens, lens_index, codes, table, table_index, work, opts) =>
  {
    const bits = opts.bits;
        //here = opts.here; /* table entry for duplication */

    let len = 0;               /* a code's length in bits */
    let sym = 0;               /* index of code symbols */
    let min = 0, max = 0;          /* minimum and maximum code lengths */
    let root = 0;              /* number of index bits for root table */
    let curr = 0;              /* number of index bits for current table */
    let drop = 0;              /* code bits to drop for sub-table */
    let left = 0;                   /* number of prefix codes available */
    let used = 0;              /* code entries in table used */
    let huff = 0;              /* Huffman code */
    let incr;              /* for incrementing code, index */
    let fill;              /* index for replicating entries */
    let low;               /* low bits for current root entry */
    let mask;              /* mask for low root bits */
    let next;             /* next available space in table */
    let base = null;     /* base value table to use */
  //  let shoextra;    /* extra bits table to use */
    let match;                  /* use base and extra for symbol >= match */
    const count = new Uint16Array(MAXBITS + 1); //[MAXBITS+1];    /* number of codes of each length */
    const offs = new Uint16Array(MAXBITS + 1); //[MAXBITS+1];     /* offsets in table for each length */
    let extra = null;

    let here_bits, here_op, here_val;

    /*
     Process a set of code lengths to create a canonical Huffman code.  The
     code lengths are lens[0..codes-1].  Each length corresponds to the
     symbols 0..codes-1.  The Huffman code is generated by first sorting the
     symbols by length from short to long, and retaining the symbol order
     for codes with equal lengths.  Then the code starts with all zero bits
     for the first code of the shortest length, and the codes are integer
     increments for the same length, and zeros are appended as the length
     increases.  For the deflate format, these bits are stored backwards
     from their more natural integer increment ordering, and so when the
     decoding tables are built in the large loop below, the integer codes
     are incremented backwards.

     This routine assumes, but does not check, that all of the entries in
     lens[] are in the range 0..MAXBITS.  The caller must assure this.
     1..MAXBITS is interpreted as that code length.  zero means that that
     symbol does not occur in this code.

     The codes are sorted by computing a count of codes for each length,
     creating from that a table of starting indices for each length in the
     sorted table, and then entering the symbols in order in the sorted
     table.  The sorted table is work[], with that space being provided by
     the caller.

     The length counts are used for other purposes as well, i.e. finding
     the minimum and maximum length codes, determining if there are any
     codes at all, checking for a valid set of lengths, and looking ahead
     at length counts to determine sub-table sizes when building the
     decoding tables.
     */

    /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
    for (len = 0; len <= MAXBITS; len++) {
      count[len] = 0;
    }
    for (sym = 0; sym < codes; sym++) {
      count[lens[lens_index + sym]]++;
    }

    /* bound code lengths, force root to be within code lengths */
    root = bits;
    for (max = MAXBITS; max >= 1; max--) {
      if (count[max] !== 0) { break; }
    }
    if (root > max) {
      root = max;
    }
    if (max === 0) {                     /* no symbols to code at all */
      //table.op[opts.table_index] = 64;  //here.op = (var char)64;    /* invalid code marker */
      //table.bits[opts.table_index] = 1;   //here.bits = (var char)1;
      //table.val[opts.table_index++] = 0;   //here.val = (var short)0;
      table[table_index++] = (1 << 24) | (64 << 16) | 0;


      //table.op[opts.table_index] = 64;
      //table.bits[opts.table_index] = 1;
      //table.val[opts.table_index++] = 0;
      table[table_index++] = (1 << 24) | (64 << 16) | 0;

      opts.bits = 1;
      return 0;     /* no symbols, but wait for decoding to report error */
    }
    for (min = 1; min < max; min++) {
      if (count[min] !== 0) { break; }
    }
    if (root < min) {
      root = min;
    }

    /* check for an over-subscribed or incomplete set of lengths */
    left = 1;
    for (len = 1; len <= MAXBITS; len++) {
      left <<= 1;
      left -= count[len];
      if (left < 0) {
        return -1;
      }        /* over-subscribed */
    }
    if (left > 0 && (type === CODES$1 || max !== 1)) {
      return -1;                      /* incomplete set */
    }

    /* generate offsets into symbol table for each length for sorting */
    offs[1] = 0;
    for (len = 1; len < MAXBITS; len++) {
      offs[len + 1] = offs[len] + count[len];
    }

    /* sort symbols by length, by symbol order within each length */
    for (sym = 0; sym < codes; sym++) {
      if (lens[lens_index + sym] !== 0) {
        work[offs[lens[lens_index + sym]]++] = sym;
      }
    }

    /*
     Create and fill in decoding tables.  In this loop, the table being
     filled is at next and has curr index bits.  The code being used is huff
     with length len.  That code is converted to an index by dropping drop
     bits off of the bottom.  For codes where len is less than drop + curr,
     those top drop + curr - len bits are incremented through all values to
     fill the table with replicated entries.

     root is the number of index bits for the root table.  When len exceeds
     root, sub-tables are created pointed to by the root entry with an index
     of the low root bits of huff.  This is saved in low to check for when a
     new sub-table should be started.  drop is zero when the root table is
     being filled, and drop is root when sub-tables are being filled.

     When a new sub-table is needed, it is necessary to look ahead in the
     code lengths to determine what size sub-table is needed.  The length
     counts are used for this, and so count[] is decremented as codes are
     entered in the tables.

     used keeps track of how many table entries have been allocated from the
     provided *table space.  It is checked for LENS and DIST tables against
     the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
     the initial root table size constants.  See the comments in inftrees.h
     for more information.

     sym increments through all symbols, and the loop terminates when
     all codes of length max, i.e. all codes, have been processed.  This
     routine permits incomplete codes, so another loop after this one fills
     in the rest of the decoding tables with invalid code markers.
     */

    /* set up for code type */
    // poor man optimization - use if-else instead of switch,
    // to avoid deopts in old v8
    if (type === CODES$1) {
      base = extra = work;    /* dummy value--not used */
      match = 20;

    } else if (type === LENS$1) {
      base = lbase;
      extra = lext;
      match = 257;

    } else {                    /* DISTS */
      base = dbase;
      extra = dext;
      match = 0;
    }

    /* initialize opts for loop */
    huff = 0;                   /* starting code */
    sym = 0;                    /* starting code symbol */
    len = min;                  /* starting code length */
    next = table_index;              /* current table to fill in */
    curr = root;                /* current table index bits */
    drop = 0;                   /* current bits to drop from code for index */
    low = -1;                   /* trigger new sub-table when len > root */
    used = 1 << root;          /* use root table entries */
    mask = used - 1;            /* mask for comparing low */

    /* check available table space */
    if ((type === LENS$1 && used > ENOUGH_LENS$1) ||
      (type === DISTS$1 && used > ENOUGH_DISTS$1)) {
      return 1;
    }

    /* process all codes and make table entries */
    for (;;) {
      /* create table entry */
      here_bits = len - drop;
      if (work[sym] + 1 < match) {
        here_op = 0;
        here_val = work[sym];
      }
      else if (work[sym] >= match) {
        here_op = extra[work[sym] - match];
        here_val = base[work[sym] - match];
      }
      else {
        here_op = 32 + 64;         /* end of block */
        here_val = 0;
      }

      /* replicate for those indices with low len bits equal to huff */
      incr = 1 << (len - drop);
      fill = 1 << curr;
      min = fill;                 /* save offset to next table */
      do {
        fill -= incr;
        table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0;
      } while (fill !== 0);

      /* backwards increment the len-bit code huff */
      incr = 1 << (len - 1);
      while (huff & incr) {
        incr >>= 1;
      }
      if (incr !== 0) {
        huff &= incr - 1;
        huff += incr;
      } else {
        huff = 0;
      }

      /* go to next symbol, update count, len */
      sym++;
      if (--count[len] === 0) {
        if (len === max) { break; }
        len = lens[lens_index + work[sym]];
      }

      /* create new sub-table if needed */
      if (len > root && (huff & mask) !== low) {
        /* if first time, transition to sub-tables */
        if (drop === 0) {
          drop = root;
        }

        /* increment past last table */
        next += min;            /* here min is 1 << curr */

        /* determine length of next table */
        curr = len - drop;
        left = 1 << curr;
        while (curr + drop < max) {
          left -= count[curr + drop];
          if (left <= 0) { break; }
          curr++;
          left <<= 1;
        }

        /* check for enough space */
        used += 1 << curr;
        if ((type === LENS$1 && used > ENOUGH_LENS$1) ||
          (type === DISTS$1 && used > ENOUGH_DISTS$1)) {
          return 1;
        }

        /* point entry in root table to sub-table */
        low = huff & mask;
        /*table.op[low] = curr;
        table.bits[low] = root;
        table.val[low] = next - opts.table_index;*/
        table[low] = (root << 24) | (curr << 16) | (next - table_index) |0;
      }
    }

    /* fill in remaining table entry if code is incomplete (guaranteed to have
     at most one remaining entry, since if the code is incomplete, the
     maximum code length that was allowed to get this far is one bit) */
    if (huff !== 0) {
      //table.op[next + huff] = 64;            /* invalid code marker */
      //table.bits[next + huff] = len - drop;
      //table.val[next + huff] = 0;
      table[next + huff] = ((len - drop) << 24) | (64 << 16) |0;
    }

    /* set return parameters */
    //opts.table_index += used;
    opts.bits = root;
    return 0;
  };


  var inftrees = inflate_table;

  // (C) 1995-2013 Jean-loup Gailly and Mark Adler
  // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
  //
  // This software is provided 'as-is', without any express or implied
  // warranty. In no event will the authors be held liable for any damages
  // arising from the use of this software.
  //
  // Permission is granted to anyone to use this software for any purpose,
  // including commercial applications, and to alter it and redistribute it
  // freely, subject to the following restrictions:
  //
  // 1. The origin of this software must not be misrepresented; you must not
  //   claim that you wrote the original software. If you use this software
  //   in a product, an acknowledgment in the product documentation would be
  //   appreciated but is not required.
  // 2. Altered source versions must be plainly marked as such, and must not be
  //   misrepresented as being the original software.
  // 3. This notice may not be removed or altered from any source distribution.

  var constants$1 = {

    /* Allowed flush values; see deflate() and inflate() below for details */
    Z_NO_FLUSH:         0,
    Z_PARTIAL_FLUSH:    1,
    Z_SYNC_FLUSH:       2,
    Z_FULL_FLUSH:       3,
    Z_FINISH:           4,
    Z_BLOCK:            5,
    Z_TREES:            6,

    /* Return codes for the compression/decompression functions. Negative values
    * are errors, positive values are used for special but normal events.
    */
    Z_OK:               0,
    Z_STREAM_END:       1,
    Z_NEED_DICT:        2,
    Z_ERRNO:           -1,
    Z_STREAM_ERROR:    -2,
    Z_DATA_ERROR:      -3,
    Z_MEM_ERROR:       -4,
    Z_BUF_ERROR:       -5,
    //Z_VERSION_ERROR: -6,

    /* compression levels */
    Z_NO_COMPRESSION:         0,
    Z_BEST_SPEED:             1,
    Z_BEST_COMPRESSION:       9,
    Z_DEFAULT_COMPRESSION:   -1,


    Z_FILTERED:               1,
    Z_HUFFMAN_ONLY:           2,
    Z_RLE:                    3,
    Z_FIXED:                  4,
    Z_DEFAULT_STRATEGY:       0,

    /* Possible values of the data_type field (though see inflate()) */
    Z_BINARY:                 0,
    Z_TEXT:                   1,
    //Z_ASCII:                1, // = Z_TEXT (deprecated)
    Z_UNKNOWN:                2,

    /* The deflate compression method */
    Z_DEFLATED:               8
    //Z_NULL:                 null // Use -1 or null inline, depending on var type
  };

  // (C) 1995-2013 Jean-loup Gailly and Mark Adler
  // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
  //
  // This software is provided 'as-is', without any express or implied
  // warranty. In no event will the authors be held liable for any damages
  // arising from the use of this software.
  //
  // Permission is granted to anyone to use this software for any purpose,
  // including commercial applications, and to alter it and redistribute it
  // freely, subject to the following restrictions:
  //
  // 1. The origin of this software must not be misrepresented; you must not
  //   claim that you wrote the original software. If you use this software
  //   in a product, an acknowledgment in the product documentation would be
  //   appreciated but is not required.
  // 2. Altered source versions must be plainly marked as such, and must not be
  //   misrepresented as being the original software.
  // 3. This notice may not be removed or altered from any source distribution.






  const CODES = 0;
  const LENS = 1;
  const DISTS = 2;

  /* Public constants ==========================================================*/
  /* ===========================================================================*/

  const {
    Z_FINISH: Z_FINISH$1, Z_BLOCK, Z_TREES,
    Z_OK: Z_OK$1, Z_STREAM_END: Z_STREAM_END$1, Z_NEED_DICT: Z_NEED_DICT$1, Z_STREAM_ERROR: Z_STREAM_ERROR$1, Z_DATA_ERROR: Z_DATA_ERROR$1, Z_MEM_ERROR: Z_MEM_ERROR$1, Z_BUF_ERROR,
    Z_DEFLATED
  } = constants$1;


  /* STATES ====================================================================*/
  /* ===========================================================================*/


  const    HEAD = 16180;       /* i: waiting for magic header */
  const    FLAGS = 16181;      /* i: waiting for method and flags (gzip) */
  const    TIME = 16182;       /* i: waiting for modification time (gzip) */
  const    OS = 16183;         /* i: waiting for extra flags and operating system (gzip) */
  const    EXLEN = 16184;      /* i: waiting for extra length (gzip) */
  const    EXTRA = 16185;      /* i: waiting for extra bytes (gzip) */
  const    NAME = 16186;       /* i: waiting for end of file name (gzip) */
  const    COMMENT = 16187;    /* i: waiting for end of comment (gzip) */
  const    HCRC = 16188;       /* i: waiting for header crc (gzip) */
  const    DICTID = 16189;    /* i: waiting for dictionary check value */
  const    DICT = 16190;      /* waiting for inflateSetDictionary() call */
  const        TYPE = 16191;      /* i: waiting for type bits, including last-flag bit */
  const        TYPEDO = 16192;    /* i: same, but skip check to exit inflate on new block */
  const        STORED = 16193;    /* i: waiting for stored size (length and complement) */
  const        COPY_ = 16194;     /* i/o: same as COPY below, but only first time in */
  const        COPY = 16195;      /* i/o: waiting for input or output to copy stored block */
  const        TABLE = 16196;     /* i: waiting for dynamic block table lengths */
  const        LENLENS = 16197;   /* i: waiting for code length code lengths */
  const        CODELENS = 16198;  /* i: waiting for length/lit and distance code lengths */
  const            LEN_ = 16199;      /* i: same as LEN below, but only first time in */
  const            LEN = 16200;       /* i: waiting for length/lit/eob code */
  const            LENEXT = 16201;    /* i: waiting for length extra bits */
  const            DIST = 16202;      /* i: waiting for distance code */
  const            DISTEXT = 16203;   /* i: waiting for distance extra bits */
  const            MATCH = 16204;     /* o: waiting for output space to copy string */
  const            LIT = 16205;       /* o: waiting for output space to write literal */
  const    CHECK = 16206;     /* i: waiting for 32-bit check value */
  const    LENGTH = 16207;    /* i: waiting for 32-bit length (gzip) */
  const    DONE = 16208;      /* finished check, done -- remain here until reset */
  const    BAD = 16209;       /* got a data error -- remain here until reset */
  const    MEM = 16210;       /* got an inflate() memory error -- remain here until reset */
  const    SYNC = 16211;      /* looking for synchronization bytes to restart inflate() */

  /* ===========================================================================*/



  const ENOUGH_LENS = 852;
  const ENOUGH_DISTS = 592;
  //const ENOUGH =  (ENOUGH_LENS+ENOUGH_DISTS);

  const MAX_WBITS = 15;
  /* 32K LZ77 window */
  const DEF_WBITS = MAX_WBITS;


  const zswap32 = (q) => {

    return  (((q >>> 24) & 0xff) +
            ((q >>> 8) & 0xff00) +
            ((q & 0xff00) << 8) +
            ((q & 0xff) << 24));
  };


  function InflateState() {
    this.strm = null;           /* pointer back to this zlib stream */
    this.mode = 0;              /* current inflate mode */
    this.last = false;          /* true if processing last block */
    this.wrap = 0;              /* bit 0 true for zlib, bit 1 true for gzip,
                                   bit 2 true to validate check value */
    this.havedict = false;      /* true if dictionary provided */
    this.flags = 0;             /* gzip header method and flags (0 if zlib), or
                                   -1 if raw or no header yet */
    this.dmax = 0;              /* zlib header max distance (INFLATE_STRICT) */
    this.check = 0;             /* protected copy of check value */
    this.total = 0;             /* protected copy of output count */
    // TODO: may be {}
    this.head = null;           /* where to save gzip header information */

    /* sliding window */
    this.wbits = 0;             /* log base 2 of requested window size */
    this.wsize = 0;             /* window size or zero if not using window */
    this.whave = 0;             /* valid bytes in the window */
    this.wnext = 0;             /* window write index */
    this.window = null;         /* allocated sliding window, if needed */

    /* bit accumulator */
    this.hold = 0;              /* input bit accumulator */
    this.bits = 0;              /* number of bits in "in" */

    /* for string and stored block copying */
    this.length = 0;            /* literal or length of data to copy */
    this.offset = 0;            /* distance back to copy string from */

    /* for table and code decoding */
    this.extra = 0;             /* extra bits needed */

    /* fixed and dynamic code tables */
    this.lencode = null;          /* starting table for length/literal codes */
    this.distcode = null;         /* starting table for distance codes */
    this.lenbits = 0;           /* index bits for lencode */
    this.distbits = 0;          /* index bits for distcode */

    /* dynamic table building */
    this.ncode = 0;             /* number of code length code lengths */
    this.nlen = 0;              /* number of length code lengths */
    this.ndist = 0;             /* number of distance code lengths */
    this.have = 0;              /* number of code lengths in lens[] */
    this.next = null;              /* next available space in codes[] */

    this.lens = new Uint16Array(320); /* temporary storage for code lengths */
    this.work = new Uint16Array(288); /* work area for code table building */

    /*
     because we don't have pointers in js, we use lencode and distcode directly
     as buffers so we don't need codes
    */
    //this.codes = new Int32Array(ENOUGH);       /* space for code tables */
    this.lendyn = null;              /* dynamic table for length/literal codes (JS specific) */
    this.distdyn = null;             /* dynamic table for distance codes (JS specific) */
    this.sane = 0;                   /* if false, allow invalid distance too far */
    this.back = 0;                   /* bits back of last unprocessed length/lit */
    this.was = 0;                    /* initial length of match */
  }


  const inflateStateCheck = (strm) => {

    if (!strm) {
      return 1;
    }
    const state = strm.state;
    if (!state || state.strm !== strm ||
      state.mode < HEAD || state.mode > SYNC) {
      return 1;
    }
    return 0;
  };


  const inflateResetKeep = (strm) => {

    if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }
    const state = strm.state;
    strm.total_in = strm.total_out = state.total = 0;
    strm.msg = ''; /*Z_NULL*/
    if (state.wrap) {       /* to support ill-conceived Java test suite */
      strm.adler = state.wrap & 1;
    }
    state.mode = HEAD;
    state.last = 0;
    state.havedict = 0;
    state.flags = -1;
    state.dmax = 32768;
    state.head = null/*Z_NULL*/;
    state.hold = 0;
    state.bits = 0;
    //state.lencode = state.distcode = state.next = state.codes;
    state.lencode = state.lendyn = new Int32Array(ENOUGH_LENS);
    state.distcode = state.distdyn = new Int32Array(ENOUGH_DISTS);

    state.sane = 1;
    state.back = -1;
    //Tracev((stderr, "inflate: reset\n"));
    return Z_OK$1;
  };


  const inflateReset = (strm) => {

    if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }
    const state = strm.state;
    state.wsize = 0;
    state.whave = 0;
    state.wnext = 0;
    return inflateResetKeep(strm);

  };


  const inflateReset2 = (strm, windowBits) => {
    let wrap;

    /* get the state */
    if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }
    const state = strm.state;

    /* extract wrap request from windowBits parameter */
    if (windowBits < 0) {
      wrap = 0;
      windowBits = -windowBits;
    }
    else {
      wrap = (windowBits >> 4) + 5;
      if (windowBits < 48) {
        windowBits &= 15;
      }
    }

    /* set number of window bits, free window if different */
    if (windowBits && (windowBits < 8 || windowBits > 15)) {
      return Z_STREAM_ERROR$1;
    }
    if (state.window !== null && state.wbits !== windowBits) {
      state.window = null;
    }

    /* update state and reset the rest of it */
    state.wrap = wrap;
    state.wbits = windowBits;
    return inflateReset(strm);
  };


  const inflateInit2 = (strm, windowBits) => {

    if (!strm) { return Z_STREAM_ERROR$1; }
    //strm.msg = Z_NULL;                 /* in case we return an error */

    const state = new InflateState();

    //if (state === Z_NULL) return Z_MEM_ERROR;
    //Tracev((stderr, "inflate: allocated\n"));
    strm.state = state;
    state.strm = strm;
    state.window = null/*Z_NULL*/;
    state.mode = HEAD;     /* to pass state test in inflateReset2() */
    const ret = inflateReset2(strm, windowBits);
    if (ret !== Z_OK$1) {
      strm.state = null/*Z_NULL*/;
    }
    return ret;
  };


  const inflateInit = (strm) => {

    return inflateInit2(strm, DEF_WBITS);
  };


  /*
   Return state with length and distance decoding tables and index sizes set to
   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
   If BUILDFIXED is defined, then instead this routine builds the tables the
   first time it's called, and returns those tables the first time and
   thereafter.  This reduces the size of the code by about 2K bytes, in
   exchange for a little execution time.  However, BUILDFIXED should not be
   used for threaded applications, since the rewriting of the tables and virgin
   may not be thread-safe.
   */
  let virgin = true;

  let lenfix, distfix; // We have no pointers in JS, so keep tables separate


  const fixedtables = (state) => {

    /* build fixed huffman tables if first call (may not be thread safe) */
    if (virgin) {
      lenfix = new Int32Array(512);
      distfix = new Int32Array(32);

      /* literal/length table */
      let sym = 0;
      while (sym < 144) { state.lens[sym++] = 8; }
      while (sym < 256) { state.lens[sym++] = 9; }
      while (sym < 280) { state.lens[sym++] = 7; }
      while (sym < 288) { state.lens[sym++] = 8; }

      inftrees(LENS,  state.lens, 0, 288, lenfix,   0, state.work, { bits: 9 });

      /* distance table */
      sym = 0;
      while (sym < 32) { state.lens[sym++] = 5; }

      inftrees(DISTS, state.lens, 0, 32,   distfix, 0, state.work, { bits: 5 });

      /* do this just once */
      virgin = false;
    }

    state.lencode = lenfix;
    state.lenbits = 9;
    state.distcode = distfix;
    state.distbits = 5;
  };


  /*
   Update the window with the last wsize (normally 32K) bytes written before
   returning.  If window does not exist yet, create it.  This is only called
   when a window is already in use, or when output has been written during this
   inflate call, but the end of the deflate stream has not been reached yet.
   It is also called to create a window for dictionary data when a dictionary
   is loaded.

   Providing output buffers larger than 32K to inflate() should provide a speed
   advantage, since only the last 32K of output is copied to the sliding window
   upon return from inflate(), and since all distances after the first 32K of
   output will fall in the output data, making match copies simpler and faster.
   The advantage may be dependent on the size of the processor's data caches.
   */
  const updatewindow = (strm, src, end, copy) => {

    let dist;
    const state = strm.state;

    /* if it hasn't been done already, allocate space for the window */
    if (state.window === null) {
      state.wsize = 1 << state.wbits;
      state.wnext = 0;
      state.whave = 0;

      state.window = new Uint8Array(state.wsize);
    }

    /* copy state->wsize or less output bytes into the circular window */
    if (copy >= state.wsize) {
      state.window.set(src.subarray(end - state.wsize, end), 0);
      state.wnext = 0;
      state.whave = state.wsize;
    }
    else {
      dist = state.wsize - state.wnext;
      if (dist > copy) {
        dist = copy;
      }
      //zmemcpy(state->window + state->wnext, end - copy, dist);
      state.window.set(src.subarray(end - copy, end - copy + dist), state.wnext);
      copy -= dist;
      if (copy) {
        //zmemcpy(state->window, end - copy, copy);
        state.window.set(src.subarray(end - copy, end), 0);
        state.wnext = copy;
        state.whave = state.wsize;
      }
      else {
        state.wnext += dist;
        if (state.wnext === state.wsize) { state.wnext = 0; }
        if (state.whave < state.wsize) { state.whave += dist; }
      }
    }
    return 0;
  };


  const inflate$1 = (strm, flush) => {

    let state;
    let input, output;          // input/output buffers
    let next;                   /* next input INDEX */
    let put;                    /* next output INDEX */
    let have, left;             /* available input and output */
    let hold;                   /* bit buffer */
    let bits;                   /* bits in bit buffer */
    let _in, _out;              /* save starting available input and output */
    let copy;                   /* number of stored or match bytes to copy */
    let from;                   /* where to copy match bytes from */
    let from_source;
    let here = 0;               /* current decoding table entry */
    let here_bits, here_op, here_val; // paked "here" denormalized (JS specific)
    //let last;                   /* parent table entry */
    let last_bits, last_op, last_val; // paked "last" denormalized (JS specific)
    let len;                    /* length to copy for repeats, bits to drop */
    let ret;                    /* return code */
    const hbuf = new Uint8Array(4);    /* buffer for gzip header crc calculation */
    let opts;

    let n; // temporary variable for NEED_BITS

    const order = /* permutation of code lengths */
      new Uint8Array([ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]);


    if (inflateStateCheck(strm) || !strm.output ||
        (!strm.input && strm.avail_in !== 0)) {
      return Z_STREAM_ERROR$1;
    }

    state = strm.state;
    if (state.mode === TYPE) { state.mode = TYPEDO; }    /* skip check */


    //--- LOAD() ---
    put = strm.next_out;
    output = strm.output;
    left = strm.avail_out;
    next = strm.next_in;
    input = strm.input;
    have = strm.avail_in;
    hold = state.hold;
    bits = state.bits;
    //---

    _in = have;
    _out = left;
    ret = Z_OK$1;

    inf_leave: // goto emulation
    for (;;) {
      switch (state.mode) {
        case HEAD:
          if (state.wrap === 0) {
            state.mode = TYPEDO;
            break;
          }
          //=== NEEDBITS(16);
          while (bits < 16) {
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
          }
          //===//
          if ((state.wrap & 2) && hold === 0x8b1f) {  /* gzip header */
            if (state.wbits === 0) {
              state.wbits = 15;
            }
            state.check = 0/*crc32(0L, Z_NULL, 0)*/;
            //=== CRC2(state.check, hold);
            hbuf[0] = hold & 0xff;
            hbuf[1] = (hold >>> 8) & 0xff;
            state.check = crc32_1(state.check, hbuf, 2, 0);
            //===//

            //=== INITBITS();
            hold = 0;
            bits = 0;
            //===//
            state.mode = FLAGS;
            break;
          }
          if (state.head) {
            state.head.done = false;
          }
          if (!(state.wrap & 1) ||   /* check if zlib header allowed */
            (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) {
            strm.msg = 'incorrect header check';
            state.mode = BAD;
            break;
          }
          if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) {
            strm.msg = 'unknown compression method';
            state.mode = BAD;
            break;
          }
          //--- DROPBITS(4) ---//
          hold >>>= 4;
          bits -= 4;
          //---//
          len = (hold & 0x0f)/*BITS(4)*/ + 8;
          if (state.wbits === 0) {
            state.wbits = len;
          }
          if (len > 15 || len > state.wbits) {
            strm.msg = 'invalid window size';
            state.mode = BAD;
            break;
          }

          // !!! pako patch. Force use `options.windowBits` if passed.
          // Required to always use max window size by default.
          state.dmax = 1 << state.wbits;
          //state.dmax = 1 << len;

          state.flags = 0;               /* indicate zlib header */
          //Tracev((stderr, "inflate:   zlib header ok\n"));
          strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
          state.mode = hold & 0x200 ? DICTID : TYPE;
          //=== INITBITS();
          hold = 0;
          bits = 0;
          //===//
          break;
        case FLAGS:
          //=== NEEDBITS(16); */
          while (bits < 16) {
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
          }
          //===//
          state.flags = hold;
          if ((state.flags & 0xff) !== Z_DEFLATED) {
            strm.msg = 'unknown compression method';
            state.mode = BAD;
            break;
          }
          if (state.flags & 0xe000) {
            strm.msg = 'unknown header flags set';
            state.mode = BAD;
            break;
          }
          if (state.head) {
            state.head.text = ((hold >> 8) & 1);
          }
          if ((state.flags & 0x0200) && (state.wrap & 4)) {
            //=== CRC2(state.check, hold);
            hbuf[0] = hold & 0xff;
            hbuf[1] = (hold >>> 8) & 0xff;
            state.check = crc32_1(state.check, hbuf, 2, 0);
            //===//
          }
          //=== INITBITS();
          hold = 0;
          bits = 0;
          //===//
          state.mode = TIME;
          /* falls through */
        case TIME:
          //=== NEEDBITS(32); */
          while (bits < 32) {
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
          }
          //===//
          if (state.head) {
            state.head.time = hold;
          }
          if ((state.flags & 0x0200) && (state.wrap & 4)) {
            //=== CRC4(state.check, hold)
            hbuf[0] = hold & 0xff;
            hbuf[1] = (hold >>> 8) & 0xff;
            hbuf[2] = (hold >>> 16) & 0xff;
            hbuf[3] = (hold >>> 24) & 0xff;
            state.check = crc32_1(state.check, hbuf, 4, 0);
            //===
          }
          //=== INITBITS();
          hold = 0;
          bits = 0;
          //===//
          state.mode = OS;
          /* falls through */
        case OS:
          //=== NEEDBITS(16); */
          while (bits < 16) {
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
          }
          //===//
          if (state.head) {
            state.head.xflags = (hold & 0xff);
            state.head.os = (hold >> 8);
          }
          if ((state.flags & 0x0200) && (state.wrap & 4)) {
            //=== CRC2(state.check, hold);
            hbuf[0] = hold & 0xff;
            hbuf[1] = (hold >>> 8) & 0xff;
            state.check = crc32_1(state.check, hbuf, 2, 0);
            //===//
          }
          //=== INITBITS();
          hold = 0;
          bits = 0;
          //===//
          state.mode = EXLEN;
          /* falls through */
        case EXLEN:
          if (state.flags & 0x0400) {
            //=== NEEDBITS(16); */
            while (bits < 16) {
              if (have === 0) { break inf_leave; }
              have--;
              hold += input[next++] << bits;
              bits += 8;
            }
            //===//
            state.length = hold;
            if (state.head) {
              state.head.extra_len = hold;
            }
            if ((state.flags & 0x0200) && (state.wrap & 4)) {
              //=== CRC2(state.check, hold);
              hbuf[0] = hold & 0xff;
              hbuf[1] = (hold >>> 8) & 0xff;
              state.check = crc32_1(state.check, hbuf, 2, 0);
              //===//
            }
            //=== INITBITS();
            hold = 0;
            bits = 0;
            //===//
          }
          else if (state.head) {
            state.head.extra = null/*Z_NULL*/;
          }
          state.mode = EXTRA;
          /* falls through */
        case EXTRA:
          if (state.flags & 0x0400) {
            copy = state.length;
            if (copy > have) { copy = have; }
            if (copy) {
              if (state.head) {
                len = state.head.extra_len - state.length;
                if (!state.head.extra) {
                  // Use untyped array for more convenient processing later
                  state.head.extra = new Uint8Array(state.head.extra_len);
                }
                state.head.extra.set(
                  input.subarray(
                    next,
                    // extra field is limited to 65536 bytes
                    // - no need for additional size check
                    next + copy
                  ),
                  /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/
                  len
                );
                //zmemcpy(state.head.extra + len, next,
                //        len + copy > state.head.extra_max ?
                //        state.head.extra_max - len : copy);
              }
              if ((state.flags & 0x0200) && (state.wrap & 4)) {
                state.check = crc32_1(state.check, input, copy, next);
              }
              have -= copy;
              next += copy;
              state.length -= copy;
            }
            if (state.length) { break inf_leave; }
          }
          state.length = 0;
          state.mode = NAME;
          /* falls through */
        case NAME:
          if (state.flags & 0x0800) {
            if (have === 0) { break inf_leave; }
            copy = 0;
            do {
              // TODO: 2 or 1 bytes?
              len = input[next + copy++];
              /* use constant limit because in js we should not preallocate memory */
              if (state.head && len &&
                  (state.length < 65536 /*state.head.name_max*/)) {
                state.head.name += String.fromCharCode(len);
              }
            } while (len && copy < have);

            if ((state.flags & 0x0200) && (state.wrap & 4)) {
              state.check = crc32_1(state.check, input, copy, next);
            }
            have -= copy;
            next += copy;
            if (len) { break inf_leave; }
          }
          else if (state.head) {
            state.head.name = null;
          }
          state.length = 0;
          state.mode = COMMENT;
          /* falls through */
        case COMMENT:
          if (state.flags & 0x1000) {
            if (have === 0) { break inf_leave; }
            copy = 0;
            do {
              len = input[next + copy++];
              /* use constant limit because in js we should not preallocate memory */
              if (state.head && len &&
                  (state.length < 65536 /*state.head.comm_max*/)) {
                state.head.comment += String.fromCharCode(len);
              }
            } while (len && copy < have);
            if ((state.flags & 0x0200) && (state.wrap & 4)) {
              state.check = crc32_1(state.check, input, copy, next);
            }
            have -= copy;
            next += copy;
            if (len) { break inf_leave; }
          }
          else if (state.head) {
            state.head.comment = null;
          }
          state.mode = HCRC;
          /* falls through */
        case HCRC:
          if (state.flags & 0x0200) {
            //=== NEEDBITS(16); */
            while (bits < 16) {
              if (have === 0) { break inf_leave; }
              have--;
              hold += input[next++] << bits;
              bits += 8;
            }
            //===//
            if ((state.wrap & 4) && hold !== (state.check & 0xffff)) {
              strm.msg = 'header crc mismatch';
              state.mode = BAD;
              break;
            }
            //=== INITBITS();
            hold = 0;
            bits = 0;
            //===//
          }
          if (state.head) {
            state.head.hcrc = ((state.flags >> 9) & 1);
            state.head.done = true;
          }
          strm.adler = state.check = 0;
          state.mode = TYPE;
          break;
        case DICTID:
          //=== NEEDBITS(32); */
          while (bits < 32) {
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
          }
          //===//
          strm.adler = state.check = zswap32(hold);
          //=== INITBITS();
          hold = 0;
          bits = 0;
          //===//
          state.mode = DICT;
          /* falls through */
        case DICT:
          if (state.havedict === 0) {
            //--- RESTORE() ---
            strm.next_out = put;
            strm.avail_out = left;
            strm.next_in = next;
            strm.avail_in = have;
            state.hold = hold;
            state.bits = bits;
            //---
            return Z_NEED_DICT$1;
          }
          strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
          state.mode = TYPE;
          /* falls through */
        case TYPE:
          if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; }
          /* falls through */
        case TYPEDO:
          if (state.last) {
            //--- BYTEBITS() ---//
            hold >>>= bits & 7;
            bits -= bits & 7;
            //---//
            state.mode = CHECK;
            break;
          }
          //=== NEEDBITS(3); */
          while (bits < 3) {
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
          }
          //===//
          state.last = (hold & 0x01)/*BITS(1)*/;
          //--- DROPBITS(1) ---//
          hold >>>= 1;
          bits -= 1;
          //---//

          switch ((hold & 0x03)/*BITS(2)*/) {
            case 0:                             /* stored block */
              //Tracev((stderr, "inflate:     stored block%s\n",
              //        state.last ? " (last)" : ""));
              state.mode = STORED;
              break;
            case 1:                             /* fixed block */
              fixedtables(state);
              //Tracev((stderr, "inflate:     fixed codes block%s\n",
              //        state.last ? " (last)" : ""));
              state.mode = LEN_;             /* decode codes */
              if (flush === Z_TREES) {
                //--- DROPBITS(2) ---//
                hold >>>= 2;
                bits -= 2;
                //---//
                break inf_leave;
              }
              break;
            case 2:                             /* dynamic block */
              //Tracev((stderr, "inflate:     dynamic codes block%s\n",
              //        state.last ? " (last)" : ""));
              state.mode = TABLE;
              break;
            case 3:
              strm.msg = 'invalid block type';
              state.mode = BAD;
          }
          //--- DROPBITS(2) ---//
          hold >>>= 2;
          bits -= 2;
          //---//
          break;
        case STORED:
          //--- BYTEBITS() ---// /* go to byte boundary */
          hold >>>= bits & 7;
          bits -= bits & 7;
          //---//
          //=== NEEDBITS(32); */
          while (bits < 32) {
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
          }
          //===//
          if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) {
            strm.msg = 'invalid stored block lengths';
            state.mode = BAD;
            break;
          }
          state.length = hold & 0xffff;
          //Tracev((stderr, "inflate:       stored length %u\n",
          //        state.length));
          //=== INITBITS();
          hold = 0;
          bits = 0;
          //===//
          state.mode = COPY_;
          if (flush === Z_TREES) { break inf_leave; }
          /* falls through */
        case COPY_:
          state.mode = COPY;
          /* falls through */
        case COPY:
          copy = state.length;
          if (copy) {
            if (copy > have) { copy = have; }
            if (copy > left) { copy = left; }
            if (copy === 0) { break inf_leave; }
            //--- zmemcpy(put, next, copy); ---
            output.set(input.subarray(next, next + copy), put);
            //---//
            have -= copy;
            next += copy;
            left -= copy;
            put += copy;
            state.length -= copy;
            break;
          }
          //Tracev((stderr, "inflate:       stored end\n"));
          state.mode = TYPE;
          break;
        case TABLE:
          //=== NEEDBITS(14); */
          while (bits < 14) {
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
          }
          //===//
          state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257;
          //--- DROPBITS(5) ---//
          hold >>>= 5;
          bits -= 5;
          //---//
          state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1;
          //--- DROPBITS(5) ---//
          hold >>>= 5;
          bits -= 5;
          //---//
          state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4;
          //--- DROPBITS(4) ---//
          hold >>>= 4;
          bits -= 4;
          //---//
  //#ifndef PKZIP_BUG_WORKAROUND
          if (state.nlen > 286 || state.ndist > 30) {
            strm.msg = 'too many length or distance symbols';
            state.mode = BAD;
            break;
          }
  //#endif
          //Tracev((stderr, "inflate:       table sizes ok\n"));
          state.have = 0;
          state.mode = LENLENS;
          /* falls through */
        case LENLENS:
          while (state.have < state.ncode) {
            //=== NEEDBITS(3);
            while (bits < 3) {
              if (have === 0) { break inf_leave; }
              have--;
              hold += input[next++] << bits;
              bits += 8;
            }
            //===//
            state.lens[order[state.have++]] = (hold & 0x07);//BITS(3);
            //--- DROPBITS(3) ---//
            hold >>>= 3;
            bits -= 3;
            //---//
          }
          while (state.have < 19) {
            state.lens[order[state.have++]] = 0;
          }
          // We have separate tables & no pointers. 2 commented lines below not needed.
          //state.next = state.codes;
          //state.lencode = state.next;
          // Switch to use dynamic table
          state.lencode = state.lendyn;
          state.lenbits = 7;

          opts = { bits: state.lenbits };
          ret = inftrees(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts);
          state.lenbits = opts.bits;

          if (ret) {
            strm.msg = 'invalid code lengths set';
            state.mode = BAD;
            break;
          }
          //Tracev((stderr, "inflate:       code lengths ok\n"));
          state.have = 0;
          state.mode = CODELENS;
          /* falls through */
        case CODELENS:
          while (state.have < state.nlen + state.ndist) {
            for (;;) {
              here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/
              here_bits = here >>> 24;
              here_op = (here >>> 16) & 0xff;
              here_val = here & 0xffff;

              if ((here_bits) <= bits) { break; }
              //--- PULLBYTE() ---//
              if (have === 0) { break inf_leave; }
              have--;
              hold += input[next++] << bits;
              bits += 8;
              //---//
            }
            if (here_val < 16) {
              //--- DROPBITS(here.bits) ---//
              hold >>>= here_bits;
              bits -= here_bits;
              //---//
              state.lens[state.have++] = here_val;
            }
            else {
              if (here_val === 16) {
                //=== NEEDBITS(here.bits + 2);
                n = here_bits + 2;
                while (bits < n) {
                  if (have === 0) { break inf_leave; }
                  have--;
                  hold += input[next++] << bits;
                  bits += 8;
                }
                //===//
                //--- DROPBITS(here.bits) ---//
                hold >>>= here_bits;
                bits -= here_bits;
                //---//
                if (state.have === 0) {
                  strm.msg = 'invalid bit length repeat';
                  state.mode = BAD;
                  break;
                }
                len = state.lens[state.have - 1];
                copy = 3 + (hold & 0x03);//BITS(2);
                //--- DROPBITS(2) ---//
                hold >>>= 2;
                bits -= 2;
                //---//
              }
              else if (here_val === 17) {
                //=== NEEDBITS(here.bits + 3);
                n = here_bits + 3;
                while (bits < n) {
                  if (have === 0) { break inf_leave; }
                  have--;
                  hold += input[next++] << bits;
                  bits += 8;
                }
                //===//
                //--- DROPBITS(here.bits) ---//
                hold >>>= here_bits;
                bits -= here_bits;
                //---//
                len = 0;
                copy = 3 + (hold & 0x07);//BITS(3);
                //--- DROPBITS(3) ---//
                hold >>>= 3;
                bits -= 3;
                //---//
              }
              else {
                //=== NEEDBITS(here.bits + 7);
                n = here_bits + 7;
                while (bits < n) {
                  if (have === 0) { break inf_leave; }
                  have--;
                  hold += input[next++] << bits;
                  bits += 8;
                }
                //===//
                //--- DROPBITS(here.bits) ---//
                hold >>>= here_bits;
                bits -= here_bits;
                //---//
                len = 0;
                copy = 11 + (hold & 0x7f);//BITS(7);
                //--- DROPBITS(7) ---//
                hold >>>= 7;
                bits -= 7;
                //---//
              }
              if (state.have + copy > state.nlen + state.ndist) {
                strm.msg = 'invalid bit length repeat';
                state.mode = BAD;
                break;
              }
              while (copy--) {
                state.lens[state.have++] = len;
              }
            }
          }

          /* handle error breaks in while */
          if (state.mode === BAD) { break; }

          /* check for end-of-block code (better have one) */
          if (state.lens[256] === 0) {
            strm.msg = 'invalid code -- missing end-of-block';
            state.mode = BAD;
            break;
          }

          /* build code tables -- note: do not change the lenbits or distbits
             values here (9 and 6) without reading the comments in inftrees.h
             concerning the ENOUGH constants, which depend on those values */
          state.lenbits = 9;

          opts = { bits: state.lenbits };
          ret = inftrees(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts);
          // We have separate tables & no pointers. 2 commented lines below not needed.
          // state.next_index = opts.table_index;
          state.lenbits = opts.bits;
          // state.lencode = state.next;

          if (ret) {
            strm.msg = 'invalid literal/lengths set';
            state.mode = BAD;
            break;
          }

          state.distbits = 6;
          //state.distcode.copy(state.codes);
          // Switch to use dynamic table
          state.distcode = state.distdyn;
          opts = { bits: state.distbits };
          ret = inftrees(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts);
          // We have separate tables & no pointers. 2 commented lines below not needed.
          // state.next_index = opts.table_index;
          state.distbits = opts.bits;
          // state.distcode = state.next;

          if (ret) {
            strm.msg = 'invalid distances set';
            state.mode = BAD;
            break;
          }
          //Tracev((stderr, 'inflate:       codes ok\n'));
          state.mode = LEN_;
          if (flush === Z_TREES) { break inf_leave; }
          /* falls through */
        case LEN_:
          state.mode = LEN;
          /* falls through */
        case LEN:
          if (have >= 6 && left >= 258) {
            //--- RESTORE() ---
            strm.next_out = put;
            strm.avail_out = left;
            strm.next_in = next;
            strm.avail_in = have;
            state.hold = hold;
            state.bits = bits;
            //---
            inffast(strm, _out);
            //--- LOAD() ---
            put = strm.next_out;
            output = strm.output;
            left = strm.avail_out;
            next = strm.next_in;
            input = strm.input;
            have = strm.avail_in;
            hold = state.hold;
            bits = state.bits;
            //---

            if (state.mode === TYPE) {
              state.back = -1;
            }
            break;
          }
          state.back = 0;
          for (;;) {
            here = state.lencode[hold & ((1 << state.lenbits) - 1)];  /*BITS(state.lenbits)*/
            here_bits = here >>> 24;
            here_op = (here >>> 16) & 0xff;
            here_val = here & 0xffff;

            if (here_bits <= bits) { break; }
            //--- PULLBYTE() ---//
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
            //---//
          }
          if (here_op && (here_op & 0xf0) === 0) {
            last_bits = here_bits;
            last_op = here_op;
            last_val = here_val;
            for (;;) {
              here = state.lencode[last_val +
                      ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];
              here_bits = here >>> 24;
              here_op = (here >>> 16) & 0xff;
              here_val = here & 0xffff;

              if ((last_bits + here_bits) <= bits) { break; }
              //--- PULLBYTE() ---//
              if (have === 0) { break inf_leave; }
              have--;
              hold += input[next++] << bits;
              bits += 8;
              //---//
            }
            //--- DROPBITS(last.bits) ---//
            hold >>>= last_bits;
            bits -= last_bits;
            //---//
            state.back += last_bits;
          }
          //--- DROPBITS(here.bits) ---//
          hold >>>= here_bits;
          bits -= here_bits;
          //---//
          state.back += here_bits;
          state.length = here_val;
          if (here_op === 0) {
            //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
            //        "inflate:         literal '%c'\n" :
            //        "inflate:         literal 0x%02x\n", here.val));
            state.mode = LIT;
            break;
          }
          if (here_op & 32) {
            //Tracevv((stderr, "inflate:         end of block\n"));
            state.back = -1;
            state.mode = TYPE;
            break;
          }
          if (here_op & 64) {
            strm.msg = 'invalid literal/length code';
            state.mode = BAD;
            break;
          }
          state.extra = here_op & 15;
          state.mode = LENEXT;
          /* falls through */
        case LENEXT:
          if (state.extra) {
            //=== NEEDBITS(state.extra);
            n = state.extra;
            while (bits < n) {
              if (have === 0) { break inf_leave; }
              have--;
              hold += input[next++] << bits;
              bits += 8;
            }
            //===//
            state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;
            //--- DROPBITS(state.extra) ---//
            hold >>>= state.extra;
            bits -= state.extra;
            //---//
            state.back += state.extra;
          }
          //Tracevv((stderr, "inflate:         length %u\n", state.length));
          state.was = state.length;
          state.mode = DIST;
          /* falls through */
        case DIST:
          for (;;) {
            here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/
            here_bits = here >>> 24;
            here_op = (here >>> 16) & 0xff;
            here_val = here & 0xffff;

            if ((here_bits) <= bits) { break; }
            //--- PULLBYTE() ---//
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
            //---//
          }
          if ((here_op & 0xf0) === 0) {
            last_bits = here_bits;
            last_op = here_op;
            last_val = here_val;
            for (;;) {
              here = state.distcode[last_val +
                      ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];
              here_bits = here >>> 24;
              here_op = (here >>> 16) & 0xff;
              here_val = here & 0xffff;

              if ((last_bits + here_bits) <= bits) { break; }
              //--- PULLBYTE() ---//
              if (have === 0) { break inf_leave; }
              have--;
              hold += input[next++] << bits;
              bits += 8;
              //---//
            }
            //--- DROPBITS(last.bits) ---//
            hold >>>= last_bits;
            bits -= last_bits;
            //---//
            state.back += last_bits;
          }
          //--- DROPBITS(here.bits) ---//
          hold >>>= here_bits;
          bits -= here_bits;
          //---//
          state.back += here_bits;
          if (here_op & 64) {
            strm.msg = 'invalid distance code';
            state.mode = BAD;
            break;
          }
          state.offset = here_val;
          state.extra = (here_op) & 15;
          state.mode = DISTEXT;
          /* falls through */
        case DISTEXT:
          if (state.extra) {
            //=== NEEDBITS(state.extra);
            n = state.extra;
            while (bits < n) {
              if (have === 0) { break inf_leave; }
              have--;
              hold += input[next++] << bits;
              bits += 8;
            }
            //===//
            state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;
            //--- DROPBITS(state.extra) ---//
            hold >>>= state.extra;
            bits -= state.extra;
            //---//
            state.back += state.extra;
          }
  //#ifdef INFLATE_STRICT
          if (state.offset > state.dmax) {
            strm.msg = 'invalid distance too far back';
            state.mode = BAD;
            break;
          }
  //#endif
          //Tracevv((stderr, "inflate:         distance %u\n", state.offset));
          state.mode = MATCH;
          /* falls through */
        case MATCH:
          if (left === 0) { break inf_leave; }
          copy = _out - left;
          if (state.offset > copy) {         /* copy from window */
            copy = state.offset - copy;
            if (copy > state.whave) {
              if (state.sane) {
                strm.msg = 'invalid distance too far back';
                state.mode = BAD;
                break;
              }
  // (!) This block is disabled in zlib defaults,
  // don't enable it for binary compatibility
  //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
  //          Trace((stderr, "inflate.c too far\n"));
  //          copy -= state.whave;
  //          if (copy > state.length) { copy = state.length; }
  //          if (copy > left) { copy = left; }
  //          left -= copy;
  //          state.length -= copy;
  //          do {
  //            output[put++] = 0;
  //          } while (--copy);
  //          if (state.length === 0) { state.mode = LEN; }
  //          break;
  //#endif
            }
            if (copy > state.wnext) {
              copy -= state.wnext;
              from = state.wsize - copy;
            }
            else {
              from = state.wnext - copy;
            }
            if (copy > state.length) { copy = state.length; }
            from_source = state.window;
          }
          else {                              /* copy from output */
            from_source = output;
            from = put - state.offset;
            copy = state.length;
          }
          if (copy > left) { copy = left; }
          left -= copy;
          state.length -= copy;
          do {
            output[put++] = from_source[from++];
          } while (--copy);
          if (state.length === 0) { state.mode = LEN; }
          break;
        case LIT:
          if (left === 0) { break inf_leave; }
          output[put++] = state.length;
          left--;
          state.mode = LEN;
          break;
        case CHECK:
          if (state.wrap) {
            //=== NEEDBITS(32);
            while (bits < 32) {
              if (have === 0) { break inf_leave; }
              have--;
              // Use '|' instead of '+' to make sure that result is signed
              hold |= input[next++] << bits;
              bits += 8;
            }
            //===//
            _out -= left;
            strm.total_out += _out;
            state.total += _out;
            if ((state.wrap & 4) && _out) {
              strm.adler = state.check =
                  /*UPDATE_CHECK(state.check, put - _out, _out);*/
                  (state.flags ? crc32_1(state.check, output, _out, put - _out) : adler32_1(state.check, output, _out, put - _out));

            }
            _out = left;
            // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too
            if ((state.wrap & 4) && (state.flags ? hold : zswap32(hold)) !== state.check) {
              strm.msg = 'incorrect data check';
              state.mode = BAD;
              break;
            }
            //=== INITBITS();
            hold = 0;
            bits = 0;
            //===//
            //Tracev((stderr, "inflate:   check matches trailer\n"));
          }
          state.mode = LENGTH;
          /* falls through */
        case LENGTH:
          if (state.wrap && state.flags) {
            //=== NEEDBITS(32);
            while (bits < 32) {
              if (have === 0) { break inf_leave; }
              have--;
              hold += input[next++] << bits;
              bits += 8;
            }
            //===//
            if ((state.wrap & 4) && hold !== (state.total & 0xffffffff)) {
              strm.msg = 'incorrect length check';
              state.mode = BAD;
              break;
            }
            //=== INITBITS();
            hold = 0;
            bits = 0;
            //===//
            //Tracev((stderr, "inflate:   length matches trailer\n"));
          }
          state.mode = DONE;
          /* falls through */
        case DONE:
          ret = Z_STREAM_END$1;
          break inf_leave;
        case BAD:
          ret = Z_DATA_ERROR$1;
          break inf_leave;
        case MEM:
          return Z_MEM_ERROR$1;
        case SYNC:
          /* falls through */
        default:
          return Z_STREAM_ERROR$1;
      }
    }

    // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave"

    /*
       Return from inflate(), updating the total counts and the check value.
       If there was no progress during the inflate() call, return a buffer
       error.  Call updatewindow() to create and/or update the window state.
       Note: a memory error from inflate() is non-recoverable.
     */

    //--- RESTORE() ---
    strm.next_out = put;
    strm.avail_out = left;
    strm.next_in = next;
    strm.avail_in = have;
    state.hold = hold;
    state.bits = bits;
    //---

    if (state.wsize || (_out !== strm.avail_out && state.mode < BAD &&
                        (state.mode < CHECK || flush !== Z_FINISH$1))) {
      if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ;
    }
    _in -= strm.avail_in;
    _out -= strm.avail_out;
    strm.total_in += _in;
    strm.total_out += _out;
    state.total += _out;
    if ((state.wrap & 4) && _out) {
      strm.adler = state.check = /*UPDATE_CHECK(state.check, strm.next_out - _out, _out);*/
        (state.flags ? crc32_1(state.check, output, _out, strm.next_out - _out) : adler32_1(state.check, output, _out, strm.next_out - _out));
    }
    strm.data_type = state.bits + (state.last ? 64 : 0) +
                      (state.mode === TYPE ? 128 : 0) +
                      (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0);
    if (((_in === 0 && _out === 0) || flush === Z_FINISH$1) && ret === Z_OK$1) {
      ret = Z_BUF_ERROR;
    }
    return ret;
  };


  const inflateEnd = (strm) => {

    if (inflateStateCheck(strm)) {
      return Z_STREAM_ERROR$1;
    }

    let state = strm.state;
    if (state.window) {
      state.window = null;
    }
    strm.state = null;
    return Z_OK$1;
  };


  const inflateGetHeader = (strm, head) => {

    /* check state */
    if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }
    const state = strm.state;
    if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR$1; }

    /* save header structure */
    state.head = head;
    head.done = false;
    return Z_OK$1;
  };


  const inflateSetDictionary = (strm, dictionary) => {
    const dictLength = dictionary.length;

    let state;
    let dictid;
    let ret;

    /* check state */
    if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }
    state = strm.state;

    if (state.wrap !== 0 && state.mode !== DICT) {
      return Z_STREAM_ERROR$1;
    }

    /* check for correct dictionary identifier */
    if (state.mode === DICT) {
      dictid = 1; /* adler32(0, null, 0)*/
      /* dictid = adler32(dictid, dictionary, dictLength); */
      dictid = adler32_1(dictid, dictionary, dictLength, 0);
      if (dictid !== state.check) {
        return Z_DATA_ERROR$1;
      }
    }
    /* copy dictionary to window using updatewindow(), which will amend the
     existing dictionary if appropriate */
    ret = updatewindow(strm, dictionary, dictLength, dictLength);
    if (ret) {
      state.mode = MEM;
      return Z_MEM_ERROR$1;
    }
    state.havedict = 1;
    // Tracev((stderr, "inflate:   dictionary set\n"));
    return Z_OK$1;
  };


  var inflateReset_1 = inflateReset;
  var inflateReset2_1 = inflateReset2;
  var inflateResetKeep_1 = inflateResetKeep;
  var inflateInit_1 = inflateInit;
  var inflateInit2_1 = inflateInit2;
  var inflate_2$1 = inflate$1;
  var inflateEnd_1 = inflateEnd;
  var inflateGetHeader_1 = inflateGetHeader;
  var inflateSetDictionary_1 = inflateSetDictionary;
  var inflateInfo = 'pako inflate (from Nodeca project)';

  /* Not implemented
  module.exports.inflateCodesUsed = inflateCodesUsed;
  module.exports.inflateCopy = inflateCopy;
  module.exports.inflateGetDictionary = inflateGetDictionary;
  module.exports.inflateMark = inflateMark;
  module.exports.inflatePrime = inflatePrime;
  module.exports.inflateSync = inflateSync;
  module.exports.inflateSyncPoint = inflateSyncPoint;
  module.exports.inflateUndermine = inflateUndermine;
  module.exports.inflateValidate = inflateValidate;
  */

  var inflate_1$1 = {
  	inflateReset: inflateReset_1,
  	inflateReset2: inflateReset2_1,
  	inflateResetKeep: inflateResetKeep_1,
  	inflateInit: inflateInit_1,
  	inflateInit2: inflateInit2_1,
  	inflate: inflate_2$1,
  	inflateEnd: inflateEnd_1,
  	inflateGetHeader: inflateGetHeader_1,
  	inflateSetDictionary: inflateSetDictionary_1,
  	inflateInfo: inflateInfo
  };

  const _has = (obj, key) => {
    return Object.prototype.hasOwnProperty.call(obj, key);
  };

  var assign = function (obj /*from1, from2, from3, ...*/) {
    const sources = Array.prototype.slice.call(arguments, 1);
    while (sources.length) {
      const source = sources.shift();
      if (!source) { continue; }

      if (typeof source !== 'object') {
        throw new TypeError(source + 'must be non-object');
      }

      for (const p in source) {
        if (_has(source, p)) {
          obj[p] = source[p];
        }
      }
    }

    return obj;
  };


  // Join array of chunks to single array.
  var flattenChunks = (chunks) => {
    // calculate data length
    let len = 0;

    for (let i = 0, l = chunks.length; i < l; i++) {
      len += chunks[i].length;
    }

    // join chunks
    const result = new Uint8Array(len);

    for (let i = 0, pos = 0, l = chunks.length; i < l; i++) {
      let chunk = chunks[i];
      result.set(chunk, pos);
      pos += chunk.length;
    }

    return result;
  };

  var common = {
  	assign: assign,
  	flattenChunks: flattenChunks
  };

  // String encode/decode helpers


  // Quick check if we can use fast array to bin string conversion
  //
  // - apply(Array) can fail on Android 2.2
  // - apply(Uint8Array) can fail on iOS 5.1 Safari
  //
  let STR_APPLY_UIA_OK = true;

  try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; }


  // Table with utf8 lengths (calculated by first byte of sequence)
  // Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,
  // because max possible codepoint is 0x10ffff
  const _utf8len = new Uint8Array(256);
  for (let q = 0; q < 256; q++) {
    _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1);
  }
  _utf8len[254] = _utf8len[254] = 1; // Invalid sequence start


  // convert string to array (typed, when possible)
  var string2buf = (str) => {
    if (typeof TextEncoder === 'function' && TextEncoder.prototype.encode) {
      return new TextEncoder().encode(str);
    }

    let buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;

    // count binary size
    for (m_pos = 0; m_pos < str_len; m_pos++) {
      c = str.charCodeAt(m_pos);
      if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {
        c2 = str.charCodeAt(m_pos + 1);
        if ((c2 & 0xfc00) === 0xdc00) {
          c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
          m_pos++;
        }
      }
      buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4;
    }

    // allocate buffer
    buf = new Uint8Array(buf_len);

    // convert
    for (i = 0, m_pos = 0; i < buf_len; m_pos++) {
      c = str.charCodeAt(m_pos);
      if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {
        c2 = str.charCodeAt(m_pos + 1);
        if ((c2 & 0xfc00) === 0xdc00) {
          c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
          m_pos++;
        }
      }
      if (c < 0x80) {
        /* one byte */
        buf[i++] = c;
      } else if (c < 0x800) {
        /* two bytes */
        buf[i++] = 0xC0 | (c >>> 6);
        buf[i++] = 0x80 | (c & 0x3f);
      } else if (c < 0x10000) {
        /* three bytes */
        buf[i++] = 0xE0 | (c >>> 12);
        buf[i++] = 0x80 | (c >>> 6 & 0x3f);
        buf[i++] = 0x80 | (c & 0x3f);
      } else {
        /* four bytes */
        buf[i++] = 0xf0 | (c >>> 18);
        buf[i++] = 0x80 | (c >>> 12 & 0x3f);
        buf[i++] = 0x80 | (c >>> 6 & 0x3f);
        buf[i++] = 0x80 | (c & 0x3f);
      }
    }

    return buf;
  };

  // Helper
  const buf2binstring = (buf, len) => {
    // On Chrome, the arguments in a function call that are allowed is `65534`.
    // If the length of the buffer is smaller than that, we can use this optimization,
    // otherwise we will take a slower path.
    if (len < 65534) {
      if (buf.subarray && STR_APPLY_UIA_OK) {
        return String.fromCharCode.apply(null, buf.length === len ? buf : buf.subarray(0, len));
      }
    }

    let result = '';
    for (let i = 0; i < len; i++) {
      result += String.fromCharCode(buf[i]);
    }
    return result;
  };


  // convert array to string
  var buf2string = (buf, max) => {
    const len = max || buf.length;

    if (typeof TextDecoder === 'function' && TextDecoder.prototype.decode) {
      return new TextDecoder().decode(buf.subarray(0, max));
    }

    let i, out;

    // Reserve max possible length (2 words per char)
    // NB: by unknown reasons, Array is significantly faster for
    //     String.fromCharCode.apply than Uint16Array.
    const utf16buf = new Array(len * 2);

    for (out = 0, i = 0; i < len;) {
      let c = buf[i++];
      // quick process ascii
      if (c < 0x80) { utf16buf[out++] = c; continue; }

      let c_len = _utf8len[c];
      // skip 5 & 6 byte codes
      if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; }

      // apply mask on first byte
      c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;
      // join the rest
      while (c_len > 1 && i < len) {
        c = (c << 6) | (buf[i++] & 0x3f);
        c_len--;
      }

      // terminated by end of string?
      if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; }

      if (c < 0x10000) {
        utf16buf[out++] = c;
      } else {
        c -= 0x10000;
        utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff);
        utf16buf[out++] = 0xdc00 | (c & 0x3ff);
      }
    }

    return buf2binstring(utf16buf, out);
  };


  // Calculate max possible position in utf8 buffer,
  // that will not break sequence. If that's not possible
  // - (very small limits) return max size as is.
  //
  // buf[] - utf8 bytes array
  // max   - length limit (mandatory);
  var utf8border = (buf, max) => {

    max = max || buf.length;
    if (max > buf.length) { max = buf.length; }

    // go back from last position, until start of sequence found
    let pos = max - 1;
    while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }

    // Very small and broken sequence,
    // return max, because we should return something anyway.
    if (pos < 0) { return max; }

    // If we came to start of buffer - that means buffer is too small,
    // return max too.
    if (pos === 0) { return max; }

    return (pos + _utf8len[buf[pos]] > max) ? pos : max;
  };

  var strings = {
  	string2buf: string2buf,
  	buf2string: buf2string,
  	utf8border: utf8border
  };

  // (C) 1995-2013 Jean-loup Gailly and Mark Adler
  // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
  //
  // This software is provided 'as-is', without any express or implied
  // warranty. In no event will the authors be held liable for any damages
  // arising from the use of this software.
  //
  // Permission is granted to anyone to use this software for any purpose,
  // including commercial applications, and to alter it and redistribute it
  // freely, subject to the following restrictions:
  //
  // 1. The origin of this software must not be misrepresented; you must not
  //   claim that you wrote the original software. If you use this software
  //   in a product, an acknowledgment in the product documentation would be
  //   appreciated but is not required.
  // 2. Altered source versions must be plainly marked as such, and must not be
  //   misrepresented as being the original software.
  // 3. This notice may not be removed or altered from any source distribution.

  var messages = {
    2:      'need dictionary',     /* Z_NEED_DICT       2  */
    1:      'stream end',          /* Z_STREAM_END      1  */
    0:      '',                    /* Z_OK              0  */
    '-1':   'file error',          /* Z_ERRNO         (-1) */
    '-2':   'stream error',        /* Z_STREAM_ERROR  (-2) */
    '-3':   'data error',          /* Z_DATA_ERROR    (-3) */
    '-4':   'insufficient memory', /* Z_MEM_ERROR     (-4) */
    '-5':   'buffer error',        /* Z_BUF_ERROR     (-5) */
    '-6':   'incompatible version' /* Z_VERSION_ERROR (-6) */
  };

  // (C) 1995-2013 Jean-loup Gailly and Mark Adler
  // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
  //
  // This software is provided 'as-is', without any express or implied
  // warranty. In no event will the authors be held liable for any damages
  // arising from the use of this software.
  //
  // Permission is granted to anyone to use this software for any purpose,
  // including commercial applications, and to alter it and redistribute it
  // freely, subject to the following restrictions:
  //
  // 1. The origin of this software must not be misrepresented; you must not
  //   claim that you wrote the original software. If you use this software
  //   in a product, an acknowledgment in the product documentation would be
  //   appreciated but is not required.
  // 2. Altered source versions must be plainly marked as such, and must not be
  //   misrepresented as being the original software.
  // 3. This notice may not be removed or altered from any source distribution.

  function ZStream() {
    /* next input byte */
    this.input = null; // JS specific, because we have no pointers
    this.next_in = 0;
    /* number of bytes available at input */
    this.avail_in = 0;
    /* total number of input bytes read so far */
    this.total_in = 0;
    /* next output byte should be put there */
    this.output = null; // JS specific, because we have no pointers
    this.next_out = 0;
    /* remaining free space at output */
    this.avail_out = 0;
    /* total number of bytes output so far */
    this.total_out = 0;
    /* last error message, NULL if no error */
    this.msg = ''/*Z_NULL*/;
    /* not visible by applications */
    this.state = null;
    /* best guess about the data type: binary or text */
    this.data_type = 2/*Z_UNKNOWN*/;
    /* adler32 value of the uncompressed data */
    this.adler = 0;
  }

  var zstream = ZStream;

  // (C) 1995-2013 Jean-loup Gailly and Mark Adler
  // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
  //
  // This software is provided 'as-is', without any express or implied
  // warranty. In no event will the authors be held liable for any damages
  // arising from the use of this software.
  //
  // Permission is granted to anyone to use this software for any purpose,
  // including commercial applications, and to alter it and redistribute it
  // freely, subject to the following restrictions:
  //
  // 1. The origin of this software must not be misrepresented; you must not
  //   claim that you wrote the original software. If you use this software
  //   in a product, an acknowledgment in the product documentation would be
  //   appreciated but is not required.
  // 2. Altered source versions must be plainly marked as such, and must not be
  //   misrepresented as being the original software.
  // 3. This notice may not be removed or altered from any source distribution.

  function GZheader() {
    /* true if compressed data believed to be text */
    this.text       = 0;
    /* modification time */
    this.time       = 0;
    /* extra flags (not used when writing a gzip file) */
    this.xflags     = 0;
    /* operating system */
    this.os         = 0;
    /* pointer to extra field or Z_NULL if none */
    this.extra      = null;
    /* extra field length (valid if extra != Z_NULL) */
    this.extra_len  = 0; // Actually, we don't need it in JS,
                         // but leave for few code modifications

    //
    // Setup limits is not necessary because in js we should not preallocate memory
    // for inflate use constant limit in 65536 bytes
    //

    /* space at extra (only when reading header) */
    // this.extra_max  = 0;
    /* pointer to zero-terminated file name or Z_NULL */
    this.name       = '';
    /* space at name (only when reading header) */
    // this.name_max   = 0;
    /* pointer to zero-terminated comment or Z_NULL */
    this.comment    = '';
    /* space at comment (only when reading header) */
    // this.comm_max   = 0;
    /* true if there was or will be a header crc */
    this.hcrc       = 0;
    /* true when done reading gzip header (not used when writing a gzip file) */
    this.done       = false;
  }

  var gzheader = GZheader;

  const toString = Object.prototype.toString;

  /* Public constants ==========================================================*/
  /* ===========================================================================*/

  const {
    Z_NO_FLUSH, Z_FINISH,
    Z_OK, Z_STREAM_END, Z_NEED_DICT, Z_STREAM_ERROR, Z_DATA_ERROR, Z_MEM_ERROR
  } = constants$1;

  /* ===========================================================================*/


  /**
   * class Inflate
   *
   * Generic JS-style wrapper for zlib calls. If you don't need
   * streaming behaviour - use more simple functions: [[inflate]]
   * and [[inflateRaw]].
   **/

  /* internal
   * inflate.chunks -> Array
   *
   * Chunks of output data, if [[Inflate#onData]] not overridden.
   **/

  /**
   * Inflate.result -> Uint8Array|String
   *
   * Uncompressed result, generated by default [[Inflate#onData]]
   * and [[Inflate#onEnd]] handlers. Filled after you push last chunk
   * (call [[Inflate#push]] with `Z_FINISH` / `true` param).
   **/

  /**
   * Inflate.err -> Number
   *
   * Error code after inflate finished. 0 (Z_OK) on success.
   * Should be checked if broken data possible.
   **/

  /**
   * Inflate.msg -> String
   *
   * Error message, if [[Inflate.err]] != 0
   **/


  /**
   * new Inflate(options)
   * - options (Object): zlib inflate options.
   *
   * Creates new inflator instance with specified params. Throws exception
   * on bad params. Supported options:
   *
   * - `windowBits`
   * - `dictionary`
   *
   * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
   * for more information on these.
   *
   * Additional options, for internal needs:
   *
   * - `chunkSize` - size of generated data chunks (16K by default)
   * - `raw` (Boolean) - do raw inflate
   * - `to` (String) - if equal to 'string', then result will be converted
   *   from utf8 to utf16 (javascript) string. When string output requested,
   *   chunk length can differ from `chunkSize`, depending on content.
   *
   * By default, when no options set, autodetect deflate/gzip data format via
   * wrapper header.
   *
   * ##### Example:
   *
   * ```javascript
   * const pako = require('pako')
   * const chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9])
   * const chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]);
   *
   * const inflate = new pako.Inflate({ level: 3});
   *
   * inflate.push(chunk1, false);
   * inflate.push(chunk2, true);  // true -> last chunk
   *
   * if (inflate.err) { throw new Error(inflate.err); }
   *
   * console.log(inflate.result);
   * ```
   **/
  function Inflate(options) {
    this.options = common.assign({
      chunkSize: 1024 * 64,
      windowBits: 15,
      to: ''
    }, options || {});

    const opt = this.options;

    // Force window size for `raw` data, if not set directly,
    // because we have no header for autodetect.
    if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) {
      opt.windowBits = -opt.windowBits;
      if (opt.windowBits === 0) { opt.windowBits = -15; }
    }

    // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate
    if ((opt.windowBits >= 0) && (opt.windowBits < 16) &&
        !(options && options.windowBits)) {
      opt.windowBits += 32;
    }

    // Gzip header has no info about windows size, we can do autodetect only
    // for deflate. So, if window size not set, force it to max when gzip possible
    if ((opt.windowBits > 15) && (opt.windowBits < 48)) {
      // bit 3 (16) -> gzipped data
      // bit 4 (32) -> autodetect gzip/deflate
      if ((opt.windowBits & 15) === 0) {
        opt.windowBits |= 15;
      }
    }

    this.err    = 0;      // error code, if happens (0 = Z_OK)
    this.msg    = '';     // error message
    this.ended  = false;  // used to avoid multiple onEnd() calls
    this.chunks = [];     // chunks of compressed data

    this.strm   = new zstream();
    this.strm.avail_out = 0;

    let status  = inflate_1$1.inflateInit2(
      this.strm,
      opt.windowBits
    );

    if (status !== Z_OK) {
      throw new Error(messages[status]);
    }

    this.header = new gzheader();

    inflate_1$1.inflateGetHeader(this.strm, this.header);

    // Setup dictionary
    if (opt.dictionary) {
      // Convert data if needed
      if (typeof opt.dictionary === 'string') {
        opt.dictionary = strings.string2buf(opt.dictionary);
      } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') {
        opt.dictionary = new Uint8Array(opt.dictionary);
      }
      if (opt.raw) { //In raw mode we need to set the dictionary early
        status = inflate_1$1.inflateSetDictionary(this.strm, opt.dictionary);
        if (status !== Z_OK) {
          throw new Error(messages[status]);
        }
      }
    }
  }

  /**
   * Inflate#push(data[, flush_mode]) -> Boolean
   * - data (Uint8Array|ArrayBuffer): input data
   * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE
   *   flush modes. See constants. Skipped or `false` means Z_NO_FLUSH,
   *   `true` means Z_FINISH.
   *
   * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with
   * new output chunks. Returns `true` on success. If end of stream detected,
   * [[Inflate#onEnd]] will be called.
   *
   * `flush_mode` is not needed for normal operation, because end of stream
   * detected automatically. You may try to use it for advanced things, but
   * this functionality was not tested.
   *
   * On fail call [[Inflate#onEnd]] with error code and return false.
   *
   * ##### Example
   *
   * ```javascript
   * push(chunk, false); // push one of data chunks
   * ...
   * push(chunk, true);  // push last chunk
   * ```
   **/
  Inflate.prototype.push = function (data, flush_mode) {
    const strm = this.strm;
    const chunkSize = this.options.chunkSize;
    const dictionary = this.options.dictionary;
    let status, _flush_mode, last_avail_out;

    if (this.ended) return false;

    if (flush_mode === ~~flush_mode) _flush_mode = flush_mode;
    else _flush_mode = flush_mode === true ? Z_FINISH : Z_NO_FLUSH;

    // Convert data if needed
    if (toString.call(data) === '[object ArrayBuffer]') {
      strm.input = new Uint8Array(data);
    } else {
      strm.input = data;
    }

    strm.next_in = 0;
    strm.avail_in = strm.input.length;

    for (;;) {
      if (strm.avail_out === 0) {
        strm.output = new Uint8Array(chunkSize);
        strm.next_out = 0;
        strm.avail_out = chunkSize;
      }

      status = inflate_1$1.inflate(strm, _flush_mode);

      if (status === Z_NEED_DICT && dictionary) {
        status = inflate_1$1.inflateSetDictionary(strm, dictionary);

        if (status === Z_OK) {
          status = inflate_1$1.inflate(strm, _flush_mode);
        } else if (status === Z_DATA_ERROR) {
          // Replace code with more verbose
          status = Z_NEED_DICT;
        }
      }

      // Skip snyc markers if more data follows and not raw mode
      while (strm.avail_in > 0 &&
             status === Z_STREAM_END &&
             strm.state.wrap > 0 &&
             data[strm.next_in] !== 0)
      {
        inflate_1$1.inflateReset(strm);
        status = inflate_1$1.inflate(strm, _flush_mode);
      }

      switch (status) {
        case Z_STREAM_ERROR:
        case Z_DATA_ERROR:
        case Z_NEED_DICT:
        case Z_MEM_ERROR:
          this.onEnd(status);
          this.ended = true;
          return false;
      }

      // Remember real `avail_out` value, because we may patch out buffer content
      // to align utf8 strings boundaries.
      last_avail_out = strm.avail_out;

      if (strm.next_out) {
        if (strm.avail_out === 0 || status === Z_STREAM_END) {

          if (this.options.to === 'string') {

            let next_out_utf8 = strings.utf8border(strm.output, strm.next_out);

            let tail = strm.next_out - next_out_utf8;
            let utf8str = strings.buf2string(strm.output, next_out_utf8);

            // move tail & realign counters
            strm.next_out = tail;
            strm.avail_out = chunkSize - tail;
            if (tail) strm.output.set(strm.output.subarray(next_out_utf8, next_out_utf8 + tail), 0);

            this.onData(utf8str);

          } else {
            this.onData(strm.output.length === strm.next_out ? strm.output : strm.output.subarray(0, strm.next_out));
          }
        }
      }

      // Must repeat iteration if out buffer is full
      if (status === Z_OK && last_avail_out === 0) continue;

      // Finalize if end of stream reached.
      if (status === Z_STREAM_END) {
        status = inflate_1$1.inflateEnd(this.strm);
        this.onEnd(status);
        this.ended = true;
        return true;
      }

      if (strm.avail_in === 0) break;
    }

    return true;
  };


  /**
   * Inflate#onData(chunk) -> Void
   * - chunk (Uint8Array|String): output data. When string output requested,
   *   each chunk will be string.
   *
   * By default, stores data blocks in `chunks[]` property and glue
   * those in `onEnd`. Override this handler, if you need another behaviour.
   **/
  Inflate.prototype.onData = function (chunk) {
    this.chunks.push(chunk);
  };


  /**
   * Inflate#onEnd(status) -> Void
   * - status (Number): inflate status. 0 (Z_OK) on success,
   *   other if not.
   *
   * Called either after you tell inflate that the input stream is
   * complete (Z_FINISH). By default - join collected chunks,
   * free memory and fill `results` / `err` properties.
   **/
  Inflate.prototype.onEnd = function (status) {
    // On success - join
    if (status === Z_OK) {
      if (this.options.to === 'string') {
        this.result = this.chunks.join('');
      } else {
        this.result = common.flattenChunks(this.chunks);
      }
    }
    this.chunks = [];
    this.err = status;
    this.msg = this.strm.msg;
  };


  /**
   * inflate(data[, options]) -> Uint8Array|String
   * - data (Uint8Array|ArrayBuffer): input data to decompress.
   * - options (Object): zlib inflate options.
   *
   * Decompress `data` with inflate/ungzip and `options`. Autodetect
   * format via wrapper header by default. That's why we don't provide
   * separate `ungzip` method.
   *
   * Supported options are:
   *
   * - windowBits
   *
   * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
   * for more information.
   *
   * Sugar (options):
   *
   * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify
   *   negative windowBits implicitly.
   * - `to` (String) - if equal to 'string', then result will be converted
   *   from utf8 to utf16 (javascript) string. When string output requested,
   *   chunk length can differ from `chunkSize`, depending on content.
   *
   *
   * ##### Example:
   *
   * ```javascript
   * const pako = require('pako');
   * const input = pako.deflate(new Uint8Array([1,2,3,4,5,6,7,8,9]));
   * let output;
   *
   * try {
   *   output = pako.inflate(input);
   * } catch (err) {
   *   console.log(err);
   * }
   * ```
   **/
  function inflate(input, options) {
    const inflator = new Inflate(options);

    inflator.push(input);

    // That will never happens, if you don't cheat with options :)
    if (inflator.err) throw inflator.msg || messages[inflator.err];

    return inflator.result;
  }


  /**
   * inflateRaw(data[, options]) -> Uint8Array|String
   * - data (Uint8Array|ArrayBuffer): input data to decompress.
   * - options (Object): zlib inflate options.
   *
   * The same as [[inflate]], but creates raw data, without wrapper
   * (header and adler32 crc).
   **/
  function inflateRaw(input, options) {
    options = options || {};
    options.raw = true;
    return inflate(input, options);
  }


  /**
   * ungzip(data[, options]) -> Uint8Array|String
   * - data (Uint8Array|ArrayBuffer): input data to decompress.
   * - options (Object): zlib inflate options.
   *
   * Just shortcut to [[inflate]], because it autodetects format
   * by header.content. Done for convenience.
   **/


  var Inflate_1 = Inflate;
  var inflate_2 = inflate;
  var inflateRaw_1 = inflateRaw;
  var ungzip = inflate;
  var constants = constants$1;

  var inflate_1 = {
  	Inflate: Inflate_1,
  	inflate: inflate_2,
  	inflateRaw: inflateRaw_1,
  	ungzip: ungzip,
  	constants: constants
  };

  exports.Inflate = Inflate_1;
  exports.constants = constants;
  exports["default"] = inflate_1;
  exports.inflate = inflate_2;
  exports.inflateRaw = inflateRaw_1;
  exports.ungzip = ungzip;

  Object.defineProperty(exports, '__esModule', { value: true });

}));


/***/ }),

/***/ 357:
/***/ (function(module, exports) {

var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*
	SuperGif

	Example usage:

		<img src="./example1_preview.gif" rel:animated_src="./example1.gif" width="360" height="360" rel:auto_play="1" />

		<script type="text/javascript">
			$$('img').each(function (img_tag) {
				if (/.*\.gif/.test(img_tag.src)) {
					var rub = new SuperGif({ gif: img_tag } );
					rub.load();
				}
			});
		</script>

	Image tag attributes:

		rel:animated_src -	If this url is specified, it's loaded into the player instead of src.
							This allows a preview frame to be shown until animated gif data is streamed into the canvas

		rel:auto_play -		Defaults to 1 if not specified. If set to zero, a call to the play() method is needed

	Constructor options args

		gif 				Required. The DOM element of an img tag.
		loop_mode			Optional. Setting this to false will force disable looping of the gif.
		auto_play 			Optional. Same as the rel:auto_play attribute above, this arg overrides the img tag info.
		max_width			Optional. Scale images over max_width down to max_width. Helpful with mobile.
 		on_end				Optional. Add a callback for when the gif reaches the end of a single loop (one iteration). The first argument passed will be the gif HTMLElement.
		loop_delay			Optional. The amount of time to pause (in ms) after each single loop (iteration).
		draw_while_loading	Optional. Determines whether the gif will be drawn to the canvas whilst it is loaded.
		show_progress_bar	Optional. Only applies when draw_while_loading is set to true.

	Instance methods

		// loading
		load( callback )		Loads the gif specified by the src or rel:animated_src sttributie of the img tag into a canvas element and then calls callback if one is passed
		load_url( src, callback )	Loads the gif file specified in the src argument into a canvas element and then calls callback if one is passed

		// play controls
		play -				Start playing the gif
		pause -				Stop playing the gif
		move_to(i) -		Move to frame i of the gif
		move_relative(i) -	Move i frames ahead (or behind if i < 0)

		// getters
		get_canvas			The canvas element that the gif is playing in. Handy for assigning event handlers to.
		get_playing			Whether or not the gif is currently playing
		get_loading			Whether or not the gif has finished loading/parsing
		get_auto_play		Whether or not the gif is set to play automatically
		get_length			The number of frames in the gif
		get_current_frame	The index of the currently displayed frame of the gif
		get_frames	        An array containing the data for all parsed frames
		get_duration	    Returns the duration of the gif in hundredths of a second (standard for GIF spec)
		get_duration_ms	    Returns the duration of the gif in milliseconds

		For additional customization (viewport inside iframe) these params may be passed:
		c_w, c_h - width and height of canvas
		vp_t, vp_l, vp_ w, vp_h - top, left, width and height of the viewport

		A bonus: few articles to understand what is going on
			http://enthusiasms.org/post/16976438906
			http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp
			http://humpy77.deviantart.com/journal/Frame-Delay-Times-for-Animated-GIFs-214150546

*/
(function (root, factory) {
   if (true) {
       !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
		__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
		(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
		__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
   } else {}
}(this, function () {
   // Generic functions
   var bitsToNum = function (ba) {
       return ba.reduce(function (s, n) {
           return s * 2 + n;
       }, 0);
   };

   var byteToBitArr = function (bite) {
       var a = [];
       for (var i = 7; i >= 0; i--) {
           a.push( !! (bite & (1 << i)));
       }
       return a;
   };

   // Stream
   /**
    * @constructor
    */
   // Make compiler happy.
   var Stream = function (data) {
       this.data = data;
       this.len = this.data.length;
       this.pos = 0;

       this.readByte = function () {
           if (this.pos >= this.data.length) {
               throw new Error('Attempted to read past end of stream.');
           }
           if (data instanceof Uint8Array)
               return data[this.pos++];
           else
               return data.charCodeAt(this.pos++) & 0xFF;
       };

       this.readBytes = function (n) {
           var bytes = [];
           for (var i = 0; i < n; i++) {
               bytes.push(this.readByte());
           }
           return bytes;
       };

       this.read = function (n) {
           var s = '';
           for (var i = 0; i < n; i++) {
               s += String.fromCharCode(this.readByte());
           }
           return s;
       };

       this.readUnsigned = function () { // Little-endian.
           var a = this.readBytes(2);
           return (a[1] << 8) + a[0];
       };
   };

   var lzwDecode = function (minCodeSize, data) {
       // TODO: Now that the GIF parser is a bit different, maybe this should get an array of bytes instead of a String?
       var pos = 0; // Maybe this streaming thing should be merged with the Stream?
       var readCode = function (size) {
           var code = 0;
           for (var i = 0; i < size; i++) {
               if (data.charCodeAt(pos >> 3) & (1 << (pos & 7))) {
                   code |= 1 << i;
               }
               pos++;
           }
           return code;
       };

       var output = [];

       var clearCode = 1 << minCodeSize;
       var eoiCode = clearCode + 1;

       var codeSize = minCodeSize + 1;

       var dict = [];

       var clear = function () {
           dict = [];
           codeSize = minCodeSize + 1;
           for (var i = 0; i < clearCode; i++) {
               dict[i] = [i];
           }
           dict[clearCode] = [];
           dict[eoiCode] = null;

       };

       var code;
       var last;

       while (true) {
           last = code;
           code = readCode(codeSize);

           if (code === clearCode) {
               clear();
               continue;
           }
           if (code === eoiCode) break;

           if (code < dict.length) {
               if (last !== clearCode) {
                   dict.push(dict[last].concat(dict[code][0]));
               }
           }
           else {
               if (code !== dict.length) throw new Error('Invalid LZW code.');
               dict.push(dict[last].concat(dict[last][0]));
           }
           output.push.apply(output, dict[code]);

           if (dict.length === (1 << codeSize) && codeSize < 12) {
               // If we're at the last code and codeSize is 12, the next code will be a clearCode, and it'll be 12 bits long.
               codeSize++;
           }
       }

       // I don't know if this is technically an error, but some GIFs do it.
       //if (Math.ceil(pos / 8) !== data.length) throw new Error('Extraneous LZW bytes.');
       return output;
   };


   // The actual parsing; returns an object with properties.
   var parseGIF = function (st, handler) {
       handler || (handler = {});

       // LZW (GIF-specific)
       var parseCT = function (entries) { // Each entry is 3 bytes, for RGB.
           var ct = [];
           for (var i = 0; i < entries; i++) {
               ct.push(st.readBytes(3));
           }
           return ct;
       };

       var readSubBlocks = function () {
           var size, data;
           data = '';
           do {
               size = st.readByte();
               data += st.read(size);
           } while (size !== 0);
           return data;
       };

       var parseHeader = function () {
           var hdr = {};
           hdr.sig = st.read(3);
           hdr.ver = st.read(3);
           if (hdr.sig !== 'GIF') throw new Error('Not a GIF file.'); // XXX: This should probably be handled more nicely.
           hdr.width = st.readUnsigned();
           hdr.height = st.readUnsigned();

           var bits = byteToBitArr(st.readByte());
           hdr.gctFlag = bits.shift();
           hdr.colorRes = bitsToNum(bits.splice(0, 3));
           hdr.sorted = bits.shift();
           hdr.gctSize = bitsToNum(bits.splice(0, 3));

           hdr.bgColor = st.readByte();
           hdr.pixelAspectRatio = st.readByte(); // if not 0, aspectRatio = (pixelAspectRatio + 15) / 64
           if (hdr.gctFlag) {
               hdr.gct = parseCT(1 << (hdr.gctSize + 1));
           }
           handler.hdr && handler.hdr(hdr);
       };

       var parseExt = function (block) {
           var parseGCExt = function (block) {
               var blockSize = st.readByte(); // Always 4
               var bits = byteToBitArr(st.readByte());
               block.reserved = bits.splice(0, 3); // Reserved; should be 000.
               block.disposalMethod = bitsToNum(bits.splice(0, 3));
               block.userInput = bits.shift();
               block.transparencyGiven = bits.shift();

               block.delayTime = st.readUnsigned();

               block.transparencyIndex = st.readByte();

               block.terminator = st.readByte();

               handler.gce && handler.gce(block);
           };

           var parseComExt = function (block) {
               block.comment = readSubBlocks();
               handler.com && handler.com(block);
           };

           var parsePTExt = function (block) {
               // No one *ever* uses this. If you use it, deal with parsing it yourself.
               var blockSize = st.readByte(); // Always 12
               block.ptHeader = st.readBytes(12);
               block.ptData = readSubBlocks();
               handler.pte && handler.pte(block);
           };

           var parseAppExt = function (block) {
               var parseNetscapeExt = function (block) {
                   var blockSize = st.readByte(); // Always 3
                   block.unknown = st.readByte(); // ??? Always 1? What is this?
                   block.iterations = st.readUnsigned();
                   block.terminator = st.readByte();
                   handler.app && handler.app.NETSCAPE && handler.app.NETSCAPE(block);
               };

               var parseUnknownAppExt = function (block) {
                   block.appData = readSubBlocks();
                   // FIXME: This won't work if a handler wants to match on any identifier.
                   handler.app && handler.app[block.identifier] && handler.app[block.identifier](block);
               };

               var blockSize = st.readByte(); // Always 11
               block.identifier = st.read(8);
               block.authCode = st.read(3);
               switch (block.identifier) {
                   case 'NETSCAPE':
                       parseNetscapeExt(block);
                       break;
                   default:
                       parseUnknownAppExt(block);
                       break;
               }
           };

           var parseUnknownExt = function (block) {
               block.data = readSubBlocks();
               handler.unknown && handler.unknown(block);
           };

           block.label = st.readByte();
           switch (block.label) {
               case 0xF9:
                   block.extType = 'gce';
                   parseGCExt(block);
                   break;
               case 0xFE:
                   block.extType = 'com';
                   parseComExt(block);
                   break;
               case 0x01:
                   block.extType = 'pte';
                   parsePTExt(block);
                   break;
               case 0xFF:
                   block.extType = 'app';
                   parseAppExt(block);
                   break;
               default:
                   block.extType = 'unknown';
                   parseUnknownExt(block);
                   break;
           }
       };

       var parseImg = function (img) {
           var deinterlace = function (pixels, width) {
               // Of course this defeats the purpose of interlacing. And it's *probably*
               // the least efficient way it's ever been implemented. But nevertheless...
               var newPixels = new Array(pixels.length);
               var rows = pixels.length / width;
               var cpRow = function (toRow, fromRow) {
                   var fromPixels = pixels.slice(fromRow * width, (fromRow + 1) * width);
                   newPixels.splice.apply(newPixels, [toRow * width, width].concat(fromPixels));
               };

               // See appendix E.
               var offsets = [0, 4, 2, 1];
               var steps = [8, 8, 4, 2];

               var fromRow = 0;
               for (var pass = 0; pass < 4; pass++) {
                   for (var toRow = offsets[pass]; toRow < rows; toRow += steps[pass]) {
                       cpRow(toRow, fromRow)
                       fromRow++;
                   }
               }

               return newPixels;
           };

           img.leftPos = st.readUnsigned();
           img.topPos = st.readUnsigned();
           img.width = st.readUnsigned();
           img.height = st.readUnsigned();

           var bits = byteToBitArr(st.readByte());
           img.lctFlag = bits.shift();
           img.interlaced = bits.shift();
           img.sorted = bits.shift();
           img.reserved = bits.splice(0, 2);
           img.lctSize = bitsToNum(bits.splice(0, 3));

           if (img.lctFlag) {
               img.lct = parseCT(1 << (img.lctSize + 1));
           }

           img.lzwMinCodeSize = st.readByte();

           var lzwData = readSubBlocks();

           img.pixels = lzwDecode(img.lzwMinCodeSize, lzwData);

           if (img.interlaced) { // Move
               img.pixels = deinterlace(img.pixels, img.width);
           }

           handler.img && handler.img(img);
       };

       var parseBlock = function () {
           var block = {};
           block.sentinel = st.readByte();

           switch (String.fromCharCode(block.sentinel)) { // For ease of matching
               case '!':
                   block.type = 'ext';
                   parseExt(block);
                   break;
               case ',':
                   block.type = 'img';
                   parseImg(block);
                   break;
               case ';':
                   block.type = 'eof';
                   handler.eof && handler.eof(block);
                   break;
               default:
                   throw new Error('Unknown block: 0x' + block.sentinel.toString(16)); // TODO: Pad this with a 0.
           }

           if (block.type !== 'eof') setTimeout(parseBlock, 0);
       };

       var parse = function () {
           parseHeader();
           setTimeout(parseBlock, 0);
       };

       parse();
   };

   var SuperGif = function ( opts ) {
       var options = {
           //viewport position
           vp_l: 0,
           vp_t: 0,
           vp_w: null,
           vp_h: null,
           //canvas sizes
           c_w: null,
           c_h: null
       };
       for (var i in opts ) { options[i] = opts[i] }
       if (options.vp_w && options.vp_h) options.is_vp = true;

       var stream;
       var hdr;

       var loadError = null;
       var loading = false;

       var transparency = null;
       var delay = null;
       var disposalMethod = null;
       var disposalRestoreFromIdx = null;
       var lastDisposalMethod = null;
       var frame = null;
       var lastImg = null;

       var playing = true;
       var forward = true;

       var ctx_scaled = false;

       var frames = [];
       var frameOffsets = []; // elements have .x and .y properties

       var gif = options.gif;
       if (typeof options.auto_play == 'undefined')
           options.auto_play = (!gif.getAttribute('rel:auto_play') || gif.getAttribute('rel:auto_play') == '1');

       var onEndListener = (options.hasOwnProperty('on_end') ? options.on_end : null);
       var onErrorListener = (options.hasOwnProperty('on_error') ? options.on_error : null);
       var loopDelay = (options.hasOwnProperty('loop_delay') ? options.loop_delay : 0);
       var overrideLoopMode = (options.hasOwnProperty('loop_mode') ? options.loop_mode : 'auto');
       var drawWhileLoading = (options.hasOwnProperty('draw_while_loading') ? options.draw_while_loading : true);
       var showProgressBar = drawWhileLoading ? (options.hasOwnProperty('show_progress_bar') ? options.show_progress_bar : true) : false;
       var progressBarHeight = (options.hasOwnProperty('progressbar_height') ? options.progressbar_height : 25);
       var progressBarBackgroundColor = (options.hasOwnProperty('progressbar_background_color') ? options.progressbar_background_color : 'rgba(255,255,255,0.4)');
       var progressBarForegroundColor = (options.hasOwnProperty('progressbar_foreground_color') ? options.progressbar_foreground_color : 'rgba(255,0,22,.8)');

       var clear = function () {
           transparency = null;
           delay = null;
           lastDisposalMethod = disposalMethod;
           disposalMethod = null;
           frame = null;
       };

       // XXX: There's probably a better way to handle catching exceptions when
       // callbacks are involved.
       var doParse = function () {
           try {
               parseGIF(stream, handler);
           }
           catch (err) {
               doLoadError('parse');
           }
       };

       var doText = function (text) {
           toolbar.innerHTML = text; // innerText? Escaping? Whatever.
           toolbar.style.visibility = 'visible';
       };

       var setSizes = function(w, h) {
           canvas.width = w * get_canvas_scale();
           canvas.height = h * get_canvas_scale();
           toolbar.style.minWidth = ( w * get_canvas_scale() ) + 'px';

           tmpCanvas.width = w;
           tmpCanvas.height = h;
           tmpCanvas.style.width = w + 'px';
           tmpCanvas.style.height = h + 'px';
           tmpCanvas.getContext('2d').setTransform(1, 0, 0, 1, 0, 0);
       };

       var setFrameOffset = function(frame, offset) {
           if (!frameOffsets[frame]) {
               frameOffsets[frame] = offset;
               return;
           }
           if (typeof offset.x !== 'undefined') {
               frameOffsets[frame].x = offset.x;
           }
           if (typeof offset.y !== 'undefined') {
               frameOffsets[frame].y = offset.y;
           }
       };

       var doShowProgress = function (pos, length, draw) {
           if (draw && showProgressBar) {
               var height = progressBarHeight;
               var left, mid, top, width;
               if (options.is_vp) {
                   if (!ctx_scaled) {
                       top = (options.vp_t + options.vp_h - height);
                       height = height;
                       left = options.vp_l;
                       mid = left + (pos / length) * options.vp_w;
                       width = canvas.width;
                   } else {
                       top = (options.vp_t + options.vp_h - height) / get_canvas_scale();
                       height = height / get_canvas_scale();
                       left = (options.vp_l / get_canvas_scale() );
                       mid = left + (pos / length) * (options.vp_w / get_canvas_scale());
                       width = canvas.width / get_canvas_scale();
                   }
                   //some debugging, draw rect around viewport
                   if (false) { var w, h, l, t; }
               }
               else {
                   top = (canvas.height - height) / (ctx_scaled ? get_canvas_scale() : 1);
                   mid = ((pos / length) * canvas.width) / (ctx_scaled ? get_canvas_scale() : 1);
                   width = canvas.width / (ctx_scaled ? get_canvas_scale() : 1 );
                   height /= ctx_scaled ? get_canvas_scale() : 1;
               }

               ctx.fillStyle = progressBarBackgroundColor;
               ctx.fillRect(mid, top, width - mid, height);

               ctx.fillStyle = progressBarForegroundColor;
               ctx.fillRect(0, top, mid, height);
           }
       };

       var doLoadError = function (originOfError) {
           var drawError = function () {
               ctx.fillStyle = 'black';
               ctx.fillRect(0, 0, options.c_w ? options.c_w : hdr.width, options.c_h ? options.c_h : hdr.height);
               ctx.strokeStyle = 'red';
               ctx.lineWidth = 3;
               ctx.moveTo(0, 0);
               ctx.lineTo(options.c_w ? options.c_w : hdr.width, options.c_h ? options.c_h : hdr.height);
               ctx.moveTo(0, options.c_h ? options.c_h : hdr.height);
               ctx.lineTo(options.c_w ? options.c_w : hdr.width, 0);
               ctx.stroke();
           };

           loadError = originOfError;
           hdr = {
               width: gif.width,
               height: gif.height
           }; // Fake header.
           frames = [];
           drawError();

           if (originOfError)
            onErrorListener (originOfError);
       };

       var doHdr = function (_hdr) {
           hdr = _hdr;
           setSizes(hdr.width, hdr.height)
       };

       var doGCE = function (gce) {
           pushFrame();
           clear();
           transparency = gce.transparencyGiven ? gce.transparencyIndex : null;
           delay = gce.delayTime;
           disposalMethod = gce.disposalMethod;
           // We don't have much to do with the rest of GCE.
       };

       var pushFrame = function () {
           if (!frame) return;
           frames.push({
                           data: frame.getImageData(0, 0, hdr.width, hdr.height),
                           delay: delay
                       });
           frameOffsets.push({ x: 0, y: 0 });
       };

       var doImg = function (img) {
           if (!frame) frame = tmpCanvas.getContext('2d');

           var currIdx = frames.length;

           //ct = color table, gct = global color table
           var ct = img.lctFlag ? img.lct : hdr.gct; // TODO: What if neither exists?

           /*
           Disposal method indicates the way in which the graphic is to
           be treated after being displayed.

           Values :    0 - No disposal specified. The decoder is
                           not required to take any action.
                       1 - Do not dispose. The graphic is to be left
                           in place.
                       2 - Restore to background color. The area used by the
                           graphic must be restored to the background color.
                       3 - Restore to previous. The decoder is required to
                           restore the area overwritten by the graphic with
                           what was there prior to rendering the graphic.

                           Importantly, "previous" means the frame state
                           after the last disposal of method 0, 1, or 2.
           */
           if (currIdx > 0) {
               if (lastDisposalMethod === 3) {
                   // Restore to previous
                   // If we disposed every frame including first frame up to this point, then we have
                   // no composited frame to restore to. In this case, restore to background instead.
                   if (disposalRestoreFromIdx !== null) {
                      frame.putImageData(frames[disposalRestoreFromIdx].data, 0, 0);
                   } else {
                      frame.clearRect(lastImg.leftPos, lastImg.topPos, lastImg.width, lastImg.height);
                   }
               } else {
                   disposalRestoreFromIdx = currIdx - 1;
               }

               if (lastDisposalMethod === 2) {
                   // Restore to background color
                   // Browser implementations historically restore to transparent; we do the same.
                   // http://www.wizards-toolkit.org/discourse-server/viewtopic.php?f=1&t=21172#p86079
                   frame.clearRect(lastImg.leftPos, lastImg.topPos, lastImg.width, lastImg.height);
               }
           }
           // else, Undefined/Do not dispose.
           // frame contains final pixel data from the last frame; do nothing

           //Get existing pixels for img region after applying disposal method
           var imgData = frame.getImageData(img.leftPos, img.topPos, img.width, img.height);

           //apply color table colors
           img.pixels.forEach(function (pixel, i) {
               // imgData.data === [R,G,B,A,R,G,B,A,...]
               if (pixel !== transparency) {
                   imgData.data[i * 4 + 0] = ct[pixel][0];
                   imgData.data[i * 4 + 1] = ct[pixel][1];
                   imgData.data[i * 4 + 2] = ct[pixel][2];
                   imgData.data[i * 4 + 3] = 255; // Opaque.
               }
           });

           frame.putImageData(imgData, img.leftPos, img.topPos);

           if (!ctx_scaled) {
               ctx.scale(get_canvas_scale(),get_canvas_scale());
               ctx_scaled = true;
           }

           // We could use the on-page canvas directly, except that we draw a progress
           // bar for each image chunk (not just the final image).
           if (drawWhileLoading) {
               ctx.drawImage(tmpCanvas, 0, 0);
               drawWhileLoading = options.auto_play;
           }

           lastImg = img;
       };

       var player = (function () {
           var i = -1;
           var iterationCount = 0;

           var showingInfo = false;
           var pinned = false;

           /**
            * Gets the index of the frame "up next".
            * @returns {number}
            */
           var getNextFrameNo = function () {
               var delta = (forward ? 1 : -1);
               return (i + delta + frames.length) % frames.length;
           };

           var stepFrame = function (amount) { // XXX: Name is confusing.
               i = i + amount;

               putFrame();
           };

           var step = (function () {
               var stepping = false;

               var completeLoop = function () {
                   if (onEndListener !== null)
                       onEndListener(gif);
                   iterationCount++;

                   if (overrideLoopMode !== false || iterationCount < 0) {
                       doStep();
                   } else {
                       stepping = false;
                       playing = false;
                   }
               };

               var doStep = function () {
                   stepping = playing;
                   if (!stepping) return;

                   stepFrame(1);
                   var delay = frames[i].delay * 10;
                   if (!delay) delay = 100; // FIXME: Should this even default at all? What should it be?

                   var nextFrameNo = getNextFrameNo();
                   if (nextFrameNo === 0) {
                       delay += loopDelay;
                       setTimeout(completeLoop, delay);
                   } else {
                       setTimeout(doStep, delay);
                   }
               };

               return function () {
                   if (!stepping) setTimeout(doStep, 0);
               };
           }());

           var putFrame = function () {
               var offset;
               i = parseInt(i, 10);

               if (i > frames.length - 1){
                   i = 0;
               }

               if (i < 0){
                   i = 0;
               }

               offset = frameOffsets[i];

               tmpCanvas.getContext("2d").putImageData(frames[i].data, offset.x, offset.y);
               ctx.globalCompositeOperation = "copy";
               ctx.drawImage(tmpCanvas, 0, 0);
           };

           var play = function () {
               playing = true;
               step();
           };

           var pause = function () {
               playing = false;
           };


           return {
               init: function () {
                   if (loadError) return;

                   if ( ! (options.c_w && options.c_h) ) {
                       ctx.scale(get_canvas_scale(),get_canvas_scale());
                   }

                   if (options.auto_play) {
                       step();
                   }
                   else {
                       i = 0;
                       putFrame();
                   }
               },
               step: step,
               play: play,
               pause: pause,
               playing: playing,
               move_relative: stepFrame,
               current_frame: function() { return i; },
               length: function() { return frames.length },
               move_to: function ( frame_idx ) {
                   i = frame_idx;
                   putFrame();
               }
           }
       }());

       var doDecodeProgress = function (draw) {
           doShowProgress(stream.pos, stream.data.length, draw);
       };

       var doNothing = function () {};
       /**
        * @param{boolean=} draw Whether to draw progress bar or not; this is not idempotent because of translucency.
        *                       Note that this means that the text will be unsynchronized with the progress bar on non-frames;
        *                       but those are typically so small (GCE etc.) that it doesn't really matter. TODO: Do this properly.
        */
       var withProgress = function (fn, draw) {
           return function (block) {
               fn(block);
               doDecodeProgress(draw);
           };
       };


       var handler = {
           hdr: withProgress(doHdr),
           gce: withProgress(doGCE),
           com: withProgress(doNothing),
           // I guess that's all for now.
           app: {
               // TODO: Is there much point in actually supporting iterations?
               NETSCAPE: withProgress(doNothing)
           },
           img: withProgress(doImg, true),
           eof: function (block) {
               //toolbar.style.display = '';
               pushFrame();
               doDecodeProgress(false);
               if ( ! (options.c_w && options.c_h) ) {
                   canvas.width = hdr.width * get_canvas_scale();
                   canvas.height = hdr.height * get_canvas_scale();
               }
               player.init();
               loading = false;
               if (load_callback) {
                   load_callback(gif);
               }

           }
       };

       var init = function () {
           var parent = gif.parentNode;

           var div = document.createElement('div');
           canvas = document.createElement('canvas');
           ctx = canvas.getContext('2d');
           toolbar = document.createElement('div');

           tmpCanvas = document.createElement('canvas');

           div.width = canvas.width = gif.width;
           div.height = canvas.height = gif.height;
           toolbar.style.minWidth = gif.width + 'px';

           div.className = 'jsgif';
           toolbar.className = 'jsgif_toolbar';
           div.appendChild(canvas);
           div.appendChild(toolbar);

           parent.insertBefore(div, gif);
           parent.removeChild(gif);

           if (options.c_w && options.c_h) setSizes(options.c_w, options.c_h);
           initialized=true;
       };

       var get_canvas_scale = function() {
           var scale;
           if (options.max_width && hdr && hdr.width > options.max_width) {
               scale = options.max_width / hdr.width;
           }
           else {
               scale = 1;
           }
           return scale;
       }

       var canvas, ctx, toolbar, tmpCanvas;
       var initialized = false;
       var load_callback = false;

       var load_setup = function(callback) {
           if (loading) return false;
           if (callback) load_callback = callback;
           else load_callback = false;

           loading = true;
           frames = [];
           clear();
           disposalRestoreFromIdx = null;
           lastDisposalMethod = null;
           frame = null;
           lastImg = null;

           return true;
       }

       var calculateDuration = function() {
           return frames.reduce(function(duration, frame) {
               return duration + frame.delay;
           }, 0);
       }

       return {
           // play controls
           play: player.play,
           pause: player.pause,
           move_relative: player.move_relative,
           move_to: player.move_to,

           // getters for instance vars
           get_playing      : function() { return playing },
           get_canvas       : function() { return canvas },
           get_canvas_scale : function() { return get_canvas_scale() },
           get_loading      : function() { return loading },
           get_auto_play    : function() { return options.auto_play },
           get_length       : function() { return player.length() },
           get_frames       : function() { return frames },
           get_duration     : function() { return calculateDuration() },
           get_duration_ms  : function() { return calculateDuration() * 10 },
           get_current_frame: function() { return player.current_frame() },
           load_url: function(src,callback){
               if (!load_setup(callback)) return;

               var h = new XMLHttpRequest();
               // new browsers (XMLHttpRequest2-compliant)
               h.open('GET', src, true);

               if ('overrideMimeType' in h) {
                   h.overrideMimeType('text/plain; charset=x-user-defined');
               }

               // old browsers (XMLHttpRequest-compliant)
               else if ('responseType' in h) {
                   h.responseType = 'arraybuffer';
               }

               // IE9 (Microsoft.XMLHTTP-compliant)
               else {
                   h.setRequestHeader('Accept-Charset', 'x-user-defined');
               }

               h.onloadstart = function() {
                   // Wait until connection is opened to replace the gif element with a canvas to avoid a blank img
                   if (!initialized) init();
               };
               h.onload = function(e) {
                   if (this.status != 200) {
                       doLoadError('xhr - response');
                   }
                   // emulating response field for IE9
                   if (!('response' in this)) {
                       this.response = new VBArray(this.responseText).toArray().map(String.fromCharCode).join('');
                   }
                   var data = this.response;
                   if (data.toString().indexOf("ArrayBuffer") > 0) {
                       data = new Uint8Array(data);
                   }

                   stream = new Stream(data);
                   setTimeout(doParse, 0);
               };
               h.onprogress = function (e) {
                   if (e.lengthComputable) doShowProgress(e.loaded, e.total, true);
               };
               h.onerror = function() { doLoadError('xhr'); };
               h.send();
           },
           load: function (callback) {
               this.load_url(gif.getAttribute('rel:animated_src') || gif.src,callback);
           },
           load_raw: function(arr, callback) {
               if (!load_setup(callback)) return;
               if (!initialized) init();
               stream = new Stream(arr);
               setTimeout(doParse, 0);
           },
           set_frame_offset: setFrameOffset
       };
   };

   return SuperGif;
}));


/***/ })

/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/ 
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ 	// Check if module is in cache
/******/ 	var cachedModule = __webpack_module_cache__[moduleId];
/******/ 	if (cachedModule !== undefined) {
/******/ 		return cachedModule.exports;
/******/ 	}
/******/ 	// Create a new module (and put it into the cache)
/******/ 	var module = __webpack_module_cache__[moduleId] = {
/******/ 		// no module.id needed
/******/ 		// no module.loaded needed
/******/ 		exports: {}
/******/ 	};
/******/ 
/******/ 	// Execute the module function
/******/ 	__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ 
/******/ 	// Return the exports of the module
/******/ 	return module.exports;
/******/ }
/******/ 
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ 	// define getter functions for harmony exports
/******/ 	__webpack_require__.d = (exports, definition) => {
/******/ 		for(var key in definition) {
/******/ 			if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 				Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 			}
/******/ 		}
/******/ 	};
/******/ })();
/******/ 
/******/ /* webpack/runtime/global */
/******/ (() => {
/******/ 	__webpack_require__.g = (function() {
/******/ 		if (typeof globalThis === 'object') return globalThis;
/******/ 		try {
/******/ 			return this || new Function('return this')();
/******/ 		} catch (e) {
/******/ 			if (typeof window === 'object') return window;
/******/ 		}
/******/ 	})();
/******/ })();
/******/ 
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ 	__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/ 
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
(() => {

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  Z: () => (/* binding */ x_ite)
});

;// CONCATENATED MODULE: ./src/x_ite/Namespace.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

const Namespace = new Map ();

Object .defineProperty (Namespace, "add",
{
   value (name, path, module)
   {
      if (Namespace .hasOwnProperty (name))
      {
         // if (!path .match (/\/components\/\w+$/i))
         //    console .warn (`Module ${name} (${path}) already defined.`);
      }
      else
      {
         const X3D = window [Symbol .for ("X_ITE.X3D-8.12.5")];

         if (X3D)
            X3D [name] = module;

         Namespace [name] = module;
      }

      Namespace .set (path, module);
   },
});

Namespace .add ("Namespace", "x_ite/Namespace", Namespace);

/* harmony default export */ const x_ite_Namespace = (Namespace);

;// CONCATENATED MODULE: ./src/x_ite/Base/X3DConstants.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

let
   BROWSER_EVENT = 0,
   LOAD_STATE    = 0,
   FIELD_TYPE    = 0,
   NODE_TYPE     = 0;

const X3DConstants =
{
   // Browser event

   CONNECTION_ERROR:  BROWSER_EVENT ++,
   BROWSER_EVENT:     BROWSER_EVENT ++,
   INITIALIZED_EVENT: BROWSER_EVENT ++,
   SHUTDOWN_EVENT:    BROWSER_EVENT ++,
   INITIALIZED_ERROR: BROWSER_EVENT ++,

   // Load state

   NOT_STARTED_STATE: LOAD_STATE ++,
   IN_PROGRESS_STATE: LOAD_STATE ++,
   COMPLETE_STATE:    LOAD_STATE ++,
   FAILED_STATE:      LOAD_STATE ++,

   // Access type

   initializeOnly: 0b001,
   inputOnly:      0b010,
   outputOnly:     0b100,
   inputOutput:    0b111,

   // X3DField

   SFBool:      FIELD_TYPE ++,
   SFColor:     FIELD_TYPE ++,
   SFColorRGBA: FIELD_TYPE ++,
   SFDouble:    FIELD_TYPE ++,
   SFFloat:     FIELD_TYPE ++,
   SFImage:     FIELD_TYPE ++,
   SFInt32:     FIELD_TYPE ++,
   SFMatrix3d:  FIELD_TYPE ++,
   SFMatrix3f:  FIELD_TYPE ++,
   SFMatrix4d:  FIELD_TYPE ++,
   SFMatrix4f:  FIELD_TYPE ++,
   SFNode:      FIELD_TYPE ++,
   SFRotation:  FIELD_TYPE ++,
   SFString:    FIELD_TYPE ++,
   SFTime:      FIELD_TYPE ++,
   SFVec2d:     FIELD_TYPE ++,
   SFVec2f:     FIELD_TYPE ++,
   SFVec3d:     FIELD_TYPE ++,
   SFVec3f:     FIELD_TYPE ++,
   SFVec4d:     FIELD_TYPE ++,
   SFVec4f:     FIELD_TYPE ++,

   VrmlMatrix:  FIELD_TYPE ++,

   // X3DArrayField

   MFBool:      FIELD_TYPE ++,
   MFColor:     FIELD_TYPE ++,
   MFColorRGBA: FIELD_TYPE ++,
   MFDouble:    FIELD_TYPE ++,
   MFFloat:     FIELD_TYPE ++,
   MFImage:     FIELD_TYPE ++,
   MFInt32:     FIELD_TYPE ++,
   MFMatrix3d:  FIELD_TYPE ++,
   MFMatrix3f:  FIELD_TYPE ++,
   MFMatrix4d:  FIELD_TYPE ++,
   MFMatrix4f:  FIELD_TYPE ++,
   MFNode:      FIELD_TYPE ++,
   MFRotation:  FIELD_TYPE ++,
   MFString:    FIELD_TYPE ++,
   MFTime:      FIELD_TYPE ++,
   MFVec2d:     FIELD_TYPE ++,
   MFVec2f:     FIELD_TYPE ++,
   MFVec3d:     FIELD_TYPE ++,
   MFVec3f:     FIELD_TYPE ++,
   MFVec4d:     FIELD_TYPE ++,
   MFVec4f:     FIELD_TYPE ++,

   // Abstract nodes and nodes types are added later.

   X3DBaseNode: NODE_TYPE,

   [Symbol .toStringTag]: "X3DConstants",
};

Object .defineProperty (X3DConstants, "addNode",
{
   value ({ typeName })
   {
      if (this .hasOwnProperty (typeName))
         return;

      this [typeName] = ++ NODE_TYPE;
   },
});

const __default__ = X3DConstants;
;

x_ite_Namespace .add ("X3DConstants", "x_ite/Base/X3DConstants", __default__);
/* harmony default export */ const Base_X3DConstants = (__default__);
;// CONCATENATED MODULE: ./src/standard/Math/Algorithm.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

const Algorithm =
{
   radians (value)
   {
      return value * (Math .PI / 180);
   },
   degrees (value)
   {
      return value * (180 / Math .PI);
   },
   random (min, max)
   {
      return min + Math .random () * (max - min);
   },
   fract (value)
   {
      return value % 1;
   },
   clamp (value, min, max)
   {
      // https://registry.khronos.org/OpenGL-Refpages/gl4/html/clamp.xhtml
      return Math .min (Math .max (value, min), max);
   },
   interval (value, low, high)
   {
      if (value >= high)
         return ((value - low) % (high - low)) + low;

      if (value < low)
         return ((value - high) % (high - low)) + high;

      return value;
   },
   roundToMultiple (value, multiple)
   {
      return Math .ceil (value / multiple) * multiple;
   },
   lerp (source, destination, t)
   {
      return source + t * (destination - source);
   },
   slerp (source, destination, t)
   {
      let cosom = source .dot (destination);

      // if (cosom <= -1) ... vectors are inverse colinear.

      if (cosom >= 1) // Both normal vectors are equal.
         return source;

      if (cosom < 0)
      {
         // Reverse signs so we travel the short way round.
         cosom = -cosom;
         destination .negate ();
      }

      const
         omega  = Math .acos (cosom),
         sinom  = Math .sin  (omega),
         scale0 = Math .sin ((1 - t) * omega) / sinom,
         scale1 = Math .sin (t * omega) / sinom;

      source .x = source .x * scale0 + destination .x * scale1;
      source .y = source .y * scale0 + destination .y * scale1;
      source .z = source .z * scale0 + destination .z * scale1;
      source .w = source .w * scale0 + destination .w * scale1;

      return source;
   },
   simpleSlerp (source, destination, t)
   {
      const cosom = source .dot (destination);

      // if (cosom <= -1) ... vectors are inverse colinear.

      if (cosom >= 1) // Both normal vectors are equal.
         return source;

      const
         omega  = Math .acos (cosom),
         sinom  = Math .sin  (omega),
         scale0 = Math .sin ((1 - t) * omega) / sinom,
         scale1 = Math .sin (t * omega) / sinom;

      source .x = source .x * scale0 + destination .x * scale1;
      source .y = source .y * scale0 + destination .y * scale1;
      source .z = source .z * scale0 + destination .z * scale1;
      source .w = source .w * scale0 + destination .w * scale1;

      return source;
   },
   isPowerOfTwo (n)
   {
      return ((n - 1) & n) === 0;
   },
   nextPowerOfTwo (n)
   {
      ///  Returns the next power of two of @a n. If n is a power of two, n is returned.

      if (Algorithm .isPowerOfTwo (n))
         return n;

      return 1 << (32 - Math .clz32 (n));
   },
   bitCount (n)
   {
      n = n - ((n >>> 1) & 0x55555555);
      n = (n & 0x33333333) + ((n >>> 2) & 0x33333333);
      return ((n + (n >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24;
   },
   cmp (lhs, rhs)
   {
      return lhs > rhs ? 1 : lhs < rhs ? -1 : 0;
   },
   // lexicographicallyCompare (lhs, rhs)
   // {
   //    const
   //       length1 = lhs .length,
   //       length2 = rhs .length;

   //    for (let i = 0; i < length1 && i < length2; ++ i)
   //    {
   //       if (lhs [i] < rhs [i])
   //          return -1;

   //       if (rhs [i] < lhs [i])
   //          return 1;
   //    }

   //    return Algorithm .cmp (length1, length2);
   // },
   less (lhs, rhs)
   {
      return lhs < rhs;
   },
   greater (lhs, rhs)
   {
      return lhs > rhs;
   },
   lowerBound (array, first, last, value, comp = Algorithm.less)
   {
      // https://en.cppreference.com/w/cpp/algorithm/lower_bound

      let
         index = 0,
         step  = 0,
         count = last - first;

      while (count > 0)
      {
         step  = count >>> 1;
         index = first + step;

         if (comp (array [index], value))
         {
            first  = ++ index;
            count -= step + 1;
         }
         else
            count = step;
      }

      return first;
   },
   upperBound (array, first, last, value, comp = Algorithm.less)
   {
      // sen.cppreference.com/w/cpp/algorithm/upper_bound

      let
         index = 0,
         step  = 0,
         count = last - first;

      while (count > 0)
      {
         step  = count >>> 1;
         index = first + step;

         if (comp (value, array [index]))
            count = step;

         else
         {
            first  = ++ index;
            count -= step + 1;
         }
      }

      return first;
   },
};

const Algorithm_default_ = Algorithm;
;

x_ite_Namespace .add ("Algorithm", "standard/Math/Algorithm", Algorithm_default_);
/* harmony default export */ const Math_Algorithm = (Algorithm_default_);
;// CONCATENATED MODULE: ./src/x_ite/InputOutput/Generator.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function Generator ({ style = "TIDY", indent = "", precision = 7, doublePrecision = 15, html = false, closingTags = false })
{
   this .string          = "";
   this .indent          = indent;
   this .listIndent      = indent;
   this .precision       = Math_Algorithm .clamp (precision, 1, 21);
   this .doublePrecision = Math_Algorithm .clamp (doublePrecision, 1, 21);
   this .html            = html;
   this .closingTags     = html || closingTags;

   this .floatFormat = new Intl .NumberFormat ("en", {
      notation: "standard",
      maximumSignificantDigits: this .precision,
      useGrouping: false,
   }) .format;

   this .floatExponentialFormat = new Intl .NumberFormat ("en", {
      notation: "scientific",
      maximumSignificantDigits: this .precision,
      useGrouping: false,
   }) .format;

   this .doubleFormat = new Intl .NumberFormat ("en", {
      notation: "standard",
      maximumSignificantDigits: this .doublePrecision,
      useGrouping: false,
   }) .format;

   this .doubleExponentialFormat = new Intl .NumberFormat ("en", {
      notation: "scientific",
      maximumSignificantDigits: this .doublePrecision,
      useGrouping: false,
   }) .format;

   this .Style (style);

   this .executionContextStack = [ ];
   this .importedNodesIndex    = new Map ();
   this .exportedNodesIndex    = new Map ();
   this .nodes                 = new Set ();
   this .names                 = new Map ();
   this .namesByNode           = new Map ();
   this .importedNames         = new Map ();
   this .routeNodes            = new Set ();
   this .level                 = 0;
   this .containerFields       = [ ];
   this .units                 = true;
   this .unitCategories        = [ ];

   this .PushExecutionContext (null);
}

Object .assign (Generator .prototype,
{
   Style (style)
   {
      switch (style)
      {
         case "CLEAN":
         {
            this .listIndent = "";

            this .comma          = " ";
            this .break          = " ";
            this .tidyBreak      = "";
            this .tidySpace      = "";
            this .indentChar     = "";
            this .listEnclosure  = "";
            this .listBreak      = "";
            this .listIndentChar = "";
            this .attribBreak    = " ";
            break;
         }
         case "SMALL":
         {
            this .listIndent = "";

            this .comma          = ",";
            this .break          = "\n";
            this .tidyBreak      = "\n";
            this .tidySpace      = "";
            this .indentChar     = "";
            this .listEnclosure  = "";
            this .listBreak      = "";
            this .listIndentChar = "";
            this .attribBreak    = " ";
            break;
         }
         case "COMPACT":
         {
            this .listIndent = "";

            this .comma          = ",";
            this .break          = "\n";
            this .tidyBreak      = "\n";
            this .tidySpace      = " ";
            this .indentChar     = "  ";
            this .listEnclosure  = " ";
            this .listBreak      = " ";
            this .listIndentChar = "";
            this .attribBreak    = " ";
            break;
         }
         case "TIDY":
         default:
         {
            this .comma          = ",";
            this .break          = "\n";
            this .tidyBreak      = "\n";
            this .tidySpace      = " ";
            this .indentChar     = "  ";
            this .listEnclosure  = "\n";
            this .listBreak      = "\n";
            this .listIndentChar = "  ";
            this .attribBreak    = "\n";
            break;
         }
      }
   },
   Comma ()
   {
      return this .comma;
   },
   Break ()
   {
      return this .break;
   },
   TidyBreak ()
   {
      return this .tidyBreak;
   },
   ForceBreak ()
   {
      return "\n";
   },
   Space ()
   {
      return " ";
   },
   TidySpace ()
   {
      return this .tidySpace;
   },
   ListStart ()
   {
      return this .listEnclosure;
   },
   ListEnd ()
   {
      return this .listEnclosure;
   },
   ListBreak ()
   {
      return this .listBreak;
   },
   AttribBreak ()
   {
      return this .attribBreak;
   },
   Indent ()
   {
      return this .indent;
   },
   ListIndent ()
   {
      return this .listIndent;
   },
   IncIndent ()
   {
      this .indent     += this .indentChar;
      this .listIndent += this .listIndentChar;

      return "";
   },
   DecIndent ()
   {
      this .indent     = this .indent     .slice (0, this .indent     .length - this .indentChar     .length);
      this .listIndent = this .listIndent .slice (0, this .listIndent .length - this .listIndentChar .length);

      return "";
   },
   FloatFormat  (value)
   {
      if (Number .isFinite (value))
      {
         const exponent = Math .log10 (Math .abs (value));

         if ((this .precision > exponent && exponent >= -4) || value === 0)
            return this .floatFormat (value);

         return this .floatExponentialFormat (value) .toLowerCase ();
      }
      else
      {
         return String (value);
      }
   },
   DoubleFormat  (value)
   {
      if (Number .isFinite (value))
      {
         const exponent = Math .log10 (Math .abs (value));

         if ((this .doublePrecision > exponent && exponent >= -4) || value === 0)
            return this .doubleFormat (value);

         return this .doubleExponentialFormat (value) .toLowerCase ();
      }
      else
      {
         return String (value);
      }
   },
   PushExecutionContext (executionContext)
   {
      this .executionContextStack .push (executionContext);

      if (!this .names .has (executionContext))
         this .names .set (executionContext, Object .assign (new Set (), { index: 0 }));

      if (!this .importedNodesIndex .has (executionContext))
         this .importedNodesIndex .set (executionContext, new Set ());

      if (!this .exportedNodesIndex .has (executionContext))
         this .exportedNodesIndex .set (executionContext, new Set ());
   },
   PopExecutionContext ()
   {
      this .executionContextStack .pop ();

      if (this .ExecutionContext ())
         return;

      this .importedNodesIndex .clear ();
      this .exportedNodesIndex .clear ();
   },
   ExecutionContext ()
   {
      return this .executionContextStack .at (-1);
   },
   EnterScope ()
   {
      ++ this .level;
   },
   LeaveScope ()
   {
      -- this .level;

      if (this .level === 0)
      {
         this .nodes         .clear ();
         this .namesByNode   .clear ();
         this .importedNames .clear ();
      }
   },
   NamedNodes (namedNodes)
   {
      const
         names       = this .names .get (this .ExecutionContext ()),
         namesByNode = this .namesByNode;

      for (const node of namedNodes)
      {
         if (node .getNodeName () .match (/^_\d+$/))
            continue;

         names .add (node .getNodeName ());
         namesByNode .set (node .getValue (), node .getNodeName ())
      }
   },
   ExportedNodes (exportedNodes)
   {
      const index = this .exportedNodesIndex .get (this .ExecutionContext ());

      for (const exportedNode of exportedNodes)
         index .add (exportedNode .getLocalNode ())
   },
   ImportedNodes (importedNodes)
   {
      const index = this .importedNodesIndex .get (this .ExecutionContext ());

      for (const importedNode of importedNodes)
      {
         try
         {
            index .add (importedNode .getInlineNode ());
         }
         catch
         { }
      }
   },
   AddImportedNode (exportedNode, importedName)
   {
      this .importedNames .set (exportedNode, importedName);
   },
   AddRouteNode (routeNode)
   {
      this .routeNodes .add (routeNode);
   },
   ExistsRouteNode (routeNode)
   {
      return this .namesByNode .get (routeNode) || this .routeNodes .has (routeNode);
   },
   IsSharedNode (baseNode)
   {
      return this .ExecutionContext () !== baseNode .getExecutionContext ();
   },
   AddNode (baseNode)
   {
      this .nodes .add (baseNode);

      this .AddRouteNode (baseNode);
   },
   ExistsNode (baseNode)
   {
      return this .nodes .has (baseNode);
   },
   Name (baseNode)
   {
      // Is the node already in index.

      const name = this .namesByNode .get (baseNode);

      if (name !== undefined)
      {
         return name;
      }
      else
      {
         const names = this .names .get (this .ExecutionContext ());

         // The node has no name.

         if (!this .NeedsName (baseNode))
            return "";

         const newName = `_${++ names .index}`;

         // Add to indices.

         names .add (newName);
         this .namesByNode .set (baseNode, newName);

         return newName;
      }
   },
   NeedsName (baseNode)
   {
      if (baseNode .getCloneCount () > 1)
         return true;

      if (baseNode .hasRoutes ())
         return true;

      const
         executionContext = baseNode .getExecutionContext (),
         index            = this .importedNodesIndex .get (executionContext);

      if (index)
      {
         if (index .has (baseNode))
            return true;
      }
      else
      {
         const index = this .exportedNodesIndex .get (executionContext);

         if (index)
         {
            if (index .has (baseNode))
               return true;
         }

         return false;
      }
   },
   LocalName (baseNode)
   {
      const importedName = this .importedNames .get (baseNode);

      if (importedName !== undefined)
         return importedName;

      if (this .ExistsNode (baseNode))
         return this .Name (baseNode);

      throw new Error (`Couldn't get local name for node '${baseNode .getTypeName ()}'.`);
   },
   PushContainerField (field)
   {
      this .containerFields .push (field);
   },
   PopContainerField ()
   {
      this .containerFields .pop ();
   },
   ContainerField ()
   {
      if (this .containerFields .length)
         return this .containerFields [this .containerFields .length - 1];

      return null;
   },
   AccessType (accessType)
   {
      switch (accessType)
      {
         case Base_X3DConstants .initializeOnly:
            return "initializeOnly";
         case Base_X3DConstants .inputOnly:
            return "inputOnly";
         case Base_X3DConstants .outputOnly:
            return "outputOnly";
         case Base_X3DConstants .inputOutput:
            return "inputOutput";
      }
   },
   SetUnits (value)
   {
      this .units = value;
   },
   GetUnits ()
   {
      return this .units;
   },
   PushUnitCategory (category)
   {
      this .unitCategories .push (category);
   },
   PopUnitCategory ()
   {
      this .unitCategories .pop ();
   },
   Unit (category)
   {
      if (this .unitCategories .length == 0)
         return category;

      return this .unitCategories .at (-1);
   },
   ToUnit (category, value)
   {
      if (this .units)
      {
         const executionContext = this .ExecutionContext ();

         if (executionContext)
            return executionContext .toUnit (category, value);
      }

      return value;
   },
   XMLEncode: (() =>
   {
      const map = {
         "\\": "\\\\",
         "\r": "&#xD;",
         "\n": "&#xA;",
         "\t": "&#x9;",
         "\"": "\\\"",
         "'": "&apos;",
         "<": "&lt;",
         ">": "&gt;",
         "&": "&amp;",
      };

      const regex = /([\\\r\n\t"'<>&])/g;

      return function (string)
      {
         return string .replace (regex, char => map [char]);
      };
   })(),
   XMLEncodeSourceText: (() =>
   {
      const map = {
         "\\": "\\\\",
         "\"": "\\\"",
         "'": "&apos;",
         "<": "&lt;",
         ">": "&gt;",
         "&": "&amp;",
      };

      const regex = /([\\"'<>&])/g;

      return function (string)
      {
         return string .replace (regex, char => map [char]);
      };
   })(),
   JSONEncode: (() =>
   {
      const map = {
         "\\": "\\\\",
         "\r": "\\r",
         "\n": "\\n",
         "\t": "\\t",
         "\"": "\\\"",
      };

      const regex = /([\\\t\n\r"])/g;

      return function (string)
      {
         return string .replace (regex, char => map [char]);
      };
   })(),
   JSONNumber (value)
   {
      switch (value)
      {
         case "NaN":
         case "Infinity":
         case "-Infinity":
            return '"' + value + '"';
         default:
            return value;
      }
   },
   JSONRemoveComma ()
   {
      // this .string = this .string .replace (/,(\s*)$/s, "$1");

      this .string = this .string .trimEnd ();

      if (this .string .endsWith (','))
         this .string = this .string .slice (0, -1);

      this .string += this .TidyBreak ();
   },
});

for (const key of Object .keys (Generator .prototype))
   Object .defineProperty (Generator .prototype, key, { enumerable: false });

const Generator_default_ = Generator;
;

x_ite_Namespace .add ("Generator", "x_ite/InputOutput/Generator", Generator_default_);
/* harmony default export */ const InputOutput_Generator = (Generator_default_);
;// CONCATENATED MODULE: ./src/standard/Utility/MapUtilities.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

const MapUtilities =
{
   assign: (() =>
   {
      function callback (value, key)
      {
         this .set (key, value);
      }

      return function (m1, m2)
      {
         m1 .clear ();
         m2 .forEach (callback, m1);

         return m1;
      };
   })(),
   values: (() =>
   {
      function callback (value)
      {
         this .push (value);
      }

      return function (a, m)
      {
         a .length = 0;

         m .forEach (callback, a);

         return a;
      };
   })(),
};

const MapUtilities_default_ = MapUtilities;
;

x_ite_Namespace .add ("MapUtilities", "standard/Utility/MapUtilities", MapUtilities_default_);
/* harmony default export */ const Utility_MapUtilities = (MapUtilities_default_);
;// CONCATENATED MODULE: ./src/x_ite/DEVELOPMENT.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

// Modified during dist build.

const DEVELOPMENT_default_ = false;
;

x_ite_Namespace .add ("DEVELOPMENT", "x_ite/DEVELOPMENT", DEVELOPMENT_default_);
/* harmony default export */ const DEVELOPMENT = (DEVELOPMENT_default_);
;// CONCATENATED MODULE: ./src/x_ite/Base/X3DObject.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





const
   _name      = Symbol (),
   _interests = Symbol (),
   _values    = Symbol (),
   _userData  = Symbol ();

function X3DObject () { }

Object .assign (X3DObject .prototype,
{
   [_name]: "",
   [_interests]: new Map (),
   [_values]: [ ],
   [_userData]: new Map (),
   getId ()
   {
      return X3DObject .getId (this);
   },
   getTypeName ()
   {
      return this .constructor .typeName;
   },
   setName (value)
   {
      this [_name] = value;
   },
   getName ()
   {
      return this [_name];
   },
   getDisplayName ()
   {
      return this [_name];
   },
   hasInterest (callbackName, object)
   {
      return this [_interests] .has (X3DObject .getInterestId (callbackName, object));
   },
   addInterest (callbackName, object, ... args)
   {
      if (this [_interests] === X3DObject .prototype [_interests])
      {
         this [_interests] = new Map ();
         this [_values]    = [ ];
      }

      const
         interestId = X3DObject .getInterestId (callbackName, object),
         callback   = object [callbackName];

      this [_interests] .set (interestId, callback .bind (object, ... args, this));
   },
   removeInterest (callbackName, object)
   {
      this [_interests] .delete (X3DObject .getInterestId (callbackName, object));
   },
   getInterests ()
   {
      return this [_interests];
   },
   processInterests ()
   {
      if (this [_interests] .size)
      {
         for (const interest of Utility_MapUtilities .values (this [_values], this [_interests]))
            interest ();
      }
   },
   getUserData (key)
   {
      return this [_userData] .get (key)
         ?? this [_userData] .map ?.get (key);
   },
   setUserData (key, value)
   {
      try
      {
         if (this [_userData] === X3DObject .prototype [_userData])
            this [_userData] = new WeakMap ();

         this [_userData] .set (key, value);
      }
      catch
      {
         if (!this [_userData] .map)
            this [_userData] .map = new Map ();

         this [_userData] .map .set (key, value);
      }
   },
   removeUserData (key)
   {
      if (this [_userData] .delete (key))
         return;

      this [_userData] .map ?.delete (key);
   },
   toString (options = Object .prototype)
   {
      const generator = new InputOutput_Generator (options);

      if (options .scene)
         generator .PushExecutionContext (options .scene);

      this .toStream (generator);

      return generator .string;
   },
   toVRMLString (options = Object .prototype)
   {
      const generator = new InputOutput_Generator (options);

      if (options .scene)
         generator .PushExecutionContext (options .scene);

      this .toVRMLStream (generator);

      return generator .string;
   },
   toXMLString (options = Object .prototype)
   {
      const generator = new InputOutput_Generator (options);

      if (options .scene)
         generator .PushExecutionContext (options .scene);

      this .toXMLStream (generator);

      return generator .string;
   },
   toJSONString (options = Object .prototype)
   {
      const generator = new InputOutput_Generator (options);

      if (options .scene)
         generator .PushExecutionContext (options .scene);

      this .toJSONStream (generator);

      return generator .string;
   },
   toStream (generator)
   {
      generator .string = Object .prototype .toString .call (this);
   },
   dispose ()
   {
      this [_interests] .clear ();
      this [_userData] .map ?.clear ();
   },
});

for (const key of Object .keys (X3DObject .prototype))
   Object .defineProperty (X3DObject .prototype, key, { enumerable: false });

Object .defineProperties (X3DObject .prototype,
{
   [Symbol .toStringTag]:
   {
      get () { return this .getTypeName (); },
   },
});

Object .assign (X3DObject,
{
   getId: DEVELOPMENT ? (() =>
   {
      const
         map      = new WeakMap (),
         cache    = [ ],
         registry = new FinalizationRegistry (id => cache .push (id));

      let counter = BigInt (0);

      return function (object)
      {
         const id = map .get (object);

         if (id !== undefined)
         {
            return id;
         }
         else
         {
            const id = cache .pop () ?? ++ counter;

            map .set (object, id);
            registry .register (object, id);

            return id;
         }
      };
   })() : (() =>
   {
      const map = new WeakMap ();

      let counter = 0;

      return function (object)
      {
         const id = map .get (object);

         if (id !== undefined)
            return id;

         map .set (object, ++ counter);

         return counter;
      };
   })(),
   getInterestId (callbackName, object)
   {
      return `${this .getId (object)}.${this .getId (object [callbackName])}`;
   },
});

const X3DObject_default_ = X3DObject;
;

x_ite_Namespace .add ("X3DObject", "x_ite/Base/X3DObject", X3DObject_default_);
/* harmony default export */ const Base_X3DObject = (X3DObject_default_);
;// CONCATENATED MODULE: ./src/x_ite/Base/X3DChildObject.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




const
   _modificationTime = Symbol (),
   _tainted          = Symbol (),
   _parents          = Symbol (),
   _registry         = Symbol ();

function X3DChildObject ()
{
   Base_X3DObject .call (this);
}

if (DEVELOPMENT)
{
   Object .assign (Object .setPrototypeOf (X3DChildObject .prototype, Base_X3DObject .prototype),
   {
      [_modificationTime]: 0,
      [_tainted]: false,
      [_parents]: new Map (),
      [_registry]: new FinalizationRegistry (Function .prototype),
      isInitializable ()
      {
         return true;
      },
      isInput ()
      {
         return false;
      },
      isOutput ()
      {
         return false;
      },
      setModificationTime (value)
      {
         this [_modificationTime] = value;
      },
      getModificationTime ()
      {
         return this [_modificationTime];
      },
      setTainted (value)
      {
         this [_tainted] = value;
      },
      isTainted ()
      {
         return this [_tainted];
      },
      addEvent ()
      {
         this .setModificationTime (Date .now ());

         for (const parent of this [_parents] .values ())
            parent .deref () ?.addEvent (this);
      },
      addEventObject (field, event)
      {
         this .setModificationTime (Date .now ());

         for (const parent of this [_parents] .values ())
            parent .deref () ?.addEventObject (this, event);
      },
      processEvent ()
      {
         this .setTainted (false);
         this .processInterests ();
      },
      collectCloneCount ()
      {
         let cloneCount = 0;

         for (const weakRef of this [_parents] .values ())
            cloneCount += weakRef .deref () ?.collectCloneCount ();

         return cloneCount;
      },
      addParent (parent)
      {
         if (this [_parents] === X3DChildObject .prototype [_parents])
         {
            this [_parents]  = new Map ();
            this [_registry] = new FinalizationRegistry (id =>
            {
               this [_parents] .delete (id);
               this .parentsChanged ();
            });
         }

         this [_parents] .set (parent .getId (), new WeakRef (parent));
         this [_registry] .register (parent, parent .getId (), parent);

         this .parentsChanged ();
      },
      removeParent (parent)
      {
         this [_parents] .delete (parent .getId ());
         this [_registry] .unregister (parent);

         this .parentsChanged ();
      },
      getParents ()
      {
         const parents = new Set ();

         for (const weakRef of this [_parents] .values ())
            parents .add (weakRef .deref ())

         parents .delete (undefined);

         return parents;
      },
      parentsChanged () { },
      dispose ()
      {
         this [_parents] .clear ();

         Base_X3DObject .prototype .dispose .call (this);
      },
   });
}
else
{
   Object .assign (Object .setPrototypeOf (X3DChildObject .prototype, Base_X3DObject .prototype),
   {
      [_modificationTime]: 0,
      [_tainted]: false,
      [_parents]: new Set (),
      isInitializable ()
      {
         return true;
      },
      isInput ()
      {
         return false;
      },
      isOutput ()
      {
         return false;
      },
      setModificationTime (value)
      {
         this [_modificationTime] = value;
      },
      getModificationTime ()
      {
         return this [_modificationTime];
      },
      setTainted (value)
      {
         this [_tainted] = value;
      },
      isTainted ()
      {
         return this [_tainted];
      },
      addEvent ()
      {
         this .setModificationTime (Date .now ());

         for (const parent of this [_parents])
            parent .addEvent (this);
      },
      addEventObject (field, event)
      {
         this .setModificationTime (Date .now ());

         for (const parent of this [_parents])
            parent .addEventObject (this, event);
      },
      processEvent ()
      {
         this .setTainted (false);
         this .processInterests ();
      },
      collectCloneCount ()
      {
         let cloneCount = 0;

         for (const parent of this [_parents])
            cloneCount += parent .collectCloneCount ();

         return cloneCount;
      },
      addParent (parent)
      {
         if (this [_parents] === X3DChildObject .prototype [_parents])
            this [_parents] = new Set ();

         this [_parents] .add (parent);

         this .parentsChanged ();
      },
      removeParent (parent)
      {
         this [_parents] .delete (parent);

         this .parentsChanged ();
      },
      getParents ()
      {
         return this [_parents];
      },
      parentsChanged () { },
      dispose ()
      {
         this [_parents] .clear ();

         Base_X3DObject .prototype .dispose .call (this);
      },
   });
}

for (const key of Object .keys (X3DChildObject .prototype))
   Object .defineProperty (X3DChildObject .prototype, key, { enumerable: false });

const X3DChildObject_default_ = X3DChildObject;
;

x_ite_Namespace .add ("X3DChildObject", "x_ite/Base/X3DChildObject", X3DChildObject_default_);
/* harmony default export */ const Base_X3DChildObject = (X3DChildObject_default_);
;// CONCATENATED MODULE: ./src/x_ite/Base/Events.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

const Events = Object .assign ([ ],
{
   create (field)
   {
      const event = this .pop () ?? new Set ();

      event .field = field;
      event .clear ();

      return event;
   },
   copy (event)
   {
      const copy = this .create (event .field);

      for (const source of event)
         copy .add (source);

      return copy;
   },
});

for (const key of Object .keys (Events))
   Object .defineProperty (Events, key, { enumerable: false });

const Events_default_ = Events;
;

x_ite_Namespace .add ("Events", "x_ite/Base/Events", Events_default_);
/* harmony default export */ const Base_Events = (Events_default_);
;// CONCATENATED MODULE: ./src/x_ite/Base/X3DFieldDefinition.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function X3DFieldDefinition (accessType, name, value)
{
   Object .defineProperties (this,
   {
      accessType: { value: accessType, enumerable: true },
      dataType: { value: value .getType (), enumerable: true },
      name: { value: name, enumerable: true },
      value: { value: value },
   });
}

Object .setPrototypeOf (X3DFieldDefinition .prototype, Base_X3DObject .prototype);

for (const key of Object .keys (X3DFieldDefinition .prototype))
   Object .defineProperty (X3DFieldDefinition .prototype, key, { enumerable: false });

Object .defineProperties (X3DFieldDefinition,
{
   typeName:
   {
      value: "X3DFieldDefinition",
      enumerable: true,
   },
});

const X3DFieldDefinition_default_ = X3DFieldDefinition;
;

x_ite_Namespace .add ("X3DFieldDefinition", "x_ite/Base/X3DFieldDefinition", X3DFieldDefinition_default_);
/* harmony default export */ const Base_X3DFieldDefinition = (X3DFieldDefinition_default_);
;// CONCATENATED MODULE: ./src/x_ite/Base/X3DInfoArray.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



const
   _array     = Symbol (),
   _index     = Symbol (),
   _valueType = Symbol ();

const handler =
{
   get (target, key)
   {
      const value = target [key];

      if (value !== undefined)
         return value;

      if (typeof key === "string")
      {
         const index = +key;

         if (Number .isInteger (index))
            return target [_array] [index];

         return;
      }
   },
   set (target, key, value)
   {
      if (target [key] === undefined)
         return false;

      target [key] = value;
      return true;
   },
   has (target, key)
   {
      if (Number .isInteger (+key))
         return key < target [_array] .length;

      return key in target;
   },
   ownKeys (target)
   {
      return Object .keys (target [_array]);
   },
   getOwnPropertyDescriptor (target, key)
   {
      if (typeof key !== "string")
         return;

      const index = +key;

      if (Number .isInteger (index) && index < target [_array] .length)
      {
         const propertyDescriptor = Object .getOwnPropertyDescriptor (target [_array], key);

         if (propertyDescriptor)
            propertyDescriptor .writable = false;

         return propertyDescriptor;
      }
   },
};

function X3DInfoArray (values, valueType)
{
   const proxy = new Proxy (this, handler);

   Base_X3DChildObject .call (this);

   this [_array]     = [ ];
   this [_index]     = new Map ();
   this [_valueType] = valueType;

   for (const [key, value] of values)
      this .add (key, value);

   return proxy;
}

Object .assign (Object .setPrototypeOf (X3DInfoArray .prototype, Base_X3DChildObject .prototype),
{
   *[Symbol .iterator] ()
   {
      yield* this [_array];
   },
   copy ()
   {
      const copy = new (this .constructor) ();

      copy .assign (this);

      return copy;
   },
   assign (array)
   {
      if (!(array instanceof this .constructor))
         throw new Error ("Couldn't assign info array, wrong type.");

      this [_array] = Array .from (array [_array]);
      this [_index] = new Map (array [_index]);

      this .addEvent ();
   },
   equals (array)
   {
      const
         a      = this [_array],
         b      = array [_array],
         length = a .length;

      if (a === b)
         return true;

      if (length !== b .length)
         return false;

      for (let i = 0; i < length; ++ i)
      {
         if (a [i] !== b [i])
            return false;
      }

      return true;
   },
   has (key)
   {
      return this [_index] .has (key);
   },
   get (key)
   {
      return this [_index] .get (key);
   },
   add (key, value)
   {
      if (this [_index] .has (key))
         throw new Error (`Couldn't add value to ${this .getTypeName ()}, key '${key}' already exists.`);

      if (!(value instanceof this [_valueType]))
         throw new Error (`Couldn't add value to ${this .getTypeName ()}, value for key '${key}' has wrong type.`);

      this [_array] .push (value);
      this [_index] .set (key, value);

      this .addEvent ();
   },
   alias (alias, value)
   {
      this [_index] .set (alias, value);

      this .addEvent ();
   },
   update (oldKey, newKey, value)
   {
      // TODO: update alias.

      if (!(value instanceof this [_valueType]))
         throw new Error (`Couldn't update value of ${this .getTypeName ()}, value for key '${key}' has wrong type.`);

      const oldValue = this [_index] .get (oldKey);

      if (oldKey !== newKey)
         this .remove (newKey);

      this [_index] .delete (oldKey);
      this [_index] .set (newKey, value);

      if (oldValue !== undefined)
      {
         const index = this [_array] .indexOf (oldValue);

         if (index > -1)
            this [_array] [index] = value;
      }
      else
      {
         this [_array] .push (value);
      }

      this .addEvent ();
   },
   remove (key)
   {
      // TODO: remove alias.

      const value = this [_index] .get (key);

      if (value === undefined)
         return;

      const index = this [_array] .indexOf (value);

      this [_index] .delete (key);

      if (index > -1)
         this [_array] .splice (index, 1);

      this .addEvent ();
   },
   at: Array .prototype .at,
   // concat: Array .prototype .concat,
   // copyWithin: Array.prototype.copyWithin,
   entries: Array .prototype .entries,
   every: Array .prototype .every,
   // fill: Array .prototype .fill,
   filter (callbackFn, thisArg)
   {
      return new (this .constructor) (Array .prototype .filter .call (this, callbackFn, thisArg));
   },
   find: Array .prototype .find,
   findIndex: Array .prototype .findIndex,
   findLast: Array .prototype .findLast,
   findLastIndex: Array .prototype .findLastIndex,
   // flat: Array .prototype .flat,
   // flatMap: Array .prototype .flatMap,
   forEach: Array .prototype .forEach,
   includes: Array .prototype .includes,
   indexOf: Array .prototype .indexOf,
   join: Array .prototype .join,
   keys: Array .prototype .keys,
   lastIndexOf: Array .prototype .lastIndexOf,
   map (callbackFn, thisArg)
   {
      return new (this .constructor) (Array .prototype .map .call (this, callbackFn, thisArg));
   },
   reduce: Array .prototype .reduce,
   reduceRight: Array .prototype .reduceRight,
   // reverse: Array .prototype .reverse,
   slice (start, end)
   {
      return new (this .constructor) (Array .prototype .slice .call (this, start, end));
   },
   some: Array .prototype .some,
   // sort: Array .prototype .sort,
   toReversed ()
   {
      return new (this .constructor) ([... this] .reverse ());
   },
   toSorted (compareFn)
   {
      return new (this .constructor) ([... this] .sort (compareFn));
   },
   toSpliced (start, deleteCount, ... insertValues)
   {
      const array = [... this];

      array .splice (start, deleteCount, ... insertValues)

      return new (this .constructor) (array);
   },
   values: Array .prototype .values,
   with (index, value)
   {
      const array = [... this];

      array [index] = value;

      return new (this .constructor) (array);
   },
   toVRMLStream (generator)
   {
      for (const value of this [_array])
      {
         try
         {
            value .toVRMLStream (generator);

            generator .string += generator .Break ();

            if (this .getTypeName () .match (/Proto/))
               generator .string += generator .TidyBreak ();
         }
         catch (error)
         {
            // console .error (error);
         }
      }
   },
   toXMLStream (generator)
   {
      for (const value of this [_array])
      {
         try
         {
            value .toXMLStream (generator);

            generator .string += generator .TidyBreak ();
         }
         catch (error)
         {
            // console .error (error);
         }
      }
   },
   toJSONStream (generator, comma)
   {
      let lastProperty = false;

      for (const value of this [_array])
      {
         try
         {
            value .toJSONStream (generator, true);

            generator .string += ',';
            generator .string += generator .TidyBreak ();

            lastProperty = true;
         }
         catch (error)
         {
            // console .error (error);
         }
      }

      if (lastProperty && !comma)
         generator .JSONRemoveComma ();

      return lastProperty;
   },
});

for (const key of Object .keys (X3DInfoArray .prototype))
   Object .defineProperty (X3DInfoArray .prototype, key, { enumerable: false });

Object .defineProperties (X3DInfoArray .prototype,
{
   length:
   {
      get () { return this [_array] .length; },
   },
});

const X3DInfoArray_default_ = X3DInfoArray;
;

x_ite_Namespace .add ("X3DInfoArray", "x_ite/Base/X3DInfoArray", X3DInfoArray_default_);
/* harmony default export */ const Base_X3DInfoArray = (X3DInfoArray_default_);
;// CONCATENATED MODULE: ./src/x_ite/Base/FieldDefinitionArray.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function FieldDefinitionArray (values = [ ])
{
   return Base_X3DInfoArray .call (this, Array .from (values, value => [value .name, value]), Base_X3DFieldDefinition);
}

Object .setPrototypeOf (FieldDefinitionArray .prototype, Base_X3DInfoArray .prototype);

for (const key of Object .keys (FieldDefinitionArray .prototype))
   Object .defineProperty (FieldDefinitionArray .prototype, key, { enumerable: false });

Object .defineProperties (FieldDefinitionArray,
{
   typeName:
   {
      value: "FieldDefinitionArray",
      enumerable: true,
   },
});

const FieldDefinitionArray_default_ = FieldDefinitionArray;
;

x_ite_Namespace .add ("FieldDefinitionArray", "x_ite/Base/FieldDefinitionArray", FieldDefinitionArray_default_);
/* harmony default export */ const Base_FieldDefinitionArray = (FieldDefinitionArray_default_);
;// CONCATENATED MODULE: ./src/x_ite/Base/X3DField.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






const
   _value               = Symbol (),
   _accessType          = Symbol (),
   _unit                = Symbol (),
   _references          = Symbol (),
   _referencesCallbacks = Symbol (),
   _fieldInterests      = Symbol (),
   _fieldCallbacks      = Symbol (),
   _inputRoutes         = Symbol (),
   _outputRoutes        = Symbol (),
   _routeCallbacks      = Symbol (),
   _uniformLocation     = Symbol .for ("X_ITE.X3DField.uniformLocation");

function X3DField (value)
{
   Base_X3DChildObject .call (this);

   this [_value] = value;
}

Object .assign (Object .setPrototypeOf (X3DField .prototype, Base_X3DChildObject .prototype),
{
   [_value]: null,
   [_accessType]: Base_X3DConstants .initializeOnly,
   [_unit]: null,
   [_references]: new Set (),
   [_referencesCallbacks]: new Map (),
   [_fieldInterests]: new Set (),
   [_fieldCallbacks]: new Map (),
   [_inputRoutes]: new Set (),
   [_outputRoutes]: new Set (),
   [_routeCallbacks]: new Map (),
   [_uniformLocation]: null,
   create ()
   {
      return new (this .constructor) ();
   },
   equals (field)
   {
      return this [_value] === field .valueOf ();
   },
   assign (field)
   {
      // Assigns field to this field.
      this .set (field .getValue ());
      this .addEvent ();
   },
   set (value)
   {
      // Sets internal value without generating event.
      this [_value] = value;
   },
   setValue (value)
   {
      // Sets internal value and generates event.
      this .set (value instanceof this .constructor ? value .getValue () : value);
      this .addEvent ();
   },
   getValue ()
   {
      return this [_value];
   },
   getType ()
   {
      return Base_X3DConstants [this .constructor .typeName];
   },
   setAccessType (value)
   {
      this [_accessType] = value;
   },
   getAccessType ()
   {
      return this [_accessType];
   },
   isInitializable ()
   {
      return !! (this [_accessType] & Base_X3DConstants .initializeOnly);
   },
   isInput ()
   {
      return !! (this [_accessType] & Base_X3DConstants .inputOnly);
   },
   isOutput ()
   {
      return !! (this [_accessType] & Base_X3DConstants .outputOnly);
   },
   isReadable ()
   {
      return this [_accessType] !== Base_X3DConstants .inputOnly;
   },
   isWritable ()
   {
      return this [_accessType] !== Base_X3DConstants .outputOnly;
   },
   setUnit (value)
   {
      this [_unit] = value;
   },
   getUnit ()
   {
      return this [_unit];
   },
   hasReferences ()
   {
      return this [_references] .size !== 0;
   },
   isReference (accessType)
   {
      return accessType === this [_accessType] || accessType === Base_X3DConstants .inputOutput;
   },
   addReference (reference)
   {
      const references = this .getReferences ();

      if (references .has (reference))
         return;

      references .add (reference);

      // Create IS relationship

      switch (this .getAccessType () & reference .getAccessType ())
      {
         case Base_X3DConstants .initializeOnly:
            reference .addFieldInterest (this);
            this .assign (reference);
            break;
         case Base_X3DConstants .inputOnly:
            reference .addFieldInterest (this);
            break;
         case Base_X3DConstants .outputOnly:
            this .addFieldInterest (reference);
            break;
         case Base_X3DConstants .inputOutput:
            reference .addFieldInterest (this);
            this .addFieldInterest (reference);
            this .assign (reference);
            break;
      }

      this .processReferencesCallbacks ();
   },
   removeReference (reference)
   {
      this .getReferences () .delete (reference);

      // Create IS relationship

      switch (this .getAccessType () & reference .getAccessType ())
      {
         case Base_X3DConstants .initializeOnly:
            reference .removeFieldInterest (this);
            break;
         case Base_X3DConstants .inputOnly:
            reference .removeFieldInterest (this);
            break;
         case Base_X3DConstants .outputOnly:
            this .removeFieldInterest (reference);
            break;
         case Base_X3DConstants .inputOutput:
            reference .removeFieldInterest (this);
            this .removeFieldInterest (reference);
            break;
      }

      this .processReferencesCallbacks ();
   },
   getReferences ()
   {
      if (this [_references] === X3DField .prototype [_references])
         this [_references] = new Set ();

      return this [_references];
   },
   addReferencesCallback (key, object)
   {
      if (this [_referencesCallbacks] === X3DField .prototype [_referencesCallbacks])
         this [_referencesCallbacks] = new Map ();

      this [_referencesCallbacks] .set (key, object);
   },
   removeReferencesCallback (key)
   {
      this [_referencesCallbacks] .delete (key);
   },
   getReferencesCallbacks ()
   {
      return this [_referencesCallbacks];
   },
   processReferencesCallbacks: (() =>
   {
      const referencesCallbacksTemp = [ ];

      return function ()
      {
         if (this [_referencesCallbacks] .size)
         {
            for (const referencesCallback of Utility_MapUtilities .values (referencesCallbacksTemp, this [_referencesCallbacks]))
               referencesCallback ();
         }
      };
   })(),
   addFieldInterest (field)
   {
      if (this [_fieldInterests] === X3DField .prototype [_fieldInterests])
         this [_fieldInterests] = new Set ();

      this [_fieldInterests] .add (field);
   },
   removeFieldInterest (field)
   {
      this [_fieldInterests] .delete (field);
   },
   getFieldInterests ()
   {
      return this [_fieldInterests];
   },
   addFieldCallback (key, object)
   {
      if (this [_fieldCallbacks] === X3DField .prototype [_fieldCallbacks])
         this [_fieldCallbacks] = new Map ();

      this [_fieldCallbacks] .set (key, object);
   },
   removeFieldCallback (key)
   {
      this [_fieldCallbacks] .delete (key);
   },
   getFieldCallbacks ()
   {
      return this [_fieldCallbacks];
   },
   addInputRoute (route)
   {
      if (this [_inputRoutes] === X3DField .prototype [_inputRoutes])
         this [_inputRoutes] = new Set ();

      this [_inputRoutes] .add (route);

      this .processRouteCallbacks ();
   },
   removeInputRoute (route)
   {
      this [_inputRoutes] .delete (route);

      this .processRouteCallbacks ();
   },
   getInputRoutes ()
   {
      return this [_inputRoutes];
   },
   addOutputRoute (route)
   {
      if (this [_outputRoutes] === X3DField .prototype [_outputRoutes])
         this [_outputRoutes] = new Set ();

      this [_outputRoutes] .add (route);

      this .processRouteCallbacks ();
   },
   removeOutputRoute (route)
   {
      this [_outputRoutes] .delete (route);

      this .processRouteCallbacks ();
   },
   getOutputRoutes ()
   {
      return this [_outputRoutes];
   },
   addRouteCallback (key, object)
   {
      // Processed if routes are changed.

      if (this [_routeCallbacks] === X3DField .prototype [_routeCallbacks])
         this [_routeCallbacks] = new Map ();

      this [_routeCallbacks] .set (key, object);
   },
   removeRouteCallback (key)
   {
      this [_routeCallbacks] .delete (key);
   },
   getRouteCallbacks ()
   {
      return this [_routeCallbacks];
   },
   processRouteCallbacks: (() =>
   {
      const routeCallbacksTemp = [ ];

      return function ()
      {
         if (this [_routeCallbacks] .size)
         {
            for (const routeCallback of Utility_MapUtilities .values (routeCallbacksTemp, this [_routeCallbacks]))
               routeCallback ();
         }
      };
   })(),
   processEvent: (() =>
   {
      const fieldCallbacksTemp = [ ];

      return function (event = Base_Events .create (this))
      {
         if (event .has (this))
            return;

         event .add (this);

         this .setTainted (false);

         const field = event .field;

         if (field !== this)
            this .set (field .getValue (), field .length);

         // Process interests.

         this .processInterests ();

         // Process routes.

         let first = true;

         for (const fieldInterest of this [_fieldInterests])
         {
            if (first)
            {
               first = false;
               fieldInterest .addEventObject (this, event);
            }
            else
            {
               fieldInterest .addEventObject (this, Base_Events .copy (event));
            }
         }

         if (first)
            Base_Events .push (event);

         // Process field callbacks.

         if (this [_fieldCallbacks] .size)
         {
            for (const fieldCallback of Utility_MapUtilities .values (fieldCallbacksTemp, this [_fieldCallbacks]))
               fieldCallback (this .valueOf ());
         }
      };
   })(),
   fromString (string, scene)
   {
      // Function will be overridden in VRMLParser.
   },
   dispose ()
   {
      this [_references]          .clear ();
      this [_referencesCallbacks] .clear ();
      this [_fieldInterests]      .clear ();
      this [_fieldCallbacks]      .clear ();
      this [_routeCallbacks]      .clear ();

      for (const route of new Set (this [_inputRoutes]))
         route .dispose ();

      for (const route of new Set (this [_outputRoutes]))
         route .dispose ();

      Base_X3DChildObject .prototype .dispose .call (this);
   }
});

for (const key of Object .keys (X3DField .prototype))
   Object .defineProperty (X3DField .prototype, key, { enumerable: false });

const X3DField_default_ = X3DField;
;

x_ite_Namespace .add ("X3DField", "x_ite/Base/X3DField", X3DField_default_);
/* harmony default export */ const Base_X3DField = (X3DField_default_);
;// CONCATENATED MODULE: ./src/x_ite/Base/FieldArray.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function FieldArray (values = [ ])
{
   return Base_X3DInfoArray .call (this, Array .from (values, value => [value .getName (), value]), Base_X3DField);
}

Object .setPrototypeOf (FieldArray .prototype, Base_X3DInfoArray .prototype);

for (const key of Object .keys (FieldArray .prototype))
   Object .defineProperty (FieldArray .prototype, key, { enumerable: false });

Object .defineProperties (FieldArray,
{
   typeName:
   {
      value: "FieldArray",
      enumerable: true,
   },
});

const FieldArray_default_ = FieldArray;
;

x_ite_Namespace .add ("FieldArray", "x_ite/Base/FieldArray", FieldArray_default_);
/* harmony default export */ const Base_FieldArray = (FieldArray_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFBool.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function SFBool (value)
{
   Base_X3DField .call (this, !! value);
}

Object .assign (Object .setPrototypeOf (SFBool .prototype, Base_X3DField .prototype),
{
   copy ()
   {
      return new SFBool (this .getValue ());
   },
   isDefaultValue ()
   {
      return this .getValue () === false;
   },
   set (value)
   {
      Base_X3DField .prototype .set .call (this, !! value);
   },
   valueOf: Base_X3DField .prototype .getValue,
   toStream (generator)
   {
      generator .string += this .getValue () ? "TRUE" : "FALSE";
   },
   toVRMLStream (generator)
   {
      this .toStream (generator);
   },
   toXMLStream (generator)
   {
      generator .string += this .getValue () ? "true" : "false";
   },
   toJSONStream (generator)
   {
      this .toJSONStreamValue (generator);
   },
   toJSONStreamValue (generator)
   {
      generator .string += this .getValue () ? "true" : "false";
   },
});

for (const key of Object .keys (SFBool .prototype))
   Object .defineProperty (SFBool .prototype, key, { enumerable: false });

Object .defineProperties (SFBool,
{
   typeName:
   {
      value: "SFBool",
      enumerable: true,
   },
});

const SFBool_default_ = SFBool;
;

x_ite_Namespace .add ("SFBool", "x_ite/Fields/SFBool", SFBool_default_);
/* harmony default export */ const Fields_SFBool = (SFBool_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Numbers/Color3.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



const { clamp, interval, degrees } = Math_Algorithm;

const
   _r = Symbol .for ("X_ITE.Color3.r"),
   _g = Symbol .for ("X_ITE.Color3.g"),
   _b = Symbol .for ("X_ITE.Color3.b");

function Color3 (r, g, b)
{
   this [_r] = clamp (r, 0, 1);
   this [_g] = clamp (g, 0, 1);
   this [_b] = clamp (b, 0, 1);
}

Object .assign (Color3 .prototype,
{
   *[Symbol .iterator] ()
   {
      yield this [_r];
      yield this [_g];
      yield this [_b];
   },
   copy ()
   {
      const copy = Object .create (Color3 .prototype);
      copy [_r] = this [_r];
      copy [_g] = this [_g];
      copy [_b] = this [_b];
      return copy;
   },
   assign (color)
   {
      this [_r] = color [_r];
      this [_g] = color [_g];
      this [_b] = color [_b];
      return this;
   },
   set (r, g, b)
   {
      this [_r] = clamp (r, 0, 1);
      this [_g] = clamp (g, 0, 1);
      this [_b] = clamp (b, 0, 1);
      return this;
   },
   equals (color)
   {
      return this [_r] === color [_r] &&
             this [_g] === color [_g] &&
             this [_b] === color [_b];
   },
   getHSV (result)
   {
      let h, s, v;

      const min = Math .min (this [_r], this [_g], this [_b]);
      const max = Math .max (this [_r], this [_g], this [_b]);
      v = max; // value

      const delta = max - min;

      if (max !== 0 && delta !== 0)
      {
         s = delta / max; // s

         if (this [_r] === max)
            h =     (this [_g] - this [_b]) / delta;  // between yellow & magenta
         else if (this [_g] === max)
            h = 2 + (this [_b] - this [_r]) / delta;  // between cyan & yellow
         else
            h = 4 + (this [_r] - this [_g]) / delta;  // between magenta & cyan

         h *= Math .PI / 3;  // radiants
         if (h < 0)
            h += Math .PI * 2;
      }
      else
         s = h = 0;         // s = 0, h is undefined

      result [0] = h;
      result [1] = s;
      result [2] = v;

      return result;
   },
   setHSV (h, s, v)
   {
      s = clamp (s, 0, 1),
      v = clamp (v, 0, 1);

      // H is given on [0, 2 * Pi]. S and V are given on [0, 1].
      // RGB are each returned on [0, 1].

      if (s === 0)
      {
         // achromatic (grey)
         this [_r] = this [_g] = this [_b] = v;
      }
      else
      {
         const w = degrees (interval (h, 0, Math .PI * 2)) / 60;     // sector 0 to 5

         const i = Math .floor (w);
         const f = w - i;                      // factorial part of h
         const p = v * ( 1 - s );
         const q = v * ( 1 - s * f );
         const t = v * ( 1 - s * ( 1 - f ) );

         switch (i % 6)
         {
            case 0:  this [_r] = v; this [_g] = t; this [_b] = p; break;
            case 1:  this [_r] = q; this [_g] = v; this [_b] = p; break;
            case 2:  this [_r] = p; this [_g] = v; this [_b] = t; break;
            case 3:  this [_r] = p; this [_g] = q; this [_b] = v; break;
            case 4:  this [_r] = t; this [_g] = p; this [_b] = v; break;
            default: this [_r] = v; this [_g] = p; this [_b] = q; break;
         }
      }

      return this;
   },
   toString ()
   {
      return this [_r] + " " +
             this [_g] + " " +
             this [_b];
   },
});

const r = {
   get () { return this [_r]; },
   set (value) { this [_r] = clamp (value, 0, 1); },
};

const g = {
   get () { return this [_g]; },
   set (value) { this [_g] = clamp (value, 0, 1); },
};

const b = {
   get () { return this [_b]; },
   set (value) { this [_b] = clamp (value, 0, 1); },
};

Object .defineProperties (Color3 .prototype,
{
   length: { value: 3 },
   0: r,
   1: g,
   2: b,
   r: Object .assign ({ enumerable: true }, r),
   g: Object .assign ({ enumerable: true }, g),
   b: Object .assign ({ enumerable: true }, b),
});

Object .assign (Color3,
{
   Black: new Color3 (0, 0, 0),
   White: new Color3 (1, 1, 1),
   HSV (h, s, v)
   {
      const color = Object .create (this .prototype);
      color .setHSV (h, s, v);
      return color;
   },
   lerp (a, b, t, r)
   {
      // Linearly interpolate in HSV space between source color @a a and destination color @a b by an amount of @a t.
      // Source and destination color must be in HSV space. The resulting HSV color is stored in @a r.

      let
         [ha, sa, va] = a,
         [hb, sb, vb] = b;

      if (sa === 0)
         ha = hb;

      if (sb === 0)
         hb = ha;

      const range = Math .abs (hb - ha);

      if (range <= Math .PI)
      {
         r [0] = ha + t * (hb - ha);
         r [1] = sa + t * (sb - sa);
         r [2] = va + t * (vb - va);
         return r;
      }

      const
         PI2  = Math .PI * 2,
         step = (PI2 - range) * t;

      let h = ha < hb ? ha - step : ha + step;

      if (h < 0)
         h += PI2;

      else if (h > PI2)
         h -= PI2;

      r [0] = h;
      r [1] = sa + t * (sb - sa);
      r [2] = va + t * (vb - va);
      return r;
   },
});

const Color3_default_ = Color3;
;

x_ite_Namespace .add ("Color3", "standard/Math/Numbers/Color3", Color3_default_);
/* harmony default export */ const Numbers_Color3 = (Color3_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFColor.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function SFColor (r, g, b)
{
   switch (arguments .length)
   {
      case 0:
         Base_X3DField .call (this, new Numbers_Color3 (0, 0, 0));
         break;

      case 1:
         Base_X3DField .call (this, arguments [0]);
         break;

      case 3:
         Base_X3DField .call (this, new Numbers_Color3 (+r, +g, +b));
         break;

      default:
         throw new Error ("Invalid arguments.");
   }
}

Object .assign (Object .setPrototypeOf (SFColor .prototype, Base_X3DField .prototype),
{
   *[Symbol .iterator] ()
   {
      yield* this .getValue ();
   },
   copy ()
   {
      return new SFColor (this .getValue () .copy ());
   },
   equals (color)
   {
      return this .getValue () .equals (color .getValue ());
   },
   isDefaultValue ()
   {
      return this .getValue () .equals (Numbers_Color3 .Black);
   },
   set (value)
   {
      this .getValue () .assign (value);
   },
   getHSV ()
   {
      return this .getValue () .getHSV ([ ]);
   },
   setHSV (h, s, v)
   {
      this .getValue () .setHSV (h, s, v);
      this .addEvent ();
   },
   lerp: (() =>
   {
      const
         s = [ ],
         d = [ ],
         r = [ ];

      return function (destination, t)
      {
         const result = new SFColor ();

         this .getValue () .getHSV (s);
         destination .getValue () .getHSV (d);

         Numbers_Color3 .lerp (s, d, t, r);

         result .setHSV (r [0], r [1], r [2]);

         return result;
      };
   })(),
   toStream (generator)
   {
      const
         value = this .getValue (),
         last  = value .length - 1;

      for (let i = 0; i < last; ++ i)
      {
         generator .string += generator .FloatFormat (value [i]);
         generator .string += generator .Space ();
      }

      generator .string += generator .FloatFormat (value [last]);
   },
   toVRMLStream (generator)
   {
      this .toStream (generator);
   },
   toXMLStream (generator)
   {
      this .toStream (generator);
   },
   toJSONStream (generator)
   {
      generator .string += '[';
      generator .string += generator .TidySpace ();

      this .toJSONStreamValue (generator);

      generator .string += generator .TidySpace ();
      generator .string += ']';
   },
   toJSONStreamValue (generator)
   {
      const
         value = this .getValue (),
         last  = value .length - 1;

      for (let i = 0; i < last; ++ i)
      {
         generator .string += generator .JSONNumber (generator .FloatFormat (value [i]));
         generator .string += ',';
         generator .string += generator .TidySpace ();
      }

      generator .string += generator .JSONNumber (generator .FloatFormat (value [last]));
   },
});

for (const key of Object .keys (SFColor .prototype))
   Object .defineProperty (SFColor .prototype, key, { enumerable: false });

const SFColor_r = {
   get ()
   {
      return this .getValue () .r;
   },
   set (value)
   {
      this .getValue () .r = +value;
      this .addEvent ();
   },
};

const SFColor_g = {
   get ()
   {
      return this .getValue () .g;
   },
   set (value)
   {
      this .getValue () .g = +value;
      this .addEvent ();
   },
};

const SFColor_b = {
   get ()
   {
      return this .getValue () .b;
   },
   set (value)
   {
      this .getValue () .b = +value;
      this .addEvent ();
   },
};

Object .defineProperties (SFColor .prototype,
{
   0: SFColor_r,
   1: SFColor_g,
   2: SFColor_b,
   r: Object .assign ({ enumerable: true }, SFColor_r),
   g: Object .assign ({ enumerable: true }, SFColor_g),
   b: Object .assign ({ enumerable: true }, SFColor_b),
});

Object .defineProperties (SFColor,
{
   typeName:
   {
      value: "SFColor",
      enumerable: true,
   },
});

const SFColor_default_ = SFColor;
;

x_ite_Namespace .add ("SFColor", "x_ite/Fields/SFColor", SFColor_default_);
/* harmony default export */ const Fields_SFColor = (SFColor_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Numbers/Color4.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




const { clamp: Color4_clamp } = Math_Algorithm;

const
   Color4_r = Symbol .for ("X_ITE.Color3.r"),
   Color4_g = Symbol .for ("X_ITE.Color3.g"),
   Color4_b = Symbol .for ("X_ITE.Color3.b"),
   _a = Symbol ();

function Color4 (r, g, b, a)
{
   this [Color4_r] = Color4_clamp (r, 0, 1);
   this [Color4_g] = Color4_clamp (g, 0, 1);
   this [Color4_b] = Color4_clamp (b, 0, 1);
   this [_a] = Color4_clamp (a, 0, 1);
}

Object .assign (Color4 .prototype,
{
   *[Symbol .iterator] ()
   {
      yield this [Color4_r];
      yield this [Color4_g];
      yield this [Color4_b];
      yield this [_a];
   },
   copy ()
   {
      const copy = Object .create (Color4 .prototype);
      copy [Color4_r] = this [Color4_r];
      copy [Color4_g] = this [Color4_g];
      copy [Color4_b] = this [Color4_b];
      copy [_a] = this [_a];
      return copy;
   },
   assign (color)
   {
      this [Color4_r] = color [Color4_r];
      this [Color4_g] = color [Color4_g];
      this [Color4_b] = color [Color4_b];
      this [_a] = color [_a];
      return this;
   },
   set (r, g, b, a)
   {
      this [Color4_r] = Color4_clamp (r, 0, 1);
      this [Color4_g] = Color4_clamp (g, 0, 1);
      this [Color4_b] = Color4_clamp (b, 0, 1);
      this [_a] = Color4_clamp (a, 0, 1);
      return this;
   },
   equals (color)
   {
      return this [Color4_r] === color [Color4_r] &&
             this [Color4_g] === color [Color4_g] &&
             this [Color4_b] === color [Color4_b] &&
             this [_a] === color [_a];
   },
   getHSVA (result)
   {
      Numbers_Color3 .prototype .getHSV .call (this, result);

      result [3] = this [_a];

      return result;
   },
   setHSVA (h, s, v, a)
   {
      Numbers_Color3 .prototype .setHSV .call (this, h, s, v);

      this [_a] = Color4_clamp (a, 0, 1);

      return this;
   },
   toString ()
   {
      return this [Color4_r] + " " +
             this [Color4_g] + " " +
             this [Color4_b] + " " +
             this [_a];
   },
});

const Numbers_Color4_r = {
   get () { return this [Color4_r]; },
   set (value) { this [Color4_r] = Color4_clamp (value, 0, 1); },
};

const Numbers_Color4_g = {
   get () { return this [Color4_g]; },
   set (value) { this [Color4_g] = Color4_clamp (value, 0, 1); },
};

const Numbers_Color4_b = {
   get () { return this [Color4_b]; },
   set (value) { this [Color4_b] = Color4_clamp (value, 0, 1); },
};

const a = {
   get () { return this [_a]; },
   set (value) { this [_a] = Color4_clamp (value, 0, 1); },
};

Object .defineProperties (Color4 .prototype,
{
   length: { value: 4 },
   0: Numbers_Color4_r,
   1: Numbers_Color4_g,
   2: Numbers_Color4_b,
   3: a,
   r: Object .assign ({ enumerable: true }, Numbers_Color4_r),
   g: Object .assign ({ enumerable: true }, Numbers_Color4_g),
   b: Object .assign ({ enumerable: true }, Numbers_Color4_b),
   a: Object .assign ({ enumerable: true }, a),
});

Object .assign (Color4,
{
   Transparent: new Color4 (0, 0, 0, 0),
   Black: new Color4 (0, 0, 0, 1),
   White: new Color4 (1, 1, 1, 1),
   HSVA (h, s, v, a)
   {
      const color = Object .create (this .prototype);
      color .setHSVA (h, s, v, a);
      return color;
   },
   lerp (a, b, t, r)
   {
      // Linearely interpolate in HSVA space between source color @a a and destination color @a b by an amount of @a t.
      // Source and destination color must be in HSVA space. The resulting HSVA color is stored in @a r.
      const aa = a [3];
      Numbers_Color3 .lerp (a, b, t, r);
      r [3] = aa + t * (b [3] - aa);
      return r;
   },
});

const Color4_default_ = Color4;
;

x_ite_Namespace .add ("Color4", "standard/Math/Numbers/Color4", Color4_default_);
/* harmony default export */ const Numbers_Color4 = (Color4_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFColorRGBA.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function SFColorRGBA (r, g, b, a)
{
   switch (arguments .length)
   {
      case 0:
         Base_X3DField .call (this, new Numbers_Color4 (0, 0, 0, 0));
         break;

      case 1:
         Base_X3DField .call (this, arguments [0]);
         break;

      case 4:
         Base_X3DField .call (this, new Numbers_Color4 (+r, +g, +b, +a));
         break

      default:
         throw new Error ("Invalid arguments.");
   }
}

Object .assign (Object .setPrototypeOf (SFColorRGBA .prototype, Base_X3DField .prototype),
{
   *[Symbol .iterator] ()
   {
      yield* this .getValue ();
   },
   copy ()
   {
      return new SFColorRGBA (this .getValue () .copy ());
   },
   equals: Fields_SFColor .prototype .equals,
   isDefaultValue ()
   {
      return this .getValue () .equals (Numbers_Color4 .Transparent);
   },
   set: Fields_SFColor .prototype .set,
   getHSVA ()
   {
      return this .getValue () .getHSVA ([ ]);
   },
   setHSVA (h, s, v, a)
   {
      this .getValue () .setHSVA (h, s, v, a);
      this .addEvent ();
   },
   lerp: (() =>
   {
      const
         s = [ ],
         d = [ ],
         r = [ ];

      return function (destination, t)
      {
         const result = new SFColorRGBA ();

         this .getValue () .getHSVA (s);
         destination .getValue () .getHSVA (d);

         Numbers_Color4 .lerp (s, d, t, r);

         result .setHSVA (r [0], r [1], r [2], r [3]);

         return result;
      };
   })(),
   toStream: Fields_SFColor .prototype .toStream,
   toVRMLStream: Fields_SFColor .prototype .toVRMLStream,
   toXMLStream: Fields_SFColor .prototype .toXMLStream,
   toJSONStream: Fields_SFColor .prototype .toJSONStream,
   toJSONStreamValue: Fields_SFColor .prototype .toJSONStreamValue,
});

for (const key of Object .keys (SFColorRGBA .prototype))
   Object .defineProperty (SFColorRGBA .prototype, key, { enumerable: false });

const SFColorRGBA_r = {
   get ()
   {
      return this .getValue () .r;
   },
   set (value)
   {
      this .getValue () .r = +value;
      this .addEvent ();
   },
};

const SFColorRGBA_g = {
   get ()
   {
      return this .getValue () .g;
   },
   set (value)
   {
      this .getValue () .g = +value;
      this .addEvent ();
   },
};

const SFColorRGBA_b = {
   get ()
   {
      return this .getValue () .b;
   },
   set (value)
   {
      this .getValue () .b = +value;
      this .addEvent ();
   },
};

const SFColorRGBA_a = {
   get ()
   {
      return this .getValue () .a;
   },
   set (value)
   {
      this .getValue () .a = +value;
      this .addEvent ();
   },
};

Object .defineProperties (SFColorRGBA .prototype,
{
   0: SFColorRGBA_r,
   1: SFColorRGBA_g,
   2: SFColorRGBA_b,
   3: SFColorRGBA_a,
   r: Object .assign ({ enumerable: true }, SFColorRGBA_r),
   g: Object .assign ({ enumerable: true }, SFColorRGBA_g),
   b: Object .assign ({ enumerable: true }, SFColorRGBA_b),
   a: Object .assign ({ enumerable: true }, SFColorRGBA_a),
});

Object .defineProperties (SFColorRGBA,
{
   typeName:
   {
      value: "SFColorRGBA",
      enumerable: true,
   },
});

const SFColorRGBA_default_ = SFColorRGBA;
;

x_ite_Namespace .add ("SFColorRGBA", "x_ite/Fields/SFColorRGBA", SFColorRGBA_default_);
/* harmony default export */ const Fields_SFColorRGBA = (SFColorRGBA_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFDouble.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function SFDouble (value)
{
   Base_X3DField .call (this, arguments .length ? +value : 0);
}

Object .assign (Object .setPrototypeOf (SFDouble .prototype, Base_X3DField .prototype),
{
   copy ()
   {
      return new SFDouble (this .getValue ());
   },
   isDefaultValue ()
   {
      return this .getValue () === 0;
   },
   set (value)
   {
      Base_X3DField .prototype .set .call (this, +value);
   },
   valueOf: Base_X3DField .prototype .getValue,
   toStream (generator)
   {
      const category = generator .Unit (this .getUnit ());

      generator .string += generator .DoubleFormat (generator .ToUnit (category, this .getValue ()));
   },
   toVRMLStream (generator)
   {
      this .toStream (generator);
   },
   toXMLStream (generator)
   {
      this .toStream (generator);
   },
   toJSONStream (generator)
   {
      this .toJSONStreamValue (generator);
   },
   toJSONStreamValue (generator)
   {
      const category = generator .Unit (this .getUnit ());

      generator .string += generator .JSONNumber (generator .DoubleFormat (generator .ToUnit (category, this .getValue ())));
   },
});

for (const key of Object .keys (SFDouble .prototype))
   Object .defineProperty (SFDouble .prototype, key, { enumerable: false });

Object .defineProperties (SFDouble,
{
   typeName:
   {
      value: "SFDouble",
      enumerable: true,
   },
});

const SFDouble_default_ = SFDouble;
;

x_ite_Namespace .add ("SFDouble", "x_ite/Fields/SFDouble", SFDouble_default_);
/* harmony default export */ const Fields_SFDouble = (SFDouble_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFFloat.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function SFFloat (value)
{
   Base_X3DField .call (this, arguments .length ? +value : 0);
}

Object .assign (Object .setPrototypeOf (SFFloat .prototype, Base_X3DField .prototype),
{
   copy ()
   {
      return new SFFloat (this .getValue ());
   },
   isDefaultValue ()
   {
      return this .getValue () === 0;
   },
   set (value)
   {
      Base_X3DField .prototype .set .call (this, +value);
   },
   valueOf: Base_X3DField .prototype .getValue,
   toStream (generator)
   {
      const category = generator .Unit (this .getUnit ());

      generator .string += generator .FloatFormat (generator .ToUnit (category, this .getValue ()));
   },
   toVRMLStream (generator)
   {
      this .toStream (generator);
   },
   toXMLStream (generator)
   {
      this .toStream (generator);
   },
   toJSONStream (generator)
   {
      this .toJSONStreamValue (generator);
   },
   toJSONStreamValue (generator)
   {
      const category = generator .Unit (this .getUnit ());

      generator .string += generator .JSONNumber (generator .FloatFormat (generator .ToUnit (category, this .getValue ())));
   },
});

for (const key of Object .keys (SFFloat .prototype))
   Object .defineProperty (SFFloat .prototype, key, { enumerable: false });

Object .defineProperties (SFFloat,
{
   typeName:
   {
      value: "SFFloat",
      enumerable: true,
   },
});

const SFFloat_default_ = SFFloat;
;

x_ite_Namespace .add ("SFFloat", "x_ite/Fields/SFFloat", SFFloat_default_);
/* harmony default export */ const Fields_SFFloat = (SFFloat_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFInt32.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function SFInt32 (value)
{
   Base_X3DField .call (this, value|0);
}

Object .assign (Object .setPrototypeOf (SFInt32 .prototype, Base_X3DField .prototype),
{
   copy ()
   {
      return new SFInt32 (this .getValue ());
   },
   isDefaultValue ()
   {
      return this .getValue () === 0;
   },
   set (value)
   {
      Base_X3DField .prototype .set .call (this, value|0);
   },
   valueOf: Base_X3DField .prototype .getValue,
   toStream (generator)
   {
      generator .string += this .getValue () .toString ();
   },
   toVRMLStream (generator)
   {
      this .toStream (generator);
   },
   toXMLStream (generator)
   {
      this .toStream (generator);
   },
   toJSONStream (generator)
   {
      this .toStream (generator);
   },
   toJSONStreamValue (generator)
   {
      this .toStream (generator);
   },
});

for (const key of Object .keys (SFInt32 .prototype))
   Object .defineProperty (SFInt32 .prototype, key, { enumerable: false });

Object .defineProperties (SFInt32,
{
   typeName:
   {
      value: "SFInt32",
      enumerable: true,
   },
});

const SFInt32_default_ = SFInt32;
;

x_ite_Namespace .add ("SFInt32", "x_ite/Fields/SFInt32", SFInt32_default_);
/* harmony default export */ const Fields_SFInt32 = (SFInt32_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFMatrixPrototypeTemplate.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function SFMatrixPrototypeTemplate (Constructor, TypeName, Matrix, SFVec, double)
{
   const _formatter = double ? "DoubleFormat" : "FloatFormat";

   Object .defineProperties (Constructor,
   {
      typeName:
      {
         value: TypeName,
         enumerable: true,
      },
   });

   return Object .assign (Object .setPrototypeOf (Constructor .prototype, Base_X3DField .prototype),
   {
      *[Symbol .iterator] ()
      {
         yield* this .getValue ();
      },
      copy ()
      {
         return new (this .constructor) (this .getValue () .copy ());
      },
      equals (matrix)
      {
         return this .getValue () .equals (matrix .getValue ());
      },
      isDefaultValue ()
      {
         return this .getValue () .equals (Matrix .Identity);
      },
      set (value)
      {
         this .getValue () .assign (value);
      },
      setTransform (translation, rotation, scale, scaleOrientation, center)
      {
         translation      = translation      ? translation      .getValue () : null;
         rotation         = rotation         ? rotation         .getValue () : null;
         scale            = scale            ? scale            .getValue () : null;
         scaleOrientation = scaleOrientation ? scaleOrientation .getValue () : null;
         center           = center           ? center           .getValue () : null;

         this .getValue () .set (translation, rotation, scale, scaleOrientation, center);
      },
      getTransform (translation, rotation, scale, scaleOrientation, center)
      {
         translation      = translation      ? translation      .getValue () : null;
         rotation         = rotation         ? rotation         .getValue () : null;
         scale            = scale            ? scale            .getValue () : null;
         scaleOrientation = scaleOrientation ? scaleOrientation .getValue () : null;
         center           = center           ? center           .getValue () : null;

         this .getValue () .get (translation, rotation, scale, scaleOrientation, center);
      },
      determinant ()
      {
         return this .getValue () .determinant ();
      },
      transpose ()
      {
         return new (this .constructor) (this .getValue () .copy () .transpose ());
      },
      inverse ()
      {
         return new (this .constructor) (this .getValue () .copy () .inverse ());
      },
      multLeft (matrix)
      {
         return new (this .constructor) (this .getValue () .copy () .multLeft (matrix .getValue ()));
      },
      multRight (matrix)
      {
         return new (this .constructor) (this .getValue () .copy () .multRight (matrix .getValue ()));
      },
      multVecMatrix (vector)
      {
         return new SFVec (this .getValue () .multVecMatrix (vector .getValue () .copy ()));
      },
      multMatrixVec (vector)
      {
         return new SFVec (this .getValue () .multMatrixVec (vector .getValue () .copy ()));
      },
      multDirMatrix (vector)
      {
         return new SFVec (this .getValue () .multDirMatrix (vector .getValue () .copy ()));
      },
      multMatrixDir (vector)
      {
         return new SFVec (this .getValue () .multMatrixDir (vector .getValue () .copy ()));
      },
      toStream (generator)
      {
         const
            value = this .getValue (),
            last  = value .length - 1;

         for (let i = 0; i < last; ++ i)
         {
            generator .string += generator [_formatter] (value [i]);
            generator .string += generator .Space ();
         }

         generator .string += generator [_formatter] (value [last]);
      },
      toVRMLStream (generator)
      {
         this .toStream (generator);
      },
      toXMLStream (generator)
      {
         this .toStream (generator);
      },
      toJSONStream (generator)
      {
         generator .string += '[';
         generator .string += generator .TidySpace ();

         this .toJSONStreamValue (generator);

         generator .string += generator .TidySpace ();
         generator .string += ']';
      },
      toJSONStreamValue (generator)
      {
         const
            value = this .getValue (),
            last  = value .length - 1;

         for (let i = 0; i < last; ++ i)
         {
            generator .string += generator .JSONNumber (generator [_formatter] (value [i]));
            generator .string += ',';
            generator .string += generator .TidySpace ();
         }

         generator .string += generator .JSONNumber (generator [_formatter] (value [last]));
      },
   });
}

const SFMatrixPrototypeTemplate_default_ = SFMatrixPrototypeTemplate;
;

x_ite_Namespace .add ("SFMatrixPrototypeTemplate", "x_ite/Fields/SFMatrixPrototypeTemplate", SFMatrixPrototypeTemplate_default_);
/* harmony default export */ const Fields_SFMatrixPrototypeTemplate = (SFMatrixPrototypeTemplate_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFVecPrototypeTemplate.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function SFVecPrototypeTemplate (Constructor, TypeName, Vector, double)
{
   const _formatter = double ? "DoubleFormat" : "FloatFormat";

   Object .defineProperties (Constructor,
   {
      typeName:
      {
         value: TypeName,
         enumerable: true,
      },
   });

   return Object .assign (Object .setPrototypeOf (Constructor .prototype, Base_X3DField .prototype),
   {
      *[Symbol .iterator] ()
      {
         yield* this .getValue ();
      },
      copy ()
      {
         return new (this .constructor) (this .getValue () .copy ());
      },
      equals (vector)
      {
         return this .getValue () .equals (vector .getValue ());
      },
      isDefaultValue ()
      {
         return this .getValue () .equals (Vector .Zero);
      },
      set (value)
      {
         this .getValue () .assign (value);
      },
      abs ()
      {
         return new (this .constructor) (this .getValue () .copy () .abs ());
      },
      add (vector)
      {
         return new (this .constructor) (this .getValue () .copy () .add (vector .getValue ()));
      },
      distance (vector)
      {
         return this .getValue () .distance (vector .getValue ());
      },
      divide (value)
      {
         return new (this .constructor) (this .getValue () .copy () .divide (value));
      },
      divVec (vector)
      {
         return new (this .constructor) (this .getValue () .copy () .divVec (vector .getValue ()));
      },
      dot (vector)
      {
         return this .getValue () .dot (vector .getValue ());
      },
      inverse ()
      {
         return new (this .constructor) (this .getValue () .copy () .inverse ());
      },
      length ()
      {
         return this .getValue () .magnitude ();
      },
      lerp (destination, t)
      {
         return new (this .constructor) (this .getValue () .copy () .lerp (destination, t));
      },
      max (vector)
      {
         return new (this .constructor) (this .getValue () .copy () .max (vector .getValue ()));
      },
      min (vector)
      {
         return new (this .constructor) (this .getValue () .copy () .min (vector .getValue ()));
      },
      multiply (value)
      {
         return new (this .constructor) (this .getValue () .copy () .multiply (value));
      },
      multVec (vector)
      {
         return new (this .constructor) (this .getValue () .copy () .multVec (vector .getValue ()));
      },
      negate ()
      {
         return new (this .constructor) (this .getValue () .copy () .negate ());
      },
      normalize (vector)
      {
         return new (this .constructor) (this .getValue () .copy () .normalize ());
      },
      subtract (vector)
      {
         return new (this .constructor) (this .getValue () .copy () .subtract (vector .getValue ()));
      },
      toStream (generator)
      {
         const
            value    = this .getValue (),
            last     = value .length - 1,
            category = generator .Unit (this .getUnit ());

         for (let i = 0; i < last; ++ i)
         {
            generator .string += generator [_formatter] (generator .ToUnit (category, value [i]));
            generator .string += generator .Space ();
         }

         generator .string += generator [_formatter] (generator .ToUnit (category, value [last]));
      },
      toVRMLStream (generator)
      {
         this .toStream (generator);
      },
      toXMLStream (generator)
      {
         this .toStream (generator);
      },
      toJSONStream (generator)
      {
         generator .string += '[';
         generator .string += generator .TidySpace ();

         this .toJSONStreamValue (generator);

         generator .string += generator .TidySpace ();
         generator .string += ']';
      },
      toJSONStreamValue (generator)
      {
         const
            value    = this .getValue (),
            last     = value .length - 1,
            category = generator .Unit (this .getUnit ());

         for (let i = 0; i < last; ++ i)
         {
            generator .string += generator .JSONNumber (generator [_formatter] (generator .ToUnit (category, value [i])));
            generator .string += ',';
            generator .string += generator .TidySpace ();
         }

         generator .string += generator .JSONNumber (generator [_formatter] (generator .ToUnit (category, value [last])));
      },
   });
}

const SFVecPrototypeTemplate_default_ = SFVecPrototypeTemplate;
;

x_ite_Namespace .add ("SFVecPrototypeTemplate", "x_ite/Fields/SFVecPrototypeTemplate", SFVecPrototypeTemplate_default_);
/* harmony default export */ const Fields_SFVecPrototypeTemplate = (SFVecPrototypeTemplate_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Numbers/Vector2.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

function Vector2 (x, y)
{
   this .x = x;
   this .y = y;
}

Object .assign (Vector2 .prototype,
{
   *[Symbol .iterator] ()
   {
      yield this .x;
      yield this .y;
   },
   copy ()
   {
      const copy = Object .create (Vector2 .prototype);
      copy .x = this .x;
      copy .y = this .y;
      return copy;
   },
   assign (vector)
   {
      this .x = vector .x;
      this .y = vector .y;
      return this;
   },
   set (x, y)
   {
      this .x = x;
      this .y = y;
      return this;
   },
   equals (vector)
   {
      return this .x === vector .x &&
             this .y === vector .y;
   },
   negate ()
   {
      this .x = -this .x;
      this .y = -this .y;
      return this;
   },
   inverse ()
   {
      this .x = 1 / this .x;
      this .y = 1 / this .y;
      return this;
   },
   add (vector)
   {
      this .x += vector .x;
      this .y += vector .y;
      return this;
   },
   subtract (vector)
   {
      this .x -= vector .x;
      this .y -= vector .y;
      return this;
   },
   multiply (value)
   {
      this .x *= value;
      this .y *= value;
      return this;
   },
   multVec (vector)
   {
      this .x *= vector .x;
      this .y *= vector .y;
      return this;
   },
   divide (value)
   {
      this .x /= value;
      this .y /= value;
      return this;
   },
   divVec (vector)
   {
      this .x /= vector .x;
      this .y /= vector .y;
      return this;
   },
   normalize ()
   {
      const length = Math .hypot (this .x, this .y);

      if (length)
      {
         this .x /= length;
         this .y /= length;
      }

      return this;
   },
   dot (vector)
   {
      return this .x * vector .x +
             this .y * vector .y;
   },
   norm ()
   {
      const { x, y } = this;

      return x * x +
             y * y;
   },
   magnitude ()
   {
      return Math .hypot (this .x, this .y);
   },
   distance (vector)
   {
      return Math .hypot (this .x - vector .x,
                          this .y - vector .y);
   },
   lerp (destination, t)
   {
      const { x, y } = this;

      this .x = x + t * (destination .x - x);
      this .y = y + t * (destination .y - y);
      return this;
   },
   abs ()
   {
      this .x = Math .abs (this .x);
      this .y = Math .abs (this .y);
      return this;
   },
   min (vector)
   {
      let { x, y } = this;

      for (const vector of arguments)
      {
         x = Math .min (x, vector .x);
         y = Math .min (y, vector .y);
      }

      this .x = x;
      this .y = y;
      return this;
   },
   max (vector)
   {
      let { x, y } = this;

      for (const vector of arguments)
      {
         x = Math .max (x, vector .x);
         y = Math .max (y, vector .y);
      }

      this .x = x;
      this .y = y;
      return this;
   },
   toString ()
   {
      return this .x + " " +
             this .y;
   }
});

Object .defineProperties (Vector2 .prototype,
{
   length: { value: 2 },
   0:
   {
      get () { return this .x; },
      set (value) { this .x = value; },
   },
   1:
   {
      get () { return this .y; },
      set (value) { this .y = value; },
   },
});

Object .assign (Vector2,
{
   Zero: new Vector2 (0, 0),
   One: new Vector2 (1, 1),
   xAxis: new Vector2 (1, 0),
   yAxis: new Vector2 (0, 1),
});

const Vector2_default_ = Vector2;
;

x_ite_Namespace .add ("Vector2", "standard/Math/Numbers/Vector2", Vector2_default_);
/* harmony default export */ const Numbers_Vector2 = (Vector2_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFVec2.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function SFVec2Template (TypeName, double)
{
   function SFVec2 (x, y)
   {
      switch (arguments .length)
      {
         case 0:
            Base_X3DField .call (this, new Numbers_Vector2 (0, 0));
            break;

         case 1:
            Base_X3DField .call (this, arguments [0]);
            break;

         case 2:
            Base_X3DField .call (this, new Numbers_Vector2 (+x, +y));
            break;

         default:
            throw new Error ("Invalid arguments.");
      }
   }

   Fields_SFVecPrototypeTemplate (SFVec2, TypeName, Numbers_Vector2, double);

   for (const key of Object .keys (SFVec2 .prototype))
      Object .defineProperty (SFVec2 .prototype, key, { enumerable: false });

   const x = {
      get ()
      {
         return this .getValue () .x;
      },
      set (value)
      {
         this .getValue () .x = +value;
         this .addEvent ();
      },
   };

   const y = {
      get ()
      {
         return this .getValue () .y;
      },
      set (value)
      {
         this .getValue () .y = +value;
         this .addEvent ();
      },
   };

   Object .defineProperties (SFVec2 .prototype,
   {
      0: x,
      1: y,
      x: Object .assign ({ enumerable: true }, x),
      y: Object .assign ({ enumerable: true }, y),
   });

   return SFVec2;
}

const SFVec2 = {
   SFVec2d: SFVec2Template ("SFVec2d", true),
   SFVec2f: SFVec2Template ("SFVec2f", false),
};

const SFVec2_default_ = SFVec2;
;

x_ite_Namespace .add ("SFVec2", "x_ite/Fields/SFVec2", SFVec2_default_);
/* harmony default export */ const Fields_SFVec2 = (SFVec2_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Numbers/Vector3.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function Vector3 (x, y, z)
{
   this .x = x;
   this .y = y;
   this .z = z;
}

Object .assign (Vector3 .prototype,
{
   *[Symbol .iterator] ()
   {
      yield this .x;
      yield this .y;
      yield this .z;
   },
   copy ()
   {
      const copy = Object .create (Vector3 .prototype);
      copy .x = this .x;
      copy .y = this .y;
      copy .z = this .z;
      return copy;
   },
   assign (vector)
   {
      this .x = vector .x;
      this .y = vector .y;
      this .z = vector .z;
      return this;
   },
   set (x, y, z)
   {
      this .x = x;
      this .y = y;
      this .z = z;
      return this;
   },
   equals (vector)
   {
      return this .x === vector .x &&
             this .y === vector .y &&
             this .z === vector .z;
   },
   negate ()
   {
      this .x = -this .x;
      this .y = -this .y;
      this .z = -this .z;
      return this;
   },
   inverse ()
   {
      this .x = 1 / this .x;
      this .y = 1 / this .y;
      this .z = 1 / this .z;
      return this;
   },
   add (vector)
   {
      this .x += vector .x;
      this .y += vector .y;
      this .z += vector .z;
      return this;
   },
   subtract (vector)
   {
      this .x -= vector .x;
      this .y -= vector .y;
      this .z -= vector .z;
      return this;
   },
   multiply (value)
   {
      this .x *= value;
      this .y *= value;
      this .z *= value;
      return this;
   },
   multVec (vector)
   {
      this .x *= vector .x;
      this .y *= vector .y;
      this .z *= vector .z;
      return this;
   },
   divide (value)
   {
      this .x /= value;
      this .y /= value;
      this .z /= value;
      return this;
   },
   divVec (vector)
   {
      this .x /= vector .x;
      this .y /= vector .y;
      this .z /= vector .z;
      return this;
   },
   cross (vector)
   {
      const
         { x: ax, y: ay, z: az } = this,
         { x: bx, y: by, z: bz } = vector;

      this .x = ay * bz - az * by;
      this .y = az * bx - ax * bz;
      this .z = ax * by - ay * bx;

      return this;
   },
   normalize ()
   {
      const length = Math .hypot (this .x, this .y, this .z);

      if (length)
      {
         this .x /= length;
         this .y /= length;
         this .z /= length;
      }

      return this;
   },
   dot (vector)
   {
      return this .x * vector .x +
             this .y * vector .y +
             this .z * vector .z;
   },
   norm ()
   {
      const { x, y, z } = this;

      return x * x +
             y * y +
             z * z;
   },
   magnitude ()
   {
      return Math .hypot (this .x, this .y, this .z);
   },
   distance (vector)
   {
      return Math .hypot (this .x - vector .x,
                          this .y - vector .y,
                          this .z - vector .z);
   },
   lerp (destination, t)
   {
      const { x, y, z } = this;

      this .x = x + t * (destination .x - x);
      this .y = y + t * (destination .y - y);
      this .z = z + t * (destination .z - z);
      return this;
   },
   slerp: (() =>
   {
      const tmp = new Vector3 (0, 0, 0);

      return function (destination, t)
      {
         return Math_Algorithm .simpleSlerp (this, tmp .assign (destination), t);
      };
   })(),
   abs ()
   {
      this .x = Math .abs (this .x);
      this .y = Math .abs (this .y);
      this .z = Math .abs (this .z);
      return this;
   },
   min (vector)
   {
      let { x, y, z } = this;

      for (const vector of arguments)
      {
         x = Math .min (x, vector .x);
         y = Math .min (y, vector .y);
         z = Math .min (z, vector .z);
      }

      this .x = x;
      this .y = y;
      this .z = z;
      return this;
   },
   max (vector)
   {
      let { x, y, z } = this;

      for (const vector of arguments)
      {
         x = Math .max (x, vector .x);
         y = Math .max (y, vector .y);
         z = Math .max (z, vector .z);
      }

      this .x = x;
      this .y = y;
      this .z = z;
      return this;
   },
   toString ()
   {
      return this .x + " " +
             this .y + " " +
             this .z;
   }
});

Object .defineProperties (Vector3 .prototype,
{
   length: { value: 3 },
   0:
   {
      get () { return this .x; },
      set (value) { this .x = value; },
   },
   1:
   {
      get () { return this .y; },
      set (value) { this .y = value; },
   },
   2:
   {
      get () { return this .z; },
      set (value) { this .z = value; },
   },
});

Object .assign (Vector3,
{
   Zero: new Vector3 (0, 0, 0),
   One: new Vector3 (1, 1, 1),
   xAxis: new Vector3 (1, 0, 0),
   yAxis: new Vector3 (0, 1, 0),
   zAxis: new Vector3 (0, 0, 1),
});

const Vector3_default_ = Vector3;
;

x_ite_Namespace .add ("Vector3", "standard/Math/Numbers/Vector3", Vector3_default_);
/* harmony default export */ const Numbers_Vector3 = (Vector3_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Numbers/Matrix2.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function Matrix2 ()
{
   if (arguments .length)
   {
      for (let i = 0; i < 4; ++ i)
         this [i] = arguments [i];
   }
   else
   {
      this .identity ();
   }
}

Object .assign (Matrix2 .prototype,
{
   *[Symbol .iterator] ()
   {
      for (let i = 0; i < 4; ++ i)
         yield this [i];
   },
   copy ()
   {
      const copy = Object .create (Matrix2 .prototype);

      for (let i = 0; i < 4; ++ i)
         copy [i] = this [i];

      return copy;
   },
   assign (matrix)
   {
      for (let i = 0; i < 4; ++ i)
         this [i] = matrix [i];

      return this;
   },
   equals (matrix)
   {
      return this [0] === matrix [0] &&
             this [1] === matrix [1] &&
             this [2] === matrix [2] &&
             this [3] === matrix [3];
   },
   set1 (r, c, value)
   {
      this [r * this .order + c] = value;
   },
   get1 (r, c)
   {
      return this [r * this .order + c];
   },
   set ()
   {
      switch (arguments .length)
      {
         case 0:
         {
            this .identity ();
            break;
         }
         case 4:
         {
            for (let i = 0; i < 4; ++ i)
               this [i] = arguments [i];

            break;
         }
      }

      return this;
   },
   determinant1 ()
   {
      return this [0];
   },
   determinant ()
   {
      return this [0] * this [3] -
             this [1] * this [2];
   },
   transpose ()
   {
      const tmp = this [1];

      this [1] = this [2];
      this [2] = tmp;

      return this;
   },
   inverse ()
   {
      const
         { 0: A, 1: B, 2: C, 3: D } = this,
         d = A * D - B * C;

      // if (d === 0) ... determinant is zero.

      this [0] =  D / d;
      this [1] = -B / d;
      this [2] = -C / d;
      this [3] =  A / d;

      return this;
   },
   multLeft (matrix)
   {
      const
         { 0: a0, 1: a1, 2: a2, 3: a3 } = this,
         { 0: b0, 1: b1, 2: b2, 3: b3 } = matrix;

      this [0] = a0 * b0 + a2 * b1;
      this [1] = a1 * b0 + a3 * b1;
      this [2] = a0 * b2 + a2 * b3;
      this [3] = a1 * b2 + a3 * b3;

      return this;
   },
   multRight (matrix)
   {
      const
         { 0: a0, 1: a1, 2: a2, 3: a3 } = this,
         { 0: b0, 1: b1, 2: b2, 3: b3 } = matrix;

      this [0] = b0 * a0 + b2 * a1;
      this [1] = b1 * a0 + b3 * a1;
      this [2] = b0 * a2 + b2 * a3;
      this [3] = b1 * a2 + b3 * a3;

      return this;
   },
   multVecMatrix (vector)
   {
      if (typeof vector === "number")
      {
         const
            x = vector,
            w = x * this [1] + this [3];

         return (x * this [0] + this [2]) / w;
      }
      else
      {
         const { x, y } = vector;

         vector .x = x * this [0] + y * this [2];
         vector .y = x * this [1] + y * this [3];

         return vector;
      }
   },
   multMatrixVec (vector)
   {
      if (typeof vector === "number")
      {
         const
            x = vector,
            w = x * this [2] + this [3];

         return (x * this [0] + this [1]) / w;
      }
      else
      {
         const { x, y } = vector;

         vector .x = x * this [0] + y * this [1];
         vector .y = x * this [2] + y * this [3];

         return vector;
      }
   },
   identity ()
   {
      this [0] = 1;
      this [1] = 0;
      this [2] = 0;
      this [3] = 1;
   },
   toString ()
   {
      return Array .prototype .join .call (this, " ");
   },
});

Object .defineProperties (Matrix2 .prototype,
{
   order: { value: 2 },
   length: { value: 4 },
   x:
   {
      get: (() =>
      {
         const vector = new Numbers_Vector2 (0, 0);

         return function () { return vector .set (this [0], this [1]); };
      })(),
   },
   y:
   {
      get: (() =>
      {
         const vector = new Numbers_Vector2 (0, 0);

         return function () { return vector .set (this [2], this [3]); };
      })(),
   },
   xAxis:
   {
      get () { return this [0]; },
   },
   origin:
   {
      get () { return this [2]; },
   },
   submatrix:
   {
      get () { return this [0]; },
   },
});

Object .assign (Matrix2,
{
   Identity: new Matrix2 (),
});

const Matrix2_default_ = Matrix2;
;

x_ite_Namespace .add ("Matrix2", "standard/Math/Numbers/Matrix2", Matrix2_default_);
/* harmony default export */ const Numbers_Matrix2 = (Matrix2_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Algorithms/eigen_decomposition.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

const eigen_decomposition_a = [ ]; // more scratch
const eigen_decomposition_b = [ ]; // more scratch
const z = [ ]; // more scratch

// Calculate eigenvalues and eigenvectors.
// This is from SGI Inventor Matrix.cpp.
function eigen_decomposition (matrix, result)
{
   const
      ORDER   = matrix .order,
      SIZE    = matrix .length,
      values  = result .values,
      vectors = result .vectors;

   let
      sm,         // smallest entry
      theta,      // angle for Jacobi rotation
      c, s, t,    // cosine, sine, tangent of theta
      tau,        // sine / (1 + cos)
      h, g,       // two scrap values
      thresh,     // threshold below which no rotation done
      p, q, i, j; // indices

   // initializations
   for (i = 0; i < ORDER; ++ i)
   {
      eigen_decomposition_a [i] = eigen_decomposition_a [i] ?? [ ];
      eigen_decomposition_b [i] = values [i] = matrix .get1 (i, i);
      z [i] = 0;

      for (j = 0; j < ORDER; ++ j)
      {
         vectors [i] [j] = (i === j) ? 1 : 0;
         eigen_decomposition_a [i] [j] = matrix .get1 (j, i);
      }
   }

   // Why 50? I don't know--it's the way the folks who wrote the
   // algorithm did it:
   for (i = 0; i < 50; ++ i)
   {
      sm = 0;

      for (p = 0; p < ORDER - 1; ++ p)
      {
         for (q = p + 1; q < ORDER; ++ q)
            sm += Math .abs (eigen_decomposition_a [p] [q]);
      }

      if (sm === 0)
         break;

      thresh = i < 3 ?
         0.2 * sm / SIZE :
         0;

      for (p = 0; p < ORDER - 1; ++ p)
      {
         for (q = p + 1; q < ORDER; ++ q)
         {
            g = 100 * Math .abs (eigen_decomposition_a [p] [q]);

            if (i > 3
                && (Math .abs (values [p]) + g === Math .abs (values [p]))
                && (Math .abs (values [q]) + g === Math .abs (values [q]))
            )
            {
               eigen_decomposition_a [p] [q] = 0;
            }

            else if (Math .abs (eigen_decomposition_a [p] [q]) > thresh)
            {
               h = values [q] - values [p];

               if (Math .abs (h) + g === Math .abs (h))
               {
                  t = eigen_decomposition_a [p] [q] / h;
               }
               else
               {
                  theta = 0.5 * h / eigen_decomposition_a [p] [q];
                  t     = 1 / (Math .abs (theta) + Math .sqrt (1 + theta * theta));

                  if (theta < 0)  t = -t;
               }
               // End of computing tangent of rotation angle

               c           = 1 / Math .sqrt (1 + t * t);
               s           = t * c;
               tau         = s / (1 + c);
               h           = t * eigen_decomposition_a [p] [q];
               z [p]      -= h;
               z [q]      += h;
               values [p] -= h;
               values [q] += h;
               eigen_decomposition_a [p] [q]   = 0;

               for (j = 0; j < p; ++ j)
               {
                  g = eigen_decomposition_a [j] [p];
                  h = eigen_decomposition_a [j] [q];
                  eigen_decomposition_a [j] [p] = g - s * (h + g * tau);
                  eigen_decomposition_a [j] [q] = h + s * (g - h * tau);
               }

               for (j = p + 1; j < q; ++ j)
               {
                  g = eigen_decomposition_a [p] [j];
                  h = eigen_decomposition_a [j] [q];
                  eigen_decomposition_a [p] [j] = g - s * (h + g * tau);
                  eigen_decomposition_a [j] [q] = h + s * (g - h * tau);
               }

               for (j = q + 1; j < ORDER; ++ j)
               {
                  g = eigen_decomposition_a [p] [j];
                  h = eigen_decomposition_a [q] [j];
                  eigen_decomposition_a [p] [j] = g - s * (h + g * tau);
                  eigen_decomposition_a [q] [j] = h + s * (g - h * tau);
               }

               for (j = 0; j < ORDER; ++ j)
               {
                  g = vectors [j] [p];
                  h = vectors [j] [q];
                  vectors [j] [p] = g - s * (h + g * tau);
                  vectors [j] [q] = h + s * (g - h * tau);
               }
            }
         }
      }

      for (p = 0; p < ORDER; ++ p)
      {
         values [p] = eigen_decomposition_b [p] += z [p];
         z [p] = 0;
      }
   }

   return result;
}

const eigen_decomposition_default_ = eigen_decomposition;
;

x_ite_Namespace .add ("eigen_decomposition", "standard/Math/Algorithms/eigen_decomposition", eigen_decomposition_default_);
/* harmony default export */ const Algorithms_eigen_decomposition = (eigen_decomposition_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Numbers/Matrix3.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






function Matrix3 ()
{
   if (arguments .length)
   {
      for (let i = 0; i < 9; ++ i)
         this [i] = arguments [i];
   }
   else
   {
      this .identity ();
   }
}

Object .assign (Matrix3 .prototype,
{
   *[Symbol .iterator] ()
   {
      for (let i = 0; i < 9; ++ i)
         yield this [i];
   },
   copy ()
   {
      const copy = Object .create (Matrix3 .prototype);

      for (let i = 0; i < 9; ++ i)
         copy [i] = this [i];

      return copy;
   },
   assign (matrix)
   {
      for (let i = 0; i < 9; ++ i)
         this [i] = matrix [i];

      return this;
   },
   equals (matrix)
   {
      return this [0] === matrix [0] &&
             this [1] === matrix [1] &&
             this [2] === matrix [2] &&
             this [3] === matrix [3] &&
             this [4] === matrix [4] &&
             this [5] === matrix [5] &&
             this [6] === matrix [6] &&
             this [7] === matrix [7] &&
             this [8] === matrix [8];
   },
   rotation ()
   {
      return Math .atan2 (this [1], this [0]);
   },
   set1 (r, c, value)
   {
      this [r * this .order + c] = value;

      return this;
   },
   get1 (r, c)
   {
      return this [r * this .order + c];
   },
   set: (() =>
   {
      const invCenter = new Numbers_Vector2 (0, 0);

      return function (translation, rotation, scale, scaleOrientation, center)
      {
         switch (arguments .length)
         {
            case 0:
            {
               this .identity ();
               break;
            }
            case 1:
            {
               if (translation === null) translation = Numbers_Vector2 .Zero;

               this .identity ();
               this .translate (translation);
               break;
            }
            case 2:
            {
               if (translation === null) translation = Numbers_Vector2 .Zero;
               if (rotation    === null) rotation    = 0;

               this .identity ();
               this .translate (translation);

               if (rotation !== 0)
                  this .rotate (rotation);

               break;
            }
            case 3:
            {
               if (translation === null) translation = Numbers_Vector2 .Zero;
               if (rotation    === null) rotation    = 0;
               if (scale       === null) scale       = Numbers_Vector2 .One;

               this .identity ();
               this .translate (translation);

               if (rotation !== 0)
                  this .rotate (rotation);

               if (! scale .equals (Numbers_Vector2 .One))
                  this .scale  (scale);

               break;
            }
            case 4:
            {
               if (translation      === null) translation      = Numbers_Vector2 .Zero;
               if (rotation         === null) rotation         = 0;
               if (scale            === null) scale            = Numbers_Vector2 .One;
               if (scaleOrientation === null) scaleOrientation = 0;

               this .identity ();
               this .translate (translation);

               if (rotation !== 0)
                  this .rotate (rotation);

               if (! scale .equals (Numbers_Vector2 .One))
               {
                  const hasScaleOrientation = scaleOrientation !== 0;

                  if (hasScaleOrientation)
                  {
                     this .rotate (scaleOrientation);
                     this .scale (scale);
                     this .rotate (-scaleOrientation);
                  }
                  else
                     this .scale (scale);
               }

               break;
            }
            case 5:
            {
               if (translation      === null) translation      = Numbers_Vector2 .Zero;
               if (rotation         === null) rotation         = 0;
               if (scale            === null) scale            = Numbers_Vector2 .One;
               if (scaleOrientation === null) scaleOrientation = 0;
               if (center           === null) center           = Numbers_Vector2 .Zero;

               // P' = T * C * R * SR * S * -SR * -C * P
               this .identity ();
               this .translate (translation);

               const hasCenter = ! center .equals (Numbers_Vector2 .Zero);

               if (hasCenter)
                  this .translate (center);

               if (rotation !== 0)
                  this .rotate (rotation);

               if (! scale .equals (Numbers_Vector2 .One))
               {
                  if (scaleOrientation !== 0)
                  {
                     this .rotate (scaleOrientation);
                     this .scale (scale);
                     this .rotate (-scaleOrientation);
                  }
                  else
                     this .scale (scale);
               }

               if (hasCenter)
                  this .translate (invCenter .assign (center) .negate ());

               break;
            }
            case 9:
            {
               for (let i = 0; i < 9; ++ i)
                  this [i] = arguments [i];

               break;
            }
         }

         return this;
      };
   })(),
   get: (() =>
   {
      const
         dummyTranslation      = new Numbers_Vector2 (0, 0),
         dummyRotation         = new Numbers_Vector3 (0, 0, 0),
         dummyScale            = new Numbers_Vector2 (0, 0),
         dummyScaleOrientation = new Numbers_Vector3 (0, 0, 0),
         dummyCenter           = new Numbers_Vector2 (0, 0),
         rotMatrix             = new Numbers_Matrix2 (),
         soMatrix              = new Numbers_Matrix2 (),
         c                     = new Numbers_Vector2 (0, 0);

      return function (translation, rotation, scale, scaleOrientation, center)
      {
         if (translation      === null) translation      = dummyTranslation;
         if (rotation         === null) rotation         = dummyRotation;
         if (scale            === null) scale            = dummyScale;
         if (scaleOrientation === null) scaleOrientation = dummyScaleOrientation;
         if (center           === null) center           = dummyCenter;

         switch (arguments .length)
         {
            case 1:
            {
               translation .set (this [6], this [7]);
               break;
            }
            case 2:
            {
               this .factor (translation, rotMatrix, dummyScale, soMatrix);

               rotation [0] = rotMatrix [0];
               rotation [1] = rotMatrix [1];
               rotation [2] = Math .atan2 (rotMatrix [1], rotMatrix [0]);
               break;
            }
            case 3:
            {
               this .factor (translation, rotMatrix, scale, soMatrix);

               rotation [0] = rotMatrix [0];
               rotation [1] = rotMatrix [1];
               rotation [2] = Math .atan2 (rotMatrix [1], rotMatrix [0]);
               break;
            }
            case 4:
            {
               this .factor (translation, rotMatrix, scale, soMatrix);

               rotation [0] = rotMatrix [0];
               rotation [1] = rotMatrix [1];
               rotation [2] = Math .atan2 (rotMatrix [1], rotMatrix [0]);

               scaleOrientation [0] = soMatrix [0];
               scaleOrientation [1] = soMatrix [1];
               scaleOrientation [2] = Math .atan2 (soMatrix [1], soMatrix [0]);
               break;
            }
            case 5:
            {
               m .set (c .assign (center) .negate ());
               m .multLeft (this);
               m .translate (center);
               m .get (translation, rotation, scale, scaleOrientation);
               break;
            }
         }
      };
   })(),
   factor: (() =>
   {
      const
         si = new Numbers_Matrix2 (),
         u  = new Numbers_Matrix2 (),
         b  = new Numbers_Matrix2 ();

      const eigen = { values: [ ], vectors: [[ ], [ ]] };

      return function (translation, rotation, scale, scaleOrientation)
      {
         // (1) Get translation.
         translation .set (this [6], this [7]);

         // (2) Create 3x3 matrix.
         const a = this .submatrix;

         // (3) Compute det A. If negative, set sign = -1, else sign = 1
         const det      = a .determinant ();
         const det_sign = det < 0 ? -1 : 1;

         // (4) B = A * !A  (here !A means A transpose)
         b .assign (a) .transpose () .multLeft (a);
         const e = Algorithms_eigen_decomposition (b, eigen);

         // Find min / max eigenvalues and do ratio test to determine singularity.

         scaleOrientation .set (e .vectors [0] [0], e .vectors [1] [0],
                                e .vectors [0] [1], e .vectors [1] [1]);

         // Compute s = sqrt(evalues), with sign. Set si = s-inverse

         scale .x = det_sign * Math .sqrt (e .values [0]);
         scale .y = det_sign * Math .sqrt (e .values [1]);

         si [0] = 1 / scale .x;
         si [3] = 1 / scale .y;

         // (5) Compute U = !R ~S R A.
         rotation .assign (u .assign (scaleOrientation) .transpose () .multRight (si) .multRight (scaleOrientation) .multRight (a));
      };
   })(),
   determinant2 ()
   {
      return this [0] * this [4] -
             this [1] * this [3];
   },
   determinant ()
   {
      const { 0: m0, 1: m1, 2: m2, 3: m3, 4: m4, 5: m5, 6: m6, 7: m7, 8: m8 } = this;

      return m0 * (m4 * m8 - m5 * m7) -
             m1 * (m3 * m8 - m5 * m6) +
             m2 * (m3 * m7 - m4 * m6);
   },
   transpose ()
   {
      let tmp;

      tmp = this [1]; this [1] = this [3]; this [3] = tmp;
      tmp = this [2]; this [2] = this [6]; this [6] = tmp;
      tmp = this [5]; this [5] = this [7]; this [7] = tmp;

      return this;
   },
   inverse ()
   {
      const
         { 0: m0, 1: m1, 2: m2, 3: m3, 4: m4, 5: m5, 6: m6, 7: m7, 8: m8 } = this,
         t4  = m0 * m4,
         t6  = m0 * m7,
         t8  = m3 * m1,
         t10 = m3 * m7,
         t12 = m6 * m1,
         t14 = m6 * m4;

      let d = (t4 * m8 - t6 * m5 - t8 * m8 + t10 * m2 + t12 * m5 - t14 * m2);

      // if (d === 0) ... determinant is zero.

      d = 1 / d;

      const
         b0 =  (m4 * m8 - m7 * m5) * d,
         b1 = -(m1 * m8 - m7 * m2) * d,
         b2 =  (m1 * m5 - m4 * m2) * d,
         b3 = -(m3 * m8 - m6 * m5) * d,
         b4 =  (m0 * m8 - m6 * m2) * d,
         b5 = -(m0 * m5 - m3 * m2) * d;

      this [0] = b0;
      this [1] = b1;
      this [2] = b2;
      this [3] = b3;
      this [4] = b4;
      this [5] = b5;
      this [6] =  (t10 - t14) * d;
      this [7] = -(t6 - t12) * d;
      this [8] =  (t4 - t8) * d;

      return this;
   },
   multLeft (matrix)
   {
      const
         { 0: a0, 1: a1, 2: a2, 3: a3, 4: a4, 5: a5, 6: a6, 7: a7, 8: a8 } = this,
         { 0: b0, 1: b1, 2: b2, 3: b3, 4: b4, 5: b5, 6: b6, 7: b7, 8: b8 } = matrix;

      this [0] = a0 * b0 + a3 * b1 + a6 * b2;
      this [1] = a1 * b0 + a4 * b1 + a7 * b2;
      this [2] = a2 * b0 + a5 * b1 + a8 * b2;
      this [3] = a0 * b3 + a3 * b4 + a6 * b5;
      this [4] = a1 * b3 + a4 * b4 + a7 * b5;
      this [5] = a2 * b3 + a5 * b4 + a8 * b5;
      this [6] = a0 * b6 + a3 * b7 + a6 * b8;
      this [7] = a1 * b6 + a4 * b7 + a7 * b8;
      this [8] = a2 * b6 + a5 * b7 + a8 * b8;

      return this;
   },
   multRight (matrix)
   {
      const
         { 0: a0, 1: a1, 2: a2, 3: a3, 4: a4, 5: a5, 6: a6, 7: a7, 8: a8 } = this,
         { 0: b0, 1: b1, 2: b2, 3: b3, 4: b4, 5: b5, 6: b6, 7: b7, 8: b8 } = matrix;

      this [0] = a0 * b0 + a1 * b3 + a2 * b6;
      this [1] = a0 * b1 + a1 * b4 + a2 * b7;
      this [2] = a0 * b2 + a1 * b5 + a2 * b8;
      this [3] = a3 * b0 + a4 * b3 + a5 * b6;
      this [4] = a3 * b1 + a4 * b4 + a5 * b7;
      this [5] = a3 * b2 + a4 * b5 + a5 * b8;
      this [6] = a6 * b0 + a7 * b3 + a8 * b6;
      this [7] = a6 * b1 + a7 * b4 + a8 * b7;
      this [8] = a6 * b2 + a7 * b5 + a8 * b8;

      return this;
   },
   multVecMatrix (vector)
   {
      if (vector .length === 2)
      {
         const
            { x, y } = vector,
            w = x * this [2] + y * this [5] + this [8];

         vector .x = (x * this [0] + y * this [3] + this [6]) / w;
         vector .y = (x * this [1] + y * this [4] + this [7]) / w;

         return vector;
      }
      else
      {
         const { x, y, z } = vector;

         vector .x = x * this [0] + y * this [3] + z * this [6];
         vector .y = x * this [1] + y * this [4] + z * this [7];
         vector .z = x * this [2] + y * this [5] + z * this [8];

         return vector;
      }
   },
   multMatrixVec (vector)
   {
      if (vector .length === 2)
      {
         const
            { x, y } = vector,
            w = x * this [6] + y * this [7] + this [8];

         vector .x = (x * this [0] + y * this [1] + this [2]) / w;
         vector .y = (x * this [3] + y * this [4] + this [5]) / w;

         return vector;
      }
      else
      {
         const { x, y, z } = vector;

         vector .x = x * this [0] + y * this [1] + z * this [2];
         vector .y = x * this [3] + y * this [4] + z * this [5];
         vector .z = x * this [6] + y * this [7] + z * this [8];

         return vector;
      }
   },
   multDirMatrix (vector)
   {
      const { x, y } = vector;

      vector .x = x * this [0] + y * this [3];
      vector .y = x * this [1] + y * this [4];

      return vector;
   },
   multMatrixDir (vector)
   {
      const { x, y } = vector;

      vector .x = x * this [0] + y * this [1];
      vector .y = x * this [3] + y * this [4];

      return vector;
   },
   identity ()
   {
      this [0] = 1; this [1] = 0; this [2] = 0;
      this [3] = 0; this [4] = 1; this [5] = 0;
      this [6] = 0; this [7] = 0; this [8] = 1;

      return this;
   },
   translate (translation)
   {
      const { x, y } = translation;

      this [6] += this [0] * x + this [3] * y;
      this [7] += this [1] * x + this [4] * y;

      return this;
   },
   rotate (rotation)
   {
      return this .multLeft (Matrix3 .Rotation (rotation));
   },
   scale (scale)
   {
      const { x, y } = scale;

      this [0] *= x;
      this [3] *= y;

      this [1] *= x;
      this [4] *= y;

      return this;
   },
   skewX (angle)
   {
      const a = Math .tan (angle);

      this [3] += this [0] * a;
      this [4] += this [1] * a;
      this [5] += this [2] * a;

      return this;
   },
   skewY (angle)
   {
      const a = Math .tan (angle);

      this [0] += this [3] * a;
      this [1] += this [4] * a;
      this [2] += this [5] * a;

      return this;
   },
   toString ()
   {
      return Array .prototype .join .call (this, " ");
   },
});

Object .defineProperties (Matrix3 .prototype,
{
   order: { value: 3 },
   length: { value: 9 },
   x:
   {
      get: (() =>
      {
         const vector = new Numbers_Vector3 (0, 0, 0);

         return function () { return vector .set (this [0], this [1], this [2]); };
      })(),
   },
   y:
   {
      get: (() =>
      {
         const vector = new Numbers_Vector3 (0, 0, 0);

         return function () { return vector .set (this [3], this [4], this [5]); };
      })(),
   },
   z:
   {
      get: (() =>
      {
         const vector = new Numbers_Vector3 (0, 0, 0);

         return function () { return vector .set (this [6], this [7], this [8]); };
      })(),
   },
   xAxis:
   {
      get: (() =>
      {
         const vector = new Numbers_Vector2 (0, 0);

         return function () { return vector .set (this [0], this [1]); };
      })(),
   },
   yAxis:
   {
      get: (() =>
      {
         const vector = new Numbers_Vector2 (0, 0);

         return function () { return vector .set (this [3], this [4]); };
      })(),
   },
   origin:
   {
      get: (() =>
      {
         const vector = new Numbers_Vector2 (0, 0);

         return function () { return vector .set (this [6], this [7]); };
      })(),
   },
   submatrix:
   {
      get: (() =>
      {
         const matrix = new Numbers_Matrix2 ();

         return function ()
         {
            matrix [0] = this [0]; matrix [1] = this [1];
            matrix [2] = this [3]; matrix [3] = this [4];
            return matrix;
         };
      })(),
   },
});

Object .assign (Matrix3,
{
   Identity: new Matrix3 (),
   Rotation (rotation)
   {
      const
         sinAngle = Math .sin (rotation),
         cosAngle = Math .cos (rotation);

      return new Matrix3 ( cosAngle, sinAngle, 0,
                          -sinAngle, cosAngle, 0,
                           0, 0, 1);
   },
   Matrix2 (matrix)
   {
      return new Matrix3 (matrix [0], matrix [1], 0,
                          matrix [2], matrix [3], 0,
                          0, 0, 1);
   },
});

const m = new Matrix3 ();

const Matrix3_default_ = Matrix3;
;

x_ite_Namespace .add ("Matrix3", "standard/Math/Numbers/Matrix3", Matrix3_default_);
/* harmony default export */ const Numbers_Matrix3 = (Matrix3_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFMatrix3.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






function SFMatrix3Template (TypeName, SFVec2, double)
{
   function SFMatrix3 (m00, m01, m02,
                       m10, m11, m12,
                       m20, m21, m22)
   {
      switch (arguments .length)
      {
         case 0:
            Base_X3DField .call (this, new Numbers_Matrix3 ());
            break;

         case 1:
            Base_X3DField .call (this, arguments [0]);
            break;

         case 3:
         {
            const
               r0 = arguments [0],
               r1 = arguments [1],
               r2 = arguments [2];

            Base_X3DField .call (this, new Numbers_Matrix3 (r0 .x, r0 .y, r0 .z,
                                                      r1 .x, r1 .y, r1 .z,
                                                      r2 .x, r2 .y, r2 .z));

            break;
         }
         case 9:
         {
            Base_X3DField .call (this, new Numbers_Matrix3 (+m00, +m01, +m02,
                                               +m10, +m11, +m12,
                                               +m20, +m21, +m22));

            break;
         }
         default:
            throw new Error ("Invalid arguments.");
      }
   }

   Object .assign (Fields_SFMatrixPrototypeTemplate (SFMatrix3, TypeName, Numbers_Matrix3, SFVec2, double),
   {
      setTransform (translation, rotation, scale, scaleOrientation, center)
      {
         translation      = translation      ? translation      .getValue () : null;
         rotation         = rotation         ? rotation                      : 0;
         scale            = scale            ? scale            .getValue () : null;
         scaleOrientation = scaleOrientation ? scaleOrientation              : 0;
         center           = center           ? center           .getValue () : null;

         this .getValue () .set (translation, rotation, scale, scaleOrientation, center);
      },
   });

   for (const key of Object .keys (SFMatrix3 .prototype))
      Object .defineProperty (SFMatrix3 .prototype, key, { enumerable: false });

   function defineProperty (i)
   {
      Object .defineProperty (SFMatrix3 .prototype, i,
      {
         get ()
         {
            return this .getValue () [i];
         },
         set (value)
         {
            this .getValue () [i] = +value;
            this .addEvent ();
         },
         enumerable: true,
      });
   }

   for (let i = 0, length = Numbers_Matrix3 .prototype .length; i < length; ++ i)
      defineProperty (i);

   return SFMatrix3;
}

const SFMatrix3 = {
   SFMatrix3d: SFMatrix3Template ("SFMatrix3d", Fields_SFVec2 .SFVec2d, true),
   SFMatrix3f: SFMatrix3Template ("SFMatrix3f", Fields_SFVec2 .SFVec2f, false),
};

const SFMatrix3_default_ = SFMatrix3;
;

x_ite_Namespace .add ("SFMatrix3", "x_ite/Fields/SFMatrix3", SFMatrix3_default_);
/* harmony default export */ const Fields_SFMatrix3 = (SFMatrix3_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFVec3.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function SFVec3Template (TypeName, double)
{
   function SFVec3 (x, y, z)
   {
      switch (arguments .length)
      {
         case 0:
            Base_X3DField .call (this, new Numbers_Vector3 (0, 0, 0));
            break;

         case 1:
            Base_X3DField .call (this, arguments [0]);
            break;

         case 3:
            Base_X3DField .call (this, new Numbers_Vector3 (+x, +y, +z));
            break;

         default:
            throw new Error ("Invalid arguments.");
      }
   }

   Object .assign (Fields_SFVecPrototypeTemplate (SFVec3, TypeName, Numbers_Vector3, double),
   {
      cross (vector)
      {
         return new (this .constructor) (this .getValue () .copy () .cross (vector .getValue ()));
      },
   });

   for (const key of Object .keys (SFVec3 .prototype))
      Object .defineProperty (SFVec3 .prototype, key, { enumerable: false });

   const x = {
      get ()
      {
         return this .getValue () .x;
      },
      set (value)
      {
         this .getValue () .x = +value;
         this .addEvent ();
      },
   };

   const y = {
      get ()
      {
         return this .getValue () .y;
      },
      set (value)
      {
         this .getValue () .y = +value;
         this .addEvent ();
      },
   };

   const z = {
      get ()
      {
         return this .getValue () .z;
      },
      set (value)
      {
         this .getValue () .z = +value;
         this .addEvent ();
      },
   };

   Object .defineProperties (SFVec3 .prototype,
   {
      0: x,
      1: y,
      2: z,
      x: Object .assign ({ enumerable: true }, x),
      y: Object .assign ({ enumerable: true }, y),
      z: Object .assign ({ enumerable: true }, z),
   });

   return SFVec3;
}

const SFVec3 = {
   SFVec3d: SFVec3Template ("SFVec3d", true),
   SFVec3f: SFVec3Template ("SFVec3f", false),
};

const SFVec3_default_ = SFVec3;
;

x_ite_Namespace .add ("SFVec3", "x_ite/Fields/SFVec3", SFVec3_default_);
/* harmony default export */ const Fields_SFVec3 = (SFVec3_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Numbers/Vector4.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

function Vector4 (x, y, z, w)
{
   this .x = x;
   this .y = y;
   this .z = z;
   this .w = w;
}

Object .assign (Vector4 .prototype,
{
   *[Symbol .iterator] ()
   {
      yield this .x;
      yield this .y;
      yield this .z;
      yield this .w;
   },
   copy ()
   {
      const copy = Object .create (Vector4 .prototype);
      copy .x = this .x;
      copy .y = this .y;
      copy .z = this .z;
      copy .w = this .w;
      return copy;
   },
   assign (vector)
   {
      this .x = vector .x;
      this .y = vector .y;
      this .z = vector .z;
      this .w = vector .w;
      return this;
   },
   set (x, y, z, w)
   {
      this .x = x;
      this .y = y;
      this .z = z;
      this .w = w;
      return this;
   },
   equals (vector)
   {
      return this .x === vector .x &&
             this .y === vector .y &&
             this .z === vector .z &&
             this .w === vector .w;
   },
   getReal (vector)
   {
      vector .x = this .x / this .w;
      vector .y = this .y / this .w;
      vector .z = this .z / this .w;
      return vector;
   },
   negate ()
   {
      this .x = -this .x;
      this .y = -this .y;
      this .z = -this .z;
      this .w = -this .w;
      return this;
   },
   inverse ()
   {
      this .x = 1 / this .x;
      this .y = 1 / this .y;
      this .z = 1 / this .z;
      this .w = 1 / this .w;
      return this;
   },
   add (vector)
   {
      this .x += vector .x;
      this .y += vector .y;
      this .z += vector .z;
      this .w += vector .w;
      return this;
   },
   subtract (vector)
   {
      this .x -= vector .x;
      this .y -= vector .y;
      this .z -= vector .z;
      this .w -= vector .w;
      return this;
   },
   multiply (value)
   {
      this .x *= value;
      this .y *= value;
      this .z *= value;
      this .w *= value;
      return this;
   },
   multVec (vector)
   {
      this .x *= vector .x;
      this .y *= vector .y;
      this .z *= vector .z;
      this .w *= vector .w;
      return this;
   },
   divide (value)
   {
      this .x /= value;
      this .y /= value;
      this .z /= value;
      this .w /= value;
      return this;
   },
   divVec (vector)
   {
      this .x /= vector .x;
      this .y /= vector .y;
      this .z /= vector .z;
      this .w /= vector .w;
      return this;
   },
   normalize ()
   {
      const length = Math .hypot (this .x, this .y, this .z, this .w);

      if (length)
      {
         this .x /= length;
         this .y /= length;
         this .z /= length;
         this .w /= length;
      }

      return this;
   },
   dot (vector)
   {
      return this .x * vector .x +
             this .y * vector .y +
             this .z * vector .z +
             this .w * vector .w;
   },
   norm ()
   {
      const { x, y, z, w } = this;

      return x * x +
             y * y +
             z * z +
             w * w;
   },
   magnitude ()
   {
      return Math .hypot (this .x, this .y, this .z, this .w);
   },
   distance (vector)
   {
      return Math .hypot (this .x - vector .x,
                          this .y - vector .y,
                          this .z - vector .z,
                          this .w - vector .w);
   },
   lerp (destination, t)
   {
      const { x, y, z, w } = this;

      this .x = x + t * (destination .x - x);
      this .y = y + t * (destination .y - y);
      this .z = z + t * (destination .z - z);
      this .w = w + t * (destination .w - w);
      return this;
   },
   abs ()
   {
      this .x = Math .abs (this .x);
      this .y = Math .abs (this .y);
      this .z = Math .abs (this .z);
      this .w = Math .abs (this .w);
      return this;
   },
   min (vector)
   {
      let { x, y, z, w } = this;

      for (const vector of arguments)
      {
         x = Math .min (x, vector .x);
         y = Math .min (y, vector .y);
         z = Math .min (z, vector .z);
         w = Math .min (w, vector .w);
      }

      this .x = x;
      this .y = y;
      this .z = z;
      this .w = w;
      return this;
   },
   max (vector)
   {
      let { x, y, z, w } = this;

      for (const vector of arguments)
      {
         x = Math .max (x, vector .x);
         y = Math .max (y, vector .y);
         z = Math .max (z, vector .z);
         w = Math .max (w, vector .w);
      }

      this .x = x;
      this .y = y;
      this .z = z;
      this .w = w;
      return this;
   },
   toString ()
   {
      return this .x + " " +
             this .y + " " +
             this .z + " " +
             this .w;
   },
});

Object .defineProperties (Vector4 .prototype,
{
   length: { value: 4 },
   0:
   {
      get () { return this .x; },
      set (value) { this .x = value; },
   },
   1:
   {
      get () { return this .y; },
      set (value) { this .y = value; },
   },
   2:
   {
      get () { return this .z; },
      set (value) { this .z = value; },
   },
   3:
   {
      get () { return this .w; },
      set (value) { this .w = value; },
   },
});

Object .assign (Vector4,
{
   Zero: new Vector4 (0, 0, 0, 0),
   One: new Vector4 (1, 1, 1, 1),
   xAxis: new Vector4 (1, 0, 0, 0),
   yAxis: new Vector4 (0, 1, 0, 0),
   zAxis: new Vector4 (0, 0, 1, 0),
   wAxis: new Vector4 (0, 0, 0, 1),
});

const Vector4_default_ = Vector4;
;

x_ite_Namespace .add ("Vector4", "standard/Math/Numbers/Vector4", Vector4_default_);
/* harmony default export */ const Numbers_Vector4 = (Vector4_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Numbers/Quaternion.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function Quaternion (x, y, z, w)
{
   this .x = x;
   this .y = y;
   this .z = z;
   this .w = w;
}

Object .assign (Quaternion .prototype,
{
   *[Symbol .iterator] ()
   {
      yield this .x;
      yield this .y;
      yield this .z;
      yield this .w;
   },
   copy ()
   {
      const copy = Object .create (Quaternion .prototype);
      copy .x = this .x;
      copy .y = this .y;
      copy .z = this .z;
      copy .w = this .w;
      return copy;
   },
   assign (quat)
   {
      this .x = quat .x;
      this .y = quat .y;
      this .z = quat .z;
      this .w = quat .w;
      return this;
   },
   set (x, y, z, w)
   {
      this .x = x;
      this .y = y;
      this .z = z;
      this .w = w;
      return this;
   },
   setMatrix (matrix)
   {
      // First, find largest diagonal in matrix:
      if (matrix [0] > matrix [4])
      {
         var i = matrix [0] > matrix [8] ? 0 : 2;
      }
      else
      {
         var i = matrix [4] > matrix [8] ? 1 : 2;
      }

      const scaleRow = matrix [0] + matrix [4] + matrix [8];

      if (scaleRow > matrix [i * 3 + i])
      {
         // Compute w first:
         this [3] = Math .sqrt (scaleRow + 1) / 2;

         // And compute other values:
         const d = 4 * this [3];
         this [0] = (matrix [5] - matrix [7]) / d;
         this [1] = (matrix [6] - matrix [2]) / d;
         this [2] = (matrix [1] - matrix [3]) / d;
      }
      else
      {
         // Compute x, y, or z first:
         const j = (i + 1) % 3;
         const k = (i + 2) % 3;

         // Compute first value:
         this [i] = Math .sqrt (matrix [i * 3 + i] - matrix [j * 3 + j] - matrix [k * 3 + k] + 1) / 2;

         // And the others:
         const d = 4 * this [i];
         this [j] = (matrix [i * 3 + j] + matrix [j * 3 + i]) / d;
         this [k] = (matrix [i * 3 + k] + matrix [k * 3 + i]) / d;
         this [3] = (matrix [j * 3 + k] - matrix [k * 3 + j]) / d;
      }

      return this;
   },
   getMatrix (matrix = new Numbers_Matrix3 ())
   {
      const { x, y, z, w } = this;

      const
         a = x * x,
         b = x * y,
         c = y * y,
         d = y * z,
         e = z * x,
         f = z * z,
         g = w * x,
         h = w * y,
         i = w * z;

      matrix [0] = 1 - 2 * (c + f);
      matrix [1] =     2 * (b + i);
      matrix [2] =     2 * (e - h);

      matrix [3] =     2 * (b - i);
      matrix [4] = 1 - 2 * (f + a);
      matrix [5] =     2 * (d + g);

      matrix [6] =     2 * (e + h);
      matrix [7] =     2 * (d - g);
      matrix [8] = 1 - 2 * (c + a);

      return matrix;
   },
   setEuler (x, y, z, order = "XYZ")
   {
		// http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m

      const
		   c1 = Math .cos (x / 2),
		   c2 = Math .cos (y / 2),
		   c3 = Math .cos (z / 2),
		   s1 = Math .sin (x / 2),
		   s2 = Math .sin (y / 2),
		   s3 = Math .sin (z / 2);

		switch (order)
      {
			case "XYZ":
				this .x = s1 * c2 * c3 + c1 * s2 * s3;
				this .y = c1 * s2 * c3 - s1 * c2 * s3;
				this .z = c1 * c2 * s3 + s1 * s2 * c3;
				this .w = c1 * c2 * c3 - s1 * s2 * s3;
				break;

         case "ZYX":
            this .x = s1 * c2 * c3 - c1 * s2 * s3;
            this .y = c1 * s2 * c3 + s1 * c2 * s3;
            this .z = c1 * c2 * s3 - s1 * s2 * c3;
            this .w = c1 * c2 * c3 + s1 * s2 * s3;
            break;

			case "YXZ":
				this .x = s1 * c2 * c3 + c1 * s2 * s3;
				this .y = c1 * s2 * c3 - s1 * c2 * s3;
				this .z = c1 * c2 * s3 - s1 * s2 * c3;
				this .w = c1 * c2 * c3 + s1 * s2 * s3;
				break;

			case "ZXY":
				this .x = s1 * c2 * c3 - c1 * s2 * s3;
				this .y = c1 * s2 * c3 + s1 * c2 * s3;
				this .z = c1 * c2 * s3 + s1 * s2 * c3;
				this .w = c1 * c2 * c3 - s1 * s2 * s3;
				break;

			case "YZX":
				this .x = s1 * c2 * c3 + c1 * s2 * s3;
				this .y = c1 * s2 * c3 + s1 * c2 * s3;
				this .z = c1 * c2 * s3 - s1 * s2 * c3;
				this .w = c1 * c2 * c3 - s1 * s2 * s3;
				break;

			case "XZY":
				this .x = s1 * c2 * c3 - c1 * s2 * s3;
				this .y = c1 * s2 * c3 - s1 * c2 * s3;
				this .z = c1 * c2 * s3 + s1 * s2 * c3;
				this .w = c1 * c2 * c3 + s1 * s2 * s3;
				break;
		}

		return this;
	},
   getEuler (euler = [ ], order = "XYZ")
   {
      const { 0: m0, 1: m1, 2: m2, 3: m3, 4: m4, 5: m5, 6: m6, 7: m7, 8: m8 } = this .getMatrix (Quaternion_m);

		switch (order)
      {
			case "XYZ":
         {
				euler [1] = Math .asin (Math_Algorithm .clamp (m6, -1, 1));

				if (Math .abs (m6) < 0.9999999)
            {
					euler [0] = Math .atan2 (-m7, m8);
					euler [2] = Math .atan2 (-m3, m0);
				}
            else
            {
					euler [0] = Math .atan2 (m5, m4);
					euler [2] = 0;
				}

				break;
         }
			case "ZYX":
         {
				euler [1] = Math .asin (- Math_Algorithm .clamp (m2, -1, 1));

				if (Math .abs (m2) < 0.9999999)
            {
					euler [0] = Math .atan2 (m5, m8);
					euler [2] = Math .atan2 (m1, m0);
				}
            else
            {
					euler [0] = 0;
					euler [2] = Math .atan2 (-m3, m4);
				}

				break;
         }
			case "YXZ":
         {
				euler [0] = Math .asin (- Math_Algorithm .clamp (m7, -1, 1));

				if (Math .abs (m7) < 0.9999999)
            {
					euler [1] = Math .atan2 (m6, m8);
					euler [2] = Math .atan2 (m1, m4);

				}
            else
            {
					euler [1] = Math .atan2 (-m2, m0);
					euler [2] = 0;
				}

				break;
         }
			case "ZXY":
         {
				euler [0] = Math .asin (Math_Algorithm .clamp (m5, -1, 1));

				if (Math .abs (m5) < 0.9999999)
            {
					euler [1] = Math .atan2 (-m2, m8);
					euler [2] = Math .atan2 (-m3, m4);
				}
            else
            {
					euler [1] = 0;
					euler [2] = Math .atan2 (m1, m0);
				}

				break;
         }
			case "YZX":
         {
				euler [2] = Math .asin (Math_Algorithm .clamp (m1, -1, 1));

				if (Math .abs (m1) < 0.9999999)
            {
					euler [0] = Math .atan2 (-m7, m4);
					euler [1] = Math .atan2 (-m2, m0);
				}
            else
            {
					euler [0] = 0;
					euler [1] = Math .atan2 (m6, m8);
				}

				break;
         }
			case "XZY":
         {
				euler [2] = Math .asin (- Math_Algorithm .clamp (m3, -1, 1));

				if (Math .abs (m3) < 0.9999999)
            {
					euler [0] = Math .atan2 (m5, m4);
					euler [1] = Math .atan2 (m6, m0);

				}
            else
            {
					euler [0] = Math .atan2 (-m7, m8);
					euler [1] = 0;
				}

				break;
         }
		}

		return euler;
   },
   isReal ()
   {
      return !(this .x || this .y || this .z);
   },
   isImag ()
   {
      return !this .w;
   },
   equals (quat)
   {
      return this .x === quat .x &&
             this .y === quat .y &&
             this .z === quat .z &&
             this .w === quat .w;
   },
   negate ()
   {
      this .x = -this .x;
      this .y = -this .y;
      this .z = -this .z;
      this .w = -this .w;
      return this;
   },
   inverse ()
   {
      this .x = -this .x;
      this .y = -this .y;
      this .z = -this .z;
      return this;
   },
   add (quat)
   {
      this .x += quat .x;
      this .y += quat .y;
      this .z += quat .z;
      this .w += quat .w;
      return this;
   },
   subtract (quat)
   {
      this .x -= quat .x;
      this .y -= quat .y;
      this .z -= quat .z;
      this .w -= quat .w;
      return this;
   },
   multiply (value)
   {
      this .x *= value;
      this .y *= value;
      this .z *= value;
      this .w *= value;
      return this;
   },
   multLeft (quat)
   {
      const
         { x: ax, y: ay, z: az, w: aw } = this,
         { x: bx, y: by, z: bz, w: bw } = quat;

      this .x = aw * bx + ax * bw + ay * bz - az * by;
      this .y = aw * by + ay * bw + az * bx - ax * bz;
      this .z = aw * bz + az * bw + ax * by - ay * bx;
      this .w = aw * bw - ax * bx - ay * by - az * bz;

      return this;
   },
   multRight (quat)
   {
      const
         { x: ax, y: ay, z: az, w: aw } = this,
         { x: bx, y: by, z: bz, w: bw } = quat;

      this .x = bw * ax + bx * aw + by * az - bz * ay;
      this .y = bw * ay + by * aw + bz * ax - bx * az;
      this .z = bw * az + bz * aw + bx * ay - by * ax;
      this .w = bw * aw - bx * ax - by * ay - bz * az;

      return this;
   },
   divide (value)
   {
      this .x /= value;
      this .y /= value;
      this .z /= value;
      this .w /= value;
      return this;
   },
   multVecQuat (vector)
   {
      // https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Vector_rotation

      const
         { x: qx, y: qy, z: qz, w: qw } = this,
         { x: vx, y: vy, z: vz } = vector,
         tx = 2 * (qy * vz - qz * vy),
         ty = 2 * (qz * vx - qx * vz),
         tz = 2 * (qx * vy - qy * vx);

      vector .x += qw * tx + qy * tz - qz * ty;
      vector .y += qw * ty + qz * tx - qx * tz;
      vector .z += qw * tz + qx * ty - qy * tx;

      return vector;
   },
   multQuatVec (vector)
   {
      // https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Vector_rotation

      const
         { x: qx, y: qy, z: qz, w: qw } = this,
         { x: vx, y: vy, z: vz } = vector,
         tx = 2 * (qz * vy - qy * vz),
         ty = 2 * (qx * vz - qz * vx),
         tz = 2 * (qy * vx - qx * vy);

      vector .x += qw * tx - qy * tz + qz * ty;
      vector .y += qw * ty - qz * tx + qx * tz;
      vector .z += qw * tz - qx * ty + qy * tx;

      return vector;
   },
   normalize ()
   {
      const length = Math .hypot (this .x, this .y, this .z, this .w);

      if (length)
      {
         this .x /= length;
         this .y /= length;
         this .z /= length;
         this .w /= length;
      }

      return this;
   },
   dot (quat)
   {
      return this .x * quat .x +
             this .y * quat .y +
             this .z * quat .z +
             this .w * quat .w;
   },
   norm ()
   {
      const { x, y, z, w } = this;

      return x * x +
             y * y +
             z * z +
             w * w;
   },
   magnitude ()
   {
      return Math .hypot (this .x, this .y, this .z, this .w);
   },
   pow (exponent)
   {
      if (exponent instanceof Quaternion)
         return this .assign (e .assign (exponent) .multRight (this .log ()) .exp ());

      if (this .isReal ())
         return this .set (0, 0, 0, this .w ** exponent);

      const
         l     = this .magnitude (),
         theta = Math .acos (this .w / l),
         li    = this .imag .magnitude (),
         ltoe  = l ** exponent,
         et    = exponent * theta,
         scale = ltoe / li * Math .sin (et);

      this .x *= scale;
      this .y *= scale;
      this .z *= scale;
      this .w  = ltoe * Math .cos (et);
      return this;
   },
   log ()
   {
      if (this .isReal ())
      {
         if (this .w > 0)
            return this .set (0, 0, 0, Math .log (this .w));

         else
            return this .set (Math .PI, 0, 0, Math .log (-this .w));
      }

      const
         l = this .magnitude (),
         v = this .imag .normalize () .multiply (Math .acos (this .w / l)),
         w = Math .log (l);

      this .x = v .x;
      this .y = v .y;
      this .z = v .z;
      this .w = w;
      return this;
   },
   exp ()
   {
      if (this .isReal ())
         return this .set (0, 0, 0, Math .exp (this .w));

      const
         i  = this .imag,
         li = i .magnitude (),
         ew = Math .exp (this .w),
         w  = ew * Math .cos (li),
         v  = i .multiply (ew * Math .sin (li) / li);

      this .x = v .x;
      this .y = v .y;
      this .z = v .z;
      this .w = w;
      return this;
   },
   slerp (destination, t)
   {
      return Math_Algorithm .slerp (this, t1 .assign (destination), t);
   },
   squad (a, b, destination, t)
   {
      // We must use shortest path slerp to prevent flipping.  Also see spline.

      return Math_Algorithm .slerp (Math_Algorithm .slerp (this, t1 .assign (destination), t),
                               Math_Algorithm .slerp (t2 .assign (a), t3 .assign (b), t),
                               2 * t * (1 - t));
   },
   toString ()
   {
      return this .x + " " +
             this .y + " " +
             this .z + " " +
             this .w;
   },
});

Object .defineProperties (Quaternion .prototype,
{
   length: { value: 4 },
   0:
   {
      get () { return this .x; },
      set (value) { this .x = value; },
   },
   1:
   {
      get () { return this .y; },
      set (value) { this .y = value; },
   },
   2:
   {
      get () { return this .z; },
      set (value) { this .z = value; },
   },
   3:
   {
      get () { return this .w; },
      set (value) { this .w = value; },
   },
   real:
   {
      get () { return this .w; },
   },
   imag:
   {
      get: (() =>
      {
         const result = new Numbers_Vector3 (0, 0, 0);

         return function ()
         {
            return result .set (this .x,
                                this .y,
                                this .z);
         };
      })(),
   },
});

Object .assign (Quaternion,
{
   Identity: new Quaternion (0, 0, 0, 1),
   spline: (() =>
   {
      const
         q0   = new Quaternion (0, 0, 0, 1),
         q1   = new Quaternion (0, 0, 0, 1),
         q2   = new Quaternion (0, 0, 0, 1),
         q1_i = new Quaternion (0, 0, 0, 1);

      return function (Q0, Q1, Q2)
      {
         q0 .assign (Q0);
         q1 .assign (Q1);
         q2 .assign (Q2);

         // If the dot product is smaller than 0 we must negate the quaternion to prevent flipping. If we negate all
         // the terms we get a different quaternion but it represents the same rotation.

         if (q0 .dot (q1) < 0)
            q0 .negate ();

         if (q2 .dot (q1) < 0)
            q2 .negate ();

         q1_i .assign (q1) .inverse ();

         // The result must be normalized as it will be used in slerp and we can only slerp normalized vectors.

         return q1 .multRight (
            t1 .assign (q1_i) .multRight (q0) .log () .add (t2 .assign (q1_i) .multRight (q2) .log ()) .divide (-4) .exp ()
         )
         .normalize () .copy ();
      };
   })(),
});

const
   t1 = new Quaternion (0, 0, 0, 1),
   t2 = new Quaternion (0, 0, 0, 1),
   t3 = new Quaternion (0, 0, 0, 1),
   Quaternion_m  = new Numbers_Matrix3 ();

const Quaternion_default_ = Quaternion;
;

x_ite_Namespace .add ("Quaternion", "standard/Math/Numbers/Quaternion", Quaternion_default_);
/* harmony default export */ const Numbers_Quaternion = (Quaternion_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Numbers/Rotation4.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







const
   _x          = Symbol (),
   _y          = Symbol (),
   _z          = Symbol (),
   _angle      = Symbol (),
   _quaternion = Symbol ();

function Rotation4 (x, y, z, angle)
{
   this [_x]     = 0;
   this [_y]     = 0;
   this [_z]     = 1;
   this [_angle] = 0;

   switch (arguments .length)
   {
      case 0:
      {
         this [_quaternion] = new Numbers_Quaternion (0, 0, 0, 1);
         return;
      }
      case 1:
      {
         this [_quaternion] = arguments [0];
         this .update ();
         return;
      }
      case 2:
      {
         const
            arg0 = arguments [0],
            arg1 = arguments [1];

         this [_quaternion] = new Numbers_Quaternion (0, 0, 0, 1);

         if (arg1 instanceof Numbers_Vector3)
            return this .setFromToVec (arg0, arg1);

         this .set (arg0 .x,
                    arg0 .y,
                    arg0 .z,
                    arg1);

         return;
      }
      case 4:
      {
         this [_quaternion] = new Numbers_Quaternion (0, 0, 0, 1);
         this .set (x, y, z, angle);
         return;
      }
   }
}

Object .assign (Rotation4 .prototype,
{
   *[Symbol .iterator] ()
   {
      yield this [_x];
      yield this [_y];
      yield this [_z];
      yield this [_angle];
   },
   update ()
   {
      const rotation = this .get ();

      this [_x]     = rotation .x;
      this [_y]     = rotation .y;
      this [_z]     = rotation .z;
      this [_angle] = rotation .w;

      return this;
   },
   copy ()
   {
      const copy = Object .create (Rotation4 .prototype);

      copy [_x]     = this [_x];
      copy [_y]     = this [_y];
      copy [_z]     = this [_z];
      copy [_angle] = this [_angle];

      copy [_quaternion]  = this [_quaternion] .copy ();

      return copy;
   },
   assign (rotation)
   {
      this [_x]     = rotation [_x];
      this [_y]     = rotation [_y];
      this [_z]     = rotation [_z];
      this [_angle] = rotation [_angle];

      this [_quaternion] .assign (rotation [_quaternion]);

      return this;
   },
   set (x, y, z, angle)
   {
      this [_x]     = x;
      this [_y]     = y;
      this [_z]     = z;
      this [_angle] = angle;

      const scale = Math .hypot (x, y, z);

      if (scale === 0)
      {
         this [_quaternion] .set (0, 0, 0, 1);
         return this;
      }

      // Calculate quaternion

      const
         halfTheta = Math_Algorithm .interval (angle / 2, 0, Math .PI),
         ascale    = Math .sin (halfTheta) / scale;

      this [_quaternion] .set (x * ascale,
                               y * ascale,
                               z * ascale,
                               Math .cos (halfTheta));
      return this;
   },
   get: (() =>
   {
      const result = new Numbers_Vector4 (0, 0, 0, 0);

      return function ()
      {
         const quaternion = this [_quaternion];

         if (Math .abs (quaternion .w) > 1)
         {
            return Numbers_Vector4 .zAxis;
         }
         else
         {
            const
               angle = Math .acos (quaternion .w) * 2,
               scale = Math .sin (angle / 2);

            if (scale === 0)
            {
               return Numbers_Vector4 .zAxis;
            }
            else
            {
               const axis = quaternion .imag .divide (scale);

               return result .set (axis .x,
                                   axis .y,
                                   axis .z,
                                   angle);
            }
         }
      };
   })(),
   setAxisAngle (axis, angle)
   {
      return this .set (axis .x, axis .y, axis .z, angle);
   },
   setFromToVec: (() =>
   {
      const
         from = new Numbers_Vector3 (0, 0, 0),
         to   = new Numbers_Vector3 (0, 0, 0),
         cv   = new Numbers_Vector3 (0, 0, 0),
         t    = new Numbers_Vector3 (0, 0, 0);

      return function (fromVec, toVec)
      {
         // https://bitbucket.org/Coin3D/coin/src/abc9f50968c9/src/base/SbRotation.cpp

         from .assign (fromVec) .normalize ();
         to   .assign (toVec)   .normalize ();

         const
            cos_angle = Math_Algorithm .clamp (from .dot (to), -1, 1),
            crossvec  = cv .assign (from) .cross (to) .normalize (),
            crosslen  = crossvec .magnitude ();

         if (crosslen === 0)
         {
            // Parallel vectors
            // Check if they are pointing in the same direction.
            if (cos_angle > 0)
               this [_quaternion] .set (0, 0, 0, 1); // standard rotation

            // Ok, so they are parallel and pointing in the opposite direction
            // of each other.
            else
            {
               // Try crossing with x axis.
               t .assign (from) .cross (Numbers_Vector3 .xAxis);

               // If not ok, cross with y axis.
               if (t .norm () === 0)
                  t .assign (from) .cross (Numbers_Vector3 .yAxis);

               t .normalize ();

               this [_quaternion] .set (t .x, t .y, t .z, 0);
            }
         }
         else
         {
            // Vectors are not parallel
            // The abs () wrapping is to avoid problems when `dot' "overflows" a tiny wee bit,
            // which can lead to sqrt () returning NaN.
            crossvec .multiply (Math .sqrt (Math .abs (1 - cos_angle) / 2));

            this [_quaternion] .set (crossvec .x,
                                     crossvec .y,
                                     crossvec .z,
                                     Math .sqrt (Math .abs (1 + cos_angle) / 2));
         }

         this .update ();

         return this;
      };
   })(),
   setAxis (vector)
   {
      this .set (vector .x, vector .y, vector .z, this [_angle]);
   },
   getAxis (axis = new Numbers_Vector3 (0, 0, 0))
   {
      return axis .set (this [_x], this [_y], this [_z]);
   },
   setQuaternion (quaternion)
   {
      this [_quaternion] .assign (quaternion) .normalize ();
      this .update ();
      return this;
   },
   getQuaternion (quaternion = new Numbers_Quaternion (0, 0, 0, 1))
   {
      return quaternion .assign (this [_quaternion]);
   },
   setMatrix (matrix)
   {
      this [_quaternion] .setMatrix (matrix) .normalize ();
      this .update ();
      return this;
   },
   getMatrix (matrix = new Numbers_Matrix3 ())
   {
      return this [_quaternion] .getMatrix (matrix);
   },
   setEuler (x, y, z, order = "XYZ")
   {
      // Quaternion is then already normalized.
		this [_quaternion] .setEuler (x, y, z, order);
      this .update ();
		return this;
	},
   getEuler (euler = [ ], order = "XYZ")
   {
      return this [_quaternion] .getEuler (euler, order);
   },
   equals (rotation)
   {
      return this [_quaternion] .equals (rotation [_quaternion]);
   },
   inverse ()
   {
      this [_quaternion] .inverse ();
      this .update ();
      return this;
   },
   multLeft (rotation)
   {
      this [_quaternion] .multLeft (rotation [_quaternion]) .normalize ();
      this .update ();
      return this;
   },
   multRight (rotation)
   {
      this [_quaternion] .multRight (rotation [_quaternion]) .normalize ();
      this .update ();
      return this;
   },
   multVecRot (vector)
   {
      return this [_quaternion] .multVecQuat (vector);
   },
   multRotVec (vector)
   {
      return this [_quaternion] .multQuatVec (vector);
   },
   normalize ()
   {
      this [_quaternion] .normalize ();
      this .update ();
      return this;
   },
   pow (exponent)
   {
      this [_quaternion] .pow (exponent);
      this .update ();
      return this;
   },
   slerp (dest, t)
   {
      this [_quaternion] .slerp (dest [_quaternion], t);
      this .update ();
      return this;
   },
   squad (a, b, dest, t)
   {
      this [_quaternion] .squad (a [_quaternion], b [_quaternion], dest [_quaternion], t);
      this .update ();
      return this;
   },
   toString ()
   {
      return this [_x] + " " +
             this [_y] + " " +
             this [_z] + " " +
             this [_angle];
   }
});

const x = {
   get ()
   {
      return this [_x];
   },
   set (x)
   {
      this [_x] = x;
      this .set (x, this [_y], this [_z], this [_angle]);
   },
   enumerable: true,
};

const y = {
   get ()
   {
      return this [_y];
   },
   set (y)
   {
      this [_y] = y;
      this .set (this [_x], y, this [_z], this [_angle]);
   },
   enumerable: true,
};

const Rotation4_z = {
   get ()
   {
      return this [_z];
   },
   set (z)
   {
      this [_z] = z;
      this .set (this [_x], this [_y], z, this [_angle]);
   },
   enumerable: true,
};

const angle = {
   get ()
   {
      return this [_angle];
   },
   set (angle)
   {
      this [_angle] = angle;
      this .set (this [_x], this [_y], this [_z], angle);
   },
   enumerable: true,
};

Object .defineProperties (Rotation4 .prototype,
{
   length: { value: 4 },
   x: x,
   y: y,
   z: Rotation4_z,
   angle: angle,
});

x     .enumerable = false;
y     .enumerable = false;
Rotation4_z     .enumerable = false;
angle .enumerable = false;

Object .defineProperties (Rotation4 .prototype,
{
   0: x,
   1: y,
   2: Rotation4_z,
   3: angle,
});

Object .assign (Rotation4,
{
   Identity: new Rotation4 (),
   fromQuaternion (quaternion)
   {
      return new Rotation4 () .setQuaternion (quaternion);
   },
   fromMatrix (matrix)
   {
      return new Rotation4 () .setMatrix (matrix);
   },
   fromEuler (x, y, z, order = "XYZ")
   {
      return new Rotation4 () .setEuler (x, y, z, order);
   },
   spline (r0, r1, r2)
   {
      const copy = Object .create (this .prototype);
      copy [_quaternion] = Numbers_Quaternion .spline (r0 [_quaternion], r1 [_quaternion], r2 [_quaternion]);
      copy .update ();
      return copy;
   },
});

const Rotation4_default_ = Rotation4;
;

x_ite_Namespace .add ("Rotation4", "standard/Math/Numbers/Rotation4", Rotation4_default_);
/* harmony default export */ const Numbers_Rotation4 = (Rotation4_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Numbers/Matrix4.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function Matrix4_Matrix4 ()
{
   if (arguments .length)
   {
      for (let i = 0; i < 16; ++ i)
         this [i] = arguments [i];
   }
   else
   {
      this .identity ();
   }
}

Object .assign (Matrix4_Matrix4 .prototype,
{
   *[Symbol .iterator] ()
   {
      for (let i = 0; i < 16; ++ i)
         yield this [i];
   },
   copy ()
   {
      const copy = Object .create (Matrix4_Matrix4 .prototype);

      for (let i = 0; i < 16; ++ i)
         copy [i] = this [i];

      return copy;
   },
   assign (matrix)
   {
      for (let i = 0; i < 16; ++ i)
         this [i] = matrix [i];

      return this;
   },
   equals (matrix)
   {
      return this [ 0] === matrix [ 0] &&
             this [ 1] === matrix [ 1] &&
             this [ 2] === matrix [ 2] &&
             this [ 3] === matrix [ 3] &&
             this [ 4] === matrix [ 4] &&
             this [ 5] === matrix [ 5] &&
             this [ 6] === matrix [ 6] &&
             this [ 7] === matrix [ 7] &&
             this [ 8] === matrix [ 8] &&
             this [ 9] === matrix [ 9] &&
             this [10] === matrix [10] &&
             this [11] === matrix [11] &&
             this [12] === matrix [12] &&
             this [13] === matrix [13] &&
             this [14] === matrix [14] &&
             this [15] === matrix [15];
   },
   set1 (r, c, value)
   {
      this [r * this .order + c] = value;

      return this;
   },
   get1 (r, c)
   {
      return this [r * this .order + c];
   },
   set: (() =>
   {
      const
         invScaleOrientation = new Numbers_Rotation4 (),
         invCenter           = new Numbers_Vector3 (0, 0, 0);

      return function (translation, rotation, scale, scaleOrientation, center)
      {
         switch (arguments .length)
         {
            case 0:
            {
               this .identity ();
               break;
            }
            case 1:
            {
               if (translation === null) translation = Numbers_Vector3 .Zero;

               this .identity ();
               this .translate (translation);
               break;
            }
            case 2:
            {
               if (translation === null) translation = Numbers_Vector3 .Zero;
               if (rotation    === null) rotation    = Numbers_Rotation4 .Identity;

               this .identity ();
               this .translate (translation);

               if (! rotation .equals (Numbers_Rotation4 .Identity))
                  this .rotate (rotation);

               break;
            }
            case 3:
            {
               if (translation === null) translation = Numbers_Vector3 .Zero;
               if (rotation    === null) rotation    = Numbers_Rotation4 .Identity;
               if (scale       === null) scale       = Numbers_Vector3 .One;

               this .identity ();
               this .translate (translation);

               if (! rotation .equals (Numbers_Rotation4 .Identity))
                  this .rotate (rotation);

               if (! scale .equals (Numbers_Vector3 .One))
                  this .scale  (scale);

               break;
            }
            case 4:
            {
               if (translation      === null) translation      = Numbers_Vector3 .Zero;
               if (rotation         === null) rotation         = Numbers_Rotation4 .Identity;
               if (scale            === null) scale            = Numbers_Vector3 .One;
               if (scaleOrientation === null) scaleOrientation = Numbers_Rotation4 .Identity;

               this .identity ();
               this .translate (translation);

               if (! rotation .equals (Numbers_Rotation4 .Identity))
                  this .rotate (rotation);

               if (! scale .equals (Numbers_Vector3 .One))
               {
                  const hasScaleOrientation = ! scaleOrientation .equals (Numbers_Rotation4 .Identity);

                  if (hasScaleOrientation)
                  {
                     this .rotate (scaleOrientation);
                     this .scale (scale);
                     this .rotate (invScaleOrientation .assign (scaleOrientation) .inverse ());
                  }
                  else
                     this .scale (scale);
               }

               break;
            }
            case 5:
            {
               if (translation      === null) translation      = Numbers_Vector3 .Zero;
               if (rotation         === null) rotation         = Numbers_Rotation4 .Identity;
               if (scale            === null) scale            = Numbers_Vector3 .One;
               if (scaleOrientation === null) scaleOrientation = Numbers_Rotation4 .Identity;
               if (center           === null) center           = Numbers_Vector3 .Zero;

               // P' = T * C * R * SR * S * -SR * -C * P
               this .identity ();
               this .translate (translation);

               const hasCenter = ! center .equals (Numbers_Vector3 .Zero);

               if (hasCenter)
                  this .translate (center);

               if (! rotation .equals (Numbers_Rotation4 .Identity))
                  this .rotate (rotation);

               if (! scale .equals (Numbers_Vector3 .One))
               {
                  if (! scaleOrientation .equals (Numbers_Rotation4 .Identity))
                  {
                     this .rotate (scaleOrientation);
                     this .scale (scale);
                     this .rotate (invScaleOrientation .assign (scaleOrientation) .inverse ());
                  }
                  else
                     this .scale (scale);
               }

               if (hasCenter)
                  this .translate (invCenter .assign (center) .negate ());

               break;
            }
            case 16:
            {
               for (let i = 0; i < 16; ++ i)
                  this [i] = arguments [i];

               break;
            }
         }

         return this;
      };
   })(),
   get: (() =>
   {
      const
         dummyTranslation      = new Numbers_Vector3 (0, 0, 0),
         dummyRotation         = new Numbers_Rotation4 (),
         dummyScale            = new Numbers_Vector3 (0, 0, 0),
         dummyScaleOrientation = new Numbers_Rotation4 (),
         dummyCenter           = new Numbers_Vector3 (0, 0, 0),
         rot                   = new Numbers_Matrix3 (),
         so                    = new Numbers_Matrix3 (),
         c                     = new Numbers_Vector3 (0, 0, 0);

      return function (translation, rotation, scale, scaleOrientation, center)
      {
         if (translation      === null) translation      = dummyTranslation;
         if (rotation         === null) rotation         = dummyRotation;
         if (scale            === null) scale            = dummyScale;
         if (scaleOrientation === null) scaleOrientation = dummyScaleOrientation;
         if (center           === null) center           = dummyCenter;

         switch (arguments .length)
         {
            case 1:
            {
               translation .set (this [12], this [13], this [14]);
               break;
            }
            case 2:
            {
               this .factor (translation, rot, dummyScale, so);
               rotation .setMatrix (rot);
               break;
            }
            case 3:
            {
               this .factor (translation, rot, scale, so);
               rotation .setMatrix (rot);
               break;
            }
            case 4:
            {
               this .factor (translation, rot, scale, so);
               rotation         .setMatrix (rot);
               scaleOrientation .setMatrix (so);
               break;
            }
            case 5:
            {
               Matrix4_m .set (c .assign (center) .negate ());
               Matrix4_m .multLeft (this);
               Matrix4_m .translate (center);
               Matrix4_m .get (translation, rotation, scale, scaleOrientation);
               break;
            }
         }
      };
   })(),
   setRotation (rotation)
   {
      return this .setQuaternion (rotation .getQuaternion (q));
   },
   setQuaternion (quaternion)
   {
      const
         { x, y, z, w } = quaternion,
         A = y * y,
         B = z * z,
         C = x * y,
         D = z * w,
         E = z * x,
         F = y * w,
         G = x * x,
         H = y * z,
         I = x * w;

      this [0]  = 1 - 2 * (A + B);
      this [1]  = 2 * (C + D);
      this [2]  = 2 * (E - F);
      this [3]  = 0;
      this [4]  = 2 * (C - D);
      this [5]  = 1 - 2 * (B + G);
      this [6]  = 2 * (H + I);
      this [7]  = 0;
      this [8]  = 2 * (E + F);
      this [9]  = 2 * (H - I);
      this [10] = 1 - 2 * (A + G);
      this [11] = 0;
      this [12] = 0;
      this [13] = 0;
      this [14] = 0;
      this [15] = 1;

      return this;
   },
   factor: (() =>
   {
      const
         si = new Numbers_Matrix3 (),
         u  = new Numbers_Matrix3 (),
         b  = new Numbers_Matrix3 ();

      const eigen = { values: [ ], vectors: [[ ], [ ], [ ]] };

      return function (translation, rotation, scale, scaleOrientation)
      {
         // (1) Get translation.
         translation .set (this [12], this [13], this [14]);

         // (2) Create 3x3 matrix.
         const a = this .submatrix;

         // (3) Compute det A. If negative, set sign = -1, else sign = 1
         const det      = a .determinant ();
         const det_sign = det < 0 ? -1 : 1;

         // (4) B = A * !A  (here !A means A transpose)
         b .assign (a) .transpose () .multLeft (a);
         const e = Algorithms_eigen_decomposition (b, eigen);

         // Find min / max eigenvalues and do ratio test to determine singularity.

         scaleOrientation .set (e .vectors [0] [0], e .vectors [1] [0], e .vectors [2] [0],
                                e .vectors [0] [1], e .vectors [1] [1], e .vectors [2] [1],
                                e .vectors [0] [2], e .vectors [1] [2], e .vectors [2] [2]);

         // Compute s = sqrt(evalues), with sign. Set si = s-inverse

         scale .x = det_sign * Math .sqrt (e .values [0]);
         scale .y = det_sign * Math .sqrt (e .values [1]);
         scale .z = det_sign * Math .sqrt (e .values [2]);

         si [0] = 1 / scale .x;
         si [4] = 1 / scale .y;
         si [8] = 1 / scale .z;

         // (5) Compute U = !R ~S R A.
         rotation .assign (u .assign (scaleOrientation) .transpose () .multRight (si) .multRight (scaleOrientation) .multRight (a));
      };
   })(),
   determinant3 ()
   {
      const
         m00 = this [0], m01 = this [1], m02 = this [ 2],
         m04 = this [4], m05 = this [5], m06 = this [ 6],
         m08 = this [8], m09 = this [9], m10 = this [10];

      return m00 * (m05 * m10 - m06 * m09) -
             m01 * (m04 * m10 - m06 * m08) +
             m02 * (m04 * m09 - m05 * m08);
   },
   determinant ()
   {
      const
         { 0: m00, 1: m01, 2: m02, 3: m03, 4: m04, 5: m05, 6: m06, 7: m07,
           8: m08, 9: m09, 10: m10, 11: m11, 12: m12, 13: m13, 14: m14, 15: m15 } = this,
         b = m10 * m15,
         c = m14 * m11,
         d = m06 * m15,
         e = m14 * m07,
         f = m06 * m11,
         g = m10 * m07,
         h = m02 * m15,
         i = m14 * m03,
         j = m02 * m11,
         o = m10 * m03,
         r = m02 * m07,
         x = m06 * m03,
         H = b * m05 + e * m09 + f * m13 - (c * m05) - (d * m09) - (g * m13),
         I = c * m01 + h * m09 + o * m13 - (b * m01) - (i * m09) - (j * m13),
         J = d * m01 + i * m05 + r * m13 - (e * m01) - (h * m05) - (x * m13),
         K = g * m01 + j * m05 + x * m09 - (f * m01) - (o * m05) - (r * m09);

      return m00 * H + m04 * I + m08 * J + m12 * K;
   },
   transpose ()
   {
      let tmp;

      tmp = this [ 1]; this [ 1] = this [ 4]; this [ 4] = tmp;
      tmp = this [ 2]; this [ 2] = this [ 8]; this [ 8] = tmp;
      tmp = this [ 3]; this [ 3] = this [12]; this [12] = tmp;
      tmp = this [ 6]; this [ 6] = this [ 9]; this [ 9] = tmp;
      tmp = this [ 7]; this [ 7] = this [13]; this [13] = tmp;
      tmp = this [11]; this [11] = this [14]; this [14] = tmp;

      return this;
   },
   inverse ()
   {
      const
         { 0: m00, 1: m01, 2: m02, 3: m03, 4: m04, 5: m05, 6: m06, 7: m07,
           8: m08, 9: m09, 10: m10, 11: m11, 12: m12, 13: m13, 14: m14, 15: m15 } = this,
         b = m10 * m15,
         c = m14 * m11,
         d = m06 * m15,
         e = m14 * m07,
         f = m06 * m11,
         g = m10 * m07,
         h = m02 * m15,
         i = m14 * m03,
         j = m02 * m11,
         o = m10 * m03,
         r = m02 * m07,
         x = m06 * m03,
         t = m08 * m13,
         p = m12 * m09,
         v = m04 * m13,
         s = m12 * m05,
         y = m04 * m09,
         z = m08 * m05,
         A = m00 * m13,
         C = m12 * m01,
         D = m00 * m09,
         E = m08 * m01,
         F = m00 * m05,
         G = m04 * m01,
         H = b * m05 + e * m09 + f * m13 - ((c * m05) + (d * m09) + (g * m13)),
         I = c * m01 + h * m09 + o * m13 - ((b * m01) + (i * m09) + (j * m13)),
         J = d * m01 + i * m05 + r * m13 - ((e * m01) + (h * m05) + (x * m13)),
         K = g * m01 + j * m05 + x * m09 - ((f * m01) + (o * m05) + (r * m09));

      let B = m00 * H + m04 * I + m08 * J + m12 * K;

      // if (B === 0) ... determinant is zero.

      B = 1 / B;

      this [ 0] = B * H;
      this [ 1] = B * I;
      this [ 2] = B * J;
      this [ 3] = B * K;
      this [ 4] = B * (c * m04 + d * m08 + g * m12 - (b * m04) - (e * m08) - (f * m12));
      this [ 5] = B * (b * m00 + i * m08 + j * m12 - (c * m00) - (h * m08) - (o * m12));
      this [ 6] = B * (e * m00 + h * m04 + x * m12 - (d * m00) - (i * m04) - (r * m12));
      this [ 7] = B * (f * m00 + o * m04 + r * m08 - (g * m00) - (j * m04) - (x * m08));
      this [ 8] = B * (t * m07 + s * m11 + y * m15 - (p * m07) - (v * m11) - (z * m15));
      this [ 9] = B * (p * m03 + A * m11 + E * m15 - (t * m03) - (C * m11) - (D * m15));
      this [10] = B * (v * m03 + C * m07 + F * m15 - (s * m03) - (A * m07) - (G * m15));
      this [11] = B * (z * m03 + D * m07 + G * m11 - (y * m03) - (E * m07) - (F * m11));
      this [12] = B * (v * m10 + z * m14 + p * m06 - (y * m14) - (t * m06) - (s * m10));
      this [13] = B * (D * m14 + t * m02 + C * m10 - (A * m10) - (E * m14) - (p * m02));
      this [14] = B * (A * m06 + G * m14 + s * m02 - (F * m14) - (v * m02) - (C * m06));
      this [15] = B * (F * m10 + y * m02 + E * m06 - (D * m06) - (G * m10) - (z * m02));

      return this;
   },
   multLeft (matrix)
   {
      const
         { 0: a00, 1: a01, 2: a02, 3: a03, 4: a04, 5: a05, 6: a06, 7: a07,
           8: a08, 9: a09, 10: a10, 11: a11, 12: a12, 13: a13, 14: a14, 15: a15 } = this,
         { 0: b00, 1: b01, 2: b02, 3: b03, 4: b04, 5: b05, 6: b06, 7: b07,
           8: b08, 9: b09, 10: b10, 11: b11, 12: b12, 13: b13, 14: b14, 15: b15 } = matrix;

      this [ 0] = a00 * b00 + a04 * b01 + a08 * b02 + a12 * b03;
      this [ 1] = a01 * b00 + a05 * b01 + a09 * b02 + a13 * b03;
      this [ 2] = a02 * b00 + a06 * b01 + a10 * b02 + a14 * b03;
      this [ 3] = a03 * b00 + a07 * b01 + a11 * b02 + a15 * b03;
      this [ 4] = a00 * b04 + a04 * b05 + a08 * b06 + a12 * b07;
      this [ 5] = a01 * b04 + a05 * b05 + a09 * b06 + a13 * b07;
      this [ 6] = a02 * b04 + a06 * b05 + a10 * b06 + a14 * b07;
      this [ 7] = a03 * b04 + a07 * b05 + a11 * b06 + a15 * b07;
      this [ 8] = a00 * b08 + a04 * b09 + a08 * b10 + a12 * b11;
      this [ 9] = a01 * b08 + a05 * b09 + a09 * b10 + a13 * b11;
      this [10] = a02 * b08 + a06 * b09 + a10 * b10 + a14 * b11;
      this [11] = a03 * b08 + a07 * b09 + a11 * b10 + a15 * b11;
      this [12] = a00 * b12 + a04 * b13 + a08 * b14 + a12 * b15;
      this [13] = a01 * b12 + a05 * b13 + a09 * b14 + a13 * b15;
      this [14] = a02 * b12 + a06 * b13 + a10 * b14 + a14 * b15;
      this [15] = a03 * b12 + a07 * b13 + a11 * b14 + a15 * b15;

      return this;
   },
   multRight (matrix)
   {
      const
         { 0: a00, 1: a01, 2: a02, 3: a03, 4: a04, 5: a05, 6: a06, 7: a07,
           8: a08, 9: a09, 10: a10, 11: a11, 12: a12, 13: a13, 14: a14, 15: a15 } = this,
         { 0: b00, 1: b01, 2: b02, 3: b03, 4: b04, 5: b05, 6: b06, 7: b07,
           8: b08, 9: b09, 10: b10, 11: b11, 12: b12, 13: b13, 14: b14, 15: b15 } = matrix;

      this [ 0] = a00 * b00 + a01 * b04 + a02 * b08 + a03 * b12;
      this [ 1] = a00 * b01 + a01 * b05 + a02 * b09 + a03 * b13;
      this [ 2] = a00 * b02 + a01 * b06 + a02 * b10 + a03 * b14;
      this [ 3] = a00 * b03 + a01 * b07 + a02 * b11 + a03 * b15;
      this [ 4] = a04 * b00 + a05 * b04 + a06 * b08 + a07 * b12;
      this [ 5] = a04 * b01 + a05 * b05 + a06 * b09 + a07 * b13;
      this [ 6] = a04 * b02 + a05 * b06 + a06 * b10 + a07 * b14;
      this [ 7] = a04 * b03 + a05 * b07 + a06 * b11 + a07 * b15;
      this [ 8] = a08 * b00 + a09 * b04 + a10 * b08 + a11 * b12;
      this [ 9] = a08 * b01 + a09 * b05 + a10 * b09 + a11 * b13;
      this [10] = a08 * b02 + a09 * b06 + a10 * b10 + a11 * b14;
      this [11] = a08 * b03 + a09 * b07 + a10 * b11 + a11 * b15;
      this [12] = a12 * b00 + a13 * b04 + a14 * b08 + a15 * b12;
      this [13] = a12 * b01 + a13 * b05 + a14 * b09 + a15 * b13;
      this [14] = a12 * b02 + a13 * b06 + a14 * b10 + a15 * b14;
      this [15] = a12 * b03 + a13 * b07 + a14 * b11 + a15 * b15;

      return this;
   },
   multVecMatrix (vector)
   {
      if (vector .length === 3)
      {
         const
            { x, y, z } = vector,
            w = 1 / (x * this [3] + y * this [7] + z * this [11] + this [15]);

         vector .x = (x * this [0] + y * this [4] + z * this [ 8] + this [12]) * w;
         vector .y = (x * this [1] + y * this [5] + z * this [ 9] + this [13]) * w;
         vector .z = (x * this [2] + y * this [6] + z * this [10] + this [14]) * w;

         return vector;
      }
      else
      {
         const { x, y, z, w } = vector;

         vector .x = x * this [0] + y * this [4] + z * this [ 8] + w * this [12];
         vector .y = x * this [1] + y * this [5] + z * this [ 9] + w * this [13];
         vector .z = x * this [2] + y * this [6] + z * this [10] + w * this [14];
         vector .w = x * this [3] + y * this [7] + z * this [11] + w * this [15];

         return vector;
      }
   },
   multMatrixVec (vector)
   {
      if (vector .length === 3)
      {
         const
            { x, y, z } = vector,
            w = 1 / (x * this [12] + y * this [13] + z * this [14] + this [15]);

         vector .x = (x * this [0] + y * this [1] + z * this [ 2] + this [ 3]) * w;
         vector .y = (x * this [4] + y * this [5] + z * this [ 6] + this [ 7]) * w;
         vector .z = (x * this [8] + y * this [9] + z * this [10] + this [11]) * w;

         return vector;
      }
      else
      {
         const { x, y, z, w } = vector;

         vector .x = x * this [ 0] + y * this [ 1] + z * this [ 2] + w * this [ 3];
         vector .y = x * this [ 4] + y * this [ 5] + z * this [ 6] + w * this [ 7];
         vector .z = x * this [ 8] + y * this [ 9] + z * this [10] + w * this [11];
         vector .w = x * this [12] + y * this [13] + z * this [14] + w * this [15];

         return vector;
      }
   },
   multDirMatrix (vector)
   {
      const { x, y, z } = vector;

      vector .x = x * this [0] + y * this [4] + z * this [ 8];
      vector .y = x * this [1] + y * this [5] + z * this [ 9];
      vector .z = x * this [2] + y * this [6] + z * this [10];

      return vector;
   },
   multMatrixDir (vector)
   {
      const { x, y, z } = vector;

      vector .x = x * this [0] + y * this [1] + z * this [ 2];
      vector .y = x * this [4] + y * this [5] + z * this [ 6];
      vector .z = x * this [8] + y * this [9] + z * this [10];

      return vector;
   },
   identity ()
   {
      this [ 0] = 1; this [ 1] = 0; this [ 2] = 0; this [ 3] = 0;
      this [ 4] = 0; this [ 5] = 1; this [ 6] = 0; this [ 7] = 0;
      this [ 8] = 0; this [ 9] = 0; this [10] = 1; this [11] = 0;
      this [12] = 0; this [13] = 0; this [14] = 0; this [15] = 1;

      return this;
   },
   translate (translation)
   {
      const { x, y, z } = translation;

      this [12] += this [ 0] * x + this [ 4] * y + this [ 8] * z;
      this [13] += this [ 1] * x + this [ 5] * y + this [ 9] * z;
      this [14] += this [ 2] * x + this [ 6] * y + this [10] * z;

      return this;
   },
   rotate (rotation)
   {
      return this .multLeft (Matrix4_m .setQuaternion (rotation .getQuaternion (q)));
   },
   scale (scale)
   {
      const { x, y, z } = scale;

      this [ 0] *= x;
      this [ 4] *= y;
      this [ 8] *= z;

      this [ 1] *= x;
      this [ 5] *= y;
      this [ 9] *= z;

      this [ 2] *= x;
      this [ 6] *= y;
      this [10] *= z;

      return this;
   },
   toString ()
   {
      return Array .prototype .join .call (this, " ");
   },
});

Object .defineProperties (Matrix4_Matrix4 .prototype,
{
   order: { value: 4 },
   length: { value: 16 },
   x:
   {
      get: (() =>
      {
         const vector = new Numbers_Vector4 (0, 0, 0, 0);

         return function () { return vector .set (this [0], this [1], this [2], this [3]); };
      })(),
   },
   y:
   {
      get: (() =>
      {
         const vector = new Numbers_Vector4 (0, 0, 0, 0);

         return function () { return vector .set (this [4], this [5], this [6], this [7]); };
      })(),
   },
   z:
   {
      get: (() =>
      {
         const vector = new Numbers_Vector4 (0, 0, 0, 0);

         return function () { return vector .set (this [8], this [9], this [10], this [11]); };
      })(),
   },
   w:
   {
      get: (() =>
      {
         const vector = new Numbers_Vector4 (0, 0, 0, 0);

         return function () { return vector .set (this [12], this [13], this [14], this [15]); };
      })(),
   },
   xAxis:
   {
      get: (() =>
      {
         const vector = new Numbers_Vector3 (0, 0, 0);

         return function () { return vector .set (this [0], this [1], this [2]); };
      })(),
   },
   yAxis:
   {
      get: (() =>
      {
         const vector = new Numbers_Vector3 (0, 0, 0);

         return function () { return vector .set (this [4], this [5], this [6]); };
      })(),
   },
   zAxis:
   {
      get: (() =>
      {
         const vector = new Numbers_Vector3 (0, 0, 0);

         return function () { return vector .set (this [8], this [9], this [10]); };
      })(),
   },
   origin:
   {
      get: (() =>
      {
         const vector = new Numbers_Vector3 (0, 0, 0);

         return function () { return vector .set (this [12], this [13], this [14]); };
      })(),
   },
   submatrix:
   {
      get: (() =>
      {
         const matrix = new Numbers_Matrix3 ();

         return function ()
         {
            matrix [0] = this [0]; matrix [1] = this [1]; matrix [2] = this [ 2];
            matrix [3] = this [4]; matrix [4] = this [5]; matrix [5] = this [ 6];
            matrix [6] = this [8]; matrix [7] = this [9]; matrix [8] = this [10];
            return matrix;
         };
      })(),
   },
});

Object .assign (Matrix4_Matrix4,
{
   Identity: new Matrix4_Matrix4 (),
   Rotation (rotation)
   {
      return Object .create (this .prototype) .setQuaternion (rotation .getQuaternion (q));
   },
   Quaternion (quaternion)
   {
      return Object .create (this .prototype) .setQuaternion (quaternion);
   },
   Matrix3 (matrix)
   {
      return new Matrix4_Matrix4 (matrix [0], matrix [1], 0, 0,
                          matrix [3], matrix [4], 0, 0,
                          0, 0, 1, 0,
                          matrix [6], matrix [7], 0, 1);
   },
   SubMatrix (matrix)
   {
      return new Matrix4_Matrix4 (matrix [0], matrix [1], matrix [2], 0,
                          matrix [3], matrix [4], matrix [5], 0,
                          matrix [6], matrix [7], matrix [8], 0,
                          0, 0, 0, 1);
   },
});

const
   q = new Numbers_Quaternion (),
   Matrix4_m = new Matrix4_Matrix4 ();

const Matrix4_default_ = Matrix4_Matrix4;
;

x_ite_Namespace .add ("Matrix4", "standard/Math/Numbers/Matrix4", Matrix4_default_);
/* harmony default export */ const Numbers_Matrix4 = (Matrix4_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFMatrix4.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






function SFMatrix4Template (TypeName, SFVec3, double)
{
   function SFMatrix4 (m00, m01, m02, m03,
                       m10, m11, m12, m13,
                       m20, m21, m22, m23,
                       m30, m31, m32, m33)
   {
      switch (arguments .length)
      {
         case 0:
            Base_X3DField .call (this, new Numbers_Matrix4 ());
            break;

         case 1:
            Base_X3DField .call (this, arguments [0]);
            break;

         case 4:
         {
            const
               r0 = arguments [0],
               r1 = arguments [1],
               r2 = arguments [2],
               r3 = arguments [3];

            Base_X3DField .call (this, new Numbers_Matrix4 (r0 .x, r0 .y, r0 .z, r0 .w,
                                                      r1 .x, r1 .y, r1 .z, r1 .w,
                                                      r2 .x, r2 .y, r2 .z, r2 .w,
                                                      r3 .x, r3 .y, r3 .z, r3 .w));

            break;
         }
         case 16:
         {
            Base_X3DField .call (this, new Numbers_Matrix4 (+m00, +m01, +m02, +m03,
                                               +m10, +m11, +m12, +m13,
                                               +m20, +m21, +m22, +m23,
                                               +m30, +m31, +m32, +m33));

            break;
         }
         default:
            throw new Error ("Invalid arguments.");
      }
   }

   Fields_SFMatrixPrototypeTemplate (SFMatrix4, TypeName, Numbers_Matrix4, SFVec3, double);

   for (const key of Object .keys (SFMatrix4 .prototype))
      Object .defineProperty (SFMatrix4 .prototype, key, { enumerable: false });

   function defineProperty (i)
   {
      Object .defineProperty (SFMatrix4 .prototype, i,
      {
         get ()
         {
            return this .getValue () [i];
         },
         set (value)
         {
            this .getValue () [i] = value;
            this .addEvent ();
         },
         enumerable: true,
      });
   }

   for (let i = 0, length = Numbers_Matrix4 .prototype .length; i < length; ++ i)
      defineProperty (i);

   return SFMatrix4;
}

const SFMatrix4 = {
   SFMatrix4d: SFMatrix4Template ("SFMatrix4d", Fields_SFVec3 .SFVec3d, true),
   SFMatrix4f: SFMatrix4Template ("SFMatrix4f", Fields_SFVec3 .SFVec3f, false),
   VrmlMatrix: SFMatrix4Template ("VrmlMatrix", Fields_SFVec3 .SFVec3f, false),
};

const SFMatrix4_default_ = SFMatrix4;
;

x_ite_Namespace .add ("SFMatrix4", "x_ite/Fields/SFMatrix4", SFMatrix4_default_);
/* harmony default export */ const Fields_SFMatrix4 = (SFMatrix4_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFNodeCache.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




const cache = new WeakMap ();

const SFNodeCache = DEVELOPMENT ?
{
   get (baseNode)
   {
      const node = cache .get (baseNode) ?.deref ();

      if (node)
      {
         return node;
      }
      else
      {
         const node = new Fields_SFNode (baseNode);

         node .dispose = dispose;

         cache .set (baseNode, new WeakRef (node));

         return node;
      }
   },
} :
{
   get (baseNode)
   {
      const node = cache .get (baseNode);

      if (node)
      {
         return node;
      }
      else
      {
         const node = new Fields_SFNode (baseNode);

         node .dispose = dispose;

         cache .set (baseNode, node);

         return node;
      }
   },
};

function dispose ()
{
   const value = this .getValue ();

   value ?.dispose ();

   Fields_SFNode .prototype .dispose .call (this);

   cache .delete (value);
}

const SFNodeCache_default_ = SFNodeCache;
;

x_ite_Namespace .add ("SFNodeCache", "x_ite/Fields/SFNodeCache", SFNodeCache_default_);
/* harmony default export */ const Fields_SFNodeCache = (SFNodeCache_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






const
   _target = Symbol (),
   _proxy  = Symbol ();

const SFNode_handler =
{
   get (target, key)
   {
      try
      {
         const value = target [key];

         if (value !== undefined)
            return value;

         const
            node       = target .getValue (),
            field      = node .getField (key),
            accessType = field .getAccessType ();

         // Specification conform would be: accessType & X3DConstants .outputOnly.
         // But we allow read access to plain fields, too.
         if (accessType === Base_X3DConstants .inputOnly)
            return undefined;

         return field .valueOf ();
      }
      catch
      {
         return undefined;
      }
   },
   set (target, key, value)
   {
      if (key in target)
      {
         target [key] = value;
         return true;
      }

      try
      {
         const
            node       = target .getValue (),
            field      = node .getField (key),
            accessType = field .getAccessType ();

         if (accessType !== Base_X3DConstants .outputOnly)
            field .setValue (value);

         return true;
      }
      catch (error)
      {
         console .error (target, key, error);
         return false;
      }
   },
   has (target, key)
   {
      try
      {
         return !! target .getValue () .getField (key);
      }
      catch
      {
         return key in target;
      }
   },
   ownKeys (target)
   {
      const
         value   = target .getValue (),
         ownKeys = [ ];

      if (value)
      {
         for (const fieldDefinition of value .getFieldDefinitions ())
            ownKeys .push (fieldDefinition .name);
      }

      return ownKeys;
   },
   getOwnPropertyDescriptor (target, key)
   {
      const value = target .getValue ();

      if (value)
      {
         const fieldDefinition = value .getFieldDefinitions () .get (key);

         if (fieldDefinition)
         {
            return {
               value: this .get (target, key),
               writable: fieldDefinition .accessType !== Base_X3DConstants .outputOnly,
               enumerable: true,
               configurable: true,
            };
         }
      }
   },
};

function SFNode (value)
{
   // Node need to test for X3DBaseNode, because there is a special version of SFNode in Script.

   const proxy = new Proxy (this, SFNode_handler);

   this [_target] = this;
   this [_proxy]  = proxy;

   if (value)
   {
      value .addParent (proxy);

      Base_X3DField .call (this, value);
   }
   else
   {
      Base_X3DField .call (this, null);
   }

   return proxy;
}

Object .assign (Object .setPrototypeOf (SFNode .prototype, Base_X3DField .prototype),
{
   [_target]: null,
   [_proxy]: null,
   copy (instance)
   {
      const
         target = this [_target],
         value  = target .getValue ();

      if (value)
         return new SFNode (instance ? value .copy (instance) : value);

      return new SFNode ();
   },
   equals (node)
   {
      const target = this [_target];

      if (node)
         return target .getValue () === node .getValue ();

      return target .getValue () === null;
   },
   isDefaultValue ()
   {
      const target = this [_target];

      return target .getValue () === null;
   },
   set (value)
   {
      const
         target  = this [_target],
         current = target .getValue ();

      if (current)
         current .removeParent (target [_proxy]);

      // No need to test for X3DBaseNode, because there is a special version of SFNode in Script.

      if (value)
      {
         value .addParent (target [_proxy]);

         Base_X3DField .prototype .set .call (target, value);
      }
      else
      {
         Base_X3DField .prototype .set .call (target, null);
      }
   },
   getNodeTypeName ()
   {
      const
         target = this [_target],
         value  = target .getValue ();

      if (value)
         return value .getTypeName ();

      throw new Error ("SFNode.getNodeTypeName: node is null.");
   },
   getNodeName ()
   {
      const
         target = this [_target],
         value  = target .getValue ();

      if (value)
         return value .getName ();

      throw new Error ("SFNode.getNodeName: node is null.");
   },
   getNodeDisplayName ()
   {
      const
         target = this [_target],
         value  = target .getValue ();

      if (value)
         return value .getDisplayName ();

      throw new Error ("SFNode.getNodeDisplayName: node is null.");
   },
   getNodeType ()
   {
      const
         target = this [_target],
         value  = target .getValue ();

      if (value)
         return Array .from (value .getType ());

      throw new Error ("SFNode.getNodeType: node is null.");
   },
   getFieldDefinitions ()
   {
      const
         target = this [_target],
         value  = target .getValue ();

      if (value)
         return value .getFieldDefinitions ();

      throw new Error ("SFNode.getFieldDefinitions: node is null.");
   },
   getField (name)
   {
      const
         target = this [_target],
         value  = target .getValue ();

      if (value)
         return value .getField (name);

      throw new Error ("SFNode is disposed.")
   },
   addFieldCallback (name, key, object)
   {
      const target = this [_target];

      switch (arguments .length)
      {
         case 2:
         {
            return Base_X3DField .prototype .addFieldCallback .apply (target, arguments);
         }
         case 3:
         {
            const value = target .getValue ();

            if (value)
               return value .getField (name) .addFieldCallback (key, object);

            throw new Error ("SFNode.addFieldCallback: node is null.");
         }
      }
   },
   removeFieldCallback (name, key)
   {
      const target = this [_target];

      switch (arguments .length)
      {
         case 1:
         {
            return Base_X3DField .prototype .removeFieldCallback .apply (target, arguments);
         }
         case 2:
         {
            const value = target .getValue ();

            if (value)
               return value .getField (name) .removeFieldCallback (key);

            throw new Error ("SFNode.removeFieldCallback: node is null.");
         }
      }
   },
   getNodeUserData (key)
   {
      const value = this [_target] .getValue ();

      if (value)
         return value .getUserData (key);

      throw new Error ("SFNode.getNodeUserData: node is null.");
   },
   setNodeUserData (key, data)
   {
      const value = this [_target] .getValue ();

      if (value)
         return value .setUserData (key, data);

      throw new Error ("SFNode.setNodeUserData: node is null.");
   },
   removeNodeUserData (key)
   {
      const value = this [_target] .getValue ();

      if (value)
         return value .removeUserData (key);

      throw new Error ("SFNode.removeNodeUserData: node is null.");
   },
   valueOf ()
   {
      const
         target = this [_target],
         value  = target .getValue ();

      return value ? Fields_SFNodeCache .get (value) : null;
   },
   toStream (generator)
   {
      const
         target = this [_target],
         value  = target .getValue ();

      if (value)
         value .toStream (generator);
      else
         generator .string += "NULL";
   },
   toVRMLStream (generator)
   {
      const
         target = this [_target],
         value  = target .getValue ();

      if (value)
         value .toVRMLStream (generator);
      else
         generator .string += "NULL";
   },
   toXMLStream (generator)
   {
      const
         target = this [_target],
         value  = target .getValue ();

      if (value)
         value .toXMLStream (generator);
      else
         generator .string += "<!-- NULL -->";
   },
   toJSONStream (generator)
   {
      this .toJSONStreamValue (generator);
   },
   toJSONStreamValue (generator)
   {
      const
         target = this [_target],
         value  = target .getValue ();

      if (value)
         value .toJSONStream (generator);
      else
         generator .string += "null";
   },
   dispose ()
   {
      const target = this [_target];

      target .set (null);
      target .processInterests ();

      Base_X3DField .prototype .dispose .call (target);
   },
});

for (const key of Object .keys (SFNode .prototype))
   Object .defineProperty (SFNode .prototype, key, { enumerable: false });

Object .defineProperties (SFNode,
{
   typeName:
   {
      value: "SFNode",
      enumerable: true,
   },
});

const SFNode_default_ = SFNode;
;

x_ite_Namespace .add ("SFNode", "x_ite/Fields/SFNode", SFNode_default_);
/* harmony default export */ const Fields_SFNode = (SFNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFRotation.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






const
   SFVec3d    = Fields_SFVec3 .SFVec3d,
   SFVec3f    = Fields_SFVec3 .SFVec3f,
   SFMatrix3d = Fields_SFMatrix3 .SFMatrix3d,
   SFMatrix3f = Fields_SFMatrix3 .SFMatrix3f;

function SFRotation (x, y, z, angle)
{
   switch (arguments .length)
   {
      case 0:
      {
         Base_X3DField .call (this, new Numbers_Rotation4 ());
         break;
      }
      case 1:
      {
         if ((arguments [0] instanceof SFMatrix3d) || (arguments [0] instanceof SFMatrix3f))
         {
            Base_X3DField .call (this, new Numbers_Rotation4 () .setMatrix (arguments [0] .getValue ()));
            break;
         }

         Base_X3DField .call (this, arguments [0]);
         break;
      }
      case 2:
      {
         if ((arguments [1] instanceof SFVec3d) || (arguments [1] instanceof SFVec3f))
         {
            Base_X3DField .call (this, new Numbers_Rotation4 (arguments [0] .getValue (), arguments [1] .getValue ()));
            break;
         }

         Base_X3DField .call (this, new Numbers_Rotation4 (arguments [0] .getValue (), +arguments [1]));
         break;
      }
      case 4:
      {
         Base_X3DField .call (this, new Numbers_Rotation4 (+x, +y, +z, +angle));
         break;
      }
      default:
         throw new Error ("Invalid arguments.");
   }
}

Object .assign (Object .setPrototypeOf (SFRotation .prototype, Base_X3DField .prototype),
{
   *[Symbol .iterator] ()
   {
      yield* this .getValue ();
   },
   copy ()
   {
      return new SFRotation (this .getValue () .copy ());
   },
   equals (rotation)
   {
      return this .getValue () .equals (rotation .getValue ());
   },
   isDefaultValue ()
   {
      return this .getValue () .equals (Numbers_Rotation4 .Identity);
   },
   set (value)
   {
      this .getValue () .assign (value);
   },
   setAxis (vector)
   {
      this .getValue () .setAxis (vector .getValue ());
      this .addEvent ();
   },
   getAxis ()
   {
      return new SFVec3f (this .getValue () .getAxis ());
   },
   setMatrix (matrix)
   {
      this .getValue () .setMatrix (matrix .getValue ());
      this .addEvent ();
   },
   getMatrix ()
   {
      return new SFMatrix3f (this .getValue () .getMatrix ());
   },
   inverse ()
   {
      return new SFRotation (this .getValue () .copy () .inverse ());
   },
   multiply (rotation)
   {
      return new SFRotation (this .getValue () .copy () .multRight (rotation .getValue ()));
   },
   multVec (vector)
   {
      return new (vector .constructor) (this .getValue () .multVecRot (vector .getValue () .copy ()));
   },
   slerp (rotation, t)
   {
      return new SFRotation (this .getValue () .copy () .slerp (rotation .getValue (), t));
   },
   toStream (generator)
   {
      const { x, y, z, angle } = this .getValue ();

      generator .string += generator .DoubleFormat (x);
      generator .string += generator .Space ();
      generator .string += generator .DoubleFormat (y);
      generator .string += generator .Space ();
      generator .string += generator .DoubleFormat (z);
      generator .string += generator .Space ();
      generator .string += generator .DoubleFormat (generator .ToUnit ("angle", angle));
   },
   toVRMLStream (generator)
   {
      this .toStream (generator);
   },
   toXMLStream (generator)
   {
      this .toStream (generator);
   },
   toJSONStream (generator)
   {
      generator .string += '[';
      generator .string += generator .TidySpace ();

      this .toJSONStreamValue (generator);

      generator .string += generator .TidySpace ();
      generator .string += ']';
   },
   toJSONStreamValue (generator)
   {
      const { x, y, z, angle } = this .getValue ();

      generator .string += generator .JSONNumber (generator .DoubleFormat (x));
      generator .string += ',';
      generator .string += generator .TidySpace ();
      generator .string += generator .JSONNumber (generator .DoubleFormat (y));
      generator .string += ',';
      generator .string += generator .TidySpace ();
      generator .string += generator .JSONNumber (generator .DoubleFormat (z));
      generator .string += ',';
      generator .string += generator .TidySpace ();
      generator .string += generator .JSONNumber (generator .DoubleFormat (generator .ToUnit ("angle", angle)));
   },
});

for (const key of Object .keys (SFRotation .prototype))
   Object .defineProperty (SFRotation .prototype, key, { enumerable: false });

const SFRotation_x = {
   get ()
   {
      return this .getValue () .x;
   },
   set (value)
   {
      this .getValue () .x = +value;
      this .addEvent ();
   },
};

const SFRotation_y = {
   get ()
   {
      return this .getValue () .y;
   },
   set (value)
   {
      this .getValue () .y = +value;
      this .addEvent ();
   },
};

const SFRotation_z = {
   get ()
   {
      return this .getValue () .z;
   },
   set (value)
   {
      this .getValue () .z = +value;
      this .addEvent ();
   },
};

const SFRotation_angle = {
   get ()
   {
      return this .getValue () .angle;
   },
   set (value)
   {
      this .getValue () .angle = +value;
      this .addEvent ();
   },
};

Object .defineProperties (SFRotation .prototype,
{
   0: SFRotation_x,
   1: SFRotation_y,
   2: SFRotation_z,
   3: SFRotation_angle,
   x: Object .assign ({ enumerable: true }, SFRotation_x),
   y: Object .assign ({ enumerable: true }, SFRotation_y),
   z: Object .assign ({ enumerable: true }, SFRotation_z),
   angle: Object .assign ({ enumerable: true }, SFRotation_angle),
});

Object .defineProperties (SFRotation,
{
   typeName:
   {
      value: "SFRotation",
      enumerable: true,
   },
});

const SFRotation_default_ = SFRotation;
;

x_ite_Namespace .add ("SFRotation", "x_ite/Fields/SFRotation", SFRotation_default_);
/* harmony default export */ const Fields_SFRotation = (SFRotation_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFString.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function SFString (value)
{
   Base_X3DField .call (this, arguments .length ? String (value) : "");
}

Object .assign (Object .setPrototypeOf (SFString .prototype, Base_X3DField .prototype),
{
   *[Symbol .iterator] ()
   {
      yield* this .getValue ();
   },
   copy ()
   {
      return new SFString (this .getValue ());
   },
   isDefaultValue ()
   {
      return this .getValue () === "";
   },
   set (value)
   {
      Base_X3DField .prototype .set .call (this, String (value));
   },
   valueOf: Base_X3DField .prototype .getValue,
   toStream (generator)
   {
      generator .string += '"';
      generator .string += SFString .escape (this .getValue ());
      generator .string += '"';
   },
   toVRMLStream (generator)
   {
      this .toStream (generator);
   },
   toXMLStream (generator, sourceText = false)
   {
      generator .string += sourceText
         ? generator .XMLEncodeSourceText (this .getValue ())
         : generator .XMLEncode (this .getValue ());
   },
   toJSONStream (generator)
   {
      this .toJSONStreamValue (generator)
   },
   toJSONStreamValue (generator)
   {
      generator .string += '"';
      generator .string += generator .JSONEncode (this .getValue ());
      generator .string += '"';
   },
});

for (const key of Object .keys (SFString .prototype))
   Object .defineProperty (SFString .prototype, key, { enumerable: false });

Object .defineProperty (SFString .prototype, "length",
{
   get ()
   {
      return this .getValue () .length;
   },
});

Object .defineProperties (SFString,
{
   typeName:
   {
      value: "SFString",
      enumerable: true,
   },
});

Object .assign (SFString,
{
   unescape (string)
   {
      return string .replace (/\\([\\"])/g, "$1");
   },
   escape (string)
   {
      return string .replace (/([\\"])/g, "\\$1");
   },
});

const SFString_default_ = SFString;
;

x_ite_Namespace .add ("SFString", "x_ite/Fields/SFString", SFString_default_);
/* harmony default export */ const Fields_SFString = (SFString_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFTime.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function SFTime (value)
{
   Base_X3DField .call (this, arguments .length ? +value : 0);
}

Object .assign (Object .setPrototypeOf (SFTime .prototype, Base_X3DField .prototype),
{
   copy ()
   {
      return new SFTime (this .getValue ());
   },
   isDefaultValue ()
   {
      return this .getValue () === 0;
   },
   set (value)
   {
      Base_X3DField .prototype .set .call (this, +value);
   },
   valueOf: Base_X3DField .prototype .getValue,
   toStream (generator)
   {
      generator .string += this .getValue ();
   },
   toVRMLStream (generator)
   {
      this .toStream (generator);
   },
   toXMLStream (generator)
   {
      this .toStream (generator);
   },
   toJSONStream (generator)
   {
      this .toJSONStreamValue (generator);
   },
   toJSONStreamValue (generator)
   {
      generator .string += generator .JSONNumber (generator .DoubleFormat (this .getValue ()));
   },
});

for (const key of Object .keys (SFTime .prototype))
   Object .defineProperty (SFTime .prototype, key, { enumerable: false });

Object .defineProperties (SFTime,
{
   typeName:
   {
      value: "SFTime",
      enumerable: true,
   },
});

const SFTime_default_ = SFTime;
;

x_ite_Namespace .add ("SFTime", "x_ite/Fields/SFTime", SFTime_default_);
/* harmony default export */ const Fields_SFTime = (SFTime_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFVec4.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function SFVec4Template (TypeName, double)
{
   function SFVec4 (x, y, z, w)
   {
      switch (arguments .length)
      {
         case 0:
            Base_X3DField .call (this, new Numbers_Vector4 (0, 0, 0, 0));
            break;

         case 1:
            Base_X3DField .call (this, arguments [0]);
            break;

         case 4:
            Base_X3DField .call (this, new Numbers_Vector4 (+x, +y, +z, +w));
            break;

         default:
            throw new Error ("Invalid arguments.");
      }
   }

   Fields_SFVecPrototypeTemplate (SFVec4, TypeName, Numbers_Vector4, double);

   for (const key of Object .keys (SFVec4 .prototype))
      Object .defineProperty (SFVec4 .prototype, key, { enumerable: false });

   const x = {
      get ()
      {
         return this .getValue () .x;
      },
      set (value)
      {
         this .getValue () .x = +value;
         this .addEvent ();
      },
   };

   const y = {
      get ()
      {
         return this .getValue () .y;
      },
      set (value)
      {
         this .getValue () .y = +value;
         this .addEvent ();
      },
   };

   const z = {
      get ()
      {
         return this .getValue () .z;
      },
      set (value)
      {
         this .getValue () .z = +value;
         this .addEvent ();
      },
   };

   const w = {
      get ()
      {
         return this .getValue () .w;
      },
      set (value)
      {
         this .getValue () .w = +value;
         this .addEvent ();
      },
   };

   Object .defineProperties (SFVec4 .prototype,
   {
      0: x,
      1: y,
      2: z,
      3: w,
      x: Object .assign ({ enumerable: true }, x),
      y: Object .assign ({ enumerable: true }, y),
      z: Object .assign ({ enumerable: true }, z),
      w: Object .assign ({ enumerable: true }, w),
   });

   return SFVec4;
}

const SFVec4 = {
   SFVec4d: SFVec4Template ("SFVec4d", true),
   SFVec4f: SFVec4Template ("SFVec4f", false),
};

const SFVec4_default_ = SFVec4;
;

x_ite_Namespace .add ("SFVec4", "x_ite/Fields/SFVec4", SFVec4_default_);
/* harmony default export */ const Fields_SFVec4 = (SFVec4_default_);
;// CONCATENATED MODULE: ./src/x_ite/Base/X3DArrayField.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function X3DArrayField (value)
{
   Base_X3DField .call (this, value);
}

Object .assign (Object .setPrototypeOf (X3DArrayField .prototype, Base_X3DField .prototype),
{
   // Implement all function also in TypedArray, if possible.
   at: Array .prototype .at,
   // concat: Array .prototype .concat,
   // copyWithin: Array.prototype.copyWithin,
   entries: Array .prototype .entries,
   every: Array .prototype .every,
   fill: Array .prototype .fill,
   filter (/* callbackFn, thisArg */)
   {
      const array = new (this .constructor) ();

      for (const v of Array .prototype .filter .call (this, ... arguments))
         array .push (v);

      return array;
   },
   find: Array .prototype .find,
   findIndex: Array .prototype .findIndex,
   findLast: Array .prototype .findLast,
   findLastIndex: Array .prototype .findLastIndex,
   // flat: Array .prototype .flat,
   // flatMap: Array .prototype .flatMap,
   forEach: Array .prototype .forEach,
   includes: Array .prototype .includes,
   indexOf: Array .prototype .indexOf,
   join: Array .prototype .join,
   keys: Array .prototype .keys,
   lastIndexOf: Array .prototype .lastIndexOf,
   map (/* callbackFn, thisArg */)
   {
      const array = new (this .constructor) ();

      for (const v of Array .prototype .map .call (this, ... arguments))
         array .push (v);

      return array;
   },
   reduce: Array .prototype .reduce,
   reduceRight: Array .prototype .reduceRight,
   reverse: Array .prototype .reverse,
   slice (/* start, end */)
   {
      const array = new (this .constructor) ();

      for (const v of Array .prototype .slice .call (this, ... arguments))
         array .push (v);

      return array;
   },
   some: Array .prototype .some,
   sort: Array .prototype .sort,
   toReversed ()
   {
      return this .copy () .reverse ();
   },
   toSorted (/* compareFn */)
   {
      return this .copy () .sort (... arguments);
   },
   toSpliced (/* start, deleteCount, ... insertValues */)
   {
      const copy = this .copy ();

      copy .splice (... arguments);

      return copy;
   },
   values: Array .prototype .values,
   with (index, value)
   {
      const copy = this .copy ();

      copy [index] = value;

      return copy;
   },
});

for (const key of Object .keys (X3DArrayField .prototype))
   Object .defineProperty (X3DArrayField .prototype, key, { enumerable: false });

const X3DArrayField_default_ = X3DArrayField;
;

x_ite_Namespace .add ("X3DArrayField", "x_ite/Base/X3DArrayField", X3DArrayField_default_);
/* harmony default export */ const Base_X3DArrayField = (X3DArrayField_default_);
;// CONCATENATED MODULE: ./src/x_ite/Base/X3DObjectArrayField.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




const
   X3DObjectArrayField_target = Symbol (),
   X3DObjectArrayField_proxy  = Symbol (),
   _insert = Symbol (),
   _erase  = Symbol ();

const X3DObjectArrayField_handler =
{
   get (target, key)
   {
      const value = target [key];

      if (value !== undefined)
         return value;

      if (typeof key === "string")
      {
         const
            array = target .getValue (),
            index = +key;

         if (Number .isInteger (index))
         {
            if (index >= array .length)
               target .resize (index + 1);

            return array [index] .valueOf ();
         }
         else
         {
            return target [key];
         }
      }
   },
   set (target, key, value)
   {
      if (key in target)
      {
         target [key] = value;
         return true;
      }

      const
         array = target .getValue (),
         index = +key;

      if (index >= array .length)
         target .resize (index + 1);

      array [index] .setValue (value);

      return true;
   },
   has (target, key)
   {
      if (Number .isInteger (+key))
         return key < target .getValue () .length;

      return key in target;
   },
   ownKeys (target)
   {
      return Object .keys (target .getValue ());
   },
   getOwnPropertyDescriptor (target, key)
   {
      if (typeof key !== "string")
         return;

      const index = +key;

      if (Number .isInteger (index) && index < target .getValue () .length)
         return Object .getOwnPropertyDescriptor (target .getValue (), key);
   },
};

function X3DObjectArrayField (values)
{
   const proxy = new Proxy (this, X3DObjectArrayField_handler);

   Base_X3DArrayField .call (this, [ ]);

   this [X3DObjectArrayField_target] = this;
   this [X3DObjectArrayField_proxy]  = proxy;

   for (const value of values)
   	this .push (value);

   return proxy;
}

Object .assign (Object .setPrototypeOf (X3DObjectArrayField .prototype, Base_X3DArrayField .prototype),
{
   [X3DObjectArrayField_target]: null,
   [X3DObjectArrayField_proxy]: null,
   *[Symbol .iterator] ()
   {
      const
         target = this [X3DObjectArrayField_target],
         array  = target .getValue ();

      for (const value of array)
         yield value .valueOf ();
   },
   getTarget ()
   {
      return this [X3DObjectArrayField_target];
   },
   copy ()
   {
      const
         target = this [X3DObjectArrayField_target],
         copy   = target .create ();

      copy .assign (target);
      copy .setModificationTime (0);

      return copy;
   },
   equals (array)
   {
      const
         target = this [X3DObjectArrayField_target],
         a      = target .getValue (),
         b      = array .getValue (),
         length = a .length;

      if (a === b)
         return true;

      if (length !== b .length)
         return false;

      for (let i = 0; i < length; ++ i)
      {
         if (!a [i] .equals (b [i]))
            return false;
      }

      return true;
   },
   isDefaultValue ()
   {
      return this .length === 0;
   },
   set (value)
   {
      const
         target    = this [X3DObjectArrayField_target],
         array     = target .getValue (),
         newLength = value .length;

      target .resize (newLength, undefined, true);

      for (let i = 0; i < newLength; ++ i)
         array [i] .set (value [i] instanceof Base_X3DField ? value [i] .getValue () : value [i]);
   },
   setValue (value)
   {
      const target = this [X3DObjectArrayField_target];

      target .set (value instanceof X3DObjectArrayField ? value .getValue () : value);
      target .addEvent ();
   },
   unshift (value)
   {
      const
         target = this [X3DObjectArrayField_target],
         array  = target .getValue ();

      for (let i = arguments .length - 1; i >= 0; -- i)
      {
         const field = new (target .getSingleType ()) ();

         field .setValue (arguments [i]);
         target .addChildObject (field);
         array .unshift (field);
      }

      target .addEvent ();

      return array .length;
   },
   shift ()
   {
      const
         target = this [X3DObjectArrayField_target],
         array  = target .getValue ();

      if (array .length)
      {
         const
            field  = array .shift (),
            result = field .valueOf ();

         target .removeChildObject (field);
         target .addEvent ();

         return result;
      }
   },
   push (value)
   {
      const
         target = this [X3DObjectArrayField_target],
         array  = target .getValue ();

      for (const argument of arguments)
      {
         const field = new (target .getSingleType ()) ();

         field .setValue (argument);
         target .addChildObject (field);
         array .push (field);
      }

      target .addEvent ();

      return array .length;
   },
   pop ()
   {
      const
         target = this [X3DObjectArrayField_target],
         array  = target .getValue ();

      if (array .length)
      {
         const
            field  = array .pop (),
            result = field .valueOf ();

         target .removeChildObject (field);
         target .addEvent ();

         return result;
      }
   },
   splice (index, deleteCount, ... insertValues)
   {
      const
         target = this [X3DObjectArrayField_target],
         array  = target .getValue (),
         length = array .length;

      if (arguments .length === 0)
         return new (target .constructor) ();

      if (arguments .length < 2)
         deleteCount = length;

      const result = target [_erase] (index, deleteCount);

      if (insertValues .length)
         target [_insert] (index, insertValues);

      return result;
   },
   [_insert] (index, array)
   {
      const
         target = this [X3DObjectArrayField_target],
         args   = [ ];

      for (const value of array)
      {
         const field = new (target .getSingleType ()) ();

         field .setValue (value);
         target .addChildObject (field);
         args .push (field);
      }

      target .getValue () .splice (index, 0, ... args);
      target .addEvent ();
   },
   [_erase] (index, deleteCount)
   {
      const
         target = this [X3DObjectArrayField_target],
         values = target .getValue () .splice (index, deleteCount),
         result = new (target .constructor) ();

      for (const value of values)
      {
         result .push (value);
         target .removeChildObject (value);
      }

      target .addEvent ();

      return result;
   },
   resize (size, value, silently)
   {
      const
         target = this [X3DObjectArrayField_target],
         array  = target .getValue (),
         length = array .length;

      if (size < length)
      {
         for (let i = size; i < length; ++ i)
            target .removeChildObject (array [i]);

         array .length = size;

         if (!silently)
            target .addEvent ();
      }
      else if (size > length)
      {
         for (let i = length; i < size; ++ i)
         {
            const field = new (target .getSingleType ()) ();

            if (value !== undefined)
               field .setValue (value);

            target .addChildObject (field);
            array .push (field);
         }

         if (!silently)
            target .addEvent ();
      }
   },
   addChildObject (value)
   {
      value .addParent (this [X3DObjectArrayField_proxy]);
   },
   removeChildObject (value)
   {
      value .removeParent (this [X3DObjectArrayField_proxy]);
      value .dispose ();
   },
   reverse ()
   {
      const target = this [X3DObjectArrayField_target];

      target .getValue () .reverse ();
      target .addEvent ();

      return target [X3DObjectArrayField_proxy];
   },
   sort (compareFn)
   {
      const target = this [X3DObjectArrayField_target];

      Array .prototype .sort .call (this, compareFn);
      target .addEvent ();

      return target [X3DObjectArrayField_proxy];
   },
   toStream (generator)
   {
      const
         target = this [X3DObjectArrayField_target],
         array  = target .getValue ();

      switch (array .length)
      {
         case 0:
         {
            generator .string += "[";
            generator .string += generator .TidySpace ();
            generator .string += "]";
            break;
         }
         case 1:
         {
            generator .PushUnitCategory (target .getUnit ());

            array [0] .toStream (generator);

            generator .PopUnitCategory ();
            break;
         }
         default:
         {
            generator .PushUnitCategory (target .getUnit ());

            generator .string += "[";
            generator .string += generator .ListStart ();
            generator .IncIndent ();

            for (let i = 0, length = array .length - 1; i < length; ++ i)
            {
               generator .string += generator .ListIndent ();
               array [i] .toStream (generator);
               generator .string += generator .Comma ();
               generator .string += generator .ListBreak ();
            }

            generator .string += generator .ListIndent ();
            array .at (-1) .toStream (generator);

            generator .string += generator .ListEnd ();
            generator .DecIndent ();
            generator .string += generator .ListIndent ();
            generator .string += "]";

            generator .PopUnitCategory ();
            break;
         }
      }
   },
   toVRMLStream (generator)
   {
      this .toStream (generator);
   },
   toXMLStream (generator)
   {
      const
         target = this [X3DObjectArrayField_target],
         length = target .length;

      if (length)
      {
         const array = target .getValue ();

         generator .PushUnitCategory (target .getUnit ());

         for (let i = 0, length = array .length - 1; i < length; ++ i)
         {
            array [i] .toXMLStream (generator);
            generator .string += generator .Comma ();
            generator .string += generator .TidySpace ();
         }

         array .at (-1) .toXMLStream (generator);

         generator .PopUnitCategory ();
      }
   },
   toJSONStream (generator)
   {
      const
         target = this [X3DObjectArrayField_target],
         length = target .length;

      if (length)
      {
         const value = this .getValue ();

         generator .PushUnitCategory (target .getUnit ());

         generator .string += '[';
         generator .string += generator .ListBreak ();
         generator .string += generator .IncIndent ();

         for (let i = 0, n = length - 1; i < n; ++ i)
         {
            generator .string += generator .ListIndent ();

            value [i] .toJSONStreamValue (generator);

            generator .string += ',';
            generator .string += generator .ListBreak ();
         }

         generator .string += generator .ListIndent ();

         value .at (-1) .toJSONStreamValue (generator);

         generator .string += generator .ListBreak ();
         generator .string += generator .DecIndent ();
         generator .string += generator .ListIndent ();
         generator .string += ']';

         generator .PopUnitCategory ();
      }
      else
      {
         generator .string += '[';
         generator .string += generator .TidySpace ();
         generator .string += ']';
      }
   },
});

for (const key of Object .keys (X3DObjectArrayField .prototype))
   Object .defineProperty (X3DObjectArrayField .prototype, key, { enumerable: false });

Object .defineProperty (X3DObjectArrayField .prototype, "length",
{
   get () { return this [X3DObjectArrayField_target] .getValue () .length; },
   set (value) { this [X3DObjectArrayField_target] .resize (value); },
});

const X3DObjectArrayField_default_ = X3DObjectArrayField;
;

x_ite_Namespace .add ("X3DObjectArrayField", "x_ite/Base/X3DObjectArrayField", X3DObjectArrayField_default_);
/* harmony default export */ const Base_X3DObjectArrayField = (X3DObjectArrayField_default_);
;// CONCATENATED MODULE: ./src/x_ite/Base/X3DTypedArrayField.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




const
   X3DTypedArrayField_target = Symbol (),
   X3DTypedArrayField_proxy  = Symbol (),
   _cache  = Symbol (),
   _tmp    = Symbol (),
   _length = Symbol (),
   X3DTypedArrayField_insert = Symbol (),
   X3DTypedArrayField_erase  = Symbol (),
   _grow   = Symbol ();

const X3DTypedArrayField_handler =
{
   get (target, key)
   {
      const value = target [key];

      if (value !== undefined)
         return value;

      if (typeof key === "string")
      {
         const index = +key;

         if (Number .isInteger (index))
         {
            const
               components = target .getComponents (),
               valueType  = target .getValueType ();

            let array = target .getValue ();

            if (index >= target [_length])
               array = target .resize (index + 1);

            if (components === 1)
            {
               // Return native JavaScript value.
               return valueType (array [index]);
            }
            else
            {
               // Return reference to index.

               return target [_cache] [index]
                  ?? (target [_cache] [index] = createValue (target, index, components, valueType));
            }
         }
         else
         {
            return target [key];
         }
      }
   },
   set (target, key, value)
   {
      if (key in target)
      {
         target [key] = value;
         return true;
      }

      const components = target .getComponents ();

      let
         index = +key,
         array = target .getValue ();

      if (index >= target [_length])
         array = target .resize (index + 1);

      if (components === 1)
      {
         const valueType = target .getValueType ();

         array [index] = valueType (value);
      }
      else
      {
         index *= components;

         for (let c = 0; c < components; ++ c, ++ index)
            array [index] = value [c];
      }

      target .addEvent ();

      return true;
   },
   has (target, key)
   {
      if (Number .isInteger (+key))
         return key < target [_length];

      return key in target;
   },
   ownKeys (target)
   {
      const ownKeys = [ ];

      for (let i = 0, length = target [_length]; i < length; ++ i)
         ownKeys .push (String (i));

      return ownKeys;
   },
   getOwnPropertyDescriptor (target, key)
   {
      if (typeof key !== "string")
         return;

      const index = +key;

      if (Number .isInteger (index) && index < target [_length])
         return Object .getOwnPropertyDescriptor (target .getValue (), key);
   },
};

function X3DTypedArrayField (values)
{
   const proxy = new Proxy (this, X3DTypedArrayField_handler);

   Base_X3DArrayField .call (this, new (this .getArrayType ()) (16));

   this [X3DTypedArrayField_target] = this;
   this [X3DTypedArrayField_proxy]  = proxy;

   if (this .getComponents () > 1)
   {
      this [_cache] = [ ]; // Cache of elements.
      this [_tmp]   = [ ]; // Array with components size.
   }

   for (const value of values)
   	this .push (value);

   return proxy;
}

Object .assign (Object .setPrototypeOf (X3DTypedArrayField .prototype, Base_X3DArrayField .prototype),
{
   [X3DTypedArrayField_target]: null,
   [_tmp]: null,
   [_length]: 0,
   *[Symbol .iterator] ()
   {
      const
         target     = this [X3DTypedArrayField_target],
         array      = target .getValue (),
         components = target .getComponents (),
         valueType  = target .getValueType (),
         length     = target [_length];

      if (components === 1)
      {
         // Return native JavaScript value.

         for (let index = 0; index < length; ++ index)
            yield valueType (array [index]);
      }
      else
      {
         // Return reference to index.

         const cache = target [_cache];

         for (let index = 0; index < length; ++ index)
         {
            yield cache [index]
               ?? (cache [index] = createValue (target, index, components, valueType));
         }
      }
   },
   getTarget ()
   {
      return this [X3DTypedArrayField_target];
   },
   copy ()
   {
      const
         target     = this [X3DTypedArrayField_target],
         array      = target .getValue (),
         copy       = target .create (),
         copyArray  = new (target .getArrayType ()) (array);

      copy [_length] = target [_length];

      Base_X3DArrayField .prototype .set .call (copy, copyArray);

      copy .setModificationTime (0);

      return copy;
   },
   equals (other)
   {
      const
         target      = this [X3DTypedArrayField_target],
         otherTarget = other [X3DTypedArrayField_target],
         length      = target [_length];

      if (target === otherTarget)
         return true;

      if (length !== otherTarget [_length])
         return false;

      const
         a = target .getValue (),
         b = otherTarget .getValue ();

      for (let i = 0, l = length * target .getComponents (); i < l; ++ i)
      {
         if (a [i] !== b [i])
            return false;
      }

      return true;
   },
   assign (value)
   {
      const target = this [X3DTypedArrayField_target];

      target .set (value .getValue (), value .length);
      target .addEvent ();
   },
   set (otherArray /* value of field */, l /* length of field */)
   {
      const
         target      = this [X3DTypedArrayField_target],
         components  = target .getComponents (),
         length      = target [_length];

      let
         array       = target .getValue (),
         otherLength = l !== undefined ? l * components : otherArray .length;

      const
         rest = otherLength % components;

      if (rest)
      {
         otherLength -= rest;

         console .warn (`Array length must be multiple of components size, which is ${components}.`);
      }

      otherLength /= components;

      if (array .length < otherArray .length)
      {
         array = target [_grow] (otherArray .length);

         array .set (otherArray);

         if (rest)
            array .fill (0, otherLength * components, otherLength * components + rest);
      }
      else
      {
         array .set (otherArray);

         if (otherLength < length)
            array .fill (0, otherLength * components, length * components);
      }

      target [_length] = otherLength;
   },
   isDefaultValue ()
   {
      return this [_length] === 0;
   },
   setValue (value)
   {
      const target = this [X3DTypedArrayField_target];

      if (value instanceof target .constructor)
      {
         target .assign (value);
      }
      else
      {
         target .set (value);
         target .addEvent ();
      }
   },
   unshift (value)
   {
      const
         target          = this [X3DTypedArrayField_target],
         components      = target .getComponents (),
         length          = target [_length],
         argumentsLength = arguments .length,
         array           = target [_grow] ((length + argumentsLength) * components);

      array .copyWithin (argumentsLength * components, 0, length * components);

      if (components === 1)
      {
         const valueType = target .getValueType ();

         for (let a = 0; a < argumentsLength; ++ a)
            array [a] = valueType (arguments [a]);
      }
      else
      {
         for (let i = 0, a = 0; a < argumentsLength; ++ a)
         {
            const argument = arguments [a];

            for (let c = 0; c < components; ++ c, ++ i)
            {
               array [i] = argument [c];
            }
         }
      }

      target [_length] += argumentsLength;

      target .addEvent ();

      return target [_length];
   },
   shift ()
   {
      const
         target = this [X3DTypedArrayField_target],
         length = target [_length];

      if (length)
      {
         const
            array      = target .getValue (),
            components = target .getComponents (),
            valueType  = target .getValueType (),
            newLength  = length - 1;

         if (components === 1)
         {
            var value = valueType (array [0]);
         }
         else
         {
            const tmp = target [_tmp];

            for (let c = 0; c < components; ++ c)
               tmp [c] = array [c];

            var value = new valueType (... tmp);
         }

         array .copyWithin (0, components, length * components);
         array .fill (0, components * newLength, length * components);

         target [_length] = newLength;

         target .addEvent ();
         return value;
      }
   },
   push (value)
   {
      const
         target          = this [X3DTypedArrayField_target],
         components      = target .getComponents (),
         length          = target [_length],
         argumentsLength = arguments .length,
         array           = target [_grow] ((length + argumentsLength) * components);

      if (components === 1)
      {
         const valueType = target .getValueType ();

         for (let a = 0, i = length; a < argumentsLength; ++ a, ++ i)
            array [i] = valueType (arguments [a]);
      }
      else
      {
         for (let i = length * components, a = 0; a < argumentsLength; ++ a)
         {
            const argument = arguments [a];

            for (let c = 0; c < components; ++ c,  ++ i)
            {
               array [i] = argument [c];
            }
         }
      }

      target [_length] += argumentsLength;

      target .addEvent ();

      return target [_length];
   },
   pop ()
   {
      const
         target = this [X3DTypedArrayField_target],
         length = target [_length];

      if (length)
      {
         const
            array      = target .getValue (),
            components = target .getComponents (),
            valueType  = target .getValueType (),
            newLength  = length - 1;

         if (components === 1)
         {
            var value = valueType (array [length - 1]); // Don't use at(-1).
         }
         else
         {
            const tmp = target [_tmp];

            for (let c = 0, a = newLength * components; c < components; ++ c, ++ a)
               tmp [c] = array [a];

            var value = new valueType (... tmp);
         }

         array .fill (0, newLength * components, length * components);

         target [_length] = newLength;

         target .addEvent ();

         return value;
      }
   },
   splice (index, deleteCount, ... insertValues)
   {
      const
         target = this [X3DTypedArrayField_target],
         length = target [_length];

      if (arguments .length === 0)
         return new (target .constructor) ();

      index = Math .min (index|0, length);

      if (arguments .length < 2)
         deleteCount = length;

      deleteCount = deleteCount|0;

      if (index + deleteCount > length)
         deleteCount = length - index;

      const result = target [X3DTypedArrayField_erase] (index, index + deleteCount);

      if (insertValues .length)
         target [X3DTypedArrayField_insert] (index, insertValues);

      target .addEvent ();

      return result;
   },
   [X3DTypedArrayField_insert] (index, other)
   {
      const
         target      = this [X3DTypedArrayField_target],
         components  = target .getComponents (),
         length      = target [_length],
         otherLength = other .length,
         array       = target [_grow] ((length + otherLength) * components);

      index *= components;

      array .copyWithin (index + otherLength * components, index, length * components);

      if (components === 1)
      {
         const valueType = target .getValueType ();

         for (let a = 0, i = index; a < otherLength; ++ a, ++ i)
            array [i] = valueType (other [a]);
      }
      else
      {
         for (let i = 0, a = index; i < otherLength; ++ i)
         {
            const value = other [i];

            for (let c = 0; c < components; ++ c, ++ a)
               array [a] = value [c];
         }
      }

      target [_length] += otherLength;
   },
   [X3DTypedArrayField_erase] (first, last)
   {
      const
         target     = this [X3DTypedArrayField_target],
         array      = target .getValue (),
         components = target .getComponents (),
         difference = last - first,
         length     = target [_length],
         newLength  = length - difference,
         values     = target [X3DTypedArrayField_proxy] .slice (first, last);

      first *= components;
      last  *= components;

      array .copyWithin (first, last, length * components);
      array .fill (0, newLength * components, length * components);

      target [_length] = newLength;

      if (components > 1)
         target [_cache] .length = newLength;

      target .addEvent ();

      return values;
   },
   resize (newLength, value, silently)
   {
      const
         target     = this [X3DTypedArrayField_target],
         length     = target [_length],
         components = target .getComponents ();

      let array = target .getValue ();

      if (newLength < length)
      {
         array .fill (0, newLength * components, length * components);

         if (components > 1)
            target [_cache] .length = newLength;

         if (!silently)
            target .addEvent ();
      }
      else if (newLength > length)
      {
         array = target [_grow] (newLength * components);

         if (value !== undefined)
         {
            if (components === 1)
            {
               array .fill (value, length * components, newLength * components);
            }
            else
            {
               for (let i = length * components, il = newLength * components; i < il; )
               {
                  for (let c = 0; c < components; ++ c, ++ i)
                  {
                     array [i] = value [c];
                  }
               }
            }
         }

         if (!silently)
            target .addEvent ();
      }

      target [_length] = newLength;

      return array;
   },
   [_grow] (length)
   {
      const
         target = this [X3DTypedArrayField_target],
         array  = target .getValue ();

      if (length < array .length)
         return array;

      const
         maxLength = Math_Algorithm .nextPowerOfTwo (length),
         newArray  = new (target .getArrayType ()) (maxLength);

      newArray .set (array);

      Base_X3DArrayField .prototype .set .call (target, newArray);

      return newArray;
   },
   shrinkToFit ()
   {
      const
         target = this [X3DTypedArrayField_target],
         array  = target .getValue (),
         length = target [_length] * target .getComponents ();

      if (array .length == length)
         return array;

      const newArray = array .subarray (0, length);

      Base_X3DArrayField .prototype .set .call (target, newArray);

      return newArray;
   },
   reverse ()
   {
      const
         target     = this [X3DTypedArrayField_target],
         array      = target .getValue (),
         components = target .getComponents (),
         length     = target [_length] * components,
         length1_2  = Math .floor (target [_length] / 2) * components;

      if (components === 1)
      {
         for (let i = 0; i < length1_2; ++ i)
         {
            const
               i2 = length - i - 1,
               t  = array [i];

            array [i]  = array [i2];
            array [i2] = t;
         }
      }
      else
      {
         for (let i = 0; i < length1_2; i += components)
         {
            for (let c = 0; c < components; ++ c)
            {
               const
                  i1 = i + c,
                  i2 = length - i - 1 - (components - c - 1),
                  t  = array [i1];

               array [i1] = array [i2];
               array [i2] = t;
            }
         }
      }

      target .addEvent ();

      return target [X3DTypedArrayField_proxy];
   },
   sort (compareFn)
   {
      const
         target     = this [X3DTypedArrayField_target],
         array      = target .getValue (),
         components = target .getComponents (),
         length     = target [_length];

      if (components === 1)
      {
         const valueType = target .getValueType ();

         const cmp = compareFn
            ? (a, b) => compareFn (valueType (a), valueType (b))
            : Math_Algorithm .cmp;

         target .set (array .subarray (0, length) .sort (cmp));
      }
      else
      {
         const result = Array .from (target [X3DTypedArrayField_proxy], value => value .copy ())
            .sort (compareFn ?? ((a, b) =>
         {
            for (let c = 0; c < components; ++ c)
            {
               if (a [c] < b [c])
                  return -1;

               if (b [c] < a [c])
                  return 1;
            }

            return 0;
         }));

         for (let i = 0; i < length; ++ i)
         {
            const value = result [i];

            for (let c = 0, first = i * components; c < components; ++ c, ++ first)
               array [first] = value [c];
         }
      }

      target .addEvent ();

      return target [X3DTypedArrayField_proxy];
   },
   toStream (generator)
   {
      const
         target     = this [X3DTypedArrayField_target],
         array      = target .getValue (),
         length     = target [_length],
         components = target .getComponents (),
         value      = new (target .getSingleType ()) ();

      switch (length)
      {
         case 0:
         {
            generator .string += "[";
            generator .string += generator .TidySpace ();
            generator .string += "]";
            break;
         }
         case 1:
         {
            generator .PushUnitCategory (target .getUnit ());

            if (components === 1)
            {
               value .set (array [0]);

               value .toStream (generator);
            }
            else
            {
               for (let c = 0, first = 0; c < components; ++ c, ++ first)
                  value [c] = array [first];

               value .toStream (generator);
            }

            generator .PopUnitCategory ();
            break;
         }
         default:
         {
            generator .PushUnitCategory (target .getUnit ());

            generator .string += "[";
            generator .string += generator .ListStart ();
            generator .IncIndent ();

            if (components === 1)
            {
               for (let i = 0, n = length - 1; i < n; ++ i)
               {
                  generator .string += generator .ListIndent ();

                  value .set (array [i * components]);
                  value .toStream (generator);

                  generator .string += generator .Comma ();
                  generator .string += generator .ListBreak ();
               }

               generator .string += generator .ListIndent ();
               value .set (array [(length - 1) * components]);
               value .toStream (generator);
            }
            else
            {
               for (let i = 0, n = length - 1; i < n; ++ i)
               {
                  generator .string += generator .ListIndent ();

                  for (let c = 0, first = i * components; c < components; ++ c, ++ first)
                     value [c] = array [first];

                  value .toStream (generator);

                  generator .string += generator .Comma ();
                  generator .string += generator .ListBreak ();
               }

               generator .string += generator .ListIndent ();

               for (let c = 0, first = (length - 1) * components; c < components; ++ c, ++ first)
                  value [c] = array [first];

               value .toStream (generator);
            }

            generator .string += generator .ListEnd ();
            generator .DecIndent ();
            generator .string += generator .ListIndent ();
            generator .string += "]";

            generator .PopUnitCategory ();
            break;
         }
      }
   },
   toVRMLStream (generator)
   {
      this .toStream (generator);
   },
   toXMLStream (generator)
   {
      const
         target = this [X3DTypedArrayField_target],
         length = target [_length];

      if (length)
      {
         const
            array      = target .getValue (),
            components = target .getComponents (),
            value      = new (target .getSingleType ()) ();

         generator .PushUnitCategory (target .getUnit ());

         if (components === 1)
         {
            for (let i = 0, n = length - 1; i < n; ++ i)
            {
               value .set (array [i * components]);
               value .toXMLStream (generator);

               generator .string += generator .Comma ();
               generator .string += generator .TidySpace ();
            }

            value .set (array [(length - 1) * components]);

            value .toXMLStream (generator);
         }
         else
         {
            for (let i = 0, n = length - 1; i < n; ++ i)
            {
               for (let c = 0, first = i * components; c < components; ++ c, ++ first)
                  value [c] = array [first];

               value .toXMLStream (generator);

               generator .string += generator .Comma ();
               generator .string += generator .TidySpace ();
            }

            for (let c = 0, first = (length - 1) * components; c < components; ++ c, ++ first)
               value [c] = array [first];

            value .toXMLStream (generator);
         }

         generator .PopUnitCategory ();
      }
   },
   toJSONStream (generator)
   {
      const
         target = this [X3DTypedArrayField_target],
         length = target .length;

      if (length)
      {
         const
            array      = target .getValue (),
            components = target .getComponents (),
            value      = new (target .getSingleType ()) ();

         generator .PushUnitCategory (target .getUnit ());

         generator .string += '[';
         generator .string += generator .ListBreak ();
         generator .string += generator .IncIndent ();

         if (components === 1)
         {
            for (let i = 0, n = length - 1; i < n; ++ i)
            {
               generator .string += generator .ListIndent ();

               value .set (array [i * components]);
               value .toJSONStreamValue (generator);

               generator .string += ',';
               generator .string += generator .ListBreak ();
            }

            generator .string += generator .ListIndent ();

            value .set (array [(length - 1) * components]);
            value .toJSONStreamValue (generator);
         }
         else
         {
            for (let i = 0, n = length - 1; i < n; ++ i)
            {
               generator .string += generator .ListIndent ();

               for (let c = 0, first = i * components; c < components; ++ c, ++ first)
                  value [c] = array [first];

               value .toJSONStreamValue (generator);

               generator .string += ',';
               generator .string += generator .ListBreak ();
            }

            generator .string += generator .ListIndent ();

            for (let c = 0, first = (length - 1) * components; c < components; ++ c, ++ first)
               value [c] = array [first];

            value .toJSONStreamValue (generator);
         }

         generator .string += generator .ListBreak ();
         generator .string += generator .DecIndent ();
         generator .string += generator .ListIndent ();
         generator .string += ']';

         generator .PopUnitCategory ();
      }
      else
      {
         generator .string += '[';
         generator .string += generator .TidySpace ();
         generator .string += ']';
      }
   },
   dispose ()
   {
      Base_X3DArrayField .prototype .dispose .call (this [X3DTypedArrayField_target]);
   },
});

for (const key of Object .keys (X3DTypedArrayField .prototype))
   Object .defineProperty (X3DTypedArrayField .prototype, key, { enumerable: false });

Object .defineProperty (X3DTypedArrayField .prototype, "length",
{
   get () { return this [_length]; },
   set (value) { this [X3DTypedArrayField_target] .resize (value); },
});

// Getter/Setter functions to reference a value for a given index.

function createValue (target, index, components, valueType)
{
   const
      value         = new valueType (),
      internalValue = value .getValue (),
      i             = index * components;

   value .addEvent = addEvent .bind (target, i, components, internalValue);
   value .getValue = getValue .bind (target, i, components, internalValue);

   return value;
}

function getValue (index, components, value)
{
   const array = this .getValue ();

   for (let c = 0; c < components; ++ c, ++ index)
      value [c] = array [index];

   return value;
}

function addEvent (index, components, value)
{
   const array = this .getValue ();

   for (let c = 0; c < components; ++ c, ++ index)
      array [index] = value [c];

   this .addEvent ();
}

const X3DTypedArrayField_default_ = X3DTypedArrayField;
;

x_ite_Namespace .add ("X3DTypedArrayField", "x_ite/Base/X3DTypedArrayField", X3DTypedArrayField_default_);
/* harmony default export */ const Base_X3DTypedArrayField = (X3DTypedArrayField_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/ArrayFields.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




















const
   { SFMatrix3d: ArrayFields_SFMatrix3d, SFMatrix3f: ArrayFields_SFMatrix3f } = Fields_SFMatrix3,
   { SFMatrix4d, SFMatrix4f } = Fields_SFMatrix4,
   { SFVec2d, SFVec2f }       = Fields_SFVec2,
   { SFVec3d: ArrayFields_SFVec3d, SFVec3f: ArrayFields_SFVec3f }       = Fields_SFVec3,
   { SFVec4d, SFVec4f }       = Fields_SFVec4;

/*
 *  MFNode
 */

function MFNode (... args)
{
   return Base_X3DObjectArrayField .call (this, args);
}

Object .assign (Object .setPrototypeOf (MFNode .prototype, Base_X3DObjectArrayField .prototype),
{
   getSingleType ()
   {
      return Fields_SFNode;
   },
   copy (instance)
   {
      if (instance)
      {
         const copy = new MFNode ();

         for (const node of this .getValue ())
            copy .push (node .copy (instance));

         copy .setModificationTime (0);

         return copy;
      }
      else
      {
         return Base_X3DObjectArrayField .prototype .copy .call (this);
      }
   },
   toStream (generator)
   {
      const
         target = this .getTarget (),
         array  = target .getValue (),
         length = array .length;

      switch (length)
      {
         case 0:
         {
            generator .string += "[";
            generator .string += generator .TidySpace ();
            generator .string += "]";
            break;
         }
         case 1:
         {
            generator .PushUnitCategory (target .getUnit ());

            array [0] .toStream (generator);

            generator .PopUnitCategory ();
            break;
         }
         default:
         {
            generator .PushUnitCategory (target .getUnit ());

            generator .string += "[";
            generator .string += generator .TidyBreak ();
            generator .IncIndent ();

            for (let i = 0; i < length; ++ i)
            {
               generator .string += generator .Indent ();
               array [i] .toStream (generator);
               generator .string += generator .string .at (-1) === "}" ? generator .TidyBreak () : generator .Break ();
            }

            generator .DecIndent ();
            generator .string += generator .Indent ();
            generator .string += "]";

            generator .PopUnitCategory ();
            break;
         }
      }
   },
   toVRMLStream (generator)
   {
      const
         target = this .getTarget (),
         array  = target .getValue (),
         length = array .length;

      switch (length)
      {
         case 0:
         {
            generator .string += "[";
            generator .string += generator .TidySpace ();
            generator .string += "]";
            break;
         }
         case 1:
         {
            generator .EnterScope ();

            array [0] .toVRMLStream (generator);

            generator .LeaveScope ();
            break;
         }
         default:
         {
            generator .EnterScope ();

            generator .string += "[";
            generator .string += generator .TidyBreak ();
            generator .IncIndent ();

            for (const element of array)
            {
               generator .string += generator .Indent ();
               element .toVRMLStream (generator);
               generator .string += generator .string .at (-1) === "}" ? generator .TidyBreak () : generator .Break ();
            }

            generator .DecIndent ();
            generator .string += generator .Indent ();
            generator .string += "]";

            generator .LeaveScope ();
            break;
         }
      }
   },
   toXMLStream (generator)
   {
      const
         target = this .getTarget (),
         length = target .length;

      if (length)
      {
         generator .EnterScope ();

         const array = target .getValue ();

         for (let i = 0, n = length - 1; i < n; ++ i)
         {
            const node = array [i] .getValue ();

            if (node)
            {
               node .toXMLStream (generator);
               generator .string += generator .TidyBreak ();
            }
            else
            {
               generator .string += generator .Indent ();
               generator .string += "<";
               generator .string += "NULL";

               const containerField = generator .ContainerField ();

               if (containerField)
               {
                  generator .string += generator .Space ();
                  generator .string += "containerField='";
                  generator .string += generator .XMLEncode (containerField .getName ());
                  generator .string += "'";
               }

               generator .string += generator .closingTags ? "></NULL>" : "/>";
            }
         }

         const node = array .at (-1) .getValue ();

         if (node)
         {
            node .toXMLStream (generator);
         }
         else
         {
            generator .string += generator .Indent ();
            generator .string += "<";
            generator .string += "NULL";

            const containerField = generator .ContainerField ();

            if (containerField)
            {
               generator .string += generator .Space ();
               generator .string += "containerField='";
               generator .string += generator .XMLEncode (containerField .getName ());
               generator .string += "'";
            }
         }

         generator .LeaveScope ();
      }
   },
   toJSONStream (generator)
   {
      const
         target = this .getTarget (),
         length = target .length;

      if (length)
      {
         const array = target .getValue ();

         generator .EnterScope ();

         generator .string += '[';
         generator .string += generator .TidyBreak ();
         generator .string += generator .IncIndent ();

         for (let i = 0, n = length - 1; i < n; ++ i)
         {
            generator .string += generator .Indent ();

            if (array [i])
               array [i] .toJSONStreamValue (generator);
            else
               generator .string += 'null';

            generator .string += ',';
            generator .string += generator .TidyBreak ();
         }

         generator .string += generator .Indent ();

         if (array .at (-1))
            array .at (-1) .toJSONStreamValue (generator);
         else
            generator .string += 'null';

         generator .string += generator .TidyBreak ();
         generator .string += generator .DecIndent ();
         generator .string += generator .Indent ();
         generator .string += ']';

         generator .LeaveScope ();
      }
      else
      {
         generator .string += '[';
			generator .string += generator .TidySpace ();
			generator .string += ']';
      }
   },
   dispose ()
   {
      const target = this .getTarget ();

      target .resize (0, undefined, false);
      target .processInterests ();

      Base_X3DObjectArrayField .prototype .dispose .call (target);
   },
});

for (const key of Object .keys (MFNode .prototype))
   Object .defineProperty (MFNode .prototype, key, { enumerable: false });

Object .defineProperties (MFNode,
{
   typeName:
   {
      value: "MFNode",
      enumerable: true,
   },
});

function MFString (... args)
{
   return Base_X3DObjectArrayField .call (this, args);
}

Object .assign (Object .setPrototypeOf (MFString .prototype, Base_X3DObjectArrayField .prototype),
{
   getSingleType ()
   {
      return Fields_SFString;
   },
   toXMLStream (generator, sourceText = false)
   {
      const
         target = this .getTarget (),
         length = target .length;

      if (length)
      {
         const value = target .getValue ();

         for (let i = 0, n = length - 1; i < n; ++ i)
         {
            generator .string += "\"";
            value [i] .toXMLStream (generator, sourceText);
            generator .string += "\"";
            generator .string += generator .Comma ();
            generator .string += generator .TidySpace ();
         }

         generator .string += "\"";
         value .at (-1) .toXMLStream (generator, sourceText);
         generator .string += "\"";
      }
   },
});

for (const key of Object .keys (MFString .prototype))
   Object .defineProperty (MFString .prototype, key, { enumerable: false });

Object .defineProperties (MFString,
{
   typeName:
   {
      value: "MFString",
      enumerable: true,
   },
});

/**
 * MFImage
 */

function MFImage (... args)
{
   return Base_X3DObjectArrayField .call (this, args);
}

Object .assign (Object .setPrototypeOf (MFImage .prototype, Base_X3DObjectArrayField .prototype),
{
   getSingleType ()
   {
      return Fields_SFImage;
   },
});

for (const key of Object .keys (MFImage .prototype))
   Object .defineProperty (MFImage .prototype, key, { enumerable: false });

Object .defineProperties (MFImage,
{
   typeName:
   {
      value: "MFImage",
      enumerable: true,
   },
});

function TypedArrayTemplate (TypeName, SingleType, ValueType, ArrayType, Components)
{
   function ArrayField (... args)
   {
      return Base_X3DTypedArrayField .call (this, args);
   }

   Object .assign (Object .setPrototypeOf (ArrayField .prototype, Base_X3DTypedArrayField .prototype),
   {
      getSingleType ()
      {
         return SingleType;
      },
      getValueType ()
      {
         return ValueType;
      },
      getArrayType ()
      {
         return ArrayType;
      },
      getComponents ()
      {
         return Components;
      },
   });

   for (const key of Object .keys (ArrayField .prototype))
      Object .defineProperty (ArrayField .prototype, key, { enumerable: false });

   Object .defineProperties (ArrayField,
   {
      typeName:
      {
         value: TypeName,
         enumerable: true,
      },
   });

   return ArrayField;
}

const Value = value => value;

const ArrayFields =
{
   MFBool:      TypedArrayTemplate ("MFBool",      Fields_SFBool,      Boolean,     Uint8Array,   1),
   MFColor:     TypedArrayTemplate ("MFColor",     Fields_SFColor,     Fields_SFColor,     Float32Array, 3),
   MFColorRGBA: TypedArrayTemplate ("MFColorRGBA", Fields_SFColorRGBA, Fields_SFColorRGBA, Float32Array, 4),
   MFDouble:    TypedArrayTemplate ("MFDouble",    Fields_SFDouble,    Value,       Float64Array, 1),
   MFFloat:     TypedArrayTemplate ("MFFloat",     Fields_SFFloat,     Value,       Float32Array, 1),
   MFImage:     MFImage,
   MFInt32:     TypedArrayTemplate ("MFInt32",     Fields_SFInt32,     Value,       Int32Array,   1),
   MFMatrix3d:  TypedArrayTemplate ("MFMatrix3d",  ArrayFields_SFMatrix3d,  ArrayFields_SFMatrix3d,  Float64Array, 9),
   MFMatrix3f:  TypedArrayTemplate ("MFMatrix3f",  ArrayFields_SFMatrix3f,  ArrayFields_SFMatrix3f,  Float32Array, 9),
   MFMatrix4d:  TypedArrayTemplate ("MFMatrix4d",  SFMatrix4d,  SFMatrix4d,  Float64Array, 16),
   MFMatrix4f:  TypedArrayTemplate ("MFMatrix4f",  SFMatrix4f,  SFMatrix4f,  Float32Array, 16),
   MFNode:      MFNode,
   MFRotation:  TypedArrayTemplate ("MFRotation",  Fields_SFRotation,  Fields_SFRotation,  Float64Array, 4),
   MFString:    MFString,
   MFTime:      TypedArrayTemplate ("MFTime",      Fields_SFTime,      Value,       Float64Array, 1),
   MFVec2d:     TypedArrayTemplate ("MFVec2d",     SFVec2d,     SFVec2d,     Float64Array, 2),
   MFVec2f:     TypedArrayTemplate ("MFVec2f",     SFVec2f,     SFVec2f,     Float32Array, 2),
   MFVec3d:     TypedArrayTemplate ("MFVec3d",     ArrayFields_SFVec3d,     ArrayFields_SFVec3d,     Float64Array, 3),
   MFVec3f:     TypedArrayTemplate ("MFVec3f",     ArrayFields_SFVec3f,     ArrayFields_SFVec3f,     Float32Array, 3),
   MFVec4d:     TypedArrayTemplate ("MFVec4d",     SFVec4d,     SFVec4d,     Float64Array, 4),
   MFVec4f:     TypedArrayTemplate ("MFVec4f",     SFVec4f,     SFVec4f,     Float32Array, 4),
};

const ArrayFields_default_ = ArrayFields;
;

x_ite_Namespace .add ("ArrayFields", "x_ite/Fields/ArrayFields", ArrayFields_default_);
/* harmony default export */ const Fields_ArrayFields = (ArrayFields_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields/SFImage.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





const MFInt32 = Fields_ArrayFields .MFInt32;

/*
 *  Image
 */

function Image (width, height, comp, array)
{
   this .width  = Math .max (width|0, 0);
   this .height = Math .max (height|0, 0);
   this .comp   = Math_Algorithm .clamp (comp|0, 0, 4);
   this .array  = new MFInt32 ();
   this .array .setValue (array);
   this .array .length = this .width * this .height;
}

Object .assign (Image .prototype,
{
   copy ()
   {
      return new Image (this .width, this .height, this .comp, this .array);
   },
   equals (image)
   {
      return this .width  === image .width &&
             this .height === image .height &&
             this .comp   === image .comp &&
             this .array .equals (image .array);
   },
   assign (image)
   {
      this .width  = image .width;
      this .height = image .height;
      this .comp   = image .comp;
      this .array .assign (image .array);
   },
   set (width, height, comp, array)
   {
      this .width  = width|0;
      this .height = height|0;
      this .comp   = comp|0;
      this .array .assign (array);
   },
   setWidth (value)
   {
      this .width = Math .max (value|0, 0);
      this .array .length = this .width * this .height;
   },
   getWidth ()
   {
      return this .width;
   },
   setHeight (value)
   {
      this .height = Math .max (value|0, 0);
      this .array .length = this .width * this .height;
   },
   getHeight ()
   {
      return this .height;
   },
   setComp (value)
   {
      this .comp = Math_Algorithm .clamp (value|0, 0, 4);
   },
   getComp ()
   {
      return this .comp;
   },
   setArray (value)
   {
      this .array .setValue (value);
      this .array .length = this .width * this .height;
   },
   getArray ()
   {
      return this .array;
   },
});

/*
 *  SFImage
 */

const _set_size = Symbol ();

function SFImage (width, height, comp, array)
{
   switch (arguments .length)
   {
      case 0:
         Base_X3DField .call (this, new Image (0, 0, 0, new MFInt32 ()));
         break;

      case 1:
         Base_X3DField .call (this, arguments [0]);
         break;

      case 3:
         Base_X3DField .call (this, new Image (width, height, comp, new MFInt32 ()));
         break;

      case 4:
         Base_X3DField .call (this, new Image (width, height, comp, array));
         break;

      default:
         throw new Error ("Invalid arguments.");
   }

   this .getValue () .getArray () .addParent (this);
   this .addInterest (_set_size, this);
}

Object .assign (Object .setPrototypeOf (SFImage .prototype, Base_X3DField .prototype),
{
   [_set_size] ()
   {
      this .getValue () .getArray () .length = this .width * this .height;
   },
   *[Symbol .iterator] ()
   {
      yield this .width;
      yield this .height;
      yield this .comp;
      yield this .array;
   },
   copy ()
   {
      return new SFImage (this .getValue () .copy ());
   },
   equals (image)
   {
      return this .getValue () .equals (image .getValue ());
   },
   isDefaultValue ()
   {
      return (
         this .width  === 0 &&
         this .height === 0 &&
         this .comp   === 0);
   },
   set (image)
   {
      this .getValue () .assign (image);
   },
   toStream (generator)
   {
      const array = this .array;

      generator .string += this .width;
      generator .string += generator .Space ();
      generator .string += this .height;
      generator .string += generator .Space ();
      generator .string += this .comp;
      generator .string += generator .AttribBreak ();

      generator .IncIndent ();

      for (let y = 0, h = this .height; y < h; ++ y)
      {
         generator .string += generator .ListIndent ();

         const s = y * this .width;

         for (let x = 0, w = this .width; x < w; ++ x)
         {
            generator .string += "0x";
            generator .string += array [x + s] .toString (16);

            if (x !== w - 1)
               generator .string += generator .Space ();
         }

         if (y !== h - 1)
            generator .string += generator .AttribBreak ();
      }

      generator .DecIndent ();
   },
   toVRMLStream (generator)
   {
      this .toStream (generator);
   },
   toXMLStream (generator)
   {
      this .toStream (generator);
   },
   toJSONStream (generator)
   {
      generator .string += '[';
      generator .string += generator .ListBreak ();
      generator .string += generator .IncIndent ();
      generator .string += generator .ListIndent ();

      this .toJSONStreamValue (generator);

      generator .string += generator .DecIndent ();
      generator .string += generator .ListBreak ();
      generator .string += generator .ListIndent ();
      generator .string += ']';
   },
   toJSONStreamValue (generator)
   {
      const
         array  = this .array,
         length = array .length;

      generator .string += this .width;
      generator .string += ',';
      generator .string += generator .TidySpace ();
      generator .string += this .height;
      generator .string += ',';
      generator .string += generator .TidySpace ();
      generator .string += this .comp;
      generator .string += ',';

      if (this .width && this .height)
      {
         generator .string += generator .ListBreak ();
         generator .string += generator .IncIndent ();

         for (let y = 0, h = this .height; y < h; ++ y)
         {
            generator .string += generator .ListIndent ();

            const s = y * this .width;

            for (let x = 0, w = this .width; x < w; ++ x)
            {
               generator .string += array [x + s];

               if (x + s !== length - 1)
                  generator .string += ',';

               if (x !== w - 1)
                  generator .string += generator .TidySpace ();
            }

            if (y !== h - 1)
               generator .string += generator .ListBreak ();
         }

         generator .string += generator .DecIndent ();
      }
   },
});

for (const key of Object .keys (SFImage .prototype))
   Object .defineProperty (SFImage .prototype, key, { enumerable: false });

const width = {
   get ()
   {
      return this .getValue () .getWidth ();
   },
   set (value)
   {
      this .getValue () .setWidth (value);
      this .addEvent ();
   },
};

const height = {
   get ()
   {
      return this .getValue () .getHeight ();
   },
   set (value)
   {
      this .getValue () .setHeight (value);
      this .addEvent ();
   },
};

const comp = {
   get ()
   {
      return this .getValue () .getComp ();
   },
   set (value)
   {
      this .getValue () .setComp (value);
      this .addEvent ();
   },
};

const array = {
   get ()
   {
      return this .getValue () .getArray ();
   },
   set (value)
   {
      this .getValue () .setArray (value);
      this .addEvent ();
   },
};

Object .defineProperties (SFImage .prototype,
{
   x: width,
   y: height,
   width:  Object .assign ({ enumerable: true }, width),
   height: Object .assign ({ enumerable: true }, height),
   comp:   Object .assign ({ enumerable: true }, comp),
   array:  Object .assign ({ enumerable: true }, array),
});

Object .defineProperties (SFImage,
{
   typeName:
   {
      value: "SFImage",
      enumerable: true,
   },
});

const SFImage_default_ = SFImage;
;

x_ite_Namespace .add ("SFImage", "x_ite/Fields/SFImage", SFImage_default_);
/* harmony default export */ const Fields_SFImage = (SFImage_default_);
;// CONCATENATED MODULE: ./src/x_ite/Fields.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



















const Fields = {
   SFBool:      Fields_SFBool,
   SFColor:     Fields_SFColor,
   SFColorRGBA: Fields_SFColorRGBA,
   SFDouble:    Fields_SFDouble,
   SFFloat:     Fields_SFFloat,
   SFImage:     Fields_SFImage,
   SFInt32:     Fields_SFInt32,
   ... Fields_SFMatrix3,
   ... Fields_SFMatrix4,
   SFNode:      Fields_SFNode,
   SFRotation:  Fields_SFRotation,
   SFString:    Fields_SFString,
   SFTime:      Fields_SFTime,
   ... Fields_SFVec2,
   ... Fields_SFVec3,
   ... Fields_SFVec4,

   ... Fields_ArrayFields,
};

const Fields_default_ = Fields;
;

x_ite_Namespace .add ("Fields", "x_ite/Fields", Fields_default_);
/* harmony default export */ const x_ite_Fields = (Fields_default_);
;// CONCATENATED MODULE: ./src/x_ite/Parser/HTMLSupport.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This file is part of the X_ITE Project.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains "non-military use only" components.
 *
 * Copyright 2016 Andreas Plesch.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



const
   nodeTypeNames = new Map (), // (TYPENAME -> TypeName)
   fieldNames    = new Map (); // (fieldname -> fieldName)

const HTMLSupport =
{
   addConcreteNode ({ typeName, fieldDefinitions })
   {
      if (nodeTypeNames .has (typeName))
         return;

      this .addNodeTypeName (typeName);

      for (const { name, accessType } of fieldDefinitions)
      {
         if (accessType & Base_X3DConstants .initializeOnly)
            this .addFieldName (name)
      }
   },
   addNodeTypeName (typeName)
   {
      nodeTypeNames .set (typeName,                 typeName);
      nodeTypeNames .set (typeName .toUpperCase (), typeName);
   },
   getNodeTypeName (typeName)
   {
      return nodeTypeNames .get (typeName);
   },
   addFieldName (name)
   {
      fieldNames .set (name,                 name);
      fieldNames .set (name .toLowerCase (), name);
   },
   getFieldName (name)
   {
      return fieldNames .get (name);
   },
};

const HTMLSupport_default_ = HTMLSupport;
;

x_ite_Namespace .add ("HTMLSupport", "x_ite/Parser/HTMLSupport", HTMLSupport_default_);
/* harmony default export */ const Parser_HTMLSupport = (HTMLSupport_default_);
;// CONCATENATED MODULE: ./src/x_ite/Base/X3DBaseNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










const
   _browser           = Symbol (),
   _executionContext  = Symbol (),
   _type              = Symbol (),
   _fieldDefinitions  = Symbol .for ("X_ITE.X3DBaseNode.fieldDefinitions"),
   _predefinedFields  = Symbol (),
   _userDefinedFields = Symbol (),
   _childObjects      = Symbol (),
   _initialized       = Symbol (),
   _live              = Symbol (),
   _set_live__        = Symbol ();

function X3DBaseNode (executionContext, browser = executionContext .getBrowser ())
{
   if (this [_executionContext])
      return;

   Base_X3DChildObject .call (this);

   this [_browser]           = browser;
   this [_executionContext]  = executionContext;
   this [_type]              = [ Base_X3DConstants .X3DBaseNode ];
   this [_fieldDefinitions]  = this .constructor .fieldDefinitions ?? this [_fieldDefinitions];
   this [_predefinedFields]  = new Base_FieldArray ();
   this [_userDefinedFields] = new Base_FieldArray ();
   this [_childObjects]      = [ ];
   this [_live]              = true;
   this [_initialized]       = false;

   if (this .canUserDefinedFields ())
      this [_fieldDefinitions] = new Base_FieldDefinitionArray (this [_fieldDefinitions]);

   // Create fields.

   this .addChildObjects (Base_X3DConstants .outputOnly, "name_changed",     new x_ite_Fields .SFTime (),
                          Base_X3DConstants .outputOnly, "typeName_changed", new x_ite_Fields .SFTime (),
                          Base_X3DConstants .outputOnly, "parents_changed",  new x_ite_Fields .SFTime ())

   for (const fieldDefinition of this [_fieldDefinitions])
      this .addPredefinedField (fieldDefinition);
}

Object .assign (Object .setPrototypeOf (X3DBaseNode .prototype, Base_X3DChildObject .prototype),
{
   [_fieldDefinitions]: new Base_FieldDefinitionArray ([ ]),
   setName (value)
   {
      Base_X3DChildObject .prototype .setName .call (this, value)

      this ._name_changed = this [_browser] .getCurrentTime ();
   },
   getBrowser ()
   {
      return this [_browser];
   },
   getMainScene ()
   {
      let scene = this [_executionContext] .getScene ();

      while (!scene .isMainScene ())
         scene = scene .getScene ();

      return scene;
   },
   getScene ()
   {
      let executionContext = this [_executionContext];

      while (!executionContext .isScene ())
         executionContext = executionContext .getExecutionContext ();

      return executionContext;
   },
   getExecutionContext ()
   {
      return this [_executionContext];
   },
   setExecutionContext (value)
   {
      // Currently only useful for Scene.
      this [_executionContext] = value;
   },
   addType (value)
   {
      this [_type] .push (value);
   },
   getType ()
   {
      return this [_type];
   },
   create (executionContext = this [_executionContext])
   {
      return new (this .constructor) (executionContext);
   },
   copy (executionContext)
   {
      const copy = this .create (executionContext);

      for (const field of this [_predefinedFields])
         copy .getPredefinedFields () .get (field .getName ()) .assign (field);

      if (this .canUserDefinedFields ())
      {
         for (const field of this [_userDefinedFields])
            copy .addUserDefinedField (field .getAccessType (), field .getName (), field .copy ());
      }

      copy .setup ();

      return copy;
   },
   // replaceWith (replacement, cache = false)
   // {
   //    cache = cache && SFNodeCache .get (this);

   //    for (const parent of new Set (this .getParents ()))
   //    {
   //       if (parent instanceof Fields .SFNode && parent !== cache)
   //          parent .setValue (replacement)
   //    }
   // },
   setup ()
   {
      Object .freeze (this [_type]);

      this [_fieldDefinitions]  .addParent (this);
      this [_predefinedFields]  .addParent (this);
      this [_userDefinedFields] .addParent (this);

      for (const field of this [_childObjects])
         field .setTainted (false);

      for (const field of this [_predefinedFields])
         field .setTainted (false);

      for (const field of this [_userDefinedFields])
         field .setTainted (false);

      this .initialize ();

      this [_initialized] = true;
   },
   initialize ()
   { },
   isInitialized ()
   {
      return this [_initialized];
   },
   getInnerNode ()
   {
      return this;
   },
   isLive ()
   {
      ///  Returns the own live state of this node.

      return this [_live];
   },
   setLive (value)
   {
      ///  Sets the own live state of this node.  Setting the live state to false
      ///  temporarily disables this node completely.

      this [_live] = value .valueOf ();

      this [_set_live__] ();
   },
   getLive: (() =>
   {
      function getLive ()
      {
         return this ._live;
      }

      return function ()
      {
         ///  Returns the live event of this node.

         // Change function.

         Object .defineProperty (this, "getLive", { value: getLive });

         // Add isLive event.

         this .addChildObjects (Base_X3DConstants .outputOnly, "live", new x_ite_Fields .SFBool (this .getLiveState ()));

         // Event processing is done manually and immediately, so:
         this ._live .removeParent (this);

         // Connect to execution context.

         if (this .getOuterNode ?.())
            this .getOuterNode () .getLive () .addInterest (_set_live__, this);

         else if (this [_executionContext] !== this)
            this [_executionContext] .getLive () .addInterest (_set_live__, this);

         // Return field.

         return this ._live;
      };
   })(),
   getLiveState ()
   {
      ///  Determines the live state of this node.

      if (this .getOuterNode ?.())
         return this [_live] && this .getOuterNode () .getLive () .getValue ();

      else if (this !== this [_executionContext])
         return this [_live] && this [_executionContext] .getLive () .getValue ();

      return this [_live];
   },
   [_set_live__] ()
   {
      const live = this ._live;

      if (!live)
         return;

      if (this .getLiveState ())
      {
         if (live .getValue ())
            return;

         live .set (true);
         live .processEvent ();
      }
      else
      {
         if (live .getValue ())
         {
            live .set (false);
            live .processEvent ();
         }
      }
   },
   addChildObjects (/* accessType, name, field, ... */)
   {
      for (let i = 0, length = arguments .length; i < length; i += 3)
         this .addChildObject (arguments [i], arguments [i + 1], arguments [i + 2]);
   },
   addChildObject (accessType, name, field)
   {
      this [_childObjects] .push (field);

      field .setTainted (true);
      field .addParent (this);
      field .setName (name);
      field .setAccessType (accessType);

      Object .defineProperty (this, `_${name}`,
      {
         get () { return field; },
         set (value) { field .setValue (value); },
      });
   },
   getFieldDefinitions ()
   {
      return this [_fieldDefinitions];
   },
   getField (name)
   {
      const field = getFieldFromArray (this [_userDefinedFields], name)
         ?? getFieldFromArray (this [_predefinedFields], name);

      if (field)
         return field;

      throw new Error (`Unknown field '${name}' in node class ${this .getTypeName ()}.`);
   },
   getFields ()
   {
      return [... this [_predefinedFields], ... this [_userDefinedFields]];
   },
   addPredefinedField ({ accessType, name, value })
   {
      const field = value .copy ();

      field .setTainted (!this [_initialized]);
      field .addParent (this);
      field .setName (name);
      field .setAccessType (accessType);

      this [_predefinedFields] .add (name, field);

      Object .defineProperty (this, `_${name}`,
      {
         get () { return field; },
         set (value) { field .setValue (value); },
			configurable: true,
      });
   },
   addAlias (alias, field)
   {
      this [_predefinedFields] .alias (alias, field);

      if (field .isInitializable ())
         Parser_HTMLSupport .addFieldName (alias);
   },
   removePredefinedField (name)
   {
      const field = this [_predefinedFields] .get (name);

      if (!field)
         return;

      field .removeParent (this);

      this [_predefinedFields] .remove (name);

      delete this [`_${field .getName ()}`];
   },
   getPredefinedField (name)
   {
      const field = getFieldFromArray (this [_predefinedFields], name);

      if (field)
         return field;

      throw new Error (`Unknown predefined field '${name}' in node class ${this .getTypeName ()}.`);
   },
   getPredefinedFields ()
   {
      return this [_predefinedFields];
   },
   canUserDefinedFields ()
   {
      return false;
   },
   addUserDefinedField (accessType, name, field)
   {
      if (!this .canUserDefinedFields ())
         throw new Error ("Couldn't add user-defined field, node does not support this.");

      if (this [_userDefinedFields] .has (name))
         this .removeUserDefinedField (name);

      field .setTainted (!this [_initialized]);
      field .addParent (this);
      field .setName (name);
      field .setAccessType (accessType);

      this [_fieldDefinitions] .remove (name);

      this [_fieldDefinitions]  .add (name, new Base_X3DFieldDefinition (accessType, name, field));
      this [_userDefinedFields] .add (name, field);
   },
   removeUserDefinedField (name)
   {
      const field = this [_userDefinedFields] .get (name);

      if (!field)
         return;

      field .removeParent (this);

      this [_fieldDefinitions]  .remove (name);
      this [_userDefinedFields] .remove (name);
   },
   getUserDefinedField (name)
   {
      const field = getFieldFromArray (this [_userDefinedFields], name);

      if (field)
         return field;

      throw new Error (`Unknown user-defined field '${name}' in node class ${this .getTypeName ()}.`);
   },
   getUserDefinedFields ()
   {
      return this [_userDefinedFields];
   },
   getChangedFields (extended)
   {
      /* param routes: also return fields with routes */

      const changedFields = [ ];

      if (extended)
      {
         for (const field of this [_userDefinedFields])
            changedFields .push (field);
      }

      for (const field of this [_predefinedFields])
      {
         if (extended)
         {
            if (field .getInputRoutes () .size || field .getOutputRoutes () .size)
            {
               changedFields .push (field);
               continue;
            }
         }

         if (field .getReferences () .size === 0)
         {
            if (!field .isInitializable ())
               continue;

            if (this .isDefaultValue (field))
               continue;
         }

         changedFields .push (field);
      }

      return changedFields;
   },
   isDefaultValue (field)
   {
      const f = this [_userDefinedFields] .get (field .getName ()) ?? this [_predefinedFields] .get (field .getName ());

      if (f === field)
         var fieldDefinition = this [_fieldDefinitions] .get (field .getName ());
      else if (this .constructor .fieldDefinitions)
         var fieldDefinition = this .constructor .fieldDefinitions .get (field .getName ());

      if (fieldDefinition)
      {
         // User-defined fields are their own field definition value.
         if (fieldDefinition .value === field)
            return false;

         return fieldDefinition .value .equals (field);
      }

      return !field .getModificationTime ();
   },
   hasRoutes ()
   {
      ///  Returns true if there are any routes from or to fields of this node, otherwise false.

      for (const field of this [_predefinedFields])
      {
         if (field .getInputRoutes () .size || field .getOutputRoutes () .size)
            return true;
      }

      for (const field of this [_userDefinedFields])
      {
         if (field .getInputRoutes () .size || field .getOutputRoutes () .size)
            return true;
      }

      for (const importedNode of this [_executionContext] .getImportedNodes ())
      {
         if (importedNode .hasRoutes (this))
            return true;
      }

      return false;
   },
   getExtendedEventHandling ()
   {
      // Whether initializeOnly field are treated like inputOnly and inputOutput fields.
      return true;
   },
   addEvent (field)
   {
      if (field .isTainted ())
         return;

      // if (this .getTypeName () === "IndexedQuadSet")
      // {
      //    console .log (field .getName ());
      //    console .trace ();
      // }

      field .setTainted (true);

      this .addEventObject (field, Base_Events .create (field));
   },
   addEventObject (field, event)
   {
      const browser = this [_browser];

      // Register for processEvent

      browser .addTaintedField (field, event);
      browser .addBrowserEvent ();

      // Register for eventsProcessed

      if (this .isTainted ())
         return;

      if (field .isInput () || (this .getExtendedEventHandling () && field .isInitializable ()))
      {
         this .addNodeEvent ();
      }
   },
   addNodeEvent ()
   {
      if (this .isTainted ())
         return;

      const browser = this [_browser];

      this .setTainted (true);
      browser .addTaintedNode (this);
      browser .addBrowserEvent ();
   },
   parentsChanged ()
   {
      const time = this [_browser] .getCurrentTime ();

      this [_executionContext] ._sceneGraph_changed = time;
      this ._parents_changed                        = time;
   },
   dispose ()
   {
      this .setLive (false);

      for (const field of this [_childObjects])
         field .dispose ();

      for (const field of this [_predefinedFields])
         field .dispose ();

      for (const field of this [_userDefinedFields])
         field .dispose ();

      Base_X3DChildObject .prototype .dispose .call (this);
   },
});

const getFieldFromArray = (() =>
{
   const
      set_field     = /^set_(.*?)$/,
      field_changed = /^(.*?)_changed$/;

   return function (array, name)
   {
      const field = array .get (name);

      if (field)
         return field;

      const match = name .match (set_field);

      if (match)
      {
         const field = array .get (match [1]);

         if (field ?.getAccessType () === Base_X3DConstants .inputOutput)
            return field;
      }
      else
      {
         const match = name .match (field_changed);

         if (match)
         {
            const field = array .get (match [1]);

            if (field ?.getAccessType () === Base_X3DConstants .inputOutput)
               return field;
         }
      }
   };
})();

for (const key of Object .keys (X3DBaseNode .prototype))
   Object .defineProperty (X3DBaseNode .prototype, key, { enumerable: false });

Object .defineProperties (X3DBaseNode .prototype,
{
   name_changed:
   {
      get () { return this ._name_changed; },
      enumerable: false,
   },
   typeName_changed:
   {
      get () { return this ._typeName_changed; },
      enumerable: false,
   },
   parents_changed:
   {
      get () { return this ._parents_changed; },
      enumerable: false,
   },
});

const X3DBaseNode_default_ = X3DBaseNode;
;

x_ite_Namespace .add ("X3DBaseNode", "x_ite/Base/X3DBaseNode", X3DBaseNode_default_);
/* harmony default export */ const Base_X3DBaseNode = (X3DBaseNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Legacy.js
/* provided dependency */ var $ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

const Legacy =
{
   elements (elements, X3DBrowser)
   {
      if (elements .length)
      {
         console .warn ("Use of <X3DCanvas> element is depreciated, please use <x3d-canvas> element instead. See https://create3000.github.io/x_ite/#embedding-x_ite-within-a-web-page.");

         $.map (elements, element => new X3DBrowser (element));
      }
   },
   browser (browser)
   {
      const element = browser .getElement ();

      if (element .prop ("nodeName") .toUpperCase () !== "X3DCANVAS")
         return;

      if (element .attr ("src"))
         browser .attributeChangedCallback ("src", undefined, element .attr ("src"));
      else if (element .attr ("url"))
         browser .attributeChangedCallback ("url", undefined, element .attr ("url"));

      // Make element focusable.
      element .attr ("tabindex", element .attr ("tabindex") ?? 0);
   },
   error (elements, error)
   {
      console .error (error);

      // <X3DCanvas>
      elements .children (".x_ite-private-browser") .hide ();
      elements .children (":not(.x_ite-private-browser)") .show ();
   },
};

const Legacy_default_ = Legacy;
;

x_ite_Namespace .add ("Legacy", "x_ite/Browser/Legacy", Legacy_default_);
/* harmony default export */ const Browser_Legacy = (Legacy_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/VERSION.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

const VERSION_default_ = "8.12.5";
;

x_ite_Namespace .add ("VERSION", "x_ite/Browser/VERSION", VERSION_default_);
/* harmony default export */ const VERSION = (VERSION_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Core/X3DNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





const _private = Symbol ()

function X3DNode (executionContext)
{
   Base_X3DBaseNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DNode);

   this [_private] = false;
}

Object .assign (Object .setPrototypeOf (X3DNode .prototype, Base_X3DBaseNode .prototype),
{
   getComponentName ()
   {
      return this .constructor .componentName;
   },
   getContainerField ()
   {
      return this .constructor .containerField;
   },
   getSpecificationRange ()
   {
      return this .constructor .specificationRange;
   },
   copy (instance)
   {
      if (!instance || instance .getType () .includes (Base_X3DConstants .X3DExecutionContext))
      {
         return Base_X3DBaseNode .prototype .copy .call (this, instance);
      }
      else
      {
         const executionContext = instance .getBody ();

         // First try to get a named node with the node's name.

         if (this .getName () .length)
         {
            const namedNode = executionContext .getNamedNodes () .get (this .getName ());

            if (namedNode)
               return namedNode .getValue ();
         }

         // Create copy.

         const copy = this .create (executionContext);

         if (this .getNeedsName ())
            this .getExecutionContext () .updateNamedNode (this .getExecutionContext () .getUniqueName (), this);

         if (this .getName () .length)
            executionContext .updateNamedNode (this .getName (), copy);

         // Default fields

         for (const sourceField of this .getPredefinedFields ())
         {
            try
            {
               const destinationField = copy .getPredefinedField (sourceField .getName ());

               if (sourceField .hasReferences ())
               {
                  // IS relationship

                  for (const originalReference of sourceField .getReferences ())
                  {
                     try
                     {
                        destinationField .addReference (instance .getField (originalReference .getName ()));
                     }
                     catch (error)
                     {
                        console .error (error);
                     }
                  }
               }
               else
               {
                  if (sourceField .getAccessType () & Base_X3DConstants .initializeOnly)
                  {
                     switch (sourceField .getType ())
                     {
                        case Base_X3DConstants .SFNode:
                        case Base_X3DConstants .MFNode:
                           destinationField .assign (sourceField .copy (instance));
                           break;
                        default:
                           destinationField .assign (sourceField);
                           break;
                     }
                  }
               }

               destinationField .setModificationTime (sourceField .getModificationTime ());
            }
            catch (error)
            {
               console .error (error);
            }
         }

         // User-defined fields

         for (const sourceField of this .getUserDefinedFields ())
         {
            const destinationField = sourceField .copy (instance);

            copy .addUserDefinedField (sourceField .getAccessType (),
                                       sourceField .getName (),
                                       destinationField);

            if (sourceField .hasReferences ())
            {
               // IS relationship

               for (const originalReference of sourceField .getReferences ())
               {
                  try
                  {
                     destinationField .addReference (instance .getField (originalReference .getName ()));
                  }
                  catch (error)
                  {
                     console .error (`No reference '${originalReference .getName ()}' inside execution context ${instance .getTypeName ()} '${instance .getName ()}'.`);
                  }
               }
            }

            destinationField .setModificationTime (sourceField .getModificationTime ());
         }

         copy .setup ();

         return copy;
      }
   },
   getDisplayName ()
   {
      return this .getName () .replace (/_\d+$/, "");
   },
   getNeedsName ()
   {
      if (this .getName () .length)
         return false;

      if (this .getCloneCount () > 1)
         return true;

      if (this .hasRoutes ())
         return true;

      const executionContext = this .getExecutionContext ()

      for (const importedNode of executionContext .getImportedNodes ())
      {
         if (importedNode .getInlineNode () === this)
            return true;
      }

      if (executionContext .isScene ())
      {
         for (const exportedNode of executionContext .getExportedNodes ())
         {
            if (exportedNode .getLocalNode () === this)
               return true;
         }
      }

      return false;
   },
   isPrivate ()
   {
      return this [_private];
   },
   setPrivate (value)
   {
      this [_private] = value;
   },
   getCloneCount ()
   {
      return Base_X3DBaseNode .prototype .collectCloneCount .call (this);
   },
   collectCloneCount ()
   {
      return this .isPrivate () ? 0 : 1;
   },
   getSourceText ()
   {
      return null;
   },
   traverse () { },
   toStream (generator)
   {
      generator .string += this .getTypeName () + " { }";
   },
   toVRMLStream (generator)
   {
      generator .EnterScope ();

      const name = generator .Name (this);

      if (name .length)
      {
         if (generator .ExistsNode (this))
         {
            generator .string += "USE";
            generator .string += generator .Space ();
            generator .string += name;

            generator .LeaveScope ();
            return;
         }
      }

      if (name .length)
      {
         generator .AddNode (this);

         generator .string += "DEF";
         generator .string += generator .Space ();
         generator .string += name;
         generator .string += generator .Space ();
      }

      generator .string += this .getTypeName ();
      generator .string += generator .TidySpace ();
      generator .string += "{";

      const
         fields            = this .getChangedFields (),
         userDefinedFields = this .getUserDefinedFields ();

      if (this .canUserDefinedFields ())
      {
         if (userDefinedFields .length)
         {
            let
               fieldTypeLength  = 0,
               accessTypeLength = 0;

            for (const field of userDefinedFields)
            {
               fieldTypeLength  = Math .max (fieldTypeLength, field .getTypeName () .length);
               accessTypeLength = Math .max (accessTypeLength, generator .AccessType (field .getAccessType ()) .length);
            }

            const last = userDefinedFields .at (-1);

            generator .string += generator .TidyBreak ();
            generator .IncIndent ();

            for (const field of userDefinedFields)
            {
               this .toVRMLStreamUserDefinedField (generator, field, fieldTypeLength, accessTypeLength);

               if (field === last)
                  generator .string += generator .TidyBreak ();
               else
                  generator .string += generator .Break ();
            }

            generator .DecIndent ();

            if (fields .length !== 0)
               generator .string += generator .TidyBreak ();
         }
      }

      if (fields .length === 0)
      {
         if (userDefinedFields .length)
            generator .string += generator .Indent ();
         else
            generator .string += generator .TidySpace ();
      }
      else
      {
         const last = fields .at (-1);

         if (userDefinedFields .length === 0)
            generator .string += generator .TidyBreak ();

         generator .IncIndent ();

         for (const field of fields)
         {
            this .toVRMLStreamField (generator, field);

            if (field === last)
               generator .string += generator .TidyBreak ();
            else
               generator .string += generator .Break ();
         }

         generator .DecIndent ();
         generator .string += generator .Indent ();
      }

      generator .string += "}";

      generator .LeaveScope ();
   },
   toVRMLStreamUserDefinedField (generator, field, fieldTypeLength, accessTypeLength)
   {
      const sharedNode = generator .IsSharedNode (this);

      if (field .getReferences () .size === 0 || !generator .ExecutionContext () || sharedNode)
      {
         generator .string += generator .Indent ();
         generator .string += generator .AccessType (field .getAccessType ()) .padEnd (accessTypeLength, " ");
         generator .string += generator .Space ();
         generator .string += field .getTypeName () .padEnd (fieldTypeLength, " ");
         generator .string += generator .Space ();
         generator .string += field .getName ();

         if (field .isInitializable ())
         {
            generator .string += generator .Space ();

            field .toVRMLStream (generator);
         }
      }
      else
      {
         let
            index                  = 0,
            initializableReference = false;

         for (const reference of field .getReferences ())
         {
            initializableReference = initializableReference || reference .isInitializable ();

            // Output user defined reference field

            generator .string += generator .Indent ();
            generator .string += generator .AccessType (field .getAccessType ()) .padEnd (accessTypeLength, " ");
            generator .string += generator .Space ();
            generator .string += field .getTypeName () .padEnd (fieldTypeLength, " ");
            generator .string += generator .Space ();
            generator .string += field .getName ();
            generator .string += generator .Space ();
            generator .string += "IS";
            generator .string += generator .Space ();
            generator .string += reference .getName ();

            ++ index;

            if (index !== field .getReferences () .size)
               generator .string += generator .Break ();
         }

         if (field .getAccessType () === Base_X3DConstants .inputOutput && !initializableReference && !field .isDefaultValue ())
         {
            generator .string += generator .Break ();
            generator .string += generator .Indent ();
            generator .string += generator .AccessType (field .getAccessType ()) .padEnd (accessTypeLength, " ");
            generator .string += generator .Space ();
            generator .string += field .getTypeName () .padEnd (fieldTypeLength, " ");
            generator .string += generator .Space ();
            generator .string += field .getName ();

            if (field .isInitializable ())
            {
               generator .string += generator .Space ();

               field .toVRMLStream (generator);
            }
         }
      }
   },
   toVRMLStreamField (generator, field)
   {
      const sharedNode = generator .IsSharedNode (this);

      if (field .getReferences () .size === 0 || !generator .ExecutionContext () || sharedNode)
      {
         if (field .isInitializable ())
         {
            generator .string += generator .Indent ();
            generator .string += field .getName ();
            generator .string += generator .Space ();

            field .toVRMLStream (generator);
         }
      }
      else
      {
         let
            index                  = 0,
            initializableReference = false;

         for (const reference of field .getReferences ())
         {
            initializableReference = initializableReference || reference .isInitializable ();

            // Output build in reference field

            generator .string += generator .Indent ();
            generator .string += field .getName ();
            generator .string += generator .Space ();
            generator .string += "IS";
            generator .string += generator .Space ();
            generator .string += reference .getName ();

            ++ index;

            if (index !== field .getReferences () .size)
               generator .string += generator .Break ();
         }

         if (field .getAccessType () === Base_X3DConstants .inputOutput && !initializableReference && !this .isDefaultValue (field))
         {
            // Output build in field

            generator .string += generator .Break ();
            generator .string += generator .Indent ();
            generator .string += field .getName ();
            generator .string += generator .Space ();

            field .toVRMLStream (generator);
         }
      }
   },
   toXMLStream (generator)
   {
      const sharedNode = generator .IsSharedNode (this);

      generator .EnterScope ();

      const name = generator .Name (this);

      if (name .length)
      {
         if (generator .ExistsNode (this))
         {
            generator .string += generator .Indent ();
            generator .string += "<";
            generator .string += this .getTypeName ();

            if (generator .html && this .getTypeName () === "Script")
            {
               generator .string += generator .Space ();
               generator .string += "type='model/x3d+xml'";
            }

            generator .string += generator .Space ();
            generator .string += "USE='";
            generator .string += generator .XMLEncode (name);
            generator .string += "'";

            const containerField = generator .ContainerField ();

            if (containerField)
            {
               if (containerField .getName () !== this .getContainerField ())
               {
                  generator .string += generator .Space ();
                  generator .string += "containerField='";
                  generator .string += generator .XMLEncode (containerField .getName ());
                  generator .string += "'";
               }
            }

            if (generator .closingTags)
            {
               generator .string += "></";
               generator .string += this .getTypeName ();
               generator .string += ">";
            }
            else
            {
               generator .string += "/>";
            }

            generator .LeaveScope ();
            return;
         }
      }

      generator .string += generator .Indent ();
      generator .string += "<";
      generator .string += this .getTypeName ();

      if (generator .html && this .getTypeName () === "Script")
      {
         generator .string += generator .Space ();
         generator .string += "type='model/x3d+xml'";
      }

      if (name .length)
      {
         generator .AddNode (this);

         generator .string += generator .Space ();
         generator .string += "DEF='";
         generator .string += generator .XMLEncode (name);
         generator .string += "'";
      }

      const containerField = generator .ContainerField ();

      if (containerField)
      {
         if (containerField .getName () !== this .getContainerField ())
         {
            generator .string += generator .Space ();
            generator .string += "containerField='";
            generator .string += generator .XMLEncode (containerField .getName ());
            generator .string += "'";
         }
      }

      const
         fields            = this .getChangedFields (),
         userDefinedFields = this .getUserDefinedFields ();

      const
         references = [ ],
         childNodes = [ ];

      let cdata = this .getSourceText ();

      if (cdata ?.length === 0 || (generator .html && this .getTypeName () !== "Script"))
         cdata = null;

      generator .IncIndent ();
      generator .IncIndent ();

      for (const field of fields)
      {
         // If the field is a inputOutput and we have as reference only inputOnly or outputOnly we must output the value
         // for this field.

         let mustOutputValue = false;

         if (generator .ExecutionContext ())
         {
            if (field .getAccessType () === Base_X3DConstants .inputOutput && field .getReferences () .size !== 0)
            {
               if (![... field .getReferences ()] .some (reference => reference .isInitializable ()))
                  mustOutputValue = !this .isDefaultValue (field);
            }
         }

         // If we have no execution context we are not in a proto and must not generate IS references the same is true
         // if the node is a shared node as the node does not belong to the execution context.

         if (field .getReferences () .size === 0 || !generator .ExecutionContext () || sharedNode || mustOutputValue)
         {
            if (mustOutputValue)
               references .push (field);

            if (field .isInitializable ())
            {
               switch (field .getType ())
               {
                  case Base_X3DConstants .SFNode:
                  case Base_X3DConstants .MFNode:
                  {
                     childNodes .push (field);
                     break;
                  }
                  default:
                  {
                     if (field === cdata)
                        break;

                     generator .string += generator .AttribBreak ();
                     generator .string += generator .ListIndent ();
                     generator .string += field .getName ();
                     generator .string += "='";

                     field .toXMLStream (generator, field === this .getSourceText ());

                     generator .string += "'";
                     break;
                  }
               }
            }
         }
         else
         {
            references .push (field);
         }
      }

      generator .DecIndent ();
      generator .DecIndent ();

      if ((!this .canUserDefinedFields () || !userDefinedFields .length) && (!references .length || sharedNode) && !childNodes .length && !cdata)
      {
         if (generator .closingTags)
         {
            generator .string += "></";
            generator .string += this .getTypeName ();
            generator .string += ">";
         }
         else
         {
            generator .string += "/>";
         }
      }
      else
      {
         generator .string += ">";
         generator .string += generator .TidyBreak ();

         generator .IncIndent ();

         if (this .canUserDefinedFields ())
         {
            for (const field of userDefinedFields)
            {
               generator .string += generator .Indent ();
               generator .string += "<field";
               generator .string += generator .Space ();
               generator .string += "accessType='";
               generator .string += generator .AccessType (field .getAccessType ());
               generator .string += "'";
               generator .string += generator .Space ();
               generator .string += "type='";
               generator .string += field .getTypeName ();
               generator .string += "'";
               generator .string += generator .Space ();
               generator .string += "name='";
               generator .string += generator .XMLEncode (field .getName ());
               generator .string += "'";

               // If the field is a inputOutput and we have as reference only inputOnly or outputOnly we must output the value
               // for this field.

               let mustOutputValue = false;

               if (generator .ExecutionContext ())
               {
                  if (field .getAccessType () === Base_X3DConstants .inputOutput && field .getReferences () .size !== 0)
                  {
                     if (![... field .getReferences ()] .some (reference => reference .isInitializable ()))
                        mustOutputValue = true;
                  }
               }

               if ((field .getReferences () .size === 0 || !generator .ExecutionContext ()) || sharedNode || mustOutputValue)
               {
                  if (mustOutputValue && generator .ExecutionContext ())
                     references .push (field);

                  if (!field .isInitializable () || field .isDefaultValue ())
                  {
                     generator .string += generator .closingTags ? "></field>" : "/>";
                     generator .string += generator .TidyBreak ();
                  }
                  else
                  {
                     // Output value

                     switch (field .getType ())
                     {
                        case Base_X3DConstants .SFNode:
                        case Base_X3DConstants .MFNode:
                        {
                           generator .PushContainerField (null);

                           generator .string += ">";
                           generator .string += generator .TidyBreak ();

                           generator .IncIndent ();

                           field .toXMLStream (generator);

                           generator .string += generator .TidyBreak ();

                           generator .DecIndent ();

                           generator .string += generator .Indent ();
                           generator .string += "</field>";
                           generator .string += generator .TidyBreak ();

                           generator .PopContainerField ();
                           break;
                        }
                        default:
                        {
                           generator .string += generator .Space ();
                           generator .string += "value='";

                           field .toXMLStream (generator);

                           generator .string += "'";
                           generator .string += generator .closingTags ? "></field>" : "/>";
                           generator .string += generator .TidyBreak ();
                           break;
                        }
                     }
                  }
               }
               else
               {
                  if (generator .ExecutionContext ())
                     references .push (field);

                  generator .string += generator .closingTags ? "></field>" : "/>";
                  generator .string += generator .TidyBreak ();
               }
            }
         }

         if (references .length && !sharedNode)
         {
            generator .string += generator .Indent ();
            generator .string += "<IS>";
            generator .string += generator .TidyBreak ();

            generator .IncIndent ();

            for (const field of references)
            {
               const protoFields = field .getReferences ();

               for (const protoField of protoFields)
               {
                  generator .string += generator .Indent ();
                  generator .string += "<connect";
                  generator .string += generator .Space ();
                  generator .string += "nodeField='";
                  generator .string += generator .XMLEncode (field .getName ());
                  generator .string += "'";
                  generator .string += generator .Space ();
                  generator .string += "protoField='";
                  generator .string += generator .XMLEncode (protoField .getName ());
                  generator .string += "'";
                  generator .string += generator .closingTags ? "></connect>" : "/>";
                  generator .string += generator .TidyBreak ();
               }
            }

            generator .DecIndent ();

            generator .string += generator .Indent ();
            generator .string += "</IS>";
            generator .string += generator .TidyBreak ();
         }

         for (const field of childNodes)
         {
            generator .PushContainerField (field);

            field .toXMLStream (generator);

            generator .string += generator .TidyBreak ();

            generator .PopContainerField ();
         }

         if (cdata)
         {
            for (const value of cdata)
            {
               generator .string += "<![CDATA[";
               generator .string += value;
               generator .string += "]]>";
               generator .string += generator .TidyBreak ();
            }
         }

         generator .DecIndent ();

         generator .string += generator .Indent ();
         generator .string += "</";
         generator .string += this .getTypeName ();
         generator .string += ">";
      }

      generator .LeaveScope ();
   },
   toJSONStream (generator)
   {
      const sharedNode = generator .IsSharedNode (this);

      generator .EnterScope ();

      const name = generator .Name (this);

      // USE name

      if (name .length)
      {
         if (generator .ExistsNode (this))
         {
            generator .string += '{';
            generator .string += generator .TidySpace ();
            generator .string += '"';
            generator .string += this .getTypeName ();
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidyBreak ();
            generator .string += generator .IncIndent ();
            generator .string += generator .Indent ();
            generator .string += '{';
            generator .string += generator .TidyBreak ();
            generator .string += generator .IncIndent ();
            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "@USE";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '"';
            generator .string += generator .JSONEncode (name);
            generator .string += '"';
            generator .string += generator .TidyBreak ();
            generator .string += generator .DecIndent ();
            generator .string += generator .Indent ();
            generator .string += '}';
            generator .string += generator .TidyBreak ();
            generator .string += generator .DecIndent ();
            generator .string += generator .Indent ();
            generator .string += '}';

            generator .LeaveScope ();
            return;
         }
      }

      // Type name

      generator .string += '{';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += this .getTypeName ();
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();
      generator .string += generator .Indent ();
      generator .string += '{';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();


      // DEF name

      if (name .length)
      {
         generator .AddNode (this);

         generator .string += generator .Indent ();
         generator .string += '"';
         generator .string += "@DEF";
         generator .string += '"';
         generator .string += ':';
         generator .string += generator .TidySpace ();
         generator .string += '"';
         generator .string += generator .JSONEncode (name);
         generator .string += '"';
         generator .string += ',';
         generator .string += generator .TidyBreak ();
      }


      // Fields

      const
         fields            = this .getChangedFields (),
         userDefinedFields = this .getUserDefinedFields ();

      const references = [ ];

      let sourceText = this .getSourceText ();

      // Source text

      if (sourceText)
      {
         if (sourceText .length !== 1)
            sourceText = null;
      }


      // Predefined fields

      if (fields .length)
      {
         const outputFields = [ ];

         for (const field of fields)
         {
            // If the field is a inputOutput and we have as reference only inputOnly or outputOnly we must output the value
            // for this field.

            let mustOutputValue = false;

            if (generator .ExecutionContext ())
            {
               if (field .getAccessType () === Base_X3DConstants .inputOutput && field .getReferences () .size !== 0)
               {
                  if (![... field .getReferences ()] .some (reference => reference .isInitializable ()))
                     mustOutputValue = !this .isDefaultValue (field);
               }
            }

            // If we have no execution context we are not in a proto and must not generate IS references the same is true
            // if the node is a shared node as the node does not belong to the execution context.

            if (field .getReferences () .size === 0 || !generator .ExecutionContext () || sharedNode || mustOutputValue)
            {
               if (mustOutputValue)
                  references .push (field);

               if (field !== sourceText)
                  outputFields .push (field);
            }
            else
            {
               references .push (field);
            }
         }

         for (const field of outputFields)
         {
            if (field .isInitializable ())
            {
               switch (field .getType ())
               {
                  case Base_X3DConstants .SFNode:
                  case Base_X3DConstants .MFNode:
                  {
                     generator .string += generator .Indent ();
                     generator .string += '"';
                     generator .string += '-';
                     generator .string += field .getName ();
                     generator .string += '"';
                     generator .string += ':';
                     generator .string += generator .TidySpace ();

                     field .toJSONStream (generator);
                     break;
                  }
                  default:
                  {
                     generator .string += generator .Indent ();
                     generator .string += '"';
                     generator .string += '@';
                     generator .string += field .getName ();
                     generator .string += '"';
                     generator .string += ':';
                     generator .string += generator .TidySpace ();

                     field .toJSONStream (generator);
                     break;
                  }
               }

               generator .string += ',';
               generator .string += generator .TidyBreak ();
            }
         }
      }

      // User defined fields

      if (! this .canUserDefinedFields () || ! userDefinedFields .length)
         ;
      else
      {
         generator .string += generator .Indent ();
         generator .string += '"';
         generator .string += "field";
         generator .string += '"';
         generator .string += ':';
         generator .string += generator .TidySpace ();
         generator .string += '[';
         generator .string += generator .TidyBreak ();
         generator .string += generator .IncIndent ();

         for (const field of userDefinedFields)
         {
            generator .string += generator .Indent ();
            generator .string += '{';
            generator .string += generator .TidyBreak ();
            generator .string += generator .IncIndent ();

            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "@accessType";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '"';
            generator .string += generator .AccessType (field .getAccessType ());
            generator .string += '"';
            generator .string += ',';
            generator .string += generator .TidyBreak ();

            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "@type";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '"';
            generator .string += field .getTypeName ();
            generator .string += '"';
            generator .string += ',';
            generator .string += generator .TidyBreak ();

            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "@name";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '"';
            generator .string += generator .JSONEncode (field .getName ());
            generator .string += '"';

            // If the field is a inputOutput and we have as reference only inputOnly or outputOnly we must output the value
            // for this field.

            let mustOutputValue = false;

            if (generator .ExecutionContext ())
            {
               if (field .getAccessType () === Base_X3DConstants .inputOutput && field .getReferences () .size !== 0)
               {
                  if (![... field .getReferences ()] .some (reference => reference .isInitializable ()))
                     mustOutputValue = true;
               }
            }

            if ((field .getReferences () .size === 0 || !generator .ExecutionContext ()) || sharedNode || mustOutputValue)
            {
               if (mustOutputValue && generator .ExecutionContext ())
                  references .push (field);

               if (!field .isInitializable () || field .isDefaultValue ())
                  ;
               else
               {
                  // Output value

                  generator .string += ',';
                  generator .string += generator .TidyBreak ();

                  switch (field .getType ())
                  {
                     case Base_X3DConstants .SFNode:
                     {
                        generator .string += generator .Indent ();
                        generator .string += '"';
                        generator .string += "-children";
                        generator .string += '"';
                        generator .string += ':';
                        generator .string += generator .TidySpace ();
                        generator .string += '[';
                        generator .string += generator .TidyBreak ();
                        generator .string += generator .IncIndent ();
                        generator .string += generator .Indent ();

                        field .toJSONStream (generator);

                        generator .string += generator .TidyBreak ();
                        generator .string += generator .DecIndent ();
                        generator .string += generator .Indent ();
                        generator .string += ']';
                        break;
                     }
                     case Base_X3DConstants .MFNode:
                     {
                        generator .string += generator .Indent ();
                        generator .string += '"';
                        generator .string += "-children";
                        generator .string += '"';
                        generator .string += ':';
                        generator .string += generator .TidySpace ();

                        field .toJSONStream (generator);
                        break;
                     }
                     default:
                     {
                        generator .string += generator .Indent ();
                        generator .string += '"';
                        generator .string += "@value";
                        generator .string += '"';
                        generator .string += ':';
                        generator .string += generator .TidySpace ();

                        field .toJSONStream (generator);
                        break;
                     }
                  }
               }
            }
            else
            {
               if (generator .ExecutionContext ())
                  references .push (field);
            }

            generator .string += generator .TidyBreak ();
            generator .string += generator .DecIndent ();
            generator .string += generator .Indent ();
            generator .string += '}';

            if (field !== userDefinedFields .at (-1))
               generator .string += ',';

            generator .string += generator .TidyBreak ();
         }

         generator .string += generator .DecIndent ();
         generator .string += generator .Indent ();
         generator .string += ']';
         generator .string += ',';
         generator .string += generator .TidyBreak ();
      }

      // Source text

      if (sourceText)
      {
         generator .string += generator .Indent ();
         generator .string += '"';
         generator .string += "#sourceCode";
         generator .string += '"';
         generator .string += ':';
         generator .string += generator .TidySpace ();
         generator .string += '[';
         generator .string += generator .TidyBreak ();
         generator .string += generator .IncIndent ();

         const sourceTextLines = sourceText [0] .split ("\n");

         for (let i = 0, length = sourceTextLines .length; i < length; ++ i)
         {
            generator .string += generator .ListIndent ();
            generator .string += '"';
            generator .string += generator .JSONEncode (sourceTextLines [i]);
            generator .string += '"';

            if (i !== length - 1)
               generator .string += ',';

            generator .string += generator .TidyBreak ();
         }

         generator .string += generator .DecIndent ();
         generator .string += generator .Indent ();
         generator .string += ']';
         generator .string += ',';
         generator .string += generator .TidyBreak ();
      }


      // IS references

      if (references .length && !sharedNode)
      {
         generator .string += generator .Indent ();
         generator .string += '"';
         generator .string += "IS";
         generator .string += '"';
         generator .string += ':';
         generator .string += generator .TidySpace ();
         generator .string += '{';
         generator .string += generator .TidyBreak ();
         generator .string += generator .IncIndent ();
         generator .string += generator .Indent ();
         generator .string += '"';
         generator .string += "connect";
         generator .string += '"';
         generator .string += ':';
         generator .string += generator .TidySpace ();
         generator .string += '[';
         generator .string += generator .TidyBreak ();
         generator .string += generator .IncIndent ();

         for (const field of references)
         {
            const protoFields = [... field .getReferences ()];

            for (const protoField of protoFields)
            {
               generator .string += generator .Indent ();
               generator .string += '{';
               generator .string += generator .TidyBreak ();
               generator .string += generator .IncIndent ();

               generator .string += generator .Indent ();
               generator .string += '"';
               generator .string += "@nodeField";
               generator .string += '"';
               generator .string += ':';
               generator .string += generator .TidySpace ();
               generator .string += '"';
               generator .string += generator .JSONEncode (field .getName ());
               generator .string += '"';
               generator .string += ',';
               generator .string += generator .TidyBreak ();

               generator .string += generator .Indent ();
               generator .string += '"';
               generator .string += "@protoField";
               generator .string += '"';
               generator .string += ':';
               generator .string += generator .TidySpace ();
               generator .string += '"';
               generator .string += generator .JSONEncode (protoField .getName ());
               generator .string += '"';
               generator .string += generator .TidyBreak ();

               generator .string += generator .DecIndent ();
               generator .string += generator .Indent ();
               generator .string += '}';

               if (field === references .at (-1) && protoField === protoFields .at (-1))
                  ;
               else
               {
                  generator .string += ',';
               }

               generator .string += generator .TidyBreak ();
            }
         }

         generator .string += generator .DecIndent ();
         generator .string += generator .Indent ();
         generator .string += ']';
         generator .string += generator .TidyBreak ();
         generator .string += generator .DecIndent ();
         generator .string += generator .Indent ();
         generator .string += '}';
         generator .string += generator .TidyBreak ();
      }

      generator .JSONRemoveComma ();

      // End

      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';
      generator .string += generator .TidyBreak ();
      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';

      generator .LeaveScope ();
   },
   dispose ()
   {
      const executionContext = this .getExecutionContext ();

      // Remove named node if any.

      if (this .getName ())
         executionContext .removeNamedNode (this .getName ())

      if (executionContext .isScene ())
      {
         // Remove imported node if any.

         if (!executionContext .isMainScene ())
         {
            const parentContext = executionContext .getExecutionContext ();

            for (const importedNode of [... parentContext .getImportedNodes ()])
            {
               try
               {
                  if (importedNode .getExportedNode () === this)
                     parentContext .removeImportedNode (importedNode .getImportedName ());
               }
               catch (error)
               {
                  //console .error (error);
               }
            }
         }

         // Remove exported node if any.

         for (const exportedNode of [... executionContext .getExportedNodes ()])
         {
            if (exportedNode .getLocalNode () === this)
               executionContext .removeExportedNode (exportedNode .getExportedName ());
         }
      }

      // Remove node from entire scene graph.

      for (const firstParent of new Set (this .getParents ()))
      {
         if (!(firstParent instanceof x_ite_Fields .SFNode))
            continue;

         for (const secondParent of new Set (firstParent .getParents ()))
         {
            if (!(secondParent instanceof x_ite_Fields .MFNode))
               continue;

            secondParent .setValue ([... secondParent] .filter (node => node ?.getValue () !== this))
         }
      }

      for (const firstParent of new Set (this .getParents ()))
      {
         if (!(firstParent instanceof x_ite_Fields .SFNode))
            continue;

         firstParent .setValue (null);
      }

      // Call super.dispose, where fields get disposed.

      Base_X3DBaseNode .prototype .dispose .call (this);
   },
});

for (const key of Object .keys (X3DNode .prototype))
   Object .defineProperty (X3DNode .prototype, key, { enumerable: false });

Object .defineProperties (X3DNode,
{
   typeName:
   {
      value: "X3DNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Core",
      enumerable: true,
   },
});

const X3DNode_default_ = X3DNode;
;

x_ite_Namespace .add ("X3DNode", "x_ite/Components/Core/X3DNode", X3DNode_default_);
/* harmony default export */ const Core_X3DNode = (X3DNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Core/X3DMetadataObject.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function X3DMetadataObject (executionContext)
{
   this .addType (Base_X3DConstants .X3DMetadataObject);
}

Object .assign (X3DMetadataObject .prototype,
{
   initialize () { },
   dispose () { },
});

Object .defineProperties (X3DMetadataObject,
{
   typeName:
   {
      value: "X3DMetadataObject",
      enumerable: true,
   },
   componentName:
   {
      value: "Core",
      enumerable: true,
   },
});

const X3DMetadataObject_default_ = X3DMetadataObject;
;

x_ite_Namespace .add ("X3DMetadataObject", "x_ite/Components/Core/X3DMetadataObject", X3DMetadataObject_default_);
/* harmony default export */ const Core_X3DMetadataObject = (X3DMetadataObject_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Core/MetadataBoolean.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function MetadataBoolean (executionContext)
{
   Core_X3DNode           .call (this, executionContext);
   Core_X3DMetadataObject .call (this, executionContext);

   this .addType (Base_X3DConstants .MetadataBoolean);
}

Object .assign (Object .setPrototypeOf (MetadataBoolean .prototype, Core_X3DNode .prototype),
   Core_X3DMetadataObject .prototype,
{
   initialize ()
   {
      Core_X3DNode           .prototype .initialize .call (this);
      Core_X3DMetadataObject .prototype .initialize .call (this);
   },
   getContainerField (parser = false)
   {
      if (parser && this .getExecutionContext () .getSpecificationVersion () <= 3.3)
         return "metadata";

      return Core_X3DNode .prototype .getContainerField .call (this);
   },
   dispose ()
   {
      Core_X3DMetadataObject .prototype .dispose .call (this);
      Core_X3DNode           .prototype .dispose .call (this);
   },
});

Object .defineProperties (MetadataBoolean,
{
   typeName:
   {
      value: "MetadataBoolean",
      enumerable: true,
   },
   componentName:
   {
      value: "Core",
      enumerable: true,
   },
   containerField:
   {
      value: "value",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.3", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",  new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "name",      new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "reference", new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "value",     new x_ite_Fields .MFBool ()),
      ]),
      enumerable: true,
   },
});

const MetadataBoolean_default_ = MetadataBoolean;
;

x_ite_Namespace .add ("MetadataBoolean", "x_ite/Components/Core/MetadataBoolean", MetadataBoolean_default_);
/* harmony default export */ const Core_MetadataBoolean = (MetadataBoolean_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Core/MetadataDouble.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function MetadataDouble (executionContext)
{
   Core_X3DNode           .call (this, executionContext);
   Core_X3DMetadataObject .call (this, executionContext);

   this .addType (Base_X3DConstants .MetadataDouble);
}

Object .assign (Object .setPrototypeOf (MetadataDouble .prototype, Core_X3DNode .prototype),
   Core_X3DMetadataObject .prototype,
{
   initialize ()
   {
      Core_X3DNode           .prototype .initialize .call (this);
      Core_X3DMetadataObject .prototype .initialize .call (this);
   },
   getContainerField (parser = false)
   {
      if (parser && this .getExecutionContext () .getSpecificationVersion () <= 3.3)
         return "metadata";

      return Core_X3DNode .prototype .getContainerField .call (this);
   },
   dispose ()
   {
      Core_X3DMetadataObject .prototype .dispose .call (this);
      Core_X3DNode           .prototype .dispose .call (this);
   },
});

Object .defineProperties (MetadataDouble,
{
   typeName:
   {
      value: "MetadataDouble",
      enumerable: true,
   },
   componentName:
   {
      value: "Core",
      enumerable: true,
   },
   containerField:
   {
      value: "value",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",  new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "name",      new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "reference", new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "value",     new x_ite_Fields .MFDouble ()),
      ]),
      enumerable: true,
   },
});

const MetadataDouble_default_ = MetadataDouble;
;

x_ite_Namespace .add ("MetadataDouble", "x_ite/Components/Core/MetadataDouble", MetadataDouble_default_);
/* harmony default export */ const Core_MetadataDouble = (MetadataDouble_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Core/MetadataFloat.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function MetadataFloat (executionContext)
{
   Core_X3DNode           .call (this, executionContext);
   Core_X3DMetadataObject .call (this, executionContext);

   this .addType (Base_X3DConstants .MetadataFloat);
}

Object .assign (Object .setPrototypeOf (MetadataFloat .prototype, Core_X3DNode .prototype),
   Core_X3DMetadataObject .prototype,
{
   initialize ()
   {
      Core_X3DNode           .prototype .initialize .call (this);
      Core_X3DMetadataObject .prototype .initialize .call (this);
   },
   getContainerField (parser = false)
   {
      if (parser && this .getExecutionContext () .getSpecificationVersion () <= 3.3)
         return "metadata";

      return Core_X3DNode .prototype .getContainerField .call (this);
   },
   dispose ()
   {
      Core_X3DMetadataObject .prototype .dispose .call (this);
      Core_X3DNode           .prototype .dispose .call (this);
   },
});

Object .defineProperties (MetadataFloat,
{
   typeName:
   {
      value: "MetadataFloat",
      enumerable: true,
   },
   componentName:
   {
      value: "Core",
      enumerable: true,
   },
   containerField:
   {
      value: "value",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",  new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "name",      new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "reference", new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "value",     new x_ite_Fields .MFFloat ()),
      ]),
      enumerable: true,
   },
});

const MetadataFloat_default_ = MetadataFloat;
;

x_ite_Namespace .add ("MetadataFloat", "x_ite/Components/Core/MetadataFloat", MetadataFloat_default_);
/* harmony default export */ const Core_MetadataFloat = (MetadataFloat_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Core/MetadataInteger.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function MetadataInteger (executionContext)
{
   Core_X3DNode           .call (this, executionContext);
   Core_X3DMetadataObject .call (this, executionContext);

   this .addType (Base_X3DConstants .MetadataInteger);
}

Object .assign (Object .setPrototypeOf (MetadataInteger .prototype, Core_X3DNode .prototype),
   Core_X3DMetadataObject .prototype,
{
   initialize ()
   {
      Core_X3DNode           .prototype .initialize .call (this);
      Core_X3DMetadataObject .prototype .initialize .call (this);
   },
   getContainerField (parser = false)
   {
      if (parser && this .getExecutionContext () .getSpecificationVersion () <= 3.3)
         return "metadata";

      return Core_X3DNode .prototype .getContainerField .call (this);
   },
   dispose ()
   {
      Core_X3DMetadataObject .prototype .dispose .call (this);
      Core_X3DNode           .prototype .dispose .call (this);
   },
});

Object .defineProperties (MetadataInteger,
{
   typeName:
   {
      value: "MetadataInteger",
      enumerable: true,
   },
   componentName:
   {
      value: "Core",
      enumerable: true,
   },
   containerField:
   {
      value: "value",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",  new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "name",      new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "reference", new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "value",     new x_ite_Fields .MFInt32 ()),
      ]),
      enumerable: true,
   },
});

const MetadataInteger_default_ = MetadataInteger;
;

x_ite_Namespace .add ("MetadataInteger", "x_ite/Components/Core/MetadataInteger", MetadataInteger_default_);
/* harmony default export */ const Core_MetadataInteger = (MetadataInteger_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Core/MetadataSet.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function MetadataSet (executionContext)
{
   Core_X3DNode           .call (this, executionContext);
   Core_X3DMetadataObject .call (this, executionContext);

   this .addType (Base_X3DConstants .MetadataSet);
}

Object .assign (Object .setPrototypeOf (MetadataSet .prototype, Core_X3DNode .prototype),
   Core_X3DMetadataObject .prototype,
{
   initialize ()
   {
      Core_X3DNode           .prototype .initialize .call (this);
      Core_X3DMetadataObject .prototype .initialize .call (this);
   },
   getContainerField (parser = false)
   {
      if (parser && this .getExecutionContext () .getSpecificationVersion () <= 3.3)
         return "metadata";

      return Core_X3DNode .prototype .getContainerField .call (this);
   },
   dispose ()
   {
      Core_X3DMetadataObject .prototype .dispose .call (this);
      Core_X3DNode           .prototype .dispose .call (this);
   },
});

Object .defineProperties (MetadataSet,
{
   typeName:
   {
      value: "MetadataSet",
      enumerable: true,
   },
   componentName:
   {
      value: "Core",
      enumerable: true,
   },
   containerField:
   {
      value: "value",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",  new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "name",      new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "reference", new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "value",     new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const MetadataSet_default_ = MetadataSet;
;

x_ite_Namespace .add ("MetadataSet", "x_ite/Components/Core/MetadataSet", MetadataSet_default_);
/* harmony default export */ const Core_MetadataSet = (MetadataSet_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Core/MetadataString.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function MetadataString (executionContext)
{
   Core_X3DNode           .call (this, executionContext);
   Core_X3DMetadataObject .call (this, executionContext);

   this .addType (Base_X3DConstants .MetadataString);
}

Object .assign (Object .setPrototypeOf (MetadataString .prototype, Core_X3DNode .prototype),
   Core_X3DMetadataObject .prototype,
{
   initialize ()
   {
      Core_X3DNode           .prototype .initialize .call (this);
      Core_X3DMetadataObject .prototype .initialize .call (this);
   },
   getContainerField (parser = false)
   {
      if (parser && this .getExecutionContext () .getSpecificationVersion () <= 3.3)
         return "metadata";

      return Core_X3DNode .prototype .getContainerField .call (this);
   },
   dispose ()
   {
      Core_X3DMetadataObject .prototype .dispose .call (this);
      Core_X3DNode           .prototype .dispose .call (this);
   },
});

Object .defineProperties (MetadataString,
{
   typeName:
   {
      value: "MetadataString",
      enumerable: true,
   },
   componentName:
   {
      value: "Core",
      enumerable: true,
   },
   containerField:
   {
      value: "value",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",  new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "name",      new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "reference", new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "value",     new x_ite_Fields .MFString ()),
      ]),
      enumerable: true,
   },
});

const MetadataString_default_ = MetadataString;
;

x_ite_Namespace .add ("MetadataString", "x_ite/Components/Core/MetadataString", MetadataString_default_);
/* harmony default export */ const Core_MetadataString = (MetadataString_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Core/X3DChildNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function X3DChildNode (executionContext)
{
   if (this .getExecutionContext ())
      return;

   Core_X3DNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DChildNode);

   this .addChildObjects (Base_X3DConstants .outputOnly, "isCameraObject",   new x_ite_Fields .SFBool (),
                          Base_X3DConstants .outputOnly, "isPickableObject", new x_ite_Fields .SFBool ());
}

Object .assign (Object .setPrototypeOf (X3DChildNode .prototype, Core_X3DNode .prototype),
{
   setCameraObject (value)
   {
      if (value !== this ._isCameraObject .getValue ())
         this ._isCameraObject = value;
   },
   isCameraObject ()
   {
      return this ._isCameraObject .getValue ();
   },
   setPickableObject (value)
   {
      if (value !== this ._isPickableObject .getValue ())
         this ._isPickableObject = value;
   },
   isPickableObject ()
   {
      return this ._isPickableObject .getValue ();
   },
   getMustDisplay ()
   {
      return false
   },
});

Object .defineProperties (X3DChildNode,
{
   typeName:
   {
      value: "X3DChildNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Core",
      enumerable: true,
   },
});

const X3DChildNode_default_ = X3DChildNode;
;

x_ite_Namespace .add ("X3DChildNode", "x_ite/Components/Core/X3DChildNode", X3DChildNode_default_);
/* harmony default export */ const Core_X3DChildNode = (X3DChildNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Core/X3DInfoNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function X3DInfoNode (executionContext)
{
   Core_X3DChildNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DInfoNode);
}

Object .setPrototypeOf (X3DInfoNode .prototype, Core_X3DChildNode .prototype);

Object .defineProperties (X3DInfoNode,
{
   typeName:
   {
      value: "X3DInfoNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Core",
      enumerable: true,
   },
});

const X3DInfoNode_default_ = X3DInfoNode;
;

x_ite_Namespace .add ("X3DInfoNode", "x_ite/Components/Core/X3DInfoNode", X3DInfoNode_default_);
/* harmony default export */ const Core_X3DInfoNode = (X3DInfoNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Core/WorldInfo.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function WorldInfo (executionContext)
{
   Core_X3DInfoNode .call (this, executionContext);

   this .addType (Base_X3DConstants .WorldInfo);
}

Object .assign (Object .setPrototypeOf (WorldInfo .prototype, Core_X3DInfoNode .prototype),
{
   initialize ()
   {
      Core_X3DInfoNode .prototype .initialize .call (this);

      this .getExecutionContext () .addWorldInfo (this);
   },
   dispose ()
   {
      this .getExecutionContext () .removeWorldInfo (this);

      Core_X3DInfoNode .prototype .dispose .call (this);
   },
});

Object .defineProperties (WorldInfo,
{
   typeName:
   {
      value: "WorldInfo",
      enumerable: true,
   },
   componentName:
   {
      value: "Core",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "title",    new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "info",     new x_ite_Fields .MFString ()),
      ]),
      enumerable: true,
   },
});

const WorldInfo_default_ = WorldInfo;
;

x_ite_Namespace .add ("WorldInfo", "x_ite/Components/Core/WorldInfo", WorldInfo_default_);
/* harmony default export */ const Core_WorldInfo = (WorldInfo_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Core/X3DBindableNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




let modificationCount = 0;

function X3DBindableNode (executionContext)
{
   Core_X3DChildNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DBindableNode);

   this .modificationCount = 0;
}

Object .assign (Object .setPrototypeOf (X3DBindableNode .prototype, Core_X3DChildNode .prototype),
{
   initialize ()
   {
      Core_X3DChildNode .prototype .initialize .call (this);

      this ._set_bind .addInterest ("set_bind__", this);
   },
   isCameraObject ()
   {
      return true;
   },
   getModificationCount ()
   {
      return this .modificationCount;
   },
   transitionStart ()
   { },
   set_bind__ ()
   {
      this .modificationCount = ++ modificationCount;
   }
});

Object .defineProperties (X3DBindableNode,
{
   typeName:
   {
      value: "X3DBindableNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Core",
      enumerable: true,
   },
   getModificationCount:
   {
      value: function ()
      {
         return modificationCount;
      },
      enumerable: false,
   },
});

const X3DBindableNode_default_ = X3DBindableNode;
;

x_ite_Namespace .add ("X3DBindableNode", "x_ite/Components/Core/X3DBindableNode", X3DBindableNode_default_);
/* harmony default export */ const Core_X3DBindableNode = (X3DBindableNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Execution/NamedNodesHandling.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

const getUniqueName = function (array, name = "", number = false)
{
   name = String (name) .replace (/_\d+$/, "");

   let
      newName = number ? `${name}_1` : name,
      lo      = 1,
      hi      = 1;

   while (array .has (newName) || newName .length === 0)
   {
      lo   = hi;
      hi <<= 1;

      newName = `${name}_${lo}`;
   }

   lo >>>= 1;
   hi >>>= 1;

   if (lo && hi)
   {
      while (lo < hi)
      {
         const m = (lo + hi) >>> 1;

         if (array .has (`${name}_${m}`))
            lo = m + 1;
         else
            hi = m;
      }

      newName = `${name}_${lo}`;
   }

   return newName;
};

;// CONCATENATED MODULE: ./src/x_ite/Execution/NamedNodesArray.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function NamedNodesArray (values = [ ])
{
   return Base_X3DInfoArray .call (this, Array .from (values, value => [value .getNodeName (), value]), Fields_SFNode);
}

Object .setPrototypeOf (NamedNodesArray .prototype, Base_X3DInfoArray .prototype);

for (const key of Object .keys (NamedNodesArray .prototype))
   Object .defineProperty (NamedNodesArray .prototype, key, { enumerable: false });

Object .defineProperties (NamedNodesArray,
{
   typeName:
   {
      value: "NamedNodesArray",
      enumerable: true,
   },
});

const NamedNodesArray_default_ = NamedNodesArray;
;

x_ite_Namespace .add ("NamedNodesArray", "x_ite/Execution/NamedNodesArray", NamedNodesArray_default_);
/* harmony default export */ const Execution_NamedNodesArray = (NamedNodesArray_default_);
;// CONCATENATED MODULE: ./src/x_ite/Execution/X3DImportedNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






const
   _inlineNode   = Symbol (),
   _exportedName = Symbol (),
   _importedName = Symbol (),
   _routes       = Symbol ();

function X3DImportedNode (executionContext, inlineNode, exportedName, importedName)
{
   Core_X3DNode .call (this, executionContext);

   this [_inlineNode]   = inlineNode;
   this [_exportedName] = exportedName;
   this [_importedName] = importedName;
   this [_routes]       = new Set ();

   this [_inlineNode] ._loadState .addInterest ("set_loadState__", this);
}

// Must be of type X3DNode, to get routes work.
Object .assign (Object .setPrototypeOf (X3DImportedNode .prototype, Core_X3DNode .prototype),
{
   getInlineNode ()
   {
      return this [_inlineNode];
   },
   getExportedName ()
   {
      return this [_exportedName];
   },
   getExportedNode ()
   {
      return this [_inlineNode] .getInternalScene () .getExportedNode (this [_exportedName]) .getValue ();
   },
   getImportedName ()
   {
      return this [_importedName];
   },
   hasRoutes (baseNode)
   {
      for (const route of this [_routes])
      {
         if (route .sourceNode === baseNode)
            return true;

         if (route .destinationNode === baseNode)
            return true;
      }

      return false;
   },
   addRoute (sourceNode, sourceField, destinationNode, destinationField)
   {
      // Add route.

      const route = {
         sourceNode: sourceNode,
         sourceField: sourceField,
         destinationNode: destinationNode,
         destinationField: destinationField,
      };

      this [_routes] .add (route);

      // Try to resolve source or destination node routes.

      if (this [_inlineNode] .checkLoadState () === Base_X3DConstants .COMPLETE_STATE)
         this .resolveRoute (route);
   },
   resolveRoute (route)
   {
      try
      {
         const
            sourceField      = route .sourceField,
            destinationField = route .destinationField;

         let
            sourceNode      = route .sourceNode,
            destinationNode = route .destinationNode;

         if (route .real)
            route .real .dispose ();

         if (sourceNode instanceof X3DImportedNode)
            sourceNode = sourceNode .getExportedNode ();

         if (destinationNode instanceof X3DImportedNode)
            destinationNode = destinationNode .getExportedNode ();

         route .real = this .getExecutionContext () .addSimpleRoute (sourceNode, sourceField, destinationNode, destinationField);
      }
      catch (error)
      {
         console .error (error .message);
      }
   },
   deleteRoute (real)
   {
      for (const route of this [_routes])
      {
         if (route .real === real)
            this [_routes] .delete (route);
      }
   },
   deleteRoutes ()
   {
      for (const route of this [_routes])
      {
         const real = route .real

         if (real)
         {
            delete route .real;
            this .getExecutionContext () .deleteSimpleRoute (real);
         }
      }
   },
   set_loadState__ ()
   {
      switch (this [_inlineNode] .checkLoadState ())
      {
         case Base_X3DConstants .NOT_STARTED_STATE:
         case Base_X3DConstants .FAILED_STATE:
         {
            this .deleteRoutes ();
            break;
         }
         case Base_X3DConstants .COMPLETE_STATE:
         {
            this .deleteRoutes ();

            for (const route of this [_routes])
               this .resolveRoute (route);

            break;
         }
      }
   },
   toStream (generator)
   {
      Base_X3DObject .prototype .toStream .call (this, generator);
   },
   toVRMLStream (generator)
   {
      if (generator .ExistsNode (this .getInlineNode ()))
      {
         generator .string += generator .Indent ();
         generator .string += "IMPORT";
         generator .string += generator .Space ();
         generator .string += generator .Name (this .getInlineNode ());
         generator .string += ".";
         generator .string += this .getExportedName ();

         if (this .getImportedName () !== this .getExportedName ())
         {
            generator .string += generator .Space ();
            generator .string += "AS";
            generator .string += generator .Space ();
            generator .string += this .getImportedName ();
         }

         try
         {
            generator .AddRouteNode (this);
            generator .AddImportedNode (this .getExportedNode (), this .getImportedName ());
         }
         catch
         {
            // Output unresolved routes.

            for (const route of this [_routes])
            {
               const
                  sourceNode       = route .sourceNode,
                  sourceField      = route .sourceField,
                  destinationNode  = route .destinationNode,
                  destinationField = route .destinationField;

               if (generator .ExistsRouteNode (sourceNode) && generator .ExistsRouteNode (destinationNode))
               {
                  const sourceNodeName = sourceNode instanceof X3DImportedNode
                     ? sourceNode .getImportedName ()
                     : generator .Name (sourceNode);

                  const destinationNodeName = destinationNode instanceof X3DImportedNode
                     ? destinationNode .getImportedName ()
                     : generator .Name (destinationNode);

                  generator .string += generator .TidyBreak ();
                  generator .string += generator .Indent ();
                  generator .string += "ROUTE";
                  generator .string += generator .Space ();
                  generator .string += sourceNodeName;
                  generator .string += ".";
                  generator .string += sourceField;
                  generator .string += generator .Space ();
                  generator .string += "TO";
                  generator .string += generator .Space ();
                  generator .string += destinationNodeName;
                  generator .string += ".";
                  generator .string += destinationField;
               }
            }
         }
      }
      else
      {
         throw new Error ("X3DImportedNode.toXMLStream: Inline node does not exist.");
      }
   },
   toXMLStream (generator)
   {
      if (generator .ExistsNode (this .getInlineNode ()))
      {
         generator .string += generator .Indent ();
         generator .string += "<IMPORT";
         generator .string += generator .Space ();
         generator .string += "inlineDEF='";
         generator .string += generator .XMLEncode (generator .Name (this .getInlineNode ()));
         generator .string += "'";
         generator .string += generator .Space ();
         generator .string += "importedDEF='";
         generator .string += generator .XMLEncode (this .getExportedName ());
         generator .string += "'";

         if (this .getImportedName () !== this .getExportedName ())
         {
            generator .string += generator .Space ();
            generator .string += "AS='";
            generator .string += generator .XMLEncode (this .getImportedName ());
            generator .string += "'";
         }

         generator .string += generator .closingTags ? "></IMPORT>" : "/>";

         try
         {
            generator .AddRouteNode (this);
            generator .AddImportedNode (this .getExportedNode (), this .getImportedName ());
         }
         catch
         {
            // Output unresolved routes.

            for (const route of this [_routes])
            {
               const
                  sourceNode       = route .sourceNode,
                  sourceField      = route .sourceField,
                  destinationNode  = route .destinationNode,
                  destinationField = route .destinationField;

               if (generator .ExistsRouteNode (sourceNode) && generator .ExistsRouteNode (destinationNode))
               {
                  const sourceNodeName = sourceNode instanceof X3DImportedNode
                     ? sourceNode .getImportedName ()
                     : generator .Name (sourceNode);

                  const destinationNodeName = destinationNode instanceof X3DImportedNode
                     ? destinationNode .getImportedName ()
                     : generator .Name (destinationNode);

                  generator .string += generator .TidyBreak ();
                  generator .string += generator .Indent ();
                  generator .string += "<ROUTE";
                  generator .string += generator .Space ();
                  generator .string += "fromNode='";
                  generator .string += generator .XMLEncode (sourceNodeName);
                  generator .string += "'";
                  generator .string += generator .Space ();
                  generator .string += "fromField='";
                  generator .string += generator .XMLEncode (sourceField);
                  generator .string += "'";
                  generator .string += generator .Space ();
                  generator .string += "toNode='";
                  generator .string += generator .XMLEncode (destinationNodeName);
                  generator .string += "'";
                  generator .string += generator .Space ();
                  generator .string += "toField='";
                  generator .string += generator .XMLEncode (destinationField);
                  generator .string += "'";
                  generator .string += generator .closingTags ? "></ROUTE>" : "/>";
               }
            }
         }
      }
      else
      {
         throw new Error ("X3DImportedNode.toXMLStream: Inline node does not exist.");
      }
   },
   toJSONStream (generator)
   {
      if (generator .ExistsNode (this .getInlineNode ()))
      {
         generator .string += generator .Indent ();
         generator .string += '{';
         generator .string += generator .TidySpace ();
         generator .string += '"';
         generator .string += "IMPORT";
         generator .string += '"';
         generator .string += ':';
         generator .string += generator .TidyBreak ();
         generator .string += generator .IncIndent ();
         generator .string += generator .Indent ();
         generator .string += '{';
         generator .string += generator .TidyBreak ();
         generator .string += generator .IncIndent ();

         generator .string += generator .Indent ();
         generator .string += '"';
         generator .string += "@inlineDEF";
         generator .string += '"';
         generator .string += ':';
         generator .string += generator .TidySpace ();
         generator .string += '"';
         generator .string += generator .JSONEncode (generator .Name (this .getInlineNode ()));
         generator .string += '"';
         generator .string += ',';
         generator .string += generator .TidyBreak ();

         generator .string += generator .Indent ();
         generator .string += '"';
         generator .string += "@importedDEF";
         generator .string += '"';
         generator .string += ':';
         generator .string += generator .TidySpace ();
         generator .string += '"';
         generator .string += generator .JSONEncode (this .getExportedName ());
         generator .string += '"';

         if (this .getImportedName () !== this .getExportedName ())
         {
            generator .string += ',';
            generator .string += generator .TidyBreak ();
            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "@AS";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '"';
            generator .string += generator .JSONEncode (this .getImportedName ());
            generator .string += '"';
            generator .string += generator .TidyBreak ();
         }
         else
         {
            generator .string += generator .TidyBreak ();
         }

         generator .string += generator .DecIndent ();
         generator .string += generator .Indent ();
         generator .string += '}';
         generator .string += generator .TidyBreak ();
         generator .string += generator .DecIndent ();
         generator .string += generator .Indent ();
         generator .string += '}';

         try
         {
            generator .AddRouteNode (this);
            generator .AddImportedNode (this .getExportedNode (), this .getImportedName ());
         }
         catch
         {
            // Output unresolved routes.

            for (const route of this [_routes])
            {
               const
                  sourceNode       = route .sourceNode,
                  sourceField      = route .sourceField,
                  destinationNode  = route .destinationNode,
                  destinationField = route .destinationField;

               if (generator .ExistsRouteNode (sourceNode) && generator .ExistsRouteNode (destinationNode))
               {
                  const sourceNodeName = sourceNode instanceof X3DImportedNode
                     ? sourceNode .getImportedName ()
                     : generator .Name (sourceNode);

                  const destinationNodeName = destinationNode instanceof X3DImportedNode
                     ? destinationNode .getImportedName ()
                     : generator .Name (destinationNode);

                  generator .string += ',';
                  generator .string += generator .TidyBreak ();
                  generator .string += generator .Indent ();
                  generator .string += '{';
                  generator .string += generator .TidySpace ();
                  generator .string += '"';
                  generator .string += "ROUTE";
                  generator .string += '"';
                  generator .string += ':';
                  generator .string += generator .TidyBreak ();
                  generator .string += generator .IncIndent ();
                  generator .string += generator .Indent ();
                  generator .string += '{';
                  generator .string += generator .TidyBreak ();
                  generator .string += generator .IncIndent ();

                  generator .string += generator .Indent ();
                  generator .string += '"';
                  generator .string += "@fromNode";
                  generator .string += '"';
                  generator .string += ':';
                  generator .string += generator .TidySpace ();
                  generator .string += '"';
                  generator .string += generator .JSONEncode (sourceNodeName);
                  generator .string += '"';
                  generator .string += ',';
                  generator .string += generator .TidyBreak ();

                  generator .string += generator .Indent ();
                  generator .string += '"';
                  generator .string += "@fromField";
                  generator .string += '"';
                  generator .string += ':';
                  generator .string += generator .TidySpace ();
                  generator .string += '"';
                  generator .string += generator .JSONEncode (sourceField);
                  generator .string += '"';
                  generator .string += ',';
                  generator .string += generator .TidyBreak ();

                  generator .string += generator .Indent ();
                  generator .string += '"';
                  generator .string += "@toNode";
                  generator .string += '"';
                  generator .string += ':';
                  generator .string += generator .TidySpace ();
                  generator .string += '"';
                  generator .string += generator .JSONEncode (destinationNodeName);
                  generator .string += '"';
                  generator .string += ',';
                  generator .string += generator .TidyBreak ();

                  generator .string += generator .Indent ();
                  generator .string += '"';
                  generator .string += "@toField";
                  generator .string += '"';
                  generator .string += ':';
                  generator .string += generator .TidySpace ();
                  generator .string += '"';
                  generator .string += generator .JSONEncode (destinationField);
                  generator .string += '"';
                  generator .string += generator .TidyBreak ();

                  generator .string += generator .DecIndent ();
                  generator .string += generator .Indent ();
                  generator .string += '}';
                  generator .string += generator .TidyBreak ();
                  generator .string += generator .DecIndent ();
                  generator .string += generator .Indent ();
                  generator .string += '}';
               }
            }
         }
      }
      else
      {
         throw new Error ("X3DImportedNode.toJSONStream: Inline node does not exist.");
      }
   },
   dispose ()
   {
      this [_inlineNode] ._loadState .removeInterest ("set_loadState__", this);

      this .deleteRoutes ();

      Core_X3DNode .prototype .dispose .call (this);
   },
});

for (const key of Object .keys (X3DImportedNode .prototype))
   Object .defineProperty (X3DImportedNode .prototype, key, { enumerable: false });

Object .defineProperties (X3DImportedNode .prototype,
{
   inlineNode:
   {
      get ()
      {
         return Fields_SFNodeCache .get (this [_inlineNode]);
      },
      enumerable: true,
   },
   exportedName:
   {
      get ()
      {
         return this [_exportedName];
      },
      enumerable: true,
   },
   exportedNode:
   {
      get ()
      {
         return this [_inlineNode] .getInternalScene () .getExportedNode (this [_exportedName]);
      },
      enumerable: true,
   },
   importedName:
   {
      get ()
      {
         return this [_importedName];
      },
      enumerable: true,
   },
});

Object .defineProperties (X3DImportedNode,
{
   typeName:
   {
      value: "X3DImportedNode",
      enumerable: true,
   },
});

const X3DImportedNode_default_ = X3DImportedNode;
;

x_ite_Namespace .add ("X3DImportedNode", "x_ite/Execution/X3DImportedNode", X3DImportedNode_default_);
/* harmony default export */ const Execution_X3DImportedNode = (X3DImportedNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Execution/ImportedNodesArray.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function ImportedNodesArray (values = [ ])
{
   return Base_X3DInfoArray .call (this, Array .from (values, value => [value .getImportedName (), value]), Execution_X3DImportedNode);
}

Object .setPrototypeOf (ImportedNodesArray .prototype, Base_X3DInfoArray .prototype);

for (const key of Object .keys (ImportedNodesArray .prototype))
   Object .defineProperty (ImportedNodesArray .prototype, key, { enumerable: false });

Object .defineProperties (ImportedNodesArray,
{
   typeName:
   {
      value: "ImportedNodesArray",
      enumerable: true,
   },
});

const ImportedNodesArray_default_ = ImportedNodesArray;
;

x_ite_Namespace .add ("ImportedNodesArray", "x_ite/Execution/ImportedNodesArray", ImportedNodesArray_default_);
/* harmony default export */ const Execution_ImportedNodesArray = (ImportedNodesArray_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Networking/X3DUrlObject.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




const
   X3DUrlObject_cache                   = Symbol (),
   _autoRefreshStartTime    = Symbol (),
   _autoRefreshCompleteTime = Symbol (),
   _autoRefreshId           = Symbol ();

function X3DUrlObject (executionContext)
{
   this .addType (Base_X3DConstants .X3DUrlObject);

   this .addChildObjects (Base_X3DConstants .outputOnly,  "loadState", new x_ite_Fields .SFInt32 (Base_X3DConstants .NOT_STARTED_STATE),
                          Base_X3DConstants .inputOutput, "loadData",  new x_ite_Fields .SFTime ());

   this [X3DUrlObject_cache]                = true;
   this [_autoRefreshStartTime] = Date .now ();
}

Object .assign (X3DUrlObject .prototype,
{
   initialize ()
   {
      this .getLive () .addInterest ("set_live__", this);

      this ._load                 .addInterest ("set_load__",        this);
      this ._url                  .addInterest ("set_url__",         this);
      this ._loadData             .addInterest ("loadData",          this);
      this ._autoRefresh          .addInterest ("set_autoRefresh__", this);
      this ._autoRefreshTimeLimit .addInterest ("set_autoRefresh__", this);
   },
   setLoadState (value, notify = true)
   {
      this ._loadState = value;

      if (value === Base_X3DConstants .COMPLETE_STATE)
      {
         this [_autoRefreshCompleteTime] = Date .now ();
         this .setAutoRefreshTimer (this ._autoRefresh .getValue ());
      }

      if (!notify)
         return;

      switch (value)
      {
         case Base_X3DConstants .NOT_STARTED_STATE:
            break;
         case Base_X3DConstants .IN_PROGRESS_STATE:
         {
            this .getScene () .addLoadingObject (this);
            break;
         }
         case Base_X3DConstants .COMPLETE_STATE:
         case Base_X3DConstants .FAILED_STATE:
         {
            this .getScene () .removeLoadingObject (this);
            break;
         }
      }
   },
   checkLoadState ()
   {
      return this ._loadState .getValue ();
   },
   getLoadState ()
   {
      return this ._loadState;
   },
   setCache (value)
   {
      this [X3DUrlObject_cache] = value;
   },
   getCache ()
   {
      return this [X3DUrlObject_cache] && this .getBrowser () .getBrowserOption ("Cache");
   },
   requestImmediateLoad (cache = true)
   {
      return new Promise ((resolve, reject) =>
      {
         const loading = () =>
         {
            const _loading = Symbol ();

            this ._loadState .addFieldCallback (_loading, () =>
            {
               switch (this .checkLoadState ())
               {
                  case Base_X3DConstants .COMPLETE_STATE:
                     this ._loadState .removeFieldCallback (_loading);
                     resolve ();
                     break;
                  case Base_X3DConstants .FAILED_STATE:
                     this ._loadState .removeFieldCallback (_loading);
                     reject ();
                     break;
               }
            })
         };

         const loadState = this .checkLoadState ();

         switch (loadState)
         {
            case Base_X3DConstants .IN_PROGRESS_STATE:
            {
               loading ();
               return;
            }
            case Base_X3DConstants .COMPLETE_STATE:
            {
               resolve ();
               return;
            }
            case Base_X3DConstants .FAILED_STATE:
            {
               reject ();
               return;
            }
         }

         const browser = this .getBrowser ();

         if (!browser .getBrowserOption ("LoadUrlObjects") && this .getExecutionContext () !== browser .getPrivateScene () && !this .isExternProto)
         {
            resolve ();
            return;
         }

         if (!this ._load .getValue ())
         {
            reject ();
            return;
         }

         if (this ._url .length === 0)
         {
            resolve ();
            return;
         }

         this .setCache (cache);
         this .setLoadState (Base_X3DConstants .IN_PROGRESS_STATE);

         if (this .isInitialized ())
            // Buffer prevents double load of the scene if load and url field are set at the same time.
            this ._loadData = this .getBrowser () .getCurrentTime ();
         else
            this .loadData ();

         loading ();
      });
   },
   loadNow ()
   {
      this .setLoadState (Base_X3DConstants .NOT_STARTED_STATE);

      return this .requestImmediateLoad ();
   },
   loadData ()
   { },
   requestUnload ()
   {
      const loadState = this .checkLoadState ();

      if (loadState === Base_X3DConstants .NOT_STARTED_STATE || loadState === Base_X3DConstants .FAILED_STATE)
         return;

      this .setLoadState (Base_X3DConstants .NOT_STARTED_STATE);
      this .unloadData ();
   },
   unloadNow ()
   {
      this .requestUnload ();
   },
   unloadData ()
   { },
   setAutoRefreshTimer (autoRefreshInterval)
   {
      clearTimeout (this [_autoRefreshId]);

      if (this ._autoRefresh .getValue () <= 0)
         return;

      const autoRefreshTimeLimit = this ._autoRefreshTimeLimit .getValue ();

      if (autoRefreshTimeLimit !== 0)
      {
         if ((Date .now () - this [_autoRefreshStartTime]) / 1000 > autoRefreshTimeLimit - autoRefreshInterval)
            return;
      }

      this [_autoRefreshId] = setTimeout (this .performAutoRefresh .bind (this), autoRefreshInterval * 1000);
   },
   performAutoRefresh ()
   {
      this .setLoadState (Base_X3DConstants .NOT_STARTED_STATE);
      this .requestImmediateLoad (false) .catch (Function .prototype);
   },
   set_live__ ()
   {
      if (this .getLive () .getValue ())
         this .set_autoRefresh__ ();
      else
         clearTimeout (this [_autoRefreshId]);
   },
   set_load__ ()
   {
      if (this ._load .getValue ())
         this .requestImmediateLoad () .catch (Function .prototype);
      else
         this .requestUnload ();
   },
   set_url__ ()
   {
      if (!this ._load .getValue ())
         return;

      this .setLoadState (Base_X3DConstants .NOT_STARTED_STATE);
      this .requestImmediateLoad () .catch (Function .prototype);
   },
   set_autoRefresh__ ()
   {
      if (this .checkLoadState () !== Base_X3DConstants .COMPLETE_STATE)
         return;

      const
         elapsedTime = (Date .now () - this [_autoRefreshCompleteTime]) / 1000,
         autoRefresh = this ._autoRefresh .getValue ();

      let autoRefreshInterval = autoRefresh - elapsedTime;

      if (autoRefreshInterval < 0)
         autoRefreshInterval = Math .ceil (elapsedTime / autoRefresh) * autoRefresh - elapsedTime;

      this .setAutoRefreshTimer (autoRefreshInterval);
   },
   dispose () { },
});

Object .defineProperties (X3DUrlObject,
{
   typeName:
   {
      value: "X3DUrlObject",
      enumerable: true,
   },
   componentName:
   {
      value: "Networking",
      enumerable: true,
   },
});

const X3DUrlObject_default_ = X3DUrlObject;
;

x_ite_Namespace .add ("X3DUrlObject", "x_ite/Components/Networking/X3DUrlObject", X3DUrlObject_default_);
/* harmony default export */ const Networking_X3DUrlObject = (X3DUrlObject_default_);
;// CONCATENATED MODULE: ./src/x_ite/Prototype/X3DProtoDeclarationNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function X3DProtoDeclarationNode (executionContext)
{
   Base_X3DBaseNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DProtoDeclarationNode);

   this .addChildObjects (Base_X3DConstants .outputOnly, "updateInstances", new x_ite_Fields .SFTime ());
}

Object .assign (Object .setPrototypeOf (X3DProtoDeclarationNode .prototype, Base_X3DBaseNode .prototype),
{
   canUserDefinedFields ()
   {
      return true;
   },
   createInstance (executionContext, setup = true /* non-public argument */)
   {
      if (setup === false)
      {
         return new Core_X3DPrototypeInstance (executionContext, this);
      }
      else
      {
         const instance = new Core_X3DPrototypeInstance (executionContext, this);

         instance .setup ();

         return Fields_SFNodeCache .get (instance);
      }
   },
   newInstance ()
   {
      return this .createInstance (this .getExecutionContext ());
   },
   requestUpdateInstances ()
   {
      this ._updateInstances = this .getBrowser () .getCurrentTime ();
   },
   updateInstances ()
   {
      this ._updateInstances .processEvent ();
   },
});

for (const key of Object .keys (X3DProtoDeclarationNode .prototype))
   Object .defineProperty (X3DProtoDeclarationNode .prototype, key, { enumerable: false });

Object .defineProperties (X3DProtoDeclarationNode,
{
   typeName:
   {
      value: "X3DProtoDeclarationNode",
      enumerable: true,
   },
});

Base_X3DConstants .addNode (X3DProtoDeclarationNode);

const X3DProtoDeclarationNode_default_ = X3DProtoDeclarationNode;
;

x_ite_Namespace .add ("X3DProtoDeclarationNode", "x_ite/Prototype/X3DProtoDeclarationNode", X3DProtoDeclarationNode_default_);
/* harmony default export */ const Prototype_X3DProtoDeclarationNode = (X3DProtoDeclarationNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Parser/X3DParser.js
/* provided dependency */ var X3DParser_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

function X3DParser (scene)
{
   this .scene             = scene;
   this .executionContexts = [ scene ];
   this .prototypes        = [ ];
}

Object .assign (X3DParser .prototype,
{
   getBrowser ()
   {
      return this .scene .getBrowser ();
   },
   getScene ()
   {
      return this .scene;
   },
   getExecutionContext ()
   {
      return this .executionContexts .at (-1);
   },
   pushExecutionContext (executionContext)
   {
      return this .executionContexts .push (executionContext);
   },
   popExecutionContext ()
   {
      this .executionContexts .pop ();
   },
   getPrototype ()
   {
      return this .prototypes .at (-1);
   },
   pushPrototype (prototype)
   {
      return this .prototypes .push (prototype);
   },
   popPrototype ()
   {
      this .prototypes .pop ();
   },
   isInsideProtoDefinition ()
   {
      return !! this .prototypes .length;
   },
   loadComponents ()
   {
      const
         browser = this .getBrowser (),
         scene   = this .getScene ();

      return Promise .all ([
         browser .loadComponents (scene .getProfile () || browser .getProfile ("Full")),
         browser .loadComponents (scene .getComponents ()),
      ]);
   },
   setUnits (units)
   {
      if (units)
         delete this .fromUnit;
      else
         this .fromUnit = function (category, value) { return value; };
   },
   fromUnit (category, value)
   {
      return this .scene .fromUnit (category, value);
   },
   convertColor (value, defaultColor = "white")
   {
      const
         wrap   = X3DParser_$("<div></div>") .hide () .css ("color", defaultColor) .appendTo (X3DParser_$("body")),
         div    = X3DParser_$("<div></div>").css ("color", value) .appendTo (wrap),
         rgb    = window .getComputedStyle (div [0]) .color,
         values = rgb .replace (/^rgba?\(|\)$/g, "") .split (/[\s,]+/) .map (s => parseFloat (s));

      wrap .remove ();

      values [0] /= 255;
      values [1] /= 255;
      values [2] /= 255;

      if (typeof values [3] !== "number")
         values [3] = 1;

      return values;
   },
   sanitizeName (name = "")
   {
      // NonIdFirstChar
      name = name .replace (/^[\x30-\x39\x00-\x20\x22\x23\x27\x2b\x2c\x2d\x2e\x5b\x5c\x5d\x7b\x7d\x7f]*/, "");

      // NonIdChars
      name = name .replace (/[\x00-\x20\x22\x23\x27\x2c\x2e\x5b\x5c\x5d\x7b\x7d\x7f]+/g, "-");

      // Spaces
      name = name .trim () .replace (/[\s_-]+/g, "-");

      // Trim
      name = name .replace (/^-+|-+$/g, "");

      return name;
   },
});

const X3DParser_default_ = X3DParser;
;

x_ite_Namespace .add ("X3DParser", "x_ite/Parser/X3DParser", X3DParser_default_);
/* harmony default export */ const Parser_X3DParser = (X3DParser_default_);
;// CONCATENATED MODULE: ./src/x_ite/Parser/Expressions.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

function parse (parser)
{
   this .lastIndex = parser .lastIndex;

   parser .result = this .exec (parser .input);

   if (parser .result)
   {
      parser .lastIndex = this .lastIndex;
      return true;
   }

   return false;
}

function lookahead (parser)
{
   const
      lastIndex = parser .lastIndex,
      result    = this .parse (parser);

   parser .lastIndex = lastIndex;

   return result;
}

function Expressions (Grammar)
{
   for (const value of Object .values (Grammar))
   {
      value .parse     = parse;
      value .lookahead = lookahead;
   }

   return Grammar;
}

const Expressions_default_ = Expressions;
;

x_ite_Namespace .add ("Expressions", "x_ite/Parser/Expressions", Expressions_default_);
/* harmony default export */ const Parser_Expressions = (Expressions_default_);
;// CONCATENATED MODULE: ./src/x_ite/Prototype/X3DProtoDeclaration.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








const
   _body = Symbol ();

function X3DProtoDeclaration (executionContext)
{
   Prototype_X3DProtoDeclarationNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DProtoDeclaration)

   this [_body] = new Execution_X3DExecutionContext (executionContext, this);
   this [_body] .setLive (false);
   this .setLive (false);
}

Object .assign (Object .setPrototypeOf (X3DProtoDeclaration .prototype, Prototype_X3DProtoDeclarationNode .prototype),
{
   initialize ()
   {
      Prototype_X3DProtoDeclarationNode .prototype .initialize .call (this);

      this [_body] .setup ();
   },
   getProtoDeclaration ()
   {
      return this;
   },
   getBody ()
   {
      return this [_body];
   },
   canUserDefinedFields ()
   {
      return true;
   },
   toVRMLStream (generator)
   {
      generator .string += generator .Indent ();
      generator .string += "PROTO";
      generator .string += generator .Space ();
      generator .string += this .getName ();
      generator .string += generator .TidySpace ();
      generator .string += "[";

      generator .EnterScope ();

      const userDefinedFields = this .getUserDefinedFields ();

      if (userDefinedFields .length === 0)
      {
         generator .string += generator .TidySpace ();
      }
      else
      {
         let
            fieldTypeLength  = 0,
            accessTypeLength = 0;

         for (const field of userDefinedFields)
         {
            fieldTypeLength  = Math .max (fieldTypeLength, field .getTypeName () .length);
            accessTypeLength = Math .max (accessTypeLength, generator .AccessType (field .getAccessType ()) .length);
         }

         generator .string += generator .TidyBreak ();

         generator .IncIndent ();

         for (const field of userDefinedFields)
         {
            this .toVRMLStreamUserDefinedField (generator, field, fieldTypeLength, accessTypeLength);

            generator .string += generator .Break ();
         }

         generator .DecIndent ();

         generator .string += generator .Indent ();
      }

      generator .LeaveScope ();

      generator .string += "]";
      generator .string += generator .TidyBreak ();

      generator .string += generator .Indent ();
      generator .string += "{";
      generator .string += generator .TidyBreak ();

      generator .IncIndent ();

      this [_body] .toVRMLStream (generator);

      generator .DecIndent ();

      generator .string += generator .Indent ();
      generator .string += "}";
   },
   toVRMLStreamUserDefinedField (generator, field, fieldTypeLength, accessTypeLength)
   {
      generator .string += generator .Indent ();
      generator .string += generator .AccessType (field .getAccessType ()) .padEnd (accessTypeLength, " ");
      generator .string += generator .Space ();
      generator .string += field .getTypeName () .padEnd (fieldTypeLength, " ");
      generator .string += generator .Space ();
      generator .string += field .getName ();

      if (field .isInitializable ())
      {
         generator .string += generator .Space ();

         field .toVRMLStream (generator);
      }
   },
   toXMLStream (generator)
   {
      generator .string += generator .Indent ();
      generator .string += "<ProtoDeclare";
      generator .string += generator .Space ();
      generator .string += "name='";
      generator .string += generator .XMLEncode (this .getName ());
      generator .string += "'";
      generator .string += ">";
      generator .string += generator .TidyBreak ();

      // <ProtoInterface>

      generator .EnterScope ();

      const userDefinedFields = this .getUserDefinedFields ();

      if (userDefinedFields .length !== 0)
      {
         generator .IncIndent ();

         generator .string += generator .Indent ();
         generator .string += "<ProtoInterface>";
         generator .string += generator .TidyBreak ();

         generator .IncIndent ();

         for (const field of userDefinedFields)
         {
            generator .string += generator .Indent ();
            generator .string += "<field";
            generator .string += generator .Space ();
            generator .string += "accessType='";
            generator .string += generator .AccessType (field .getAccessType ());
            generator .string += "'";
            generator .string += generator .Space ();
            generator .string += "type='";
            generator .string += field .getTypeName ();
            generator .string += "'";
            generator .string += generator .Space ();
            generator .string += "name='";
            generator .string += generator .XMLEncode (field .getName ());
            generator .string += "'";

            if (field .isDefaultValue ())
            {
               generator .string += generator .closingTags ? "></field>" : "/>";
               generator .string += generator .TidyBreak ();
            }
            else
            {
               switch (field .getType ())
               {
                  case Base_X3DConstants .SFNode:
                  case Base_X3DConstants .MFNode:
                  {
                     generator .PushContainerField (field);

                     generator .string += ">";
                     generator .string += generator .TidyBreak ();

                     generator .IncIndent ();

                     field .toXMLStream (generator);

                     generator .string += generator .TidyBreak ();

                     generator .DecIndent ();

                     generator .string += generator .Indent ();
                     generator .string += "</field>";
                     generator .string += generator .TidyBreak ();

                     generator .PopContainerField ();
                     break;
                  }
                  default:
                  {
                     generator .string += generator .Space ();
                     generator .string += "value='";

                     field .toXMLStream (generator);

                     generator .string += "'";
                     generator .string += generator .closingTags ? "></field>" : "/>";
                     generator .string += generator .TidyBreak ();
                     break;
                  }
               }
            }
         }

         generator .DecIndent ();

         generator .string += generator .Indent ();
         generator .string += "</ProtoInterface>";
         generator .string += generator .TidyBreak ();

         generator .DecIndent ();
      }

      generator .LeaveScope ();

      // </ProtoInterface>

      // <ProtoBody>

      generator .IncIndent ();

      generator .string += generator .Indent ();
      generator .string += "<ProtoBody>";
      generator .string += generator .TidyBreak ();

      generator .IncIndent ();

      this [_body] .toXMLStream (generator);

      generator .DecIndent ();

      generator .string += generator .Indent ();
      generator .string += "</ProtoBody>";
      generator .string += generator .TidyBreak ();

      generator .DecIndent ();

      // </ProtoBody>

      generator .string += generator .Indent ();
      generator .string += "</ProtoDeclare>";
   },
   toJSONStream (generator)
   {
      generator .string += generator .Indent ();
      generator .string += '{';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += "ProtoDeclare";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();
      generator .string += generator .Indent ();
      generator .string += '{';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();
      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "@name";
      generator .string += '"';
      generator .string += ':';
      generator .string += '"';
      generator .string += generator .JSONEncode (this .getName ());
      generator .string += '"';
      generator .string += ',';
      generator .string += generator .TidyBreak ();

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "ProtoInterface";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '{';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();


      // Fields

      generator .EnterScope ();

      const userDefinedFields = this .getUserDefinedFields ();

      if (userDefinedFields .length)
      {
         generator .string += generator .Indent ();
         generator .string += '"';
         generator .string += "field";
         generator .string += '"';
         generator .string += ':';
         generator .string += generator .TidySpace ();
         generator .string += '[';
         generator .string += generator .TidyBreak ();
         generator .string += generator .IncIndent ();

         for (const field of userDefinedFields)
         {
            generator .string += generator .Indent ();
            generator .string += '{';
            generator .string += generator .TidyBreak ();
            generator .string += generator .IncIndent ();

            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "@accessType";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '"';
            generator .string += generator .AccessType (field .getAccessType ());
            generator .string += '"';
            generator .string += ',';
            generator .string += generator .TidyBreak ();

            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "@type";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '"';
            generator .string += field .getTypeName ();
            generator .string += '"';
            generator .string += ',';
            generator .string += generator .TidyBreak ();

            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "@name";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '"';
            generator .string += generator .JSONEncode (field .getName ());
            generator .string += '"';

            if (field .isDefaultValue ())
            {
               generator .string += generator .TidyBreak ();
            }
            else
            {
               generator .string += ',';
               generator .string += generator .TidyBreak ();

               // Output value

               switch (field .getType ())
               {
                  case Base_X3DConstants .SFNode:
                  {
                     generator .string += generator .Indent ();
                     generator .string += '"';
                     generator .string += "-children";
                     generator .string += '"';
                     generator .string += ':';
                     generator .string += generator .TidySpace ();
                     generator .string += '[';
                     generator .string += generator .TidyBreak ();
                     generator .string += generator .IncIndent ();
                     generator .string += generator .Indent ();

                     field .toJSONStream (generator);

                     generator .string += generator .TidyBreak ();
                     generator .string += generator .DecIndent ();
                     generator .string += generator .Indent ();
                     generator .string += ']';
                     generator .string += generator .TidyBreak ();
                     break;
                  }
                  case Base_X3DConstants .MFNode:
                  {
                     generator .string += generator .Indent ();
                     generator .string += '"';
                     generator .string += "-children";
                     generator .string += '"';
                     generator .string += ':';
                     generator .string += generator .TidySpace ();

                     field .toJSONStream (generator);

                     generator .string += generator .TidyBreak ();
                     break;
                  }
                  default:
                  {
                     generator .string += generator .Indent ();
                     generator .string += '"';
                     generator .string += "@value";
                     generator .string += '"';
                     generator .string += ':';
                     generator .string += generator .TidySpace ();

                     field .toJSONStream (generator);

                     generator .string += generator .TidyBreak ();
                     break;
                  }
               }
            }

            generator .string += generator .DecIndent ();
            generator .string += generator .Indent ();
            generator .string += '}';

            if (field !== userDefinedFields .at (-1))
               generator .string += ',';

            generator .string += generator .TidyBreak ();
         }

         generator .string += generator .DecIndent ();
         generator .string += generator .Indent ();
         generator .string += ']';
      }

      generator .string += generator .DecIndent ();
      generator .string += generator .TidyBreak ();
      generator .string += generator .Indent ();
      generator .string += '}';
      generator .string += ',';
      generator .string += generator .TidyBreak ();

      generator .LeaveScope ();


      // ProtoBody

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "ProtoBody";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '{';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "-children";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '[';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();

      this [_body] .toJSONStream (generator);

      generator .JSONRemoveComma ();

      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += ']';
      generator .string += generator .TidyBreak ();

      // End

      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';
      generator .string += generator .TidyBreak ();
      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';
      generator .string += generator .TidyBreak ();
      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';
   },
});

for (const key of Object .keys (X3DProtoDeclaration .prototype))
   Object .defineProperty (X3DProtoDeclaration .prototype, key, { enumerable: false });

Object .defineProperties (X3DProtoDeclaration .prototype,
{
   name:
   {
      get: X3DProtoDeclaration .prototype .getName,
      enumerable: true,
   },
   fields:
   {
      get: X3DProtoDeclaration .prototype .getFieldDefinitions,
      enumerable: true,
   },
   isExternProto:
   {
      value: false,
      enumerable: true,
   },
});

Object .defineProperties (X3DProtoDeclaration,
{
   typeName:
   {
      value: "X3DProtoDeclaration",
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata", new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

Base_X3DConstants .addNode (X3DProtoDeclaration);

const X3DProtoDeclaration_default_ = X3DProtoDeclaration;
;

x_ite_Namespace .add ("X3DProtoDeclaration", "x_ite/Prototype/X3DProtoDeclaration", X3DProtoDeclaration_default_);
/* harmony default export */ const Prototype_X3DProtoDeclaration = (X3DProtoDeclaration_default_);
;// CONCATENATED MODULE: ./src/x_ite/Parser/VRMLParser.js
/* provided dependency */ var VRMLParser_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

















/*
 *  Grammar
 */

// VRML lexical elements
const Grammar = Parser_Expressions ({
   // General
   Whitespaces: /([\x20\n,\t\r]+)/gy,
   Comment:     /#(.*?)(?=[\n\r])/gy,
   Break:       /\r?\n/g,

   // Header
   Header:	    /^#(VRML|X3D) V(.*?) (utf8)(?:[ \t]+(.*?))?[ \t]*[\n\r]/gy,

   // Keywords
   AS:          /AS/gy,
   COMPONENT:   /COMPONENT/gy,
   DEF:         /DEF/gy,
   EXPORT:      /EXPORT/gy,
   EXTERNPROTO: /EXTERNPROTO/gy,
   FALSE:       /FALSE|false/gy,
   IMPORT:      /IMPORT/gy,
   IS:          /IS/gy,
   META:        /META/gy,
   NULL:        /NULL/gy,
   TRUE:        /TRUE|true/gy,
   PROFILE:     /PROFILE/gy,
   PROTO:       /PROTO/gy,
   ROUTE:       /ROUTE/gy,
   TO:          /TO/gy,
   UNIT:        /UNIT/gy,
   USE:         /USE/gy,

   // Terminal symbols
   OpenBrace:    /\{/gy,
   CloseBrace:   /\}/gy,
   OpenBracket:  /\[/gy,
   CloseBracket: /\]/gy,
   Period:       /\./gy,
   Colon:        /\:/gy,

   Id: /([^\x30-\x39\x00-\x20\x22\x23\x27\x2b\x2c\x2d\x2e\x5b\x5c\x5d\x7b\x7d\x7f]{1}[^\x00-\x20\x22\x23\x27\x2c\x2e\x5b\x5c\x5d\x7b\x7d\x7f]*)/gy,
   ComponentNameId: /([^\x30-\x39\x00-\x20\x22\x23\x27\x2b\x2c\x2d\x2e\x5b\x5c\x5d\x7b\x7d\x7f\x3a]{1}[^\x00-\x20\x22\x23\x27\x2c\x2e\x5b\x5c\x5d\x7b\x7d\x7f\x3a]*)/gy,

   initializeOnly: /initializeOnly/gy,
   inputOnly:      /inputOnly/gy,
   outputOnly:     /outputOnly/gy,
   inputOutput:    /inputOutput/gy,

   field:        /field/gy,
   eventIn:      /eventIn/gy,
   eventOut:     /eventOut/gy,
   exposedField: /exposedField/gy,

   FieldType: /([SM]F(?:Bool|ColorRGBA|Color|Double|Float|Image|Int32|Matrix3d|Matrix3f|Matrix4d|Matrix4f|Node|Rotation|String|Time|Vec2d|Vec2f|Vec3d|Vec3f|Vec4d|Vec4f))/gy,

   // Values
   int32:  /((?:0[xX][\da-fA-F]+)|(?:[+-]?\d+))/gy,
   double: /([+-]?(?:(?:(?:\d*\.\d+)|(?:\d+(?:\.)?))(?:[eE][+-]?\d+)?))/gy,
   string: /"((?:[^\\"]|\\\\|\\")*)"/gy,

   CONSTANTS: /([+-]?)\b(NAN|INFINITY|INF|PI|PI2|PI1_4|PI2_4|PI3_4|PI4_4|PI5_4|PI6_4|PI7_4|PI8_4|PI1_2|PI2_2|PI3_2|PI4_2|PI1_3|PI2_3|PI3_3|PI4_3|PI5_3|PI6_3|SQRT1_2|SQRT2)\b/igy,
   HTMLColor: /([a-zA-Z]+|0[xX][\da-fA-F]+|rgba?\(.*?\))/gy,
});

/*
 *  Parser
 */

function VRMLParser (scene)
{
   Parser_X3DParser .call (this, scene);
}

Object .assign (Object .setPrototypeOf (VRMLParser .prototype, Parser_X3DParser .prototype),
{
   accessTypes:
   {
      field:          Base_X3DConstants .initializeOnly,
      eventIn:        Base_X3DConstants .inputOnly,
      eventOut:       Base_X3DConstants .outputOnly,
      exposedField:   Base_X3DConstants .inputOutput,
      initializeOnly: Base_X3DConstants .initializeOnly,
      inputOnly:      Base_X3DConstants .inputOnly,
      outputOnly:     Base_X3DConstants .outputOnly,
      inputOutput:    Base_X3DConstants .inputOutput,
   },
   SFImage: new x_ite_Fields .SFImage (),
   SFNode: new x_ite_Fields .SFNode (),
   MFString: new x_ite_Fields .MFString (),
   Color3: new Numbers_Color3 (0, 0, 0),
   Color4: new Numbers_Color4 (0, 0, 0, 0),
   Matrix3: new Numbers_Matrix3 (),
   Matrix4: new Numbers_Matrix4 (),
   Rotation4: new Numbers_Rotation4 (),
   Vector2: new Numbers_Vector2 (0, 0),
   Vector3: new Numbers_Vector3 (0, 0, 0),
   Vector4: new Numbers_Vector4 (0, 0, 0, 0),
   CONSTANTS: {
      NAN: Number .NaN,
      INFINITY: Number .POSITIVE_INFINITY,
      INF: Number .POSITIVE_INFINITY,
      PI:    Math .PI,
      PI2:   Math .PI * 2,
      PI1_4: Math .PI * 1/4,
      PI2_4: Math .PI * 2/4,
      PI3_4: Math .PI * 3/4,
      PI4_4: Math .PI * 4/4,
      PI5_4: Math .PI * 5/4,
      PI6_4: Math .PI * 6/4,
      PI7_4: Math .PI * 7/4,
      PI8_4: Math .PI * 8/4,
      PI1_2: Math .PI * 1/2,
      PI2_2: Math .PI * 2/2,
      PI3_2: Math .PI * 3/2,
      PI4_2: Math .PI * 4/2,
      PI1_3: Math .PI * 1/3,
      PI2_3: Math .PI * 2/3,
      PI3_3: Math .PI * 3/3,
      PI4_3: Math .PI * 4/3,
      PI5_3: Math .PI * 5/3,
      PI6_3: Math .PI * 6/3,
      SQRT1_2: Math .SQRT1_2,
      SQRT2:   Math .SQRT2,
   },
   getEncoding ()
   {
      return "STRING";
   },
   setInput (vrmlSyntax)
   {
      this .input      = vrmlSyntax;
      this .lineNumber = 1;
      this .lastIndex  = 0;
   },
   isValid ()
   {
      if (!(typeof this .input === "string"))
         return false;

      return !! this .input .match (/^(?:#X3D|#VRML|(?:[\x20\n,\t\r]*|#.*?[\r\n])*(PROFILE|COMPONENT|META|UNIT|EXTERNPROTO|PROTO|DEF|NULL|IMPORT|EXPORT|ROUTE|\w+(?:[\x20\n,\t\r]*|#.*?[\r\n])\{|$))/);
   },
   parseIntoScene (resolve, reject)
   {
      try
      {
         this .resolve = resolve;
         this .reject  = reject;

         this .getScene () .setEncoding ("VRML");
         this .getScene () .setProfile (this .getBrowser () .getProfile ("Full"));
         this .x3dScene ();
      }
      catch (error)
      {
         //console .error (error);
         throw new Error (this .getError (error));
      }
   },
   throwOrWarn (string)
   {
      if (this .getBrowser () .isStrict ())
         throw new Error (string);

      console .warn (string);
   },
   getError (error)
   {
      //console .error (error);

      const
         string     = error .message,
         unexpected = this .lastIndex === this .input .length ? "Unexpected end of file. " : "";

      let
         rest     = this .getLine (),
         line     = this .getLastLine (),
         lastLine = this .getLastLine (),
         linePos  = line .length - rest .length + 1;

      if (line .length > 80)
      {
         line     = line .substr (linePos - 40, 80);
         lastLine = "";
         linePos  = 40;
      }

      // Format error

      const message = "\n"
         + `********************************************************************************\n`
         + `Parser error at line ${this .lineNumber}:${linePos}\n`
         + `in '${this .getExecutionContext () .getWorldURL ()}'\n`
         + `\n`
         + `${lastLine}\n`
         + `${line}\n`
         + `${Array (linePos) .join (" ")}^\n`
         + `${unexpected}${string}\n`
         + `********************************************************************************\n`
      ;

      return message;
   },
   getLine ()
   {
      let
         input     = this .input,
         lastIndex = this .lastIndex,
         line      = "";

      while (lastIndex < input .length && input [lastIndex] !== "\n" && input [lastIndex] !== "\r")
         line += input [lastIndex ++];

      this .lastIndex = lastIndex;

      return line;
   },
   getLastLine ()
   {
      let
         input     = this .input,
         lastIndex = Math .min (this .lastIndex, this .input .length - 1),
         line      = "";

      if (lastIndex < input .length && (input [lastIndex] !== "\n" || input [lastIndex] !== "\r"))
         -- lastIndex;

      while (lastIndex >= 0 && input [lastIndex] !== "\n" && input [lastIndex] !== "\r")
         line = input [lastIndex --] + line;

      this .lastIndex = lastIndex;

      return line;
   },
   comments ()
   {
      while (this .comment ())
         ;
   },
   comment ()
   {
      if (this .whitespaces ())
         return true;

      return Grammar .Comment .parse (this);
   },
   whitespaces ()
   {
      if (Grammar .Whitespaces .parse (this))
      {
         this .lines (this .result [1]);

         return true;
      }

      return false;
   },
   lines (string)
   {
      const match = string .match (Grammar .Break);

      if (match)
         this .lineNumber += match .length;
   },
   x3dScene: (() =>
   {
      const VRML =
      [
         "EnvironmentalSensor",
         "PointingDeviceSensor",
         "Scripting",
         "Sound",
         "Text",
      ];

      return function ()
      {
         const
            browser = this .getBrowser (),
            scene   = this .getScene ();

         this .headerStatement ();
         this .profileStatement ();
         this .componentStatements ();
         this .unitStatements ();
         this .metaStatements ();

         if (scene .getSpecificationVersion () === "2.0")
         {
            scene .setProfile (browser .getProfile ("Interchange"));

            for (const componentName of VRML)
               scene .updateComponent (browser .getComponent (componentName));
         }

         if (this .resolve)
         {
            this .loadComponents () .then (() =>
            {
               try
               {
                  this .statements (this .getExecutionContext () .rootNodes);

                  if (this .lastIndex < this .input .length)
                     throw new Error ("Unknown statement.");

                  this .resolve (scene);
               }
               catch (error)
               {
                  throw new Error (this .getError (error));
               }
            })
            .catch (this .reject);
         }
         else
         {
            this .statements (this .getExecutionContext () .rootNodes);

            if (this .lastIndex < this .input .length)
               throw new Error ("Unknown statement.");
         }
      };
   })(),
   headerStatement ()
   {
      Grammar .Header .lastIndex = 0;

      const result = Grammar .Header .exec (this .input);

      if (result)
      {
         this .getScene () .setSpecificationVersion (result [2]);
         this .getScene () .setEncoding             ("VRML");
         return true;
      }

      return false;
   },
   profileStatement ()
   {
      this .comments ();

      if (Grammar .PROFILE .parse (this))
      {
         if (this .profileNameId ())
         {
            const profile = this .getBrowser () .getProfile (this .result [1]);

            this .getScene () .setProfile (profile);
            return;
         }

         throw new Error ("Expected a profile name.");
      }
   },
   componentStatements ()
   {
      let component;

      while (component = this .componentStatement ())
         this .getScene () .updateComponent (component);
   },
   componentStatement ()
   {
      this .comments ();

      if (Grammar .COMPONENT .parse (this))
      {
         if (this .componentNameId ())
         {
            const componentNameIdCharacters = this .result [1];

            this .comments ();

            if (Grammar .Colon .parse (this))
            {
               if (this .componentSupportLevel ())
               {
                  const componentSupportLevel = this .value;

                  return this .getBrowser () .getComponent (componentNameIdCharacters, componentSupportLevel);
               }

               throw new Error ("Expected a component support level.");
            }

            throw new Error ("Expected a ':' after component name.");
         }

         throw new Error ("Expected a component name.");
      }

      return null;
   },
   componentSupportLevel ()
   {
      return this .int32 ();
   },
   unitStatements ()
   {
      while (this .unitStatement ())
         ;
   },
   unitStatement ()
   {
      this .comments ();

      if (Grammar .UNIT .parse (this))
      {
         if (this .categoryNameId ())
         {
            const categoryNameId = this .result [1];

            if (this .unitNameId ())
            {
               const unitNameId = this .result [1];

               if (this .unitConversionFactor ())
               {
                  const unitConversionFactor = this .value;

                  try
                  {
                     this .getScene () .updateUnit (categoryNameId, unitNameId, unitConversionFactor);
                     return true;
                  }
                  catch (error)
                  {
                     console .warn (error .message);
                     return true;
                  }
               }

               throw new Error ("Expected unit conversion factor.");
            }

            throw new Error ("Expected unit name identifier.");
         }

         throw new Error ("Expected category name identifier after UNIT statement.");
      }

      return false;
   },
   unitConversionFactor ()
   {
      return this .double ();
   },
   metaStatements ()
   {
      while (this .metaStatement ())
         ;
   },
   metaStatement ()
   {
      this .comments ();

      if (Grammar .META .parse (this))
      {
         if (this .metaKey ())
         {
            const metaKey = this .value;

            if (this .metaValue ())
            {
               const metaValue = this .value;

               this .getScene () .addMetaData (metaKey, metaValue);
               return true;
            }

            throw new Error ("Expected metadata value.");
         }

         throw new Error ("Expected metadata key.");
      }

      return false;
   },
   metaKey ()
   {
      return this .string ();
   },
   metaValue ()
   {
      return this .string ();
   },
   exportStatement ()
   {
      this .comments ();

      if (Grammar .EXPORT .parse (this))
      {
         if (this .nodeNameId ())
         {
            const localNodeNameId = this .result [1];

            this .comments ();

            const node = this .getScene () .getLocalNode (localNodeNameId);

            if (Grammar .AS .parse (this))
            {
               if (this .exportedNodeNameId ())
                  var exportedNodeNameId = this .result [1];
               else
                  throw new Error ("No name given after AS.");
            }
            else
            {
               var exportedNodeNameId = localNodeNameId;
            }

            if (this .getScene () === this .getExecutionContext ())
            {
               this .getScene () .updateExportedNode (exportedNodeNameId, node);
               return true;
            }

            throw new Error ("Export statement not allowed here.");
         }

         throw new Error ("No name given after EXPORT.");
      }

      return false;
   },
   importStatement ()
   {
      this .comments ();

      if (Grammar .IMPORT .parse (this))
      {
         if (this .nodeNameId ())
         {
            const
               inlineNodeNameId = this .result [1],
               namedNode        = this .getExecutionContext () .getNamedNode (inlineNodeNameId);

            this .comments ();

            if (Grammar .Period .parse (this))
            {
               if (this .exportedNodeNameId ())
               {
                  const exportedNodeNameId = this .result [1];

                  this .comments ();

                  if (Grammar .AS .parse (this))
                  {
                     if (this .nodeNameId ())
                        var nodeNameId = this .result [1];

                     else
                        throw new Error ("No name given after AS.");
                  }
                  else
                  {
                     var nodeNameId = exportedNodeNameId;
                  }

                  this .getExecutionContext () .updateImportedNode (namedNode, exportedNodeNameId, nodeNameId);
                  return true;
               }

               throw new Error ("Expected exported node name.");
            }

            throw new Error ("Expected a '.' after exported node name.");
         }

         throw new Error ("No name given after IMPORT statement.");
      }
      return false;
   },
   statements (field)
   {
      while (this .statement (field))
         ;
   },
   statement (field)
   {
      if (this .protoStatement ())
         return true;

      if (this .routeStatement ())
         return true;

      if (this .importStatement ())
         return true;

      if (this .exportStatement ())
         return true;

      const node = this .nodeStatement ();

      if (node !== false)
      {
         field .push (node);
         return true;
      }

      return false;
   },
   nodeStatement ()
   {
      this .comments ();

      if (Grammar .DEF .parse (this))
      {
         if (this .nodeNameId ())
            return this .node (this .result [1]);

         throw new Error ("No name given after DEF.");
      }

      if (Grammar .USE .parse (this))
      {
         if (this .nodeNameId ())
            return this .getExecutionContext () .getNamedNode (this .result [1]) .getValue ();

         throw new Error ("No name given after USE.");
      }

      if (Grammar .NULL .parse (this))
         return null;

      return this .node ("");
   },
   protoStatement ()
   {
      if (this .proto ())
         return true;

      if (this .externproto ())
         return true;

      return false;
   },
   protoStatements ()
   {
      while (this .protoStatement ())
         ;
   },
   proto ()
   {
      this .comments ();

      if (Grammar .PROTO .parse (this))
      {
         if (this .nodeTypeId ())
         {
            const nodeTypeId = this .result [1];

            this .comments ();

            if (Grammar .OpenBracket .parse (this))
            {
               const interfaceDeclarations = this .interfaceDeclarations ();

               this .comments ();

               if (Grammar .CloseBracket .parse (this))
               {
                  this .comments ();

                  if (Grammar .OpenBrace .parse (this))
                  {
                     const proto = new Prototype_X3DProtoDeclaration (this .getExecutionContext ());

                     for (const field of interfaceDeclarations)
                        proto .addUserDefinedField (field .getAccessType (), field .getName (), field);

                     this .pushPrototype (proto);
                     this .pushExecutionContext (proto .getBody ());

                     this .protoBody (proto .getBody () .rootNodes);

                     this .popExecutionContext ();
                     this .popPrototype ();

                     this .comments ();

                     if (Grammar .CloseBrace .parse (this))
                     {
                        proto .setup ();

                        try
                        {
                           const existingProto = this .getExecutionContext () .getProtoDeclaration (nodeTypeId);

                           this .getExecutionContext () .updateProtoDeclaration (this .getExecutionContext () .getUniqueProtoName (nodeTypeId), existingProto);
                        }
                        catch
                        { }

                        this .getExecutionContext () .updateProtoDeclaration (nodeTypeId, proto);

                        return true;
                     }

                     throw new Error ("Expected a '}' at the end of PROTO body.");
                  }

                  throw new Error ("Expected a '{' at the beginning of PROTO body.");
               }

               throw new Error ("Expected a ']' at the end of PROTO interface declaration.");
            }

            throw new Error ("Expected a '[' at the beginning of PROTO interface declaration.");
         }

         throw new Error ("Invalid PROTO definition name.");
      }

      return false;
   },
   protoBody (rootNodes)
   {
      this .protoStatements ();

      const rootNodeStatement = this .rootNodeStatement ();

      if (rootNodeStatement !== false)
         rootNodes .push (rootNodeStatement);

      this .statements (rootNodes);
   },
   rootNodeStatement ()
   {
      this .comments ();

      if (Grammar .DEF .parse (this))
      {
         if (this .nodeNameId ())
         {
            const
               nodeNameId = this .result [0],
               baseNode   = this .node (nodeNameId);

            if (baseNode !== false)
               return baseNode;

            throw new Error ("Expected node type name after DEF.");
         }

         throw new Error ("No name given after DEF.");
      }

      const baseNode = this .node ("");

      if (baseNode !== false)
         return baseNode;

      return false;
   },
   interfaceDeclarations ()
   {
      const interfaceDeclarations = [ ];

      let field;

      while (field = this .interfaceDeclaration ())
         interfaceDeclarations .push (field);

      return interfaceDeclarations;
   },
   restrictedInterfaceDeclaration ()
   {
      this .comments ();

      if (Grammar .inputOnly .parse (this) || Grammar .eventIn .parse (this))
      {
         if (this .fieldType ())
         {
            const fieldType = this .result [1];

            if (this .inputOnlyId ())
            {
               const
                  fieldId = this .result [1],
                  field   = new (x_ite_Fields [fieldType]) ();

               field .setAccessType (Base_X3DConstants .inputOnly);
               field .setName (fieldId);
               return field;
            }

            throw new Error ("Expected a name for field.");
         }

         this .Id ()

         throw new Error (`Unknown event or field type: '${this .result [1]}'.`);
      }

      if (Grammar .outputOnly .parse (this) || Grammar .eventOut .parse (this))
      {
         if (this .fieldType ())
         {
            const fieldType = this .result [1];

            if (this .outputOnlyId ())
            {
               const
                  fieldId = this .result [1],
                  field   = new (x_ite_Fields [fieldType]) ();

               field .setAccessType (Base_X3DConstants .outputOnly);
               field .setName (fieldId);
               return field;
            }

            throw new Error ("Expected a name for field.");
         }

         this .Id ()

         throw new Error (`Unknown event or field type: '${this .result [1]}'.`);
      }

      if (Grammar .initializeOnly .parse (this) || Grammar .field .parse (this))
      {
         if (this .fieldType ())
         {
            const fieldType = this .result [1];

            if (this .initializeOnlyId ())
            {
               const
                  fieldId = this .result [1],
                  field   = new (x_ite_Fields [fieldType]) ();

               if (this .fieldValue (field))
               {
                  field .setAccessType (Base_X3DConstants .initializeOnly);
                  field .setName (fieldId);
                  return field;
               }

               throw new Error (`Couldn't read value for field '${fieldId}'.`);
            }

            throw new Error ("Expected a name for field.");
         }

         this .Id ()

         throw new Error (`Unknown event or field type: '${this .result [1]}'.`);
      }

      return null;
   },
   interfaceDeclaration ()
   {
      const field = this .restrictedInterfaceDeclaration ();

      if (field)
         return field;

      this .comments ();

      if (Grammar .inputOutput .parse (this) || Grammar .exposedField .parse (this))
      {
         if (this .fieldType ())
         {
            const fieldType = this .result [1];

            if (this .inputOutputId ())
            {
               const
                  fieldId = this .result [1],
                  field   = new (x_ite_Fields [fieldType]) ();

               if (this .fieldValue (field))
               {
                  field .setAccessType (Base_X3DConstants .inputOutput);
                  field .setName (fieldId);
                  return field;
               }

               throw new Error (`Couldn't read value for field '${fieldId}'.`);
            }

            throw new Error ("Expected a name for field.");
         }

         this .Id ();

         throw new Error (`Unknown event or field type: '${this .result [1]}'.`);
      }

      return null;
   },
   externproto ()
   {
      this .comments ();

      if (Grammar .EXTERNPROTO .parse (this))
      {
         if (this .nodeTypeId ())
         {
            const nodeTypeId = this .result [1];

            this .comments ();

            if (Grammar .OpenBracket .parse (this))
            {
               const externInterfaceDeclarations = this .externInterfaceDeclarations ();

               this .comments ();

               if (Grammar .CloseBracket .parse (this))
               {
                  if (this .URLList (this .MFString))
                  {
                     const externproto = new Prototype_X3DExternProtoDeclaration (this .getExecutionContext (), this .MFString);

                     for (const field of externInterfaceDeclarations)
                        externproto .addUserDefinedField (field .getAccessType (), field .getName (), field);

                     externproto .setup ();

                     try
                     {
                        const existingExternProto = this .getExecutionContext () .getExternProtoDeclaration (nodeTypeId);

                        this .getExecutionContext () .updateExternProtoDeclaration (this .getExecutionContext () .getUniqueExternProtoName (nodeTypeId), existingExternProto);
                     }
                     catch
                     { }

                     this .getExecutionContext () .updateExternProtoDeclaration (nodeTypeId, externproto);
                     return true;
                  }

                  throw new Error (`Expected a URL list after EXTERNPROTO interface declaration '${nodeTypeId}'.`);
               }

               throw new Error ("Expected a ']' at the end of EXTERNPROTO interface declaration.");
            }

            throw new Error ("Expected a '[' at the beginning of EXTERNPROTO interface declaration.");
         }

         throw new Error ("Invalid EXTERNPROTO definition name.");
      }

      return false;
   },
   externInterfaceDeclarations ()
   {
      const externInterfaceDeclarations = [ ];

      let field;

      while (field = this .externInterfaceDeclaration ())
         externInterfaceDeclarations .push (field);

      return externInterfaceDeclarations;
   },
   externInterfaceDeclaration ()
   {
      this .comments ();

      if (Grammar .inputOnly .parse (this) || Grammar .eventIn .parse (this))
      {
         if (this .fieldType ())
         {
            const fieldType = this .result [1];

            if (this .inputOnlyId ())
            {
               const
                  fieldId = this .result [1],
                  field   = new (x_ite_Fields [fieldType]) ();

               field .setAccessType (Base_X3DConstants .inputOnly);
               field .setName (fieldId);
               return field;
            }

            throw new Error ("Expected a name for field.");
         }

         this .Id ()

         throw new Error (`Unknown event or field type: '${this .result [1]}'.`);
      }

      if (Grammar .outputOnly .parse (this) || Grammar .eventOut .parse (this))
      {
         if (this .fieldType ())
         {
            const fieldType = this .result [1];

            if (this .outputOnlyId ())
            {
               const
                  fieldId = this .result [1],
                  field   = new (x_ite_Fields [fieldType]) ();

               field .setAccessType (Base_X3DConstants .outputOnly);
               field .setName (fieldId);
               return field;
            }

            throw new Error ("Expected a name for field.");
         }

         this .Id ()

         throw new Error (`Unknown event or field type: '${this .result [1]}'.`);
      }

      if (Grammar .initializeOnly .parse (this) || Grammar .field .parse (this))
      {
         if (this .fieldType ())
         {
            const fieldType = this .result [1];

            if (this .initializeOnlyId ())
            {
               const
                  fieldId = this .result [1],
                  field   = new (x_ite_Fields [fieldType]) ();

               field .setAccessType (Base_X3DConstants .initializeOnly);
               field .setName (fieldId);
               return field;
            }

            throw new Error ("Expected a name for field.");
         }

         this .Id ()

         throw new Error (`Unknown event or field type: '${this .result [1]}'.`);
      }

      if (Grammar .inputOutput .parse (this) || Grammar .exposedField .parse (this))
      {
         if (this .fieldType ())
         {
            const fieldType = this .result [1];

            if (this .inputOutputId ())
            {
               const
                  fieldId = this .result [1],
                  field   = new (x_ite_Fields [fieldType]) ();

               field .setAccessType (Base_X3DConstants .inputOutput);
               field .setName (fieldId);
               return field;
            }

            throw new Error ("Expected a name for field.");
         }

         this .Id ()

         throw new Error (`Unknown event or field type: '${this .result [1]}'.`);
      }

      return null;
   },
   URLList (field)
   {
      return this .mfstringValue (field);
   },
   routeStatement ()
   {
      this .comments ();

      if (Grammar .ROUTE .parse (this))
      {
         if (this .nodeNameId ())
         {
            const
               fromNodeId = this .result [1],
               fromNode   = this .getExecutionContext () .getLocalNode (fromNodeId);

            this .comments ();

            if (Grammar .Period .parse (this))
            {
               if (this .outputOnlyId ())
               {
                  const eventOutId = this .result [1];

                  this .comments ();

                  if (Grammar .TO .parse (this))
                  {
                     if (this .nodeNameId ())
                     {
                        const
                           toNodeId = this .result [1],
                           toNode   = this .getExecutionContext () .getLocalNode (toNodeId);

                        this .comments ();

                        if (Grammar .Period .parse (this))
                        {
                           if (this .inputOnlyId ())
                           {
                              try
                              {
                                 const eventInId = this .result [1];

                                 this .getExecutionContext () .addRoute (fromNode, eventOutId, toNode, eventInId);
                                 return true;
                              }
                              catch (error)
                              {
                                 this .throwOrWarn (error .message);

                                 return true;
                              }
                           }

                           throw new Error ("Bad ROUTE specification: Expected a field name.");
                        }

                        throw new Error ("Bad ROUTE specification: Expected a '.' after node name.");
                     }

                     throw new Error ("Bad ROUTE specification: Expected a node name.");
                  }

                  throw new Error ("Bad ROUTE specification: Expected a 'TO'.");
               }

               throw new Error ("Bad ROUTE specification: Expected a field name.");
            }

            throw new Error ("Bad ROUTE specification: Expected a '.' after node name.");
         }

         throw new Error ("Bad ROUTE specification: Expected a node name.");
      }

      return false;
   },
   node (nodeNameId)
   {
      if (this .nodeTypeId ())
      {
         const nodeTypeId = this .result [1];

         const baseNode = this .getExecutionContext () .createNode (nodeTypeId, false)
            ?? this .getExecutionContext () .createProto (nodeTypeId, false);

         if (!baseNode)
            throw new Error (`Unknown node type or proto '${nodeTypeId}', you probably have insufficient component/profile statements, and/or an inappropriate specification version.`);

         if (nodeNameId .length)
         {
            try
            {
               const namedNode = this .getExecutionContext () .getNamedNode (nodeNameId);

               this .getExecutionContext () .updateNamedNode (this .getExecutionContext () .getUniqueName (nodeNameId), namedNode);
            }
            catch
            { }

            this .getExecutionContext () .updateNamedNode (nodeNameId, baseNode);
         }

         this .comments ();

         if (Grammar .OpenBrace .parse (this))
         {
            if (baseNode .canUserDefinedFields ())
               this .scriptBody (baseNode);

            else
               this .nodeBody (baseNode);

            this .comments ();

            if (Grammar .CloseBrace .parse (this))
            {
               if (!this .isInsideProtoDefinition ())
                  baseNode .setup ();

               return baseNode;
            }

            throw new Error ("Expected '}' at the end of node body.");
         }

         throw new Error ("Expected '{' at the beginning of node body.");
      }

      return false;
   },
   scriptBody (baseNode)
   {
      while (this .scriptBodyElement (baseNode))
         ;
   },
   scriptBodyElement (baseNode)
   {
      const
         lastIndex  = this .lastIndex,
         lineNumber = this .lineNumber;

      if (this .Id ())
      {
         const accessType = this .accessTypes [this .result [1]];

         if (accessType)
         {
            if (this .fieldType ())
            {
               const fieldType = this .result [1];

               if (this .Id ())
               {
                  const fieldId = this .result [1];

                  this .comments ();

                  if (Grammar .IS .parse (this))
                  {
                     if (this .isInsideProtoDefinition ())
                     {
                        if (this .Id ())
                        {
                           const isId = this .result [1];

                           try
                           {
                              var reference = this .getPrototype () .getField (isId);
                           }
                           catch
                           {
                              this .throwOrWarn (`No such event or field '${isId}' inside PROTO ${this .getPrototype () .getName ()} interface declaration.`);

                              return true;
                           }

                           if (Base_X3DConstants [fieldType] === reference .getType ())
                           {
                              if (reference .isReference (accessType))
                              {
                                 let field = VRMLParser_$.try (() => baseNode .getUserDefinedField (fieldId));

                                 if (!field)
                                 {
                                    field = new (x_ite_Fields [fieldType]) ();

                                    baseNode .addUserDefinedField (accessType, fieldId, field);
                                 }

                                 if (accessType === field .getAccessType () && reference .getType () === field .getType ())
                                 {
                                    field .addReference (reference);
                                    return true;
                                 }

                                 throw new Error (`Couldn't add field '${fieldId}', field already exists with different access type or data type.`);
                              }

                              throw new Error (`Field '${fieldId}' and '${reference .getName ()}' in PROTO '${this .getPrototype () .getName ()}' are incompatible as an IS mapping.`);
                           }

                           throw new Error (`Field '${fieldId}' and '${reference .getName ()}' in PROTO '${this .getPrototype () .getName ()}' have different types.`);
                        }

                        throw new Error ("No name give after IS statement.");
                     }

                     throw new Error ("IS statement outside PROTO definition.");
                  }
               }
            }
         }
      }

      this .lastIndex  = lastIndex;
      this .lineNumber = lineNumber;

      const field = this .interfaceDeclaration ();

      if (field)
      {
         const existingField = VRMLParser_$.try (() => baseNode .getUserDefinedField (field .getName ()));

         if (existingField)
         {
            if (existingField .getAccessType () === field .getAccessType () && existingField .getType () === field .getType ())
            {
               existingField .assign (field);
               return true;
            }

            throw new Error (`Couldn't set value for field '${field .getName ()}', field already exists with different access type or data type.`);
         }

         baseNode .addUserDefinedField (field .getAccessType (), field .getName (), field);
         return true;
      }

      return this .nodeBodyElement (baseNode);
   },
   nodeBody (baseNode)
   {
      while (this .nodeBodyElement (baseNode))
         ;
   },
   nodeBodyElement (baseNode)
   {
      if (this .protoStatement ())
         return true;

      if (this .routeStatement ())
         return true;

      if (this .Id ())
      {
         const fieldId = this .result [1];

         try
         {
            var field = baseNode .getPredefinedField (fieldId);
         }
         catch
         {
            throw new Error (`Unknown field '${fieldId}' in class '${baseNode .getTypeName ()}'.`);
         }

         this .comments ();

         if (Grammar .IS .parse (this))
         {
            if (this .isInsideProtoDefinition ())
            {
               if (this .Id ())
               {
                  const isId = this .result [1];

                  try
                  {
                     var reference = this .getPrototype () .getField (isId);
                  }
                  catch
                  {
                     this .throwOrWarn (`No such event or field '${isId}' inside PROTO ${this .getPrototype () .getName ()}`);

                     return true;
                  }

                  if (field .getType () === reference .getType ())
                  {
                     if (reference .isReference (field .getAccessType ()))
                     {
                        field .addReference (reference);
                        return true;
                     }

                     throw new Error (`Field '${field .getName ()}' and '${reference .getName ()}' in PROTO ${this .getPrototype () .getName ()} are incompatible as an IS mapping.`);
                  }

                  throw new Error (`Field '${field .getName ()}' and '${reference .getName ()}' in PROTO ${this .getPrototype () .getName ()} have different types.`);
               }

               throw new Error("No name give after IS statement.");
            }

            throw new Error ("IS statement outside PROTO definition.");
         }

         if (field .isInitializable ())
         {
            if (this .fieldValue (field))
               return true;

            throw new Error (`Couldn't read value for field '${fieldId}'.`);
         }

         throw new Error (`Couldn't assign value to ${this .accessTypeToString (field .getAccessType ())} field '${fieldId}'.`);
      }

      return false;
   },
   profileNameId () { return this .Id (); },
   componentNameId ()
   {
      this .comments ();

      return Grammar .ComponentNameId .parse (this);
   },
   categoryNameId () { return this .Id (); },
   unitNameId () { return this .Id (); },
   exportedNodeNameId () { return this .Id (); },
   nodeNameId () { return this .Id (); },
   nodeTypeId () { return this .Id (); },
   initializeOnlyId () { return this .Id (); },
   inputOnlyId () { return this .Id (); },
   outputOnlyId () { return this .Id (); },
   inputOutputId () { return this .Id (); },
   Id ()
   {
      this .comments ();

      return Grammar .Id .parse (this);
   },
   fieldType ()
   {
      this .comments ();

      return Grammar .FieldType .parse (this);
   },
   fieldValue (field)
   {
      return this [field .getType ()] (field, field .getUnit ());
   },
   bool ()
   {
      this .comments ();

      if (Grammar .TRUE .parse (this))
      {
         this .value = true;
         return true;
      }

      if (Grammar .FALSE .parse (this))
      {
         this .value = false;
         return true;
      }

      return false;
   },
   double ()
   {
      this .comments ();

      if (Grammar .double .parse (this))
      {
         this .value = parseFloat (this .result [1]);
         return true;
      }

      // Constants

      if (Grammar .CONSTANTS .parse (this))
      {
         this .value = this .CONSTANTS [this .result [2] .toUpperCase ()];

         if (this .result [1] === "-")
            this .value = - this .value;

         return true;
      }

      return false;
   },
   int32 ()
   {
      this .comments ();

      if (Grammar .int32 .parse (this))
      {
         this .value = parseInt (this .result [1]);
         return true;
      }

      return false;
   },
   string ()
   {
      this .comments ();

      if (Grammar .string .parse (this))
      {
         this .value = x_ite_Fields .SFString .unescape (this .result [1]);

         this .lines (this .value);

         return true;
      }

      return false;
   },
   sfboolValue (field)
   {
      if (this .bool ())
      {
         field .setValue (this .value);
         return true;
      }

      return false;
   },
   mfboolValue (field)
   {
      field .length = 0;

      if (this .bool ())
      {
         field .push (this .value);
         return true;
      }

      if (Grammar .OpenBracket .parse (this))
      {
         this .sfboolValues (field);

         if (Grammar .CloseBracket .parse (this))
            return true;

         throw new Error ("Expected ']'.");
      }

      return false;
   },
   sfboolValues (field)
   {
      field .length = 0;
      field         = field .getTarget ();

      while (this .bool ())
         field .push (this .value);
   },
   sfcolorValue (field)
   {
      const lastIndex = this .lastIndex;

      if (this .double ())
      {
         const r = this .value;

         if (this .double ())
         {
            const g = this .value;

            if (this .double ())
            {
               const b = this .value;

               field .r = r;
               field .g = g;
               field .b = b;

               return true;
            }
         }
      }

      this .lastIndex = lastIndex;

      this .comments ();

      if (Grammar .HTMLColor .parse (this))
      {
         const color = this .convertColor (this .result [1] .replace (/0x/i, "#"));

         field .r = color [0];
         field .g = color [1];
         field .b = color [2];

         return true;
      }

      return false;
   },
   mfcolorValue (field)
   {
      field .length = 0;

      if (this .sfcolorValue (this .Color3))
      {
         field .push (this .Color3);
         return true;
      }

      if (Grammar .OpenBracket .parse (this))
      {
         this .sfcolorValues (field);

         if (Grammar .CloseBracket .parse (this))
            return true;

         throw new Error ("Expected ']'.");
      }

      return false;
   },
   sfcolorValues (field)
   {
      field .length = 0;
      field         = field .getTarget ();

      const value = this .Color3;

      while (this .sfcolorValue (value))
         field .push (value);
   },
   sfcolorrgbaValue (field)
   {
      const lastIndex = this .lastIndex;

      if (this .double ())
      {
         const r = this .value;

         if (this .double ())
         {
            const g = this .value;

            if (this .double ())
            {
               const b = this .value;

               if (this .double ())
               {
                  const a = this .value;

                  field .r = r;
                  field .g = g;
                  field .b = b;
                  field .a = a;

                  return true;
               }
            }
         }
      }

      this .lastIndex = lastIndex;

      this .comments ();

      if (Grammar .HTMLColor .parse (this))
      {
         const color = this .convertColor (this .result [1] .replace (/0x/i, "#"));

         field .r = color [0];
         field .g = color [1];
         field .b = color [2];
         field .a = color [3];

         return true;
      }

      return false;
   },
   mfcolorrgbaValue (field)
   {
      field .length = 0;

      if (this .sfcolorrgbaValue (this .Color4))
      {
         field .push (this .Color4);
         return true;
      }

      if (Grammar .OpenBracket .parse (this))
      {
         this .sfcolorrgbaValues (field);

         if (Grammar .CloseBracket .parse (this))
            return true;

         throw new Error ("Expected ']'.");
      }

      return false;
   },
   sfcolorrgbaValues (field)
   {
      field .length = 0;
      field         = field .getTarget ();

      const value = this .Color4;

      while (this .sfcolorrgbaValue (value))
         field .push (value);
   },
   sfdoubleValue (field)
   {
      if (this .double ())
      {
         field .setValue (this .fromUnit (field .getUnit (), this .value));
         return true;
      }

      return false;
   },
   mfdoubleValue (field)
   {
      field .length = 0;

      if (this .double ())
      {
         field .push (this .fromUnit (field .getUnit (), this .value));
         return true;
      }

      if (Grammar .OpenBracket .parse (this))
      {
         this .sfdoubleValues (field);

         if (Grammar .CloseBracket .parse (this))
            return true;

         throw new Error ("Expected ']'.");
      }

      return false;
   },
   sfdoubleValues (field)
   {
      field .length = 0;
      field         = field .getTarget ();

      const unit = field .getUnit ();

      while (this .double ())
         field .push (this .fromUnit (unit, this .value));
   },
   sfimageValue (field)
   {
      if (this .int32 ())
      {
         const width = this .value;

         if (this .int32 ())
         {
            const height = this .value;

            if (this .int32 ())
            {
               const
                  comp = this .value,
                  size = width * height;

               field .width  = width;
               field .height = height;
               field .comp   = comp;

               const array = field .array;

               for (let i = 0; i < size; ++ i)
               {
                  if (this .int32 ())
                  {
                     array [i] = this .value;
                     continue;
                  }

                  return false;
               }

               return true;
            }
         }
      }

      return false;
   },
   mfimageValue (field)
   {
      field .length = 0;

      if (this .sfimageValue (this .SFImage))
      {
         field .push (this .SFImage);
         return true;
      }

      if (Grammar .OpenBracket .parse (this))
      {
         this .sfimageValues (field);

         if (Grammar .CloseBracket .parse (this))
            return true;

         throw new Error ("Expected ']'.");
      }

      return false;
   },
   sfimageValues (field)
   {
      field .length = 0;
      field         = field .getTarget ();

      const value = this .SFImage;

      while (this .sfimageValue (value))
         field .push (value);
   },
   sfint32Value (field)
   {
      if (this .int32 ())
      {
         field .setValue (this .value);
         return true;
      }

      return false;
   },
   mfint32Value (field)
   {
      field .length = 0;

      if (this .int32 ())
      {
         field .push (this .value);
         return true;
      }

      if (Grammar .OpenBracket .parse (this))
      {
         this .sfint32Values (field);

         if (Grammar .CloseBracket .parse (this))
            return true;

         throw new Error ("Expected ']'.");
      }

      return false;
   },
   sfint32Values (field)
   {
      field .length = 0;
      field         = field .getTarget ();

      while (this .int32 ())
         field .push (this .value);
   },
   sfmatrix3Value (field)
   {
      if (this .double ())
      {
         const m00 = this .value;

         if (this .double ())
         {
            const m01 = this .value;

            if (this .double ())
            {
               const m02 = this .value;

                  if (this .double ())
                  {
                     const m10 = this .value;

                     if (this .double ())
                     {
                        const m11 = this .value;

                        if (this .double ())
                        {
                           const m12 = this .value;

                           if (this .double ())
                           {
                              const m20 = this .value;

                              if (this .double ())
                              {
                                 const m21 = this .value;

                                 if (this .double ())
                                 {
                                    const m22 = this .value;

                                    field [0] = m00;
                                    field [1] = m01;
                                    field [2] = m02;
                                    field [3] = m10;
                                    field [4] = m11;
                                    field [5] = m12;
                                    field [6] = m20;
                                    field [7] = m21;
                                    field [8] = m22;

                                    return true;
                              }
                           }
                        }
                     }
                  }
               }
            }
         }
      }

      return false;
   },
   mfmatrix3Value (field)
   {
      field .length = 0;

      if (this .sfmatrix3Value (this .Matrix3))
      {
         field .push (this .Matrix3);
         return true;
      }

      if (Grammar .OpenBracket .parse (this))
      {
         this .sfmatrix3Values (field);

         if (Grammar .CloseBracket .parse (this))
            return true;

         throw new Error ("Expected ']'.");
      }

      return false;
   },
   sfmatrix3Values (field)
   {
      field .length = 0;
      field         = field .getTarget ();

      const value = this .Matrix3;

      while (this .sfmatrix3Value (value))
         field .push (value);
   },
   sfmatrix4Value (field)
   {
      if (this .double ())
      {
         const m00 = this .value;

         if (this .double ())
         {
            const m01 = this .value;

            if (this .double ())
            {
               const m02 = this .value;

               if (this .double ())
               {
                  const m03 = this .value;

                  if (this .double ())
                  {
                     const m10 = this .value;

                     if (this .double ())
                     {
                        const m11 = this .value;

                        if (this .double ())
                        {
                           const m12 = this .value;

                           if (this .double ())
                           {
                              const m13 = this .value;

                              if (this .double ())
                              {
                                 const m20 = this .value;

                                 if (this .double ())
                                 {
                                    const m21 = this .value;

                                    if (this .double ())
                                    {
                                       const m22 = this .value;

                                       if (this .double ())
                                       {
                                          const m23 = this .value;

                                          if (this .double ())
                                          {
                                             const m30 = this .value;

                                             if (this .double ())
                                             {
                                                const m31 = this .value;

                                                if (this .double ())
                                                {
                                                   const m32 = this .value;

                                                   if (this .double ())
                                                   {
                                                      const m33 = this .value;

                                                      field [ 0] = m00;
                                                      field [ 1] = m01;
                                                      field [ 2] = m02;
                                                      field [ 3] = m03;
                                                      field [ 4] = m10;
                                                      field [ 5] = m11;
                                                      field [ 6] = m12;
                                                      field [ 7] = m13;
                                                      field [ 8] = m20;
                                                      field [ 9] = m21;
                                                      field [10] = m22;
                                                      field [11] = m23;
                                                      field [12] = m30;
                                                      field [13] = m31;
                                                      field [14] = m32;
                                                      field [15] = m33;

                                                      return true;
                                                   }
                                                }
                                             }
                                          }
                                       }
                                    }
                                 }
                              }
                           }
                        }
                     }
                  }
               }
            }
         }
      }

      return false;
   },
   mfmatrix4Value (field)
   {
      field .length = 0;

      if (this .sfmatrix4Value (this .Matrix4))
      {
         field .push (this .Matrix4);
         return true;
      }

      if (Grammar .OpenBracket .parse (this))
      {
         this .sfmatrix4Values (field);

         if (Grammar .CloseBracket .parse (this))
            return true;

         throw new Error ("Expected ']'.");
      }

      return false;
   },
   sfmatrix4Values (field)
   {
      field .length = 0;
      field         = field .getTarget ();

      const value = this .Matrix4;

      while (this .sfmatrix4Value (value))
         field .push (value);
   },
   sfnodeValue (field)
   {
      const baseNode = this .nodeStatement ();

      if (baseNode !== false)
      {
         field .setValue (baseNode);
         return true;
      }

      return false;
   },
   mfnodeValue (field)
   {
      field .length = 0;

      const node = this .nodeStatement ();

      if (node !== false)
      {
         field .push (node);
         return true;
      }

      if (Grammar .OpenBracket .parse (this))
      {
         this .nodeStatements (field);

         if (Grammar .CloseBracket .parse (this))
            return true;

         throw new Error ("Expected ']'.");
      }

      return false;
   },
   nodeStatements (field)
   {
      this .statements (field);

      // let node = this .nodeStatement ();

      // while (node !== false)
      // {
      //    field .push (node);

      //    node = this .nodeStatement ();
      // }
   },
   sfrotationValue (field)
   {
      if (this .double ())
      {
         const x = this .value;

         if (this .double ())
         {
            const y = this .value;

            if (this .double ())
            {
               const z = this .value;

               if (this .double ())
               {
                  const angle = this .value;

                  field .x     = x;
                  field .y     = y;
                  field .z     = z;
                  field .angle = this .fromUnit ("angle", angle);

                  return true;
               }
            }
         }
      }

      return false;
   },
   mfrotationValue (field)
   {
      field .length = 0;

      if (this .sfrotationValue (this .Rotation4))
      {
         field .push (this .Rotation4);
         return true;
      }

      if (Grammar .OpenBracket .parse (this))
      {
         this .sfrotationValues (field);

         if (Grammar .CloseBracket .parse (this))
            return true;

         throw new Error ("Expected ']'.");
      }

      return false;
   },
   sfrotationValues (field)
   {
      field .length = 0;
      field         = field .getTarget ();

      const value = this .Rotation4;

      while (this .sfrotationValue (value))
         field .push (value);
   },
   sfstringValue (field)
   {
      if (this .string ())
      {
         field .setValue (this .value);
         return true;
      }

      return false;
   },
   mfstringValue (field)
   {
      field .length = 0;

      if (this .string ())
      {
         field .push (this .value);
         return true;
      }

      if (Grammar .OpenBracket .parse (this))
      {
         this .sfstringValues (field);

         if (Grammar .CloseBracket .parse (this))
            return true;

         throw new Error ("Expected ']'.");
      }

      return false;
   },
   sfstringValues (field)
   {
      field .length = 0;
      field         = field .getTarget ();

      while (this .string ())
         field .push (this .value);
   },
   sfvec2Value (field, unit)
   {
      if (this .double ())
      {
         const x = this .value;

         if (this .double ())
         {
            const y = this .value;

            field .x = this .fromUnit (unit, x);
            field .y = this .fromUnit (unit, y);

            return true;
         }
      }

      return false;
   },
   mfvec2Value (field)
   {
      field .length = 0;

      if (this .sfvec2Value (this .Vector2, field .getUnit ()))
      {
         field .push (this .Vector2);
         return true;
      }

      if (Grammar .OpenBracket .parse (this))
      {
         this .sfvec2Values (field);

         if (Grammar .CloseBracket .parse (this))
            return true;

         throw new Error ("Expected ']'.");
      }

      return false;
   },
   sfvec2Values (field)
   {
      field .length = 0;
      field         = field .getTarget ();

      const
         value = this .Vector2,
         unit  = field .getUnit ();

      while (this .sfvec2Value (value, unit))
         field .push (value);
   },
   sfvec3Value (field, unit)
   {
      if (this .double ())
      {
         const x = this .value;

         if (this .double ())
         {
            const y = this .value;

            if (this .double ())
            {
               const z = this .value;

               field .x = this .fromUnit (unit, x);
               field .y = this .fromUnit (unit, y);
               field .z = this .fromUnit (unit, z);

               return true;
            }
         }
      }

      return false;
   },
   mfvec3Value (field)
   {
      field .length = 0;

      if (this .sfvec3Value (this .Vector3, field .getUnit ()))
      {
         field .push (this .Vector3);
         return true;
      }

      if (Grammar .OpenBracket .parse (this))
      {
         this .sfvec3Values (field);

         if (Grammar .CloseBracket .parse (this))
            return true;

         throw new Error ("Expected ']'.");
      }

      return false;
   },
   sfvec3Values (field)
   {
      field .length = 0;
      field         = field .getTarget ();

      const
         value = this .Vector3,
         unit  = field .getUnit ();

      while (this .sfvec3Value (value, unit))
         field .push (value);
   },
   sfvec4Value (field, unit)
   {
      if (this .double ())
      {
         const x = this .value;

         if (this .double ())
         {
            const y = this .value;

            if (this .double ())
            {
               const z = this .value;

               if (this .double ())
               {
                  const w = this .value;

                  field .x = this .fromUnit (unit, x);
                  field .y = this .fromUnit (unit, y);
                  field .z = this .fromUnit (unit, z);
                  field .w = this .fromUnit (unit, w);

                  return true;
               }
            }
         }
      }

      return false;
   },
   mfvec4Value (field)
   {
      field .length = 0;

      if (this .sfvec4Value (this .Vector4, field .getUnit ()))
      {
         field .push (this .Vector4);
         return true;
      }

      if (Grammar .OpenBracket .parse (this))
      {
         this .sfvec4Values (field);

         if (Grammar .CloseBracket .parse (this))
            return true;

         throw new Error ("Expected ']'.");
      }

      return false;
   },
   sfvec4Values (field)
   {
      field .length = 0;
      field         = field .getTarget ();

      const
         value = this .Vector4,
         unit  = field .getUnit ();

      while (this .sfvec4Value (value, unit))
         field .push (value);
   },
   accessTypeToString (accessType)
   {
      switch (accessType)
      {
         case Base_X3DConstants .initializeOnly:
            return "initializeOnly";
         case Base_X3DConstants .inputOnly:
            return "inputOnly";
         case Base_X3DConstants .outputOnly:
            return "outputOnly";
         case Base_X3DConstants .inputOutput:
            return "inputOutput";
      }
   },
});

Object .assign (VRMLParser .prototype,
{
   [Base_X3DConstants .SFBool]:      VRMLParser .prototype .sfboolValue,
   [Base_X3DConstants .SFColor]:     VRMLParser .prototype .sfcolorValue,
   [Base_X3DConstants .SFColorRGBA]: VRMLParser .prototype .sfcolorrgbaValue,
   [Base_X3DConstants .SFDouble]:    VRMLParser .prototype .sfdoubleValue,
   [Base_X3DConstants .SFFloat]:     VRMLParser .prototype .sfdoubleValue,
   [Base_X3DConstants .SFImage]:     VRMLParser .prototype .sfimageValue,
   [Base_X3DConstants .SFInt32]:     VRMLParser .prototype .sfint32Value,
   [Base_X3DConstants .SFMatrix3f]:  VRMLParser .prototype .sfmatrix3Value,
   [Base_X3DConstants .SFMatrix3d]:  VRMLParser .prototype .sfmatrix3Value,
   [Base_X3DConstants .SFMatrix4f]:  VRMLParser .prototype .sfmatrix4Value,
   [Base_X3DConstants .SFMatrix4d]:  VRMLParser .prototype .sfmatrix4Value,
   [Base_X3DConstants .SFNode]:      VRMLParser .prototype .sfnodeValue,
   [Base_X3DConstants .SFRotation]:  VRMLParser .prototype .sfrotationValue,
   [Base_X3DConstants .SFString]:    VRMLParser .prototype .sfstringValue,
   [Base_X3DConstants .SFTime]:      VRMLParser .prototype .sfdoubleValue,
   [Base_X3DConstants .SFVec2d]:     VRMLParser .prototype .sfvec2Value,
   [Base_X3DConstants .SFVec2f]:     VRMLParser .prototype .sfvec2Value,
   [Base_X3DConstants .SFVec3d]:     VRMLParser .prototype .sfvec3Value,
   [Base_X3DConstants .SFVec3f]:     VRMLParser .prototype .sfvec3Value,
   [Base_X3DConstants .SFVec4d]:     VRMLParser .prototype .sfvec4Value,
   [Base_X3DConstants .SFVec4f]:     VRMLParser .prototype .sfvec4Value,

   [Base_X3DConstants .MFBool]:      VRMLParser .prototype .mfboolValue,
   [Base_X3DConstants .MFColor]:     VRMLParser .prototype .mfcolorValue,
   [Base_X3DConstants .MFColorRGBA]: VRMLParser .prototype .mfcolorrgbaValue,
   [Base_X3DConstants .MFDouble]:    VRMLParser .prototype .mfdoubleValue,
   [Base_X3DConstants .MFFloat]:     VRMLParser .prototype .mfdoubleValue,
   [Base_X3DConstants .MFImage]:     VRMLParser .prototype .mfimageValue,
   [Base_X3DConstants .MFInt32]:     VRMLParser .prototype .mfint32Value,
   [Base_X3DConstants .MFMatrix3d]:  VRMLParser .prototype .mfmatrix3Value,
   [Base_X3DConstants .MFMatrix3f]:  VRMLParser .prototype .mfmatrix3Value,
   [Base_X3DConstants .MFMatrix4d]:  VRMLParser .prototype .mfmatrix4Value,
   [Base_X3DConstants .MFMatrix4f]:  VRMLParser .prototype .mfmatrix4Value,
   [Base_X3DConstants .MFNode]:      VRMLParser .prototype .mfnodeValue,
   [Base_X3DConstants .MFRotation]:  VRMLParser .prototype .mfrotationValue,
   [Base_X3DConstants .MFString]:    VRMLParser .prototype .mfstringValue,
   [Base_X3DConstants .MFTime]:      VRMLParser .prototype .mfdoubleValue,
   [Base_X3DConstants .MFVec2d]:     VRMLParser .prototype .mfvec2Value,
   [Base_X3DConstants .MFVec2f]:     VRMLParser .prototype .mfvec2Value,
   [Base_X3DConstants .MFVec3d]:     VRMLParser .prototype .mfvec3Value,
   [Base_X3DConstants .MFVec3f]:     VRMLParser .prototype .mfvec3Value,
   [Base_X3DConstants .MFVec4d]:     VRMLParser .prototype .mfvec4Value,
   [Base_X3DConstants .MFVec4f]:     VRMLParser .prototype .mfvec4Value,
});

Base_X3DField .prototype .fromString = function (string, scene)
{
   const parser = new VRMLParser (scene);

   parser .setUnits (!!scene);
   parser .setInput (string);

   if (parser .fieldValue (this))
      return;

   throw new Error (`Couldn't read value for field '${this .getName ()}'.`);
};

const VRMLParser_default_ = VRMLParser;
;

x_ite_Namespace .add ("VRMLParser", "x_ite/Parser/VRMLParser", VRMLParser_default_);
/* harmony default export */ const Parser_VRMLParser = (VRMLParser_default_);
;// CONCATENATED MODULE: ./src/x_ite/Parser/XMLParser.js
/* provided dependency */ var XMLParser_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/














const AccessType =
{
   initializeOnly: Base_X3DConstants .initializeOnly,
   inputOnly:      Base_X3DConstants .inputOnly,
   outputOnly:     Base_X3DConstants .outputOnly,
   inputOutput:    Base_X3DConstants .inputOutput,
};

function XMLParser (scene)
{
   Parser_X3DParser .call (this, scene);

   this .protoDeclarations = [ ];
   this .parents           = [ ];
   this .parser            = new Parser_VRMLParser (scene);
   this .url               = new x_ite_Fields .MFString ();
   this .protoNames        = new Map ();
   this .protoFields       = new WeakMap ();
}

Object .assign (Object .setPrototypeOf (XMLParser .prototype, Parser_X3DParser .prototype),
{
   getEncoding ()
   {
      return "XML";
   },
   setInput (xmlElement)
   {
      try
      {
         if (typeof xmlElement === "string")
            xmlElement = XMLParser_$.parseXML (xmlElement);

         this .input = xmlElement;
         this .xml   = this .isXML (xmlElement);

         if (!this .xml)
            Object .assign (this, HTMLParser);
      }
      catch
      {
         this .input = undefined;
      }
   },
   isValid ()
   {
      return (this .input instanceof XMLDocument) || (this .input instanceof HTMLElement) || (this .input === null);
   },
   isXML (element)
   {
      if (element instanceof HTMLElement)
         return false;
      else
         return true;
   },
   parseIntoScene (resolve, reject)
   {
      this .resolve = resolve;
      this .reject  = reject;

      this .getScene () .setEncoding ("XML");
      this .getScene () .setProfile (this .getBrowser () .getProfile ("Full"));

      this .xmlElement (this .input);
   },
   xmlElement (xmlElement)
   {
      if (xmlElement === null)
         return this .resolve ?.(this .getScene ());

      switch (xmlElement .nodeName)
      {
         case "#document":
         {
            const X3D = XMLParser_$(xmlElement) .children ("X3D");

            if (X3D .length)
            {
               for (const xmlElement of X3D)
                  this .x3dElement (xmlElement);
            }
            else
            {
               if (this .resolve)
               {
                  this .loadComponents () .then (() =>
                  {
                     this .childrenElements (xmlElement);
                     this .resolve (this .getScene ());
                  })
                  .catch (this .reject);
               }
               else
               {
                  this .childrenElements (xmlElement);
               }
            }

            break;
         }
         case "X3D":
         {
            this .x3dElement (xmlElement);
            break;
         }
         case "Scene":
         case "SCENE":
         {
            if (this .resolve)
            {
               this .loadComponents () .then (() =>
               {
                  this .sceneElement (xmlElement);
                  this .resolve (this .getScene ());
               })
               .catch (this .reject);
            }
            else
            {
               this .sceneElement (xmlElement);
            }

            break;
         }
         default:
         {
            if (this .resolve)
            {
               this .loadComponents () .then (() =>
               {
                  this .childrenElements (xmlElement);
                  this .resolve (this .getScene ());
               })
               .catch (this .reject);
            }
            else
            {
               this .childrenElements (xmlElement);
            }

            break;
         }
      }
   },
   x3dElement (xmlElement)
   {
      try
      {
         // Profile

         const
            profileNameId = xmlElement .getAttribute ("profile"),
            profile       = this .getBrowser () .getProfile (profileNameId || "Full");

         XMLParser_$.data (this .scene, "X3D", xmlElement);

         this .getScene () .setProfile (profile);
      }
      catch (error)
      {
         console .error (error);
      }

      // Specification version

      const specificationVersion = xmlElement .getAttribute ("version");

      if (specificationVersion)
         this .getScene () .setSpecificationVersion (specificationVersion);

      // Process child nodes

      for (const childNode of xmlElement .childNodes)
         this .x3dElementChildHead (childNode)

      if (!this .xml)
         this .headElement (xmlElement);

      if (this .resolve)
      {
         this .loadComponents () .then (() =>
         {
            for (const childNode of xmlElement .childNodes)
               this .x3dElementChildScene (childNode)

            this .resolve (this .getScene ());
         })
         .catch (this .reject);
      }
      else
      {
         for (const childNode of xmlElement .childNodes)
            this .x3dElementChildScene (childNode)
      }
   },
   x3dElementChildHead (xmlElement)
   {
      switch (xmlElement .nodeName)
      {
         case "head":
         case "HEAD":
            this .headElement (xmlElement);
            return;
      }
   },
   x3dElementChildScene (xmlElement)
   {
      switch (xmlElement .nodeName)
      {
         case "Scene":
         case "SCENE":
            this .sceneElement (xmlElement);
            return;
      }
   },
   headElement (xmlElement)
   {
      for (const childNode of xmlElement .childNodes)
         this .headElementChild (childNode);
   },
   headElementChild (xmlElement)
   {
      switch (xmlElement .nodeName)
      {
         case "component":
         case "COMPONENT":
            this .componentElement (xmlElement);
            return;
         case "unit":
         case "UNIT":
            this .unitElement (xmlElement);
            return;
         case "meta":
         case "META":
            this .metaElement (xmlElement);
            return;
      }
   },
   componentElement (xmlElement)
   {
      try
      {
         const
            componentNameIdCharacters = xmlElement .getAttribute ("name"),
            componentSupportLevel = parseInt (xmlElement .getAttribute ("level"));

         if (componentNameIdCharacters === null)
            return console .warn ("XML Parser Error: Bad component statement. Expected name attribute.");

         if (componentSupportLevel === null)
            return console .warn ("XML Parser Error: Bad component statement. Expected level attribute.");

         const component = this .getBrowser () .getComponent (componentNameIdCharacters, componentSupportLevel);

         this .getScene () .updateComponent (component);
      }
      catch (error)
      {
         console .log (error .message);
      }
   },
   unitElement (xmlElement)
   {
      const
         category         = xmlElement .getAttribute ("category"),
         name             = xmlElement .getAttribute ("name"),
         conversionFactor = xmlElement .getAttribute ("conversionFactor"); //works for html5 as well

      if (category === null)
         return console .warn ("XML Parser Error: Bad unit statement. Expected category attribute.");

      if (name === null)
         return console .warn ("XML Parser Error: Bad unit statement. Expected name attribute.");

      if (conversionFactor === null)
         return console .warn ("XML Parser Error: Bad unit statement. Expected conversionFactor attribute.");

      this .getScene () .updateUnit (category, name, parseFloat (conversionFactor));
   },
   metaElement (xmlElement)
   {
      const
         metakey   = xmlElement .getAttribute ("name"),
         metavalue = xmlElement .getAttribute ("content");

      if (metakey === null)
         return console .warn ("XML Parser Error: Bad meta statement. Expected name attribute.");

      if (metavalue === null)
         return console .warn ("XML Parser Error: Bad meta statement. Expected content attribute.");

      this .getScene () .addMetaData (metakey, metavalue);
   },
   sceneElement (xmlElement)
   {
      XMLParser_$.data (xmlElement, "node", this .scene);

      this .childrenElements (xmlElement);
   },
   childrenElements (xmlElement)
   {
      for (const childNode of xmlElement .childNodes)
         this .childElement (childNode);
   },
   childElement (xmlElement)
   {
      switch (xmlElement .nodeName)
      {
         case "#comment":
         case "#text":
            return;

         case "#cdata-section":
            this .cdataNode (xmlElement);
            return;

         case "ExternProtoDeclare":
         case "EXTERNPROTODECLARE":
            this .externProtoDeclareElement (xmlElement);
            return;

         case "ProtoDeclare":
         case "PROTODECLARE":
            this .protoDeclareElement (xmlElement);
            return;

         case "IS":
            this .isElement (xmlElement);
            return;

         case "ProtoInstance":
         case "PROTOINSTANCE":
            this .protoInstanceElement (xmlElement);
            return;

         case "fieldValue":
         case "FIELDVALUE":
            this .fieldValueElement (xmlElement);
            return;

         case "field":
         case "FIELD":
            this .fieldElement (xmlElement);
            return;

         case "ROUTE":
            this .routeElement (xmlElement);
            return;

         case "IMPORT":
            this .importElement (xmlElement);
            return;

         case "EXPORT":
            this .exportElement (xmlElement);
            return;

         default:
            this .nodeElement (xmlElement);
            return;
      }
   },
   externProtoDeclareElement (xmlElement)
   {
      const name = xmlElement .getAttribute ("name");

      if (this .id (name))
      {
         const url = xmlElement .getAttribute ("url");

         this .parser .setInput (url ?? "");
         this .parser .sfstringValues (this .url);

         if (!this .url .length)
            console .warn ("XML Parser Error: Bad ExternProtoDeclare statement. Expected url attribute with value.");

         const externproto = new Prototype_X3DExternProtoDeclaration (this .getExecutionContext (), this .url);

         this .pushParent (externproto);
         this .protoInterfaceElement (xmlElement);
         this .popParent ();
         this .addProtoFieldNames (externproto);

         externproto .setup ();

         try
         {
            const existingExternProto = this .getExecutionContext () .getExternProtoDeclaration (name);

            this .getExecutionContext () .updateExternProtoDeclaration (this .getExecutionContext () .getUniqueExternProtoName (name), existingExternProto);
         }
         catch
         { }

         this .getExecutionContext () .updateExternProtoDeclaration (name, externproto);

         this .addProtoName (name);
      }
   },
   protoDeclareElement (xmlElement)
   {
      const name = xmlElement .getAttribute ("name");

      if (this .id (name))
      {
         const proto = new Prototype_X3DProtoDeclaration (this .getExecutionContext ());

         for (const childNode of xmlElement .childNodes)
         {
            switch (childNode .nodeName)
            {
               case "ProtoInterface":
               case "PROTOINTERFACE":
               {
                  this .pushParent (proto);
                  this .protoInterfaceElement (childNode);
                  this .popParent ();
                  this .addProtoFieldNames (proto);
                  break;
               }
               default:
                  continue;
            }

            break;
         }

         for (const childNode of xmlElement .childNodes)
         {
            switch (childNode .nodeName)
            {
               case "ProtoBody":
               case "PROTOBODY":
               {
                  this .pushPrototype (proto);
                  this .pushExecutionContext (proto .getBody ());
                  this .pushParent (proto);
                  this .protoBodyElement (childNode);
                  this .popParent ();
                  this .popExecutionContext ();
                  this .popPrototype ();
                  break;
               }
               default:
                  continue;
            }

            break;
         }

         proto .setup ();

         try
         {
            const existingProto = this .getExecutionContext () .getProtoDeclaration (name);

            this .getExecutionContext () .updateProtoDeclaration (this .getExecutionContext () .getUniqueProtoName (name), existingProto);
         }
         catch
         { }

         this .getExecutionContext () .updateProtoDeclaration (name, proto);

         this .addProtoName (name);
      }
   },
   protoInterfaceElement (xmlElement)
   {
      for (const childNode of xmlElement .childNodes)
         this .protoInterfaceElementChild (childNode);
   },
   protoInterfaceElementChild (xmlElement)
   {
      switch (xmlElement .nodeName)
      {
         case "field": // User-defined field
         case "FIELD": // User-defined field
            this .fieldElement (xmlElement);
            return;
      }
   },
   fieldElement (xmlElement)
   {
      try
      {
         if (this .getParents () .length === 0)
            return;

         const node = this .getParent ();

         if (!(node instanceof Base_X3DBaseNode))
            return;

         if (!node .canUserDefinedFields ())
            return;

         const
            accessType = AccessType [xmlElement .getAttribute ("accessType")] || Base_X3DConstants .initializeOnly,
            Field      = x_ite_Fields [xmlElement .getAttribute ("type")];

         if (!Field)
            return;

         const name = xmlElement .getAttribute ("name");

         if (!this .id (name))
            return;

         const field = new Field ();

         if (accessType & Base_X3DConstants .initializeOnly)
         {
            this .fieldValue (field, xmlElement .getAttribute ("value"));

            this .pushParent (field);
            this .childrenElements (xmlElement);
            this .popParent ();
         }

         node .addUserDefinedField (accessType, name, field);
      }
      catch (error)
      {
         console .error (error);
      }
   },
   protoBodyElement (xmlElement)
   {
      this .childrenElements (xmlElement);
   },
   isElement (xmlElement)
   {
      if (this .isInsideProtoDefinition ())
      {
         for (const childNode of xmlElement .childNodes)
            this .isElementChild (childNode);
      }
   },
   isElementChild (xmlElement)
   {
      switch (xmlElement .nodeName)
      {
         case "connect":
         case "CONNECT":
            this .connectElement (xmlElement);
            return;
      }
   },
   connectElement (xmlElement)
   {
      const
         nodeFieldName  = xmlElement .getAttribute ("nodeField"),
         protoFieldName = xmlElement .getAttribute ("protoField");

      if (nodeFieldName === null)
         return console .warn ("XML Parser Error: Bad connect statement. Expected nodeField attribute.");

      if (protoFieldName === null)
         return console .warn ("XML Parser Error: Bad connect statement. Expected protoField attribute.");

      try
      {
         if (this .getParents () .length === 0)
            return;

         const
            node  = this .getParent (),
            proto = this .getPrototype ();

         if (!(node instanceof Core_X3DNode))
            return;

         const
            nodeField  = node .getField (nodeFieldName),
            protoField = proto .getField (protoFieldName);

         if (nodeField .getType () === protoField .getType ())
         {
            if (protoField .isReference (nodeField .getAccessType ()))
               nodeField .addReference (protoField);
            else
               throw new Error (`Field '${nodeField .getName ()}' and '${protoField .getName ()}' in PROTO ${proto .getName ()} are incompatible as an IS mapping.`);
         }
         else
            throw new Error (`Field '${nodeField .getName ()}' and '${protoField .getName ()}' in PROTO ${this .proto .getName()} have different types.`);
      }
      catch (error)
      {
         console .warn (`XML Parser Error: Couldn't create IS reference. ${error .message}`);
      }
   },
   protoInstanceElement (xmlElement)
   {
      try
      {
         if (this .useAttribute (xmlElement))
            return;

         const name = xmlElement .getAttribute ("name");

         if (this .id (name))
         {
            const node = this .getExecutionContext () .createProto (name, false);

            if (!node)
               throw new Error (`Unknown proto or externproto type '${name}'.`);

            ///DOMIntegration: attach node to DOM xmlElement for access from DOM.
            XMLParser_$.data (xmlElement, "node", node);

            this .defAttribute (xmlElement, node);
            this .addNode (xmlElement, node);
            this .pushParent (node);
            this .childrenElements (xmlElement);

            if (!this .isInsideProtoDefinition ())
               node .setup ();

            this .popParent ();
         }
      }
      catch (error)
      {
         console .warn ("XML Parser Error: ", error .message);

         if (DEVELOPMENT)
            console .error (error);
      }
   },
   fieldValueElement (xmlElement)
   {
      try
      {
         if (this .getParents () .length === 0)
            return;

         const
            node = this .getParent (),
            name = xmlElement .getAttribute ("name");

         if (!(node instanceof Core_X3DPrototypeInstance))
            return;

         if (!this .id (name))
            return;

         const
            field      = node .getField (name),
            accessType = field .getAccessType ();

         if (accessType & Base_X3DConstants .initializeOnly)
         {
            if (field .getType () === Base_X3DConstants .MFNode)
            {
               field .length = 0
            }

            this .fieldValue (field, xmlElement .getAttribute ("value"));

            this .pushParent (field);
            this .childrenElements (xmlElement);
            this .popParent ();
         }
      }
      catch (error)
      {
         console .warn (`XML Parser Error: Couldn't assign field value. ${error .message}`);
      }
   },
   nodeElement (xmlElement)
   {
      try
      {
         if (this .useAttribute (xmlElement))
            return;

         const node = this .getExecutionContext () .createNode (this .nodeNameToCamelCase (xmlElement .nodeName), false)
            ?? this .getExecutionContext () .createProto (this .protoNameToCamelCase (xmlElement .nodeName), false);

         if (!node)
            throw new Error (`Unknown node type '${xmlElement .nodeName}', you probably have insufficient component/profile statements and/or an inappropriate specification version.`);

         ///DOMIntegration: attach node to DOM xmlElement for access from DOM.
         XMLParser_$.data (xmlElement, "node", node);

         //DOMIntegration: Script node support for HTML.
         if (xmlElement .nodeName === "SCRIPT")
            this .scriptElement (xmlElement);

         this .defAttribute (xmlElement, node);
         this .addNode (xmlElement, node);
         this .pushParent (node);
         this .nodeAttributes (xmlElement, node);
         this .childrenElements (xmlElement);

         if (!this .isInsideProtoDefinition ())
            node .setup ();

         this .popParent ();
      }
      catch (error)
      {
         // NULL

         if (xmlElement .nodeName == "NULL")
         {
            this .addNode (xmlElement, null);
            return;
         }

         if (DEVELOPMENT)
            console .error (error);
         else
            console .error (`XML Parser Error: ${error .message}`);
      }
   },
   scriptElement (element)
	{
		const
			domParser      = new DOMParser (),
			scriptDocument = domParser .parseFromString (element .outerHTML, "application/xml"),
			childNodes     = scriptDocument .children [0] .childNodes;

      element .textContent = "// Content moved into childNodes.";

		for (const childNode of childNodes)
		{
         // Add elements and cdata.
			if (childNode .nodeType === 1 || childNode .nodeType === 4)
            element .appendChild (childNode);
		}
	},
   routeElement (xmlElement)
   {
      try
      {
         const
            sourceNodeName      = xmlElement .getAttribute ("fromNode"),
            sourceField         = xmlElement .getAttribute ("fromField"),
            destinationNodeName = xmlElement .getAttribute ("toNode"),
            destinationField    = xmlElement .getAttribute ("toField");

         if (sourceNodeName === null)
            throw new Error ("Bad ROUTE statement: Expected fromNode attribute.");

         if (sourceField === null)
            throw new Error ("Bad ROUTE statement: Expected fromField attribute.");

         if (destinationNodeName === null)
            throw new Error ("Bad ROUTE statement: Expected toNode attribute.");

         if (destinationField === null)
            throw new Error ("Bad ROUTE statement: Expected toField attribute.");

         const
            executionContext = this .getExecutionContext (),
            sourceNode       = executionContext .getLocalNode (sourceNodeName),
            destinationNode  = executionContext .getLocalNode (destinationNodeName),
            route            = executionContext .addRoute (sourceNode, sourceField, destinationNode, destinationField);

         ///DOMIntegration: attach node to DOM xmlElement for access from DOM.
         XMLParser_$.data (xmlElement, "node", route);
      }
      catch (error)
      {
         console .warn (`XML Parser Error: ${error .message}`);

         if (DEVELOPMENT)
            console .error (error);
      }
   },
   importElement (xmlElement)
   {
      try
      {
         const
            inlineNodeName   = xmlElement .getAttribute ("inlineDEF"),
            exportedNodeName = xmlElement .getAttribute ("importedDEF") || xmlElement .getAttribute ("exportedDEF"),
            localNodeName    = xmlElement .getAttribute ("AS") || exportedNodeName;

         if (inlineNodeName === null)
            throw new Error ("Bad IMPORT statement: Expected inlineDEF attribute.");

         if (exportedNodeName === null)
            throw new Error ("Bad IMPORT statement: Expected importedDEF attribute.");

         const inlineNode = this .getExecutionContext () .getNamedNode (inlineNodeName);

         this .getExecutionContext () .updateImportedNode (inlineNode, exportedNodeName, localNodeName);
      }
      catch (error)
      {
         console .warn (`XML Parser Error: ${error .message}`);
      }
   },
   exportElement (xmlElement)
   {
      try
      {
         if (this .getScene () !== this .getExecutionContext ())
         {
            console .warn ("XML Parser Error: Export statement not allowed here.");
            return;
         }

         const
            localNodeName    = xmlElement .getAttribute ("localDEF"),
            exportedNodeName = xmlElement .getAttribute ("AS") || localNodeName;

         if (localNodeName === null)
            throw new Error ("Bad EXPORT statement: Expected localDEF attribute.");

         const localNode = this .getExecutionContext () .getLocalNode (localNodeName);

         this .getScene () .updateExportedNode (exportedNodeName, localNode);
      }
      catch (error)
      {
         console .warn (`XML Parser Error: ${error .message}`);
      }
   },
   cdataNode (xmlElement)
   {
      if (this .getParents () .length === 0)
         return;

      const node = this .getParent ();

      if (node instanceof Core_X3DNode)
         node .getSourceText () ?.push (xmlElement .data);
   },
   useAttribute (xmlElement)
   {
      try
      {
         const name = xmlElement .getAttribute ("USE");

         if (this .id (name))
         {
            const node = this .getExecutionContext () .getNamedNode (name);

            this .addNode (xmlElement, node .getValue ());
            return true;
         }
      }
      catch (error)
      {
         console .warn (`Invalid USE name: ${error .message}`);
      }

      return false;
   },
   defAttribute (xmlElement, node)
   {
      try
      {
         const name = xmlElement .getAttribute ("DEF");

         if (name)
         {
            try
            {
               const namedNode = this .getExecutionContext () .getNamedNode (name);

               this .getExecutionContext () .updateNamedNode (this .getExecutionContext () .getUniqueName (name), namedNode);
            }
            catch
            { }

            this .getExecutionContext () .updateNamedNode (name, node);
         }
      }
      catch (error)
      {
         console .warn (`Invalid DEF name: ${error .message}`);
      }
   },
   nodeAttributes (xmlElement, node)
   {
      for (const xmlAttribute of xmlElement .attributes)
         this .nodeAttribute (xmlAttribute, node);
   },
   nodeAttribute (xmlAttribute, node)
   {
      try
      {
         const field = node .getPredefinedField (this .attributeToCamelCase (node, xmlAttribute .name));

         if (field .isInitializable ())
            this .fieldValue (field, xmlAttribute .value);
      }
      catch (error)
      {
         //console .error (error);
      }
   },
   fieldValue (field, value)
   {
      if (value === null)
         return;

      this .parser .pushExecutionContext (this .getExecutionContext ());

      this .parser .setInput (value);
      this [field .getType ()] .call (this .parser, field, field .getUnit ());

      this .parser .popExecutionContext ();
   },
   id (string)
   {
      if (string === null)
         return false;

      if (string .length === 0)
         return false;

      return true;
   },
   getParents ()
   {
      return this .parents;
   },
   getParent ()
   {
      return this .parents .at (-1);
   },
   pushParent (parent)
   {
      return this .parents .push (parent);
   },
   popParent ()
   {
      this .parents .pop ();
   },
   addNode (xmlElement, node)
   {
      if (this .parents .length === 0 || this .getParent () instanceof Prototype_X3DProtoDeclaration)
      {
         this .getExecutionContext () .rootNodes .push (node);
         return;
      }

      const parent = this .getParent ();

      if (parent instanceof Base_X3DField)
      {
         switch (parent .getType ())
         {
            case Base_X3DConstants .SFNode:
               parent .setValue (node);
               return;

            case Base_X3DConstants .MFNode:
               parent .push (node);
               return;
         }

         return;
      }

      // parent is a node.

      try
      {
         const containerField = xmlElement .getAttribute ("containerField") || node ?.getContainerField (true);

         if (!containerField)
         {
            console .warn ("Node must have a container field attribute.");
            return;
         }

         const field = parent .getField (containerField);

         switch (field .getType ())
         {
            case Base_X3DConstants .SFNode:
               field .setValue (node);
               return;

            case Base_X3DConstants .MFNode:
               field .push (node);
               return;
         }
      }
      catch (error)
      {
         // console .error (error);

         if (node ?.getType () .includes (Base_X3DConstants .X3DMetadataObject))
         {
            xmlElement .setAttribute ("containerField", "metadata");

            this .addNode (xmlElement, node);
         }
      }
   },
   // Overloaded by HTMLParser.
   addProtoName (name)
   { },
   addProtoFieldNames (protoNode)
   { },
   protoNameToCamelCase (typeName)
   {
      return typeName;
   },
   nodeNameToCamelCase (typeName)
   {
      return typeName;
   },
   attributeToCamelCase (node, name)
   {
      return name;
   },
});

Object .assign (XMLParser .prototype,
{
   [Base_X3DConstants .SFBool]:      Parser_VRMLParser .prototype .sfboolValue,
   [Base_X3DConstants .SFColor]:     Parser_VRMLParser .prototype .sfcolorValue,
   [Base_X3DConstants .SFColorRGBA]: Parser_VRMLParser .prototype .sfcolorrgbaValue,
   [Base_X3DConstants .SFDouble]:    Parser_VRMLParser .prototype .sfdoubleValue,
   [Base_X3DConstants .SFFloat]:     Parser_VRMLParser .prototype .sfdoubleValue,
   [Base_X3DConstants .SFImage]:     Parser_VRMLParser .prototype .sfimageValue,
   [Base_X3DConstants .SFInt32]:     Parser_VRMLParser .prototype .sfint32Value,
   [Base_X3DConstants .SFMatrix3f]:  Parser_VRMLParser .prototype .sfmatrix3Value,
   [Base_X3DConstants .SFMatrix3d]:  Parser_VRMLParser .prototype .sfmatrix3Value,
   [Base_X3DConstants .SFMatrix4f]:  Parser_VRMLParser .prototype .sfmatrix4Value,
   [Base_X3DConstants .SFMatrix4d]:  Parser_VRMLParser .prototype .sfmatrix4Value,
   [Base_X3DConstants .SFNode] (field) { field .setValue (null); },
   [Base_X3DConstants .SFRotation]:  Parser_VRMLParser .prototype .sfrotationValue,
   [Base_X3DConstants .SFString] (field) { field .setValue (x_ite_Fields .SFString .unescape (this .input)); },
   [Base_X3DConstants .SFTime]:      Parser_VRMLParser .prototype .sfdoubleValue,
   [Base_X3DConstants .SFVec2d]:     Parser_VRMLParser .prototype .sfvec2Value,
   [Base_X3DConstants .SFVec2f]:     Parser_VRMLParser .prototype .sfvec2Value,
   [Base_X3DConstants .SFVec3d]:     Parser_VRMLParser .prototype .sfvec3Value,
   [Base_X3DConstants .SFVec3f]:     Parser_VRMLParser .prototype .sfvec3Value,
   [Base_X3DConstants .SFVec4d]:     Parser_VRMLParser .prototype .sfvec4Value,
   [Base_X3DConstants .SFVec4f]:     Parser_VRMLParser .prototype .sfvec4Value,

   [Base_X3DConstants .MFBool]:      Parser_VRMLParser .prototype .sfboolValues,
   [Base_X3DConstants .MFColor]:     Parser_VRMLParser .prototype .sfcolorValues,
   [Base_X3DConstants .MFColorRGBA]: Parser_VRMLParser .prototype .sfcolorrgbaValues,
   [Base_X3DConstants .MFDouble]:    Parser_VRMLParser .prototype .sfdoubleValues,
   [Base_X3DConstants .MFFloat]:     Parser_VRMLParser .prototype .sfdoubleValues,
   [Base_X3DConstants .MFImage]:     Parser_VRMLParser .prototype .sfimageValues,
   [Base_X3DConstants .MFInt32]:     Parser_VRMLParser .prototype .sfint32Values,
   [Base_X3DConstants .MFMatrix3d]:  Parser_VRMLParser .prototype .sfmatrix3Values,
   [Base_X3DConstants .MFMatrix3f]:  Parser_VRMLParser .prototype .sfmatrix3Values,
   [Base_X3DConstants .MFMatrix4d]:  Parser_VRMLParser .prototype .sfmatrix4Values,
   [Base_X3DConstants .MFMatrix4f]:  Parser_VRMLParser .prototype .sfmatrix4Values,
   [Base_X3DConstants .MFNode] (field) { field .length = 0; },
   [Base_X3DConstants .MFRotation]:  Parser_VRMLParser .prototype .sfrotationValues,
   [Base_X3DConstants .MFString]:    Parser_VRMLParser .prototype .sfstringValues,
   [Base_X3DConstants .MFTime]:      Parser_VRMLParser .prototype .sfdoubleValues,
   [Base_X3DConstants .MFVec2d]:     Parser_VRMLParser .prototype .sfvec2Values,
   [Base_X3DConstants .MFVec2f]:     Parser_VRMLParser .prototype .sfvec2Values,
   [Base_X3DConstants .MFVec3d]:     Parser_VRMLParser .prototype .sfvec3Values,
   [Base_X3DConstants .MFVec3f]:     Parser_VRMLParser .prototype .sfvec3Values,
   [Base_X3DConstants .MFVec4d]:     Parser_VRMLParser .prototype .sfvec4Values,
   [Base_X3DConstants .MFVec4f]:     Parser_VRMLParser .prototype .sfvec4Values,
});

// HTML Support

const HTMLParser =
{
   addProtoName (name)
   {
      //DOMIntegration: add uppercase versions of proto name.

      this .protoNames .set (name,                 name);
      this .protoNames .set (name .toUpperCase (), name);
   },
   addProtoFieldNames: (() =>
   {
      const reservedAttributes = new Set ();

      for (const reservedAttribute of [
         "DEF",
         "USE",
         "containerField",
      ])
      {
         reservedAttributes
            .add (reservedAttribute)
            .add (reservedAttribute .toLowerCase ());
      }

      return function (protoNode)
      {
         //DOMIntegration: handle lowercase versions of field names.

         const fields = new Map ();

         this .protoFields .set (protoNode, fields);

         for (const { name } of protoNode .getFieldDefinitions ())
         {
            if (reservedAttributes .has (name))
               continue;

            fields .set (name,                 name);
            fields .set (name .toLowerCase (), name);
         }
      };
   })(),
   protoNameToCamelCase (typeName)
   {
      //DOMIntegration: handle uppercase versions of node names.
      return this .protoNames .get (typeName);
   },
   nodeNameToCamelCase (typeName)
   {
      //DOMIntegration: handle uppercase versions of node names.
      return Parser_HTMLSupport .getNodeTypeName (typeName);
   },
   attributeToCamelCase (node, name)
   {
      //DOMIntegration: handle lowercase versions of field names.

      if (node instanceof Core_X3DPrototypeInstance)
         return this .protoFields .get (node .getProtoNode ()) .get (name);

      return Parser_HTMLSupport .getFieldName (name);
   },
};

const XMLParser_default_ = XMLParser;
;

x_ite_Namespace .add ("XMLParser", "x_ite/Parser/XMLParser", XMLParser_default_);
/* harmony default export */ const Parser_XMLParser = (XMLParser_default_);
;// CONCATENATED MODULE: ./src/x_ite/Parser/JSONParser.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * X3DJSONLD Copyright John Carlson, USA 2016-2017, https://coderextreme.net/X3DJSONLD
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function JSONParser (scene)
{
   Parser_X3DParser .call (this, scene);

   this .namespace = "http://www.web3d.org/specifications/x3d-namespace";
}

Object .assign (Object .setPrototypeOf (JSONParser .prototype, Parser_X3DParser .prototype),
{
   getEncoding ()
   {
      return "JSON";
   },
   setInput (json)
   {
      try
      {
         if (typeof json === "string")
            json = JSON .parse (json);

         this .input = json;
      }
      catch
      {
         this .input = undefined;
      }
   },
   isValid ()
   {
      return this .input instanceof Object;
   },
   parseIntoScene (resolve, reject)
   {
      /**
       * Load X3D JSON into an element.
       * json - the JavaScript object to convert to DOM.
       */

      const child = this .createElement ("X3D");

      this .convertToDOM (this .input, "", child);

      // Call the DOM parser.

      const parser = new Parser_XMLParser (this .getScene ());

      parser .setInput (child);
      parser .parseIntoScene (resolve, reject);

      this .getScene () .setEncoding ("JSON");
   },
   elementSetAttribute (element, key, value)
   {
      /**
       * Yet another way to set an attribute on an element.  does not allow you to
       * set JSON schema or encoding.
       */

      switch (key)
      {
         case "SON schema":
         {
            // JSON Schema
            break;
         }
         case "ncoding":
         {
            // encoding, UTF-8, UTF-16 or UTF-32
            break;
         }
         default:
         {
            if (typeof element .setAttribute === "function")
               element .setAttribute (key, value);

            break;
         }
      }
   },
   convertChildren (parentkey, object, element)
   {
      /**
       * converts children of object to DOM.
       */

      for (const key in object)
      {
         if (typeof object [key] === "object")
         {
            if (isNaN (parseInt (key)))
               this .convertObject (key, object, element, parentkey .substr (1));

            else
               this .convertToDOM (object[ key], key, element, parentkey .substr (1));
         }
      }
   },
   createElement (key, containerField)
   {
      /**
       * a method to create and element with tagnam key to DOM in a namespace.  If
       * containerField is set, then the containerField is set in the elemetn.
       */

      if (typeof this .namespace === "undefined")
      {
         var child = document .createElement (key);
      }
      else
      {
         var child = document .createElementNS (this .namespace, key);

         if (child === null || typeof child === "undefined")
         {
            console .error ("Trouble creating element for", key);

            child = document .createElement (key);
         }
      }

      if (typeof containerField !== "undefined")
         this .elementSetAttribute (child, "containerField", containerField);

      return child;
   },
   createCDATA (document, element, str)
   {
      const
         docu  = new DOMParser () .parseFromString ("<xml></xml>", "application/xml"),
         cdata = docu .createCDATASection (str);

      element .appendChild (cdata);
   },
   convertObject (key, object, element, containerField)
   {
      /**
       * convert the object at object[key] to DOM.
       */

      if (object !== null && typeof object [key] === "object")
      {
         if (key .substr (0, 1) === "@")
         {
            this .convertToDOM (object [key], key, element);
         }
         else if (key .substr (0, 1) === "-")
         {
            this .convertChildren (key, object [key], element);
         }
         else if (key === "#comment")
         {
            for (const c in object [key])
            {
               const child = document .createComment (this .commentStringToXML (object [key] [c]));

               element .appendChild (child);
            }
         }
         else if (key === "#sourceCode" || key === "@sourceCode" || key === "#sourceText")
         {
            this .createCDATA (document, element, object [key] .join ("\n"));
         }
         else
         {
            if (key === "connect" || key === "fieldValue" || key === "field" || key === "meta" || key === "component" || key === "unit")
            {
               for (const childkey in object [key])
               {
                  // for each field
                  if (typeof object [key] [childkey] === "object")
                  {
                     const child = this .createElement (key, containerField);

                     this .convertToDOM (object [key] [childkey], childkey, child);

                     element .appendChild (child);
                     element .appendChild (document .createTextNode ("\n"));
                  }
               }
            }
            else
            {
               const child = this .createElement (key, containerField);

               this .convertToDOM (object [key], key, child);

               element .appendChild (child);
               element .appendChild (document .createTextNode ("\n"));
            }
         }
      }
   },
   commentStringToXML (str)
   {
      /**
       * convert a comment string in JavaScript to XML.  Pass the string
       */

      return str .replace (/\\\\/g, "\\");
   },
   SFStringToXML (str)
   {
      /**
       * convert an SFString to XML.
       */

      return str .replace (/([\\"])/g, "\\$1");
   },
   JSONStringToXML (str)
   {
      /**
       * convert a JSON String to XML.
       */

      str = str .replace (/\\/g, "\\\\");
      str = str .replace (/\n/g, "\\n");

      return str;
   },
   convertToDOM(object, parentkey, element, containerField)
   {
      /**
       * main routine for converting a JavaScript object to DOM.
       * object is the object to convert.
       * parentkey is the key of the object in the parent.
       * element is the parent element.
       * containerField is a possible containerField.
       */

      let
         isArray        = false,
         localArray     = [ ],
         arrayOfStrings = false;

      for (const key in object)
      {
         isArray = !isNaN (parseInt (key));

         if (isArray)
         {
            switch (typeof object [key])
            {
               case "number":
               {
                  localArray .push (object [key]);
                  break;
               }
               case "string":
               {
                  localArray .push (object [key]);

                  arrayOfStrings = true;
                  break;
               }
               case "boolean":
               {
                  localArray .push (object [key]);
                  break;
               }
               case "object":
               {
                  /*
                  if (object[key] != null && typeof object[key].join === "function") {
                     localArray.push(object[key].join(" "));
                  }
                  */
                  this .convertToDOM (object [key], key, element);
                  break;
               }
               case "undefined":
               {
                  break;
               }
               default:
               {
                  console .error (`Unknown type found in array ${typeof object [key]}`);
               }
            }
         }
         else
         {
            switch (typeof object [key])
            {
               case "object":
               {
                  // This is where the whole thing starts

                  if (key === "X3D")
                     this .convertToDOM (object [key], key, element);

                  else
                     this .convertObject (key, object, element, containerField);

                  break;
               }
               case "number":
               {
                  this .elementSetAttribute (element, key .substr (1), object [key]);
                  break;
               }
               case "string":
               {
                  if (key !== "#comment")
                  {
                     // ordinary string attributes
                     this .elementSetAttribute (element, key .substr (1), this .JSONStringToXML (object [key]));
                  }
                  else
                  {
                     const child = document .createComment (this .commentStringToXML (object [key]));

                     element .appendChild (child);
                  }

                  break;
               }
               case "boolean":
               {
                  this .elementSetAttribute (element, key .substr (1), object [key]);
                  break;
               }
               case "undefined":
               {
                  break;
               }
               default:
               {
                  console .error (`Unknown type found in object ${typeof object [key]}`);
                  console .error (object);
               }
            }
         }
      }

      if (isArray)
      {
         if (parentkey .substr (0,1) === "@")
         {
            if (arrayOfStrings)
            {
               arrayOfStrings = false;

               for (const str in localArray)
                  localArray [str] = this .SFStringToXML (localArray [str]);

               this .elementSetAttribute (element, parentkey .substr (1), '"' + localArray .join ('" "') + '"');
            }
            else
            {
               // if non string array
               this .elementSetAttribute (element, parentkey .substr (1), localArray .join (" "));
            }
         }

         isArray = false;
      }

      return element;
   },
});

const JSONParser_default_ = JSONParser;
;

x_ite_Namespace .add ("JSONParser", "x_ite/Parser/JSONParser", JSONParser_default_);
/* harmony default export */ const Parser_JSONParser = (JSONParser_default_);
;// CONCATENATED MODULE: ./src/x_ite/Parser/X3DOptimizer.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






function X3DOptimizer () { }

Object .assign (X3DOptimizer .prototype,
{
   removeGroups: false,
   removeEmptyGroups: false,
   combineGroupingNodes: false,
   optimizeInterpolators: false,
   optimizeSceneGraph (nodes)
   {
      const removedNodes = [ ];

      nodes .setValue (this .optimizeNodes (nodes, true, removedNodes));

      removedNodes .forEach (node => node .dispose ());
   },
   optimizeNodes (nodes, combine, removedNodes)
   {
      return [... nodes] .flatMap (node => this .optimizeNode (node, combine, removedNodes));
   },
   optimizeNode (node, combine, removedNodes)
   {
      if (!node)
         return [ ];

      if (this .optimizeInterpolators)
         this .removeInterpolatorsWithOnlyOneValue (node, removedNodes);

      switch (node .getNodeTypeName ())
      {
         case "Transform":
         {
            node .children = this .optimizeNodes (node .children, true, removedNodes);
            break;
         }
         case "Anchor":
         case "Group":
         {
            node .children = this .optimizeNodes (node .children, true, removedNodes);

            if (this .removeEmptyGroups)
            {
               if (node .children .length === 0)
                  return [ ];
            }

            if (this .removeGroups)
               break;

            return node;
         }
         case "Collision":
         case "LOD":
         case "Switch":
         {
            this .optimizeNodes (node .children, false, removedNodes);
            return node;
         }
         case "HAnimJoint":
         case "HAnimSegment":
         case "HAnimSite":
         {
            node .children = this .optimizeNodes (node .children, true, removedNodes);
            return node;
         }
         case "HAnimHumanoid":
         {
            node .skeleton = this .optimizeNodes (node .skeleton, true, removedNodes);
            node .skin     = this .optimizeNodes (node .skin,     true, removedNodes);
            return node;
         }
         default:
         {
            return node;
         }
      }

      if (!combine)
         return node;

      if (this .removeEmptyGroups)
      {
         if (node .children .length === 0)
            return [ ];
      }

      if (!this .combineGroupingNodes)
         return node;

      if (node .getValue () .hasRoutes ())
         return node;

      if (node .getNodeTypeName () === "Transform")
      {
         node = this .combineSingleChild (node, removedNodes);

         if (!node .translation .getValue () .equals (Numbers_Vector3 .Zero))
            return node;

         if (!node .rotation .getValue () .equals (Numbers_Rotation4 .Identity))
            return node;

         if (!node .scale .getValue () .equals (Numbers_Vector3 .One))
            return node;
      }

      if (node .children)
      {
         removedNodes .push (node);

         return [... node .children];
      }

      return node;
   },
   removeInterpolatorsWithOnlyOneValue (node, removedNodes)
   {
      for (const field of node .getValue () .getFields ())
      {
         if (field .getInputRoutes () .size !== 1)
            continue;

         const
            route      = Array .from (field .getInputRoutes ()) [0],
            sourceNode = route .sourceNode;

         if (!sourceNode .getNodeType () .includes (Base_X3DConstants .X3DInterpolatorNode))
            continue;

         if (sourceNode .key .length !== 1)
            continue;

         node [route .destinationField] = sourceNode .keyValue [0];

         removedNodes .push (sourceNode);

         route .dispose ();
      }
   },
   combineSingleChild (node, removedNodes)
   {
      if (node .children .length !== 1)
         return node;

      const child = node .children [0];

      if (!child .getNodeTypeName () .match (/^(?:Transform|HAnimHumanoid)$/))
         return node;

      if (child .getValue () .hasRoutes ())
         return node;

      // Combine single Transform nodes.

      const
         translation      = new Numbers_Vector3 (0, 0, 0),
         rotation         = new Numbers_Rotation4 (),
         scale            = new Numbers_Vector3 (1, 1, 1),
         scaleOrientation = new Numbers_Rotation4 (),
         nodeMatrix       = new Numbers_Matrix4 (),
         childMatrix      = new Numbers_Matrix4 ();

      nodeMatrix .set (node .translation .getValue (),
                       node .rotation .getValue (),
                       node .scale .getValue (),
                       node .scaleOrientation .getValue (),
                       node .center .getValue ());

      childMatrix .set (child .translation .getValue (),
                        child .rotation .getValue (),
                        child .scale .getValue (),
                        child .scaleOrientation .getValue (),
                        child .center .getValue ());

      nodeMatrix .multLeft (childMatrix);

      nodeMatrix .get (translation, rotation, scale, scaleOrientation, child .center .getValue ());

      child .translation      = translation;
      child .rotation         = rotation;
      child .scale            = scale;
      child .scaleOrientation = scaleOrientation;

      if (!child .getNodeTypeName () && node .getNodeTypeName ())
      {
         const executionContext = child .getExecutionContext ();

         executionContext .addNamedNode (executionContext .getUniqueName (node .getNodeTypeName ()), child);
      }

      removedNodes .push (node);

      return child;
   },
});

const X3DOptimizer_default_ = X3DOptimizer;
;

x_ite_Namespace .add ("X3DOptimizer", "x_ite/Parser/X3DOptimizer", X3DOptimizer_default_);
/* harmony default export */ const Parser_X3DOptimizer = (X3DOptimizer_default_);
;// CONCATENATED MODULE: ./src/x_ite/Features.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



const MODULE = true;

const Features =
{
   get ENVIRONMENT ()
   {
      if (DEVELOPMENT)
         return "BROWSER";

      if (MODULE)
         return "MODULE";

      if ((typeof process === "object") && (process .release .name .search (/node|io.js/) !== -1))
         return "NODE";

      return "BROWSER";
   },
};

const Features_default_ = Features;
;

x_ite_Namespace .add ("Features", "x_ite/Features", Features_default_);
/* harmony default export */ const x_ite_Features = (Features_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Networking/URLs.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



const URLs =
{
   getScriptURL: (() =>
   {
      switch (x_ite_Features .ENVIRONMENT)
      {
         case "NODE":
         {
            var src = __webpack_require__.g .require ("url") .pathToFileURL (__filename) .href;
            break;
         }
         case "BROWSER":
         {
            var src = document .currentScript ?.src ?? document .location .href;
            break;
         }
         case "MODULE":
         {
            var src = import .meta .url;
            break;
         }
      }

      return function ()
      {
         return src;
      };
   })(),
   getProviderURL (component)
   {
      if (component)
      {
         if (this .getScriptURL () .match (/\.min\.js$/))
            component += ".min";

         return new URL ("assets/components/" + component + ".js", this .getScriptURL ()) .href;
      }

      return "https://create3000.github.io/x_ite/";
   },
   getFontsURL (file)
   {
      return new URL ("assets/fonts/" + file, this .getScriptURL ()) .href;
   },
   getLinetypeURL ()
   {
      return new URL ("assets/linetype/linetypes.png", this .getScriptURL ()) .href;
   },
   getHatchingURL (index)
   {
      return new URL ("assets/hatching/" + index + ".png", this .getScriptURL ()) .href;
   },
   getLibraryURL (file)
   {
      return new URL ("assets/lib/" + file, this .getScriptURL ()) .href;
   },
};

const URLs_default_ = URLs;
;

x_ite_Namespace .add ("URLs", "x_ite/Browser/Networking/URLs", URLs_default_);
/* harmony default export */ const Networking_URLs = (URLs_default_);
;// CONCATENATED MODULE: ./src/x_ite/Parser/GLTF2Parser.js
/* provided dependency */ var GLTF2Parser_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/













// https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html
// https://github.com/KhronosGroup/glTF-Sample-Models

const SAMPLES_PER_SECOND = 30; // in 1/s

function GLTF2Parser (scene)
{
   Parser_X3DParser    .call (this, scene);
   Parser_X3DOptimizer .call (this);

   // Optimizer

   this .removeGroups          = false;
   this .removeEmptyGroups     = true;
   this .combineGroupingNodes  = true;
   this .optimizeInterpolators = true;

   // Globals

   this .extensions            = new Set ();
   this .lights                = [ ];
   this .usedLights            = 0;
   this .buffers               = [ ];
   this .bufferViews           = [ ];
   this .accessors             = [ ];
   this .samplers              = [ ];
   this .materials             = [ ];
   this .defaultAppearance     = [ ];
   this .textureTransformNodes = [ ];
   this .meshes                = [ ];
   this .cameras               = [ ];
   this .viewpoints            = 0;
   this .nodes                 = [ ];
   this .skins                 = [ ];
   this .joints                = new Set ();
   this .animations            = 0;
}

Object .assign (Object .setPrototypeOf (GLTF2Parser .prototype, Parser_X3DParser .prototype),
   Parser_X3DOptimizer .prototype,
{
   getEncoding ()
   {
      return "JSON";
   },
   setInput (json)
   {
      try
      {
         if (typeof json === "string")
            json = JSON .parse (json);

         this .input = json;
      }
      catch
      {
         this .input = undefined;
      }
   },
   isValid: (() =>
   {
      const keys = new Set ([
         "asset",
         "extra",
         "extensions",
         "extensionsRequired",
         "extensionsUsed",
         "buffers",
         "bufferViews",
         "accessors",
         "samplers",
         "images",
         "textures",
         "materials",
         "meshes",
         "cameras",
         "skins",
         "nodes",
         "scenes",
         "scene",
         "animations",
      ]);

      return function ()
      {
         if (!(this .input instanceof Object))
            return false;

         if (!Object .keys (this .input) .every (key => keys .has (key)))
            return false;

         const asset = this .input .asset;

         if (!(asset instanceof Object && asset .version === "2.0"))
            return false;

         return true;
      };
   })(),
   setBuffers (buffers)
   {
      this .buffers = buffers;
   },
   parseIntoScene (resolve, reject)
   {
      this .rootObject (this .input)
         .then (resolve)
         .catch (reject);
   },
   rootObject: async function (glTF)
   {
      if (!(glTF instanceof Object))
         return;

      // Set profile and components.

      const
         browser = this .getBrowser (),
         scene   = this .getScene ();

      scene .setEncoding ("GLTF");
      scene .setProfile (browser .getProfile ("Interchange"));

      if (glTF .skins)
         scene .addComponent (browser .getComponent ("HAnim"));

      // Parse root objects.

      this .assetObject      (glTF .asset);
      this .extensionsArray  (glTF .extensionsUsed, this .extensions);
      this .extensionsArray  (glTF .extensionsRequired, this .extensions);
      this .extensionsObject (glTF .extensions);

      await this .loadComponents ();
      await this .buffersArray (glTF .buffers);

      if (this .extensions .has ("KHR_draco_mesh_compression"))
         this .draco = await this .createDraco ();

      this .bufferViewsArray (glTF .bufferViews);
      this .accessorsArray   (glTF .accessors);
      this .samplersArray    (glTF .samplers);

      await this .imagesArray (glTF .images);

      this .texturesArray   (glTF .textures);
      this .materialsArray  (glTF .materials);
      this .meshesArray     (glTF .meshes);
      this .camerasArray    (glTF .cameras);
      this .skinsArray      (glTF .skins);
      this .nodesArray      (glTF .nodes);
      this .scenesArray     (glTF .scenes, glTF .scene);
      this .animationsArray (glTF .animations);

      try
      {
         this .optimizeSceneGraph (this .getExecutionContext () .getRootNodes ());
      }
      catch (error)
      {
         console .error (error)
      }

      return this .getScene ();
   },
   assetObject (asset)
   {
      if (!(asset instanceof Object))
         return;

      const
         scene         = this .getExecutionContext (),
         worldURL      = scene .getWorldURL (),
         worldInfoNode = scene .createNode ("WorldInfo", false);

      for (const [key, value] of Object .entries (asset))
      {
         if (typeof value !== "string")
            continue;

         worldInfoNode ._info .push (`${key}: ${value}`);
      }

      if (asset .extras instanceof Object)
      {
         for (const [key, value] of Object .entries (asset .extras))
         {
            if (typeof value !== "string")
               continue;

            if (key === "title")
               worldInfoNode ._title = value;
            else
               worldInfoNode ._info .push (`${key}: ${value}`);
         }
      }

      worldInfoNode ._info .sort ();

      if (!worldInfoNode ._title .getValue ())
         worldInfoNode ._title = decodeURI (new URL (worldURL) .pathname .split ("/") .at (-1) || worldURL);

      worldInfoNode .setup ();

      scene .getRootNodes () .push (worldInfoNode);
   },
   extensionsArray (extensions, set)
   {
      if (!(extensions instanceof Array))
         return;

      const
         browser = this .getBrowser (),
         scene   = this .getExecutionContext ();

      for (const extension of extensions)
      {
         set .add (extension);

         switch (extension)
         {
            case "KHR_texture_transform":
            {
               const component = browser .getComponent ("Texturing3D", 2);

               if (!scene .hasComponent (component))
                  scene .addComponent (component);

               break;
            }
         }
      }
   },
   extensionsObject (extensions)
   {
      if (!(extensions instanceof Object))
         return;

      for (const [key, value] of Object .entries (extensions))
      {
         switch (key)
         {
            case "KHR_lights_punctual":
               return this .khrLightsPunctualObject (value);
         }
      }
   },
   khrLightsPunctualObject (KHR_lights_punctual)
   {
      if (!(KHR_lights_punctual instanceof Object))
         return;

      this .lightsArray (KHR_lights_punctual .lights);
   },
   lightsArray (lights)
   {
      if (!(lights instanceof Array))
         return;

      this .lights = lights;
   },
   lightObject (light)
   {
      if (!(light instanceof Object))
         return null;

      const lightNode = this .lightType (light);

      if (!lightNode)
         return null;

      const
         scene = this .getExecutionContext (),
         name  = this .sanitizeName (light .name);

      const color = new Numbers_Color3 (1, 1, 1);

      if (this .vectorValue (light .color, color))
         lightNode ._color = color;

      lightNode ._global    = true;
      lightNode ._intensity = this .numberValue (light .intensity, 1);

      lightNode .setup ();

      if (name)
      {
         scene .addNamedNode    (scene .getUniqueName       (name), lightNode);
         scene .addExportedNode (scene .getUniqueExportName (name), lightNode);
      }

      return lightNode;
   },
   lightType (light)
   {
      switch (light .type)
      {
         case "directional":
            return this .directionalLight (light);
         case "spot":
            return this .spotLight (light);
         case "point":
            return this .pointLight (light);
      }
   },
   directionalLight (light)
   {
      const
         scene     = this .getExecutionContext (),
         lightNode = scene .createNode ("DirectionalLight", false);

      return lightNode;
   },
   spotLight (light)
   {
      const
         scene     = this .getExecutionContext (),
         lightNode = scene .createNode ("SpotLight", false);

      lightNode ._radius      = this .numberValue (light .range, 0) || -1;
      lightNode ._cutOffAngle = this .numberValue (light .outerConeAngle, Math .PI / 4);
      lightNode ._beamWidth   = this .numberValue (light .innerConeAngle, 0);

      return lightNode;
   },
   pointLight (light)
   {
      const
         scene     = this .getExecutionContext (),
         lightNode = scene .createNode ("PointLight", false);

      lightNode ._radius = this .numberValue (light .range, 0) || -1;

      return lightNode;
   },
   buffersArray: async function (buffers)
   {
      if (!(buffers instanceof Array))
         return;

      this .buffers = await Promise .all (buffers .map ((buffer, i) => this .bufferObject (buffer, i)));
   },
   bufferObject: async function (buffer, i)
   {
      if (!(buffer instanceof Object))
         return;

      if (!buffer .uri)
         return this .buffers [i];

      const
         url         = new URL (buffer .uri, this .getExecutionContext () .getBaseURL ()),
         response    = await fetch (url),
         blob        = await response .blob (),
         arrayBuffer = await blob .arrayBuffer ();

      return GLTF2Parser_$.ungzip (arrayBuffer);
   },
   bufferViewsArray (bufferViews)
   {
      if (!(bufferViews instanceof Array))
         return;

      this .bufferViews = bufferViews;

      for (const bufferView of bufferViews)
         bufferView .buffer = this .bufferViewObject (bufferView);
   },
   bufferViewObject (bufferView)
   {
      if (!(bufferView instanceof Object))
         return;

      const buffer = this .buffers [bufferView .buffer];

      if (!buffer)
         return;

      const
         byteOffset = bufferView .byteOffset || 0,
         byteLength = bufferView .byteLength;

      return buffer .slice (byteOffset, byteOffset + byteLength);
   },
   accessorsArray (accessors)
   {
      if (!(accessors instanceof Array))
         return;

      this .accessors = accessors;

      for (const accessor of accessors)
         this .accessorObject (accessor);
   },
   accessorObject: (() =>
   {
      const TypedArrays = new Map ([
         [5120, Int8Array],
         [5121, Uint8Array],
         [5122, Int16Array],
         [5123, Uint16Array],
         [5124, Int32Array],
         [5125, Uint32Array],
         [5126, Float32Array],
      ]);

      const Components = new Map ([
         ["SCALAR", 1],
         ["VEC2",   2],
         ["VEC3",   3],
         ["VEC4",   4],
         ["MAT2",   4],
         ["MAT3",   9],
         ["MAT4",   16],
      ]);

      return function (accessor)
      {
         if (!(accessor instanceof Object))
            return;

         Object .defineProperty (accessor, "array",
         {
            get: () =>
            {
               const
                  TypedArray = TypedArrays .get (accessor .componentType),
                  bufferView = this .bufferViews [accessor .bufferView || 0],
                  byteOffset = accessor .byteOffset || 0,
                  byteStride = bufferView .byteStride || 0,
                  components = Components .get (accessor .type),
                  count      = accessor .count || 0,
                  stride     = byteStride ? byteStride / TypedArray .BYTES_PER_ELEMENT : components,
                  length     = Math .min (stride * count, (bufferView .byteLength - byteOffset) / TypedArray .BYTES_PER_ELEMENT),
                  array      = new TypedArray (bufferView .buffer, byteOffset, length);

               if (stride === components)
               {
                  const value = this .sparseObject (accessor .sparse, array, components);

                  Object .defineProperty (accessor, "array", { value: value });

                  return value;
               }
               else
               {
                  const
                     length = count * components,
                     dense  = new TypedArray (length);

                  for (let i = 0, j = 0; i < length; j += stride)
                  {
                     for (let c = 0; c < components; ++ c, ++ i)
                        dense [i] = array [j + c];
                  }

                  const value = this .sparseObject (accessor .sparse, dense, components);

                  Object .defineProperty (accessor, "array", { value: value });

                  return value;
               }
            },
            configurable: true,
         });

         Object .defineProperty (accessor, "normalizedArray",
         {
            get: () =>
            {
               switch (accessor .componentType)
               {
                  case 5120: // Int8Array
                     var value = Float32Array .from (accessor .array, v => Math .max (v / 127, -1));
                     break;
                  case 5121: // Uint8Array
                     var value = Float32Array .from (accessor .array, v => v / 255);
                     break;
                  case 5122: // Int16Array
                     var value = Float32Array .from (accessor .array, v => Math .max (v / 32767, -1));
                     break;
                  case 5123: // Uint16Array
                     var value = Float32Array .from (accessor .array, v => v / 65535);
                     break;
                  case 5124: // Int32Array
                     var value = Float32Array .from (accessor .array, v => Math .max (v / 2147483647, -1));
                     break;
                  case 5125: // Uint32Array
                     var value = Float32Array .from (accessor .array, v => v / 4294967295);
                     break;
                  case 5126: // Float32Array
                     var value = accessor .array;
                     break;
               }

               Object .defineProperty (accessor, "normalizedArray", { value: value });

               return value;
            },
            configurable: true,
         });
      };
   })(),
   sparseObject: (() =>
   {
      const TypedArrays = new Map ([
         [5121, Uint8Array],
         [5123, Uint16Array],
         [5125, Uint32Array],
      ]);

      return function (sparse, array, components)
      {
         if (!(sparse instanceof Object))
            return array;

         if (!(sparse .indices instanceof Object))
            return array;

         if (!(sparse .values instanceof Object))
            return array;

         const
            IndicesTypedArray = TypedArrays .get (sparse .indices .componentType),
            indicesBufferView = this .bufferViews [sparse .indices .bufferView],
            indicesByteOffset = sparse .indices .byteOffset,
            indices           = new IndicesTypedArray (indicesBufferView .buffer, indicesByteOffset, sparse .count);

         const
            ValuesTypedArray = array .constructor,
            valuesBufferView = this .bufferViews [sparse .values .bufferView],
            valuesByteOffset = sparse .values .byteOffset,
            values           = new ValuesTypedArray (valuesBufferView .buffer, valuesByteOffset, sparse .count * components);

         array = array .slice ();

         let v = 0;

         for (const i of indices)
         {
            for (let c = 0; c < components; ++ c, ++ v)
               array [i * components + c] = values [v];
         }

         return array;
      };
   })(),
   samplersArray (samplers)
   {
      if (!(samplers instanceof Array))
         return;

      this .samplers = samplers;

      for (const sampler of samplers)
         this .samplerObject (sampler);
   },
   samplerObject: (() =>
   {
      const MinificationFilters = new Map ([
         [9728, ["NEAREST_PIXEL",                false]],
         [9729, ["AVG_PIXEL",                    false]],
         [9984, ["NEAREST_PIXEL_NEAREST_MIPMAP", true]],
         [9985, ["AVG_PIXEL_NEAREST_MIPMAP",     true]],
         [9986, ["NEAREST_PIXEL_AVG_MIPMAP",     true]],
         [9987, ["AVG_PIXEL_AVG_MIPMAP",         true]],
      ]);

      const MagnificationFilters = new Map ([
         [9728, "NEAREST_PIXEL"],
         [9729, "AVG_PIXEL"],
      ]);

	   const BoundaryModes = new Map ([
         [33071, "CLAMP_TO_EDGE"],
         [33648, "MIRRORED_REPEAT"],
         [10497, "REPEAT"],
      ]);

      return function (sampler)
      {
         if (!(sampler instanceof Object))
            return;

         Object .defineProperty (sampler, "texturePropertiesNode",
         {
            get: () =>
            {
               const
                  scene                 = this .getExecutionContext (),
                  texturePropertiesNode = scene .createNode ("TextureProperties", false),
                  name                  = this .sanitizeName (sampler .name);

               if (name)
               {
                  scene .addNamedNode    (scene .getUniqueName       (name), texturePropertiesNode);
                  scene .addExportedNode (scene .getUniqueExportName (name), texturePropertiesNode);
               }

               // minFilter

               const minificationFilter = MinificationFilters .get (sampler .minFilter) ?? ["AVG_PIXEL", false];

               texturePropertiesNode ._minificationFilter = minificationFilter [0];
               texturePropertiesNode ._generateMipMaps    = minificationFilter [1];

               // magFilter

               texturePropertiesNode ._magnificationFilter = MagnificationFilters .get (sampler .magFilter) ?? "AVG_PIXEL";

               // boundaryMode

               texturePropertiesNode ._boundaryModeS = BoundaryModes .get (sampler .wrapS) ?? "REPEAT";
               texturePropertiesNode ._boundaryModeT = BoundaryModes .get (sampler .wrapT) ?? "REPEAT";

               // setup

               texturePropertiesNode .setup ();

               Object .defineProperty (sampler, "texturePropertiesNode", { value: texturePropertiesNode });

               return texturePropertiesNode;
            },
            configurable: true,
         });
      };
   })(),
   imagesArray: async function (images)
   {
      if (!(images instanceof Array))
         return;

      this .images = await Promise .all (images .map (image => this .imageObject (image)));
   },
   imageObject: async function (image)
   {
      if (!(image instanceof Object))
         return;

      if (image .uri)
         return image;

      const bufferView = this .bufferViews [image .bufferView];

      if (!bufferView)
         return image;

      const
         buffer = bufferView .buffer,
         blob   = new Blob ([new Uint8Array (buffer)], { type: image .mimeType }),
         uri    = await this .blobToDataUrl (blob);

      image .uri = uri;

      return image;
   },
   blobToDataUrl (blob)
   {
      return new Promise ((resolve, reject) =>
      {
         const fileReader = new FileReader ();

         fileReader .onload  = resolve;
         fileReader .onerror = reject;

         fileReader .readAsDataURL (blob);
      })
      .then (event => event .target .result);
   },
   texturesArray (textures)
   {
      if (!(textures instanceof Array))
         return;

      this .textures = textures;
   },
   textureObject (texture)
   {
      if (!(texture instanceof Object))
         return;

      const images = this .textureImageObject (texture);

      if (!images .length)
         return null;

      if (texture .textureNode)
         return texture .textureNode;

      const
         scene       = this .getExecutionContext (),
         textureNode = scene .createNode ("ImageTexture", false),
         name        = this .sanitizeName (texture .name || images [0] .name);

      if (name)
      {
         scene .addNamedNode    (scene .getUniqueName       (name), textureNode);
         scene .addExportedNode (scene .getUniqueExportName (name), textureNode);
      }

      textureNode ._url                  = images .map (image => image .uri);
      textureNode ._colorSpaceConversion = false;

      const sampler = this .samplers [texture .sampler];

      if (sampler instanceof Object)
         textureNode ._textureProperties = sampler .texturePropertiesNode;

      textureNode .setup ();

      return texture .textureNode = textureNode;
   },
   textureImageObject (texture)
   {
      const images = [this .images [texture .source]];

      if (this .extensions .has ("EXT_texture_webp"))
         images .unshift (this .images [texture .extensions ?.EXT_texture_webp ?.source]);

      return images .filter (image => image);
   },
   materialsArray (materials)
   {
      if (!(materials instanceof Array))
         return;

      this .materials = materials;
   },
   materialObject ({ material, mode = 4 })
   {
      if (!(material instanceof Object))
         return this .getDefaultAppearance (mode);

      if (material .appearanceNode)
         return material .appearanceNode;

      const texCoordIndices = this .texCoordIndices ("", material);

      this .texCoordIndex         = Array .from (texCoordIndices) .reduce (Math .max, -1);
      this .textureTransformNodes = [ ];
      this .texCoordMappings      = new Map ();
      material .texCoordMappings  = this .texCoordMappings;

      const
         scene          = this .getExecutionContext (),
         appearanceNode = scene .createNode ("Appearance", false),
         materialNode   = this .refineMaterial (mode, this .createMaterial (material, mode)),
         name           = this .sanitizeName (material .name);

      const emissiveFactor = new Numbers_Color3 (0, 0, 0);

      if (this .vectorValue (material .emissiveFactor, emissiveFactor))
         materialNode ._emissiveColor = emissiveFactor;

      materialNode ._emissiveTexture        = this .textureInfo    (material .emissiveTexture);
      materialNode ._emissiveTextureMapping = this .textureMapping (material .emissiveTexture);

      this .occlusionTextureInfo (material .occlusionTexture, materialNode);
      this .normalTextureInfo    (material .normalTexture,    materialNode);
      this .materialExtensions   (material .extensions,       materialNode);

      materialNode .setup ();

      for (const i of texCoordIndices)
      {
         const mapping = `TEXCOORD_${i}`;

         if (this .textureTransformNodes .length)
         {
            const textureTransformNode = scene .createNode ("TextureTransform", false);

            textureTransformNode ._mapping        = mapping;
            textureTransformNode ._translation .y = -1;
            textureTransformNode ._scale .y       = -1;

            textureTransformNode .setup ();

            this .textureTransformNodes .push (textureTransformNode);
         }

         this .texCoordMappings .set (mapping, i);
      }

      if (name)
      {
         scene .addNamedNode    (scene .getUniqueName       (name), appearanceNode);
         scene .addExportedNode (scene .getUniqueExportName (name), appearanceNode);
      }

      appearanceNode ._alphaMode        = this .stringValue (material .alphaMode, "OPAQUE");
      appearanceNode ._alphaCutoff      = this .numberValue (material .alphaCutoff, 0.5);
      appearanceNode ._material         = materialNode;
      appearanceNode ._textureTransform = this .createMultiTextureTransform (materialNode);

      appearanceNode .setup ();

      return material .appearanceNode = appearanceNode;
   },
   refineMaterial (mode, materialNode)
   {
      if (mode > 3)
         return materialNode

      switch (materialNode .getTypeName ())
      {
         default:
         {
            return materialNode;
         }
         case "Material":
         {
            const
               scene             = this .getExecutionContext (),
               unlitMaterialNode = scene .createNode ("UnlitMaterial", false);

            unlitMaterialNode ._emissiveColor          = materialNode ._diffuseColor;
            unlitMaterialNode ._emissiveTextureMapping = materialNode ._diffuseTextureMapping;
            unlitMaterialNode ._emissiveTexture        = materialNode ._diffuseTexture;

            materialNode .dispose ();

            return unlitMaterialNode;
         }
         case "PhysicalMaterial":
         {
            const
               scene             = this .getExecutionContext (),
               unlitMaterialNode = scene .createNode ("UnlitMaterial", false);

            unlitMaterialNode ._emissiveColor          = materialNode ._baseColor;
            unlitMaterialNode ._emissiveTextureMapping = materialNode ._baseTextureMapping;
            unlitMaterialNode ._emissiveTexture        = materialNode ._baseTexture;

            materialNode .dispose ();

            return unlitMaterialNode;
         }
      }
   },
   texCoordIndices (key, object, indices = new Set ())
   {
      if (!(object instanceof Object))
         return indices;

      if (key .endsWith ("Texture") && !object ?.extensions ?.KHR_texture_transform)
         indices .add (object .texCoord || 0);

      for (const [key, value] of Object .entries (object))
         this .texCoordIndices (key, value, indices);

      return indices;
   },
   createMaterial (material, mode)
   {
      const materials = [
         this .pbrMetallicRoughnessObject  .bind (this, material .pbrMetallicRoughness),
         this .pbrSpecularGlossinessObject .bind (this, material .extensions ?.KHR_materials_pbrSpecularGlossiness),
         this .pbrMetallicRoughnessObject  .bind (this, { }),
      ];

      for (const material of materials)
      {
         const materialNode = material (mode);

         if (materialNode)
            return materialNode;
      }
   },
   pbrMetallicRoughnessObject (pbrMetallicRoughness, mode)
   {
      if (!(pbrMetallicRoughness instanceof Object))
         return null;

      const
         scene        = this .getExecutionContext (),
         materialNode = scene .createNode ("PhysicalMaterial", false);

      const
         baseColorFactor = new Numbers_Color4 (0, 0, 0, 0),
         baseColor       = new Numbers_Color3 (0, 0, 0);

      if (this .vectorValue (pbrMetallicRoughness .baseColorFactor, baseColorFactor))
      {
         materialNode ._baseColor    = baseColor .set (... baseColorFactor);
         materialNode ._transparency = 1 - baseColorFactor .a;
      }

      materialNode ._metallic  = this .numberValue (pbrMetallicRoughness .metallicFactor,  1);
      materialNode ._roughness = this .numberValue (pbrMetallicRoughness .roughnessFactor, 1);

      materialNode ._baseTexture                     = this .textureInfo    (pbrMetallicRoughness .baseColorTexture);
      materialNode ._baseTextureMapping              = this .textureMapping (pbrMetallicRoughness .baseColorTexture);
      materialNode ._metallicRoughnessTexture        = this .textureInfo    (pbrMetallicRoughness .metallicRoughnessTexture);
      materialNode ._metallicRoughnessTextureMapping = this .textureMapping (pbrMetallicRoughness .metallicRoughnessTexture);

      return materialNode;
   },
   pbrSpecularGlossinessObject (pbrSpecularGlossiness)
   {
      if (!(pbrSpecularGlossiness instanceof Object))
         return null;

      const
         scene        = this .getExecutionContext (),
         materialNode = scene .createNode ("Material", false);

      const
         diffuseFactor  = new Numbers_Color4 (0, 0, 0, 0),
         diffuseColor   = new Numbers_Color3 (0, 0, 0),
         specularFactor = new Numbers_Color3 (0, 0, 0);

      if (this .vectorValue (pbrSpecularGlossiness .diffuseFactor, diffuseFactor))
      {
         materialNode ._diffuseColor = diffuseColor .set (... diffuseFactor);
         materialNode ._transparency = 1 - diffuseFactor .a;
      }
      else
      {
         materialNode ._diffuseColor = Numbers_Color3 .White;
      }

      if (this .vectorValue (pbrSpecularGlossiness .specularFactor, specularFactor))
         materialNode ._specularColor = specularFactor;
      else
         materialNode ._specularColor = Numbers_Color3 .White;

      materialNode ._shininess = this .numberValue (pbrSpecularGlossiness .glossinessFactor, 1);

      materialNode ._diffuseTexture          = this .textureInfo    (pbrSpecularGlossiness .diffuseTexture);
      materialNode ._diffuseTextureMapping   = this .textureMapping (pbrSpecularGlossiness .diffuseTexture);
      materialNode ._specularTexture         = this .textureInfo    (pbrSpecularGlossiness .specularGlossinessTexture);
      materialNode ._specularTextureMapping  = this .textureMapping (pbrSpecularGlossiness .specularGlossinessTexture);
      materialNode ._shininessTexture        = this .textureInfo    (pbrSpecularGlossiness .specularGlossinessTexture);
      materialNode ._shininessTextureMapping = this .textureMapping (pbrSpecularGlossiness .specularGlossinessTexture);

      return materialNode;
   },
   occlusionTextureInfo (occlusionTexture, materialNode)
   {
      if (!(occlusionTexture instanceof Object))
         return null;

      materialNode ._occlusionStrength       = this .numberValue (occlusionTexture .strength, 1);
      materialNode ._occlusionTexture        = this .textureInfo (occlusionTexture);
      materialNode ._occlusionTextureMapping = this .textureMapping (occlusionTexture);
   },
   normalTextureInfo (normalTexture, materialNode)
   {
      if (!(normalTexture instanceof Object))
         return null;

      materialNode ._normalScale          = this .numberValue (normalTexture .scale, 1);
      materialNode ._normalTexture        = this .textureInfo (normalTexture);
      materialNode ._normalTextureMapping = this .textureMapping (normalTexture);
   },
   textureInfo (texture)
   {
      if (!(texture instanceof Object))
         return null;

      if (texture .extensions instanceof Object)
         texture .mapping = this .textureTransformObject (texture .extensions .KHR_texture_transform, texture .texCoord || 0);
      else
         texture .mapping = `TEXCOORD_${texture .texCoord || 0}`;

      return this .textureObject (this .textures [texture .index]);
   },
   textureMapping (texture)
   {
      if (!(texture instanceof Object))
         return "";

      return texture .mapping;
   },
   materialExtensions (extensions, materialNode)
   {
      if (!(extensions instanceof Object))
         return;

      for (const [key, value] of Object .entries (extensions))
      {
         switch (key)
         {
            case "KHR_materials_unlit":
               this .khrMaterialsUnlitObject (materialNode);
               break;
            case "KHR_materials_emissive_strength":
               this .khrMaterialsEmissiveStrengthObject (value, materialNode);
               break;
         }
      }
   },
   khrMaterialsUnlitObject (materialNode)
   {
      switch (materialNode .getTypeName ())
      {
         case "PhysicalMaterial":
         {
            materialNode ._emissiveColor          = materialNode ._baseColor;
            materialNode ._emissiveTextureMapping = materialNode ._baseTextureMapping;
            materialNode ._emissiveTexture        = materialNode ._baseTexture;
            materialNode ._baseColor              = Numbers_Color3 .Black;
            materialNode ._baseTextureMapping     = "";
            materialNode ._baseTexture            = null;
            break;
         }
         case "Material":
         {
            materialNode ._emissiveColor          = materialNode ._diffuseColor;
            materialNode ._emissiveTextureMapping = materialNode ._diffuseTextureMapping;
            materialNode ._emissiveTexture        = materialNode ._diffuseTexture;
            materialNode ._diffuseColor           = Numbers_Color3 .Black;
            materialNode ._diffuseTextureMapping  = "";
            materialNode ._diffuseTexture         = null;
            break;
         }
      }
   },
   khrMaterialsEmissiveStrengthObject (KHR_materials_emissive_strength, materialNode)
   {
      if (!(KHR_materials_emissive_strength instanceof Object))
         return;

      const emissiveStrength = this .numberValue (KHR_materials_emissive_strength .emissiveStrength, 1);

      materialNode ._emissiveColor .r *= emissiveStrength;
      materialNode ._emissiveColor .g *= emissiveStrength;
      materialNode ._emissiveColor .b *= emissiveStrength;
   },
   textureTransformObject (KHR_texture_transform, texCoord)
   {
      if (!(KHR_texture_transform instanceof Object))
         return;

      if (!this .extensions .has ("KHR_texture_transform"))
         return;

      const
         scene                = this .getExecutionContext (),
         textureTransformNode = scene .createNode ("TextureTransformMatrix3D", false),
         mapping              = `TEXCOORD_${this .texCoordIndex + this .textureTransformNodes .length + 1}`;

      const
         translation = new Numbers_Vector2 (0, 0),
         scale       = new Numbers_Vector2 (1, 1),
         matrix      = new Numbers_Matrix4 ();

      matrix .scale (new Numbers_Vector3 (1, -1, 1));
      matrix .translate (new Numbers_Vector3 (0, -1, 0));

      if (this .vectorValue (KHR_texture_transform .offset, translation))
         matrix .translate (new Numbers_Vector3 (... translation, 0));

      matrix .rotate (new Numbers_Rotation4 (0, 0, -1, this .numberValue (KHR_texture_transform .rotation, 0)));

      if (this .vectorValue (KHR_texture_transform .scale, scale))
         matrix .scale (new Numbers_Vector3 (... scale, 1));

      textureTransformNode ._mapping = mapping;
      textureTransformNode ._matrix  = matrix;

      textureTransformNode .setup ();

      this .textureTransformNodes .push (textureTransformNode);
      this .texCoordMappings .set (mapping, KHR_texture_transform .texCoord ?? texCoord);

      return mapping;
   },
   meshesArray (meshes)
   {
      if (!(meshes instanceof Array))
         return;

      this .meshes = meshes;
   },
   meshObject (mesh, skin)
   {
      if (!(mesh instanceof Object))
         return;

      if (mesh .shapeNodes)
      {
         const primitives = mesh .primitives;

         if (!(primitives instanceof Array))
            return mesh .shapeNodes;

         for (const primitive of primitives)
            this .attributesJointsArray (skin, primitive .attributes ?.JOINTS, primitive .attributes ?.WEIGHTS);

         return mesh .shapeNodes;
      }

      const shapeNodes = this .primitivesArray (mesh, skin);

      // Name Shape nodes.

      const
         scene = this .getExecutionContext (),
         name  = this .sanitizeName (mesh .name);

      if (name)
      {
         for (const shapeNode of shapeNodes)
         {
            scene .addNamedNode    (scene .getUniqueName       (name), shapeNode);
            scene .addExportedNode (scene .getUniqueExportName (name), shapeNode);
         }
      }

      return mesh .shapeNodes = shapeNodes;
   },
   primitivesArray ({ primitives, weights }, skin)
   {
      if (!(primitives instanceof Array))
         return [ ];

      const shapeNodes = [ ];

      for (const primitive of primitives)
         this .primitiveObject (primitive, weights, skin, shapeNodes);

      return shapeNodes;
   },
   primitiveObject (primitive, weights, skin, shapeNodes)
   {
      if (!(primitive instanceof Object))
         return;

      this .attributesObject (primitive .attributes);
      this .targetsArray     (primitive .targets);

      primitive .indices  = this .accessors [primitive .indices];
      primitive .material = this .materials [primitive .material];

      this .primitiveExtensionsObject (primitive .extensions, primitive)

      shapeNodes .push (primitive .shapeNode = this .createShape (primitive, weights, skin));
   },
   attributesObject (attributes)
   {
      if (!(attributes instanceof Object))
         return;

      for (const key in attributes)
         attributes [key] = this .accessors [attributes [key]];

      attributes .TEXCOORD = [ ];
      attributes .COLOR    = [ ];
      attributes .JOINTS   = [ ];
      attributes .WEIGHTS  = [ ];

      for (let i = 0; attributes ["TEXCOORD_" + i]; ++ i)
         attributes .TEXCOORD .push (attributes ["TEXCOORD_" + i]);

      for (let i = 0; attributes ["COLOR_" + i]; ++ i)
         attributes .COLOR .push (attributes ["COLOR_" + i]);

      for (let i = 0; attributes ["JOINTS_" + i]; ++ i)
         attributes .JOINTS .push (attributes ["JOINTS_" + i]);

      for (let i = 0; attributes ["WEIGHTS_" + i]; ++ i)
         attributes .WEIGHTS .push (attributes ["WEIGHTS_" + i]);
   },
   targetsArray (targets)
   {
      if (!(targets instanceof Array))
         return;
   },
   primitiveExtensionsObject (extensions, primitive)
   {
      if (!(extensions instanceof Object))
         return;

      for (const [key, value] of Object .entries (extensions))
      {
         switch (key)
         {
            case "KHR_draco_mesh_compression":
               return this .khrDracoMeshCompressionObject (value, primitive);
         }
      }
   },
   khrDracoMeshCompressionObject (draco, primitive)
   {
      if (!(draco instanceof Object))
         return;

      if (!this .draco)
         return;

      function indicesCallback (array)
      {
         Object .defineProperty (primitive .indices, "array", { value: array });
      }

      function attributeCallback (key, array)
      {
         if (attributes [key])
            Object .defineProperty (attributes [key], "array", { value: array });
      }

      const
         attributes = primitive .attributes,
         dataView   = new Uint8Array (this .bufferViews [draco .bufferView] .buffer);

      this .dracoDecodeMesh (this .draco, dataView, draco .attributes, indicesCallback, attributeCallback);
   },
   dracoDecodeMesh (draco, dataView, attributes, indicesCallback, attributeCallback)
   {
      const
         buffer  = new draco .DecoderBuffer (),
         decoder = new draco .Decoder ();

      buffer .Init (dataView, dataView .byteLength);

      let geometry, status;

      try
      {
         const type = decoder .GetEncodedGeometryType (buffer);

         switch (type)
         {
            case draco .TRIANGULAR_MESH:
               geometry = new draco .Mesh ();
               status   = decoder .DecodeBufferToMesh (buffer, geometry);
               break;
            case draco .POINT_CLOUD:
               geometry = new draco .PointCloud ();
               status   = decoder .DecodeBufferToPointCloud (buffer, geometry);
               break;
            default:
               throw new Error (`Invalid geometry type ${type}.`);
         }

         if (!status .ok () || !geometry .ptr)
            throw new Error (status .error_msg ());

         if (type === draco .TRIANGULAR_MESH)
         {
            const
               numFaces   = geometry .num_faces (),
               numIndices = numFaces * 3,
               byteLength = numIndices * 4,
               ptr        = draco ._malloc (byteLength);

            try
            {
               const indices = new Uint32Array (numIndices);

               decoder .GetTrianglesUInt32Array (geometry, byteLength, ptr);

               indices .set (new Uint32Array (draco .HEAPF32 .buffer, ptr, numIndices));

               indicesCallback (indices);
            }
            finally
            {
               draco ._free (ptr);
            }
         }

         for (const [key, id] of Object .entries (attributes))
         {
            const
               attribute     = decoder .GetAttributeByUniqueId (geometry, id),
               numComponents = attribute .num_components (),
               numPoints     = geometry .num_points (),
               numValues     = numPoints * numComponents,
               byteLength    = numValues * Float32Array .BYTES_PER_ELEMENT,
               ptr           = draco ._malloc (byteLength);

            try
            {
               const array = new Float32Array (numValues);

               decoder .GetAttributeDataArrayForAllPoints (geometry, attribute, draco .DT_FLOAT32, byteLength, ptr);

               array .set (new Float32Array (draco .HEAPF32 .buffer, ptr, numValues));

               attributeCallback (key, array);
            }
            finally
            {
               draco ._free (ptr);
            }
         }
      }
      finally
      {
         if (geometry)
            draco .destroy (geometry);

         draco .destroy (decoder);
         draco .destroy (buffer);
      }
   },
   createDraco: async function ()
   {
      if (this .constructor .draco)
      {
         return this .constructor .draco;
      }
      else
      {
         const
            response = await fetch (Networking_URLs .getLibraryURL ("draco_decoder_gltf.js")),
            text     = await response .text (),
            draco    = await new Function (text) () ();

         return this .constructor .draco = draco;
      }
   },
   camerasArray (cameras)
   {
      if (!(cameras instanceof Array))
         return;

      this .cameras = cameras;
   },
   cameraObject (camera)
   {
      if (!(camera instanceof Object))
         return null;

      if (camera .viewpointNode !== undefined)
         return camera .viewpointNode;

      const viewpointNode = this .cameraType (camera);

      if (!viewpointNode)
         return camera .viewpointNode = null;

      const
         scene = this .getExecutionContext (),
         name  = this .sanitizeName (camera .name);

      // Name

      if (name)
      {
         scene .addNamedNode    (scene .getUniqueName       (name), viewpointNode);
         scene .addExportedNode (scene .getUniqueExportName (name), viewpointNode);
      }

      viewpointNode ._description      = camera .name ? this .description (camera .name) : `Viewpoint ${++ this .viewpoints}`;
      viewpointNode ._position         = Numbers_Vector3 .Zero;
      viewpointNode ._centerOfRotation = new Numbers_Vector3 (0, 0, -10);

      return camera .viewpointNode = viewpointNode;
   },
   cameraType (camera)
   {
      switch (camera .type)
      {
         case "orthographic":
            return this .orthographicCamera (camera .orthographic);
         case "perspective":
            return this .perspectiveCamera (camera .perspective);
         default:
            return null;
      }
   },
   orthographicCamera (camera)
   {
      const
         scene         = this .getExecutionContext (),
         viewpointNode = scene .createNode ("OrthoViewpoint", false);

      if (typeof camera .xmag === "number")
      {
         viewpointNode ._fieldOfView [0] = -camera .xmag / 2;
         viewpointNode ._fieldOfView [2] = +camera .xmag / 2;
      }

      if (typeof camera .ymag === "number")
      {
         viewpointNode ._fieldOfView [1] = -camera .ymag / 2;
         viewpointNode ._fieldOfView [3] = +camera .ymag / 2;
      }

      if (typeof camera .znear === "number")
         viewpointNode ._nearDistance = camera .znear;

      if (typeof camera .zfar === "number")
         viewpointNode ._farDistance = camera .zfar;

      viewpointNode .setup ();

      return viewpointNode;
   },
   perspectiveCamera (camera)
   {
      const
         scene         = this .getExecutionContext (),
         viewpointNode = scene .createNode ("Viewpoint", false);

      if (typeof camera .yfov === "number")
         viewpointNode ._fieldOfView = camera .yfov

      if (typeof camera .znear === "number")
         viewpointNode ._nearDistance = camera .znear;

      if (typeof camera .zfar === "number")
         viewpointNode ._farDistance = camera .zfar;

      viewpointNode .setup ();

      return viewpointNode;
   },
   nodesArray (nodes)
   {
      if (!(nodes instanceof Array))
         return;

      this .nodes = nodes .map ((node, index) => this .nodeObject (node, index));

      // 1. Replace skeleton nodes with humanoid.
      // 2. Add children.

      this .nodes .forEach (node => this .nodeSkeleton (node));
      this .nodes .forEach (node => this .nodeChildren (node));
   },
   nodeObject (node, index)
   {
      if (!(node instanceof Object))
         return { };

      if (node .transformNode)
         return node;

      // Create Transform or HAnimJoint.

      const
         scene         = this .getExecutionContext (),
         typeName      = this .joints .has (index) ? "HAnimJoint" : "Transform",
         transformNode = scene .createNode (typeName, false);

      node .transformNode = transformNode;

      // Create humanoid.

      const skin = this .skins [node .skin];

      if (skin)
      {
         // Skins can be cloned.

         if (!skin .humanoidNode)
            skin .humanoidNode = scene .createNode ("HAnimHumanoid", false);

         node .humanoidNode = skin .humanoidNode;
      }

      node .childNode = node .humanoidNode ?? node .transformNode;

      return node;
   },
   nodeSkeleton (node)
   {
      const skin = this .skins [node .skin];

      if (!skin)
         return;

      const
         skeleton     = this .nodes [skin .skeleton],
         humanoidNode = skin .humanoidNode;

      if (!skeleton)
         return;

      skeleton .humanoidNode = humanoidNode;
      skeleton .childNode    = humanoidNode;
   },
   nodeChildren (node)
   {
      const
         scene         = this .getExecutionContext (),
         transformNode = node .transformNode,
         name          = this .sanitizeName (node .name);

      // Name

      if (name)
      {
         scene .addNamedNode    (scene .getUniqueName       (name), transformNode);
         scene .addExportedNode (scene .getUniqueExportName (name), transformNode);

         if (transformNode .getTypeName () === "HAnimJoint")
            transformNode ._name = node .name;
      }

      // Set transformation matrix.

      const
         translation      = new Numbers_Vector3 (0, 0, 0),
         rotation         = new Numbers_Rotation4 (),
         scale            = new Numbers_Vector3 (1, 1, 1),
         scaleOrientation = new Numbers_Rotation4 (),
         quaternion       = new Numbers_Quaternion (0, 0, 0, 1),
         matrix           = new Numbers_Matrix4 ();

      if (this .vectorValue (node .matrix, matrix))
      {
         matrix .get (translation, rotation, scale, scaleOrientation);

         transformNode ._translation      = translation;
         transformNode ._rotation         = rotation;
         transformNode ._scale            = scale;
         transformNode ._scaleOrientation = scaleOrientation;
      }
      else
      {
         if (this .vectorValue (node .translation, translation))
            transformNode ._translation = translation;

         if (this .vectorValue (node .rotation, quaternion))
            transformNode ._rotation = new Numbers_Rotation4 (quaternion);

         if (this .vectorValue (node .scale, scale))
            transformNode ._scale = scale;
      }

      // Add mesh.

      const
         skin       = this .skins [node .skin],
         shapeNodes = this .meshObject (this .meshes [node .mesh], skin);

      // Add camera.

      const viewpointNode = this .cameraObject (this .cameras [node .camera]);

      if (viewpointNode)
         transformNode ._children .push (viewpointNode);

      // Add light.

      this .nodeLight (node .extensions ?.KHR_lights_punctual, transformNode);

      // Add children.

      transformNode ._children .push (... this .nodeChildrenArray (node .children));

      // Add Shape nodes.

      if (shapeNodes)
         transformNode ._children .push (... this .meshInstancing (node .extensions ?.EXT_mesh_gpu_instancing, shapeNodes));

      transformNode .setup ();

      // Skin

      if (!skin)
         return;

      const humanoidNode = skin .humanoidNode;

      if (!humanoidNode .isInitialized ())
      {
         const name = this .sanitizeName (skin .name) || transformNode .getName ();

         if (name)
         {
            scene .addNamedNode    (scene .getUniqueName       (name), humanoidNode);
            scene .addExportedNode (scene .getUniqueExportName (name), humanoidNode);
         }

         humanoidNode ._name                  = skin .name ?? node .name ?? "";
         humanoidNode ._version               = "2.0";
         humanoidNode ._skeletalConfiguration = "GLTF";

         const skeletonNode = this .nodes [skin .skeleton] ?.transformNode;

         if (skeletonNode)
            humanoidNode ._skeleton .push (skeletonNode);

         for (const [i, joint] of skin .joints .entries ())
         {
            const
               jointNode         = this .nodes [joint] ?.transformNode,
               inverseBindMatrix = skin .inverseBindMatrices [i] ?? Numbers_Matrix4 .Identity;

            if (!jointNode)
               continue;

            inverseBindMatrix .get (translation, rotation, scale);

            humanoidNode ._joints                .push (jointNode);
            humanoidNode ._jointBindingPositions .push (translation);
            humanoidNode ._jointBindingRotations .push (rotation);
            humanoidNode ._jointBindingScales    .push (scale);
         }

         humanoidNode .setup ();
      }

      if (shapeNodes ?.length)
      {
         humanoidNode ._skinNormal = shapeNodes [0] ._geometry .normal;
         humanoidNode ._skinCoord  = shapeNodes [0] ._geometry .coord;
      }

      humanoidNode ._skin .push (transformNode);
   },
   nodeLight (KHR_lights_punctual, transformNode)
   {
      if (!(KHR_lights_punctual instanceof Object))
         return;

      const lightNode = this .lightObject (this .lights [KHR_lights_punctual .light]);

      if (!lightNode)
         return;

      ++ this .usedLights;

      transformNode ._children .push (lightNode);
   },
   meshInstancing (EXT_mesh_gpu_instancing, shapeNodes)
   {
      if (!(EXT_mesh_gpu_instancing instanceof Object))
         return shapeNodes;

      let
         attributes  = EXT_mesh_gpu_instancing .attributes,
         translation = this .accessors [attributes ?.TRANSLATION],
         rotation    = this .accessors [attributes ?.ROTATION],
         scale       = this .accessors [attributes ?.SCALE],
         count       = Math .max (translation ?.count ?? 0, rotation ?.count ?? 0, scale ?.count ?? 0);

      if (!count)
         return shapeNodes;

      if (translation ?.type !== "VEC3")
         translation = null;

      if (rotation ?.type !== "VEC4")
         rotation = null;

      if (scale ?.type !== "VEC3")
         scale = null;

      const
         scene          = this .getScene (),
         transformNodes = [ ],
         tArray         = translation ?.array,
         rArray         = rotation ?.normalizedArray,
         sArray         = scale ?.array;

      for (let i = 0; i < count; ++ i)
      {
         const transformNode = scene .createNode ("Transform", false);

         if (translation && i < translation .count)
         {
            transformNode ._translation = new Numbers_Vector3 (tArray [i * 3 + 0],
                                                       tArray [i * 3 + 1],
                                                       tArray [i * 3 + 2]);
         }

         if (rotation && i < rotation .count)
         {
            transformNode ._rotation = new Numbers_Rotation4 (new Numbers_Quaternion (rArray [i * 4 + 0],
                                                                      rArray [i * 4 + 1],
                                                                      rArray [i * 4 + 2],
                                                                      rArray [i * 4 + 3]));
         }

         if (scale && i < scale .count)
         {
            transformNode ._scale = new Numbers_Vector3 (sArray [i * 3 + 0],
                                                 sArray [i * 3 + 1],
                                                 sArray [i * 3 + 2]);
         }

         transformNode ._children = shapeNodes;

         transformNode .setup ();
         transformNodes .push (transformNode);
      }

      return transformNodes;
   },
   nodeChildrenArray (children)
   {
      if (!(children instanceof Array))
         return [ ];

      const nodes = Array .from (new Set (children
         .map (index => this .nodes [index] ?.childNode)
         .filter (node => node)
         .filter (node => node .getTypeName () !== "HAnimHumanoid" || !node .getCloneCount ())
      ));

      return nodes;
   },
   skinsArray (skins)
   {
      if (!(skins instanceof Array))
         return;

      this .skins = skins;

      for (const skin of skins)
         this .skinObject (skin);
   },
   skinObject: function (skin)
   {
      if (!(skin instanceof Object))
         return;

      const scene = this .getScene ();

      skin .joints              = this .jointsArray (skin .joints);
      skin .skeleton            = skin .skeleton ?? this .skeleton (skin .joints);
      skin .inverseBindMatrices = this .inverseBindMatricesAccessors (this .accessors [skin .inverseBindMatrices]);

      skin .textureCoordinateNode      = scene .createNode ("TextureCoordinate",      false);
      skin .multiTextureCoordinateNode = scene .createNode ("MultiTextureCoordinate", false);
      skin .normalNode                 = scene .createNode ("Normal",                 false);
      skin .coordinateNode             = scene .createNode ("Coordinate",             false);

      skin .textureCoordinateNode ._mapping = "TEXCOORD_0";

      skin .textureCoordinateNode      .setup ();
      skin .multiTextureCoordinateNode .setup ();
      skin .normalNode                 .setup ();
      skin .coordinateNode             .setup ();
   },
   jointsArray: function (joints)
   {
      if (!(joints instanceof Array))
         return [ ];

      joints .forEach (index => this .joints .add (index));

      return joints;
   },
   skeleton: function (joints)
   {
      const children = new Set (joints
         .map (index => this .nodes [index])
         .filter (node => node instanceof Object)
         .filter (node => node .children instanceof Array)
         .flatMap (node => node .children));

      return joints .filter (index => !children .has (index)) [0];
   },
   inverseBindMatricesAccessors: function (inverseBindMatrices)
   {
      if (!inverseBindMatrices)
         return [ ];

      const
         array    = inverseBindMatrices .array,
         length   = array .length,
         matrices = [ ];

      for (let i = 0; i < length; i += 16)
         matrices .push (new Numbers_Matrix4 (... array .subarray (i, i + 16)));

      return matrices;
   },
   scenesArray (scenes, sceneNumber = 0)
   {
      if (!(scenes instanceof Array))
         return;

      const
         scene    = this .getExecutionContext (),
         children = scenes .map (scene => this .sceneObject (scene)) .filter (node => node);

      switch (children .length)
      {
         case 0:
         {
            return;
         }
         case 1:
         {
            if (sceneNumber === 0)
            {
               if (this .usedLights)
                  scene .getRootNodes () .push (this .createNavigationInfo ());

               scene .getRootNodes () .push (children [0]);
               return;
            }

            // Proceed with next case:
         }
         default:
         {
            // Root

            if (this .usedLights)
               scene .getRootNodes () .push (this .createNavigationInfo ());

            const switchNode = scene .createNode ("Switch", false);

            scene .addNamedNode    (scene .getUniqueName       ("Scenes"), switchNode);
            scene .addExportedNode (scene .getUniqueExportName ("Scenes"), switchNode);

            // Scenes.

            switchNode ._whichChoice = sceneNumber;
            switchNode ._children    = children;

            switchNode .setup ();

            scene .getRootNodes () .push (switchNode);
            return;
         }
      }
   },
   sceneObject (scene)
   {
      if (!(scene instanceof Object))
         return null;

      const nodes = this .sceneNodesArray (scene .nodes);

      switch (nodes .length)
      {
         case 0:
         {
            return null;
         }
         case 1:
         {
            return nodes [0];
         }
         default:
         {
            const
               scene     = this .getExecutionContext (),
               groupNode = scene .createNode ("Group", false),
               name      = this .sanitizeName (scene .name);

            if (name)
            {
               scene .addNamedNode    (scene .getUniqueName       (name), groupNode);
               scene .addExportedNode (scene .getUniqueExportName (name), groupNode);
            }

            groupNode ._children = nodes;

            groupNode .setup ();

            return groupNode;
         }
      }
   },
   sceneNodesArray (nodes)
   {
      return this .nodeChildrenArray (nodes);
   },
   animationsArray (animations)
   {
      if (!(animations instanceof Array))
         return;

      const animationNodes = animations
         .map (animation => this .animationObject (animation))
         .filter (node => node);

      if (!animationNodes .length)
         return;

      const
         scene     = this .getExecutionContext (),
         groupNode = scene .createNode ("Group", false);

      scene .addNamedNode    (scene .getUniqueName       ("Animations"), groupNode);
      scene .addExportedNode (scene .getUniqueExportName ("Animations"), groupNode);

      groupNode ._children = animationNodes;

      groupNode .setup ();

      scene .getRootNodes () .push (groupNode);
   },
   animationObject (animation)
   {
      if (!(animation instanceof Object))
         return null;

      const
         scene          = this .getExecutionContext (),
         timeSensorNode = scene .createNode ("TimeSensor", false),
         channelNodes   = this .animationChannelsArray (animation .channels, animation .samplers, timeSensorNode);

      if (!channelNodes .length)
         return null;

      const
         groupNode = scene .createNode ("Group", false),
         name      = this .sanitizeName (animation .name);

      ++ this .animations;

      scene .addNamedNode (scene .getUniqueName (name || `Animation${this .animations}`), groupNode);
      scene .addNamedNode (scene .getUniqueName (`Timer${this .animations}`), timeSensorNode);
      scene .addExportedNode (scene .getUniqueExportName (name || `Animation${this .animations}`), groupNode);
      scene .addExportedNode (scene .getUniqueExportName (`Timer${this .animations}`), timeSensorNode);

      timeSensorNode ._description = this .description (animation .name) || `Animation ${this .animations}`;
      groupNode ._children .push (timeSensorNode, ... channelNodes);

      timeSensorNode .setup ();
      groupNode .setup ();

      return groupNode;
   },
   animationChannelsArray (channels, samplers, timeSensorNode)
   {
      if (!(channels instanceof Array))
         return [ ];

      if (!(samplers instanceof Array))
         return [ ];

      const cycleInterval = samplers
         .map (sampler => this .accessors [sampler .input])
         .filter (input => input ?.array .length)
         .reduce ((value, input) => Math .max (value, input .array .at (-1)), 0);

      timeSensorNode ._cycleInterval = cycleInterval;

      return channels
         .flatMap (channel => this .animationChannelObject (channel, samplers, timeSensorNode));
   },
   animationChannelObject (channel, samplers, timeSensorNode)
   {
      if (!(channel instanceof Object))
         return [ ];

      const target = channel .target;

      if (!(target instanceof Object))
         return [ ];

      const node = this .nodes [target .node] ?.transformNode;

      if (!node)
         return [ ];

      const sampler = samplers [channel .sampler];

      if (!sampler)
         return [ ];

      const input = this .accessors [sampler .input];

      if (!input)
         return [ ];

      if (!input .array .length)
         return [ ];

      const output = this .accessors [sampler .output];

      if (!output)
         return [ ];

      if (!output .array .length)
         return [ ];

      return this .createInterpolator (timeSensorNode, node, target, sampler .interpolation, input .array, output, timeSensorNode ._cycleInterval .getValue ());
   },
   createNavigationInfo ()
   {
      const
         scene              = this .getExecutionContext (),
         navigationInfoNode = scene .createNode ("NavigationInfo", false);

      navigationInfoNode ._headlight = false;

      navigationInfoNode .setup ();

      return navigationInfoNode;
   },
   createShape (primitive, weights, skin)
   {
      const
         scene          = this .getExecutionContext (),
         shapeNode      = scene .createNode ("Shape", false),
         appearanceNode = this .materialObject (primitive),
         geometryNode   = this .createGeometry (primitive, weights, skin);

      shapeNode ._appearance = appearanceNode;
      shapeNode ._geometry   = geometryNode;

      shapeNode .setup ();

      return shapeNode;
   },
   getDefaultAppearance (mode)
   {
      mode = mode > 3;

      if (this .defaultAppearance [mode])
         return this .defaultAppearance [mode];

      const
         scene          = this .getExecutionContext (),
         appearanceNode = scene .createNode ("Appearance", false),
         materialNode   = scene .createNode (mode ? "PhysicalMaterial" : "UnlitMaterial", false);

      appearanceNode ._alphaMode = "OPAQUE";
      appearanceNode ._material  = materialNode;

      materialNode   .setup ();
      appearanceNode .setup ();

      return this .defaultAppearance [mode] = appearanceNode;
   },
   createMultiTextureTransform (materialNode)
   {
      if (!+materialNode .getTextureBits ())
         return null;

      const textureTransformNodes = this .textureTransformNodes
         .sort ((a, b) => Math_Algorithm .cmp (a ._mapping .getValue (), b ._mapping .getValue ()));

      switch (textureTransformNodes .length)
      {
         case 0:
         {
            if (this .textureTransformNode)
               return this .textureTransformNode;

            const
               scene                = this .getExecutionContext (),
               textureTransformNode = scene .createNode ("TextureTransform", false);

            textureTransformNode ._translation .y = -1;
            textureTransformNode ._scale .y       = -1;

            textureTransformNode .setup ();

            return this .textureTransformNode = textureTransformNode;
         }
         case 1:
         {
            return textureTransformNodes [0];
         }
         default:
         {
            const
               scene                = this .getExecutionContext (),
               textureTransformNode = scene .createNode ("MultiTextureTransform", false);

            textureTransformNode ._textureTransform = textureTransformNodes;

            textureTransformNode .setup ();

            return textureTransformNode;
         }
      }
   },
   createGeometry (primitive, weights, skin)
   {
      switch (primitive .mode)
      {
         case 0: // POINTS
         {
            return this .createPointSet (primitive, weights, skin);
         }
         case 1: // LINES
         {
            if (primitive .indices)
               return this .createIndexedLineSet (primitive, weights, skin, 1);

            return this .createLineSet (primitive, weights, skin);
         }
         case 2: // LINE_LOOP
         {
            return this .createIndexedLineSet (primitive, weights, skin, 2);
         }
         case 3: // LINE_STRIP
         {
            return this .createIndexedLineSet (primitive, weights, skin, 3);
         }
         default:
         case 4: // TRIANGLES
         {
            if (primitive .indices)
               return this .createIndexedTriangleSet (primitive, weights, skin);

            return this .createTriangleSet (primitive, weights, skin);
         }
         case 5: // TRIANGLE_STRIP
         {
            if (primitive .indices)
               return this .createIndexedTriangleStripSet (primitive, weights, skin);

            return this .createTriangleStripSet (primitive, weights, skin);
         }
         case 6: // TRIANGLE_FAN
         {
            if (primitive .indices)
               return this .createIndexedTriangleFanSet (primitive, weights, skin);

            return this .createTriangleFanSet (primitive, weights, skin);
         }
      }
   },
   createPointSet ({ attributes, material, targets }, weights, skin)
   {
      const
         scene        = this .getExecutionContext (),
         geometryNode = scene .createNode ("PointSet", false);

      geometryNode ._color  = this .createColor (attributes .COLOR [0], material);
      geometryNode ._normal = this .createNormal (attributes .NORMAL, targets, weights);
      geometryNode ._coord  = this .createCoordinate (attributes .POSITION, targets, weights);

      this .attributesJointsArray (skin, attributes .JOINTS, attributes .WEIGHTS);
      this .skinGeometry (skin, geometryNode);

      geometryNode .setup ();

      return geometryNode;
   },
   createIndexedLineSet ({ attributes, indices, material, targets }, weights, skin, mode)
   {
      const
         scene        = this .getExecutionContext (),
         geometryNode = scene .createNode ("IndexedLineSet", false);

      geometryNode ._color  = this .createColor (attributes .COLOR [0], material);
      geometryNode ._normal = this .createNormal (attributes .NORMAL, targets, weights);
      geometryNode ._coord  = this .createCoordinate (attributes .POSITION, targets, weights);

      switch (mode)
      {
         case 1: // LINES
         {
            const
               coordIndex = geometryNode ._coordIndex,
               array      = indices .array,
               length     = array .length;

            for (let i = 0; i < length; i += 2)
               coordIndex .push (array [i], array [i + 1], -1);

            break;
         }
         case 2: // LINE_LOOP
         {
            const coordIndex = geometryNode ._coordIndex;

            if (indices)
            {
               for (const i of indices .array)
                  coordIndex .push (i);

               if (coordIndex .length)
                  coordIndex .push (coordIndex [0], -1);
            }
            else
            {
               const coord = geometryNode ._coord;

               if (coord ?.point .length)
               {
                  for (const i of coord .point .keys ())
                     coordIndex .push (i);

                  coordIndex .push (0, -1);
               }
            }

            break;
         }
         case 3: // LINE_STRIP
         {
            const coordIndex = geometryNode ._coordIndex;

            if (indices)
            {
               for (const i of indices .array)
                  coordIndex .push (i);

               if (coordIndex .length)
                  coordIndex .push (-1);
            }
            else
            {
               const coord = geometryNode ._coord;

               if (coord ?.point .length)
               {
                  for (const i of coord .point .keys ())
                     coordIndex .push (i);

                  coordIndex .push (-1);
               }
            }

            break;
         }
      }

      this .attributesJointsArray (skin, attributes .JOINTS, attributes .WEIGHTS);
      this .skinGeometry (skin, geometryNode);

      geometryNode .setup ();

      return geometryNode;
   },
   createLineSet ({ attributes, material, targets }, weights, skin)
   {
      const
         scene        = this .getExecutionContext (),
         geometryNode = scene .createNode ("LineSet", false);

      geometryNode ._color  = this .createColor (attributes .COLOR [0], material);
      geometryNode ._normal = this .createNormal (attributes .NORMAL, targets, weights);
      geometryNode ._coord  = this .createCoordinate (attributes .POSITION, targets, weights);

      this .attributesJointsArray (skin, attributes .JOINTS, attributes .WEIGHTS);
      this .skinGeometry (skin, geometryNode);

      geometryNode .setup ();

      return geometryNode;
   },
   createIndexedTriangleSet ({ attributes, indices, material, targets }, weights, skin)
   {
      const
         scene        = this .getExecutionContext (),
         geometryNode = scene .createNode ("IndexedTriangleSet", false);

      geometryNode ._solid           = !material ?.doubleSided;
      geometryNode ._index           = indices .array;
      geometryNode ._color           = this .createColor (attributes .COLOR [0], material);
      geometryNode ._texCoord        = this .createMultiTextureCoordinate (attributes .TEXCOORD, material);
      geometryNode ._normal          = this .createNormal (attributes .NORMAL, targets, weights);
      geometryNode ._coord           = this .createCoordinate (attributes .POSITION, targets, weights);
      geometryNode ._normalPerVertex = !! geometryNode ._normal .getValue ();

      this .attributesJointsArray (skin, attributes .JOINTS, attributes .WEIGHTS);
      this .skinGeometry (skin, geometryNode);

      geometryNode .setup ();

      return geometryNode;
   },
   createTriangleSet ({ attributes, material, targets }, weights, skin)
   {
      const
         scene        = this .getExecutionContext (),
         geometryNode = scene .createNode ("TriangleSet", false);

      geometryNode ._solid           = !material ?.doubleSided;
      geometryNode ._color           = this .createColor (attributes .COLOR [0], material);
      geometryNode ._texCoord        = this .createMultiTextureCoordinate (attributes .TEXCOORD, material);
      geometryNode ._normal          = this .createNormal (attributes .NORMAL, targets, weights);
      geometryNode ._coord           = this .createCoordinate (attributes .POSITION, targets, weights);
      geometryNode ._normalPerVertex = !! geometryNode ._normal .getValue ();

      this .attributesJointsArray (skin, attributes .JOINTS, attributes .WEIGHTS);
      this .skinGeometry (skin, geometryNode);

      geometryNode .setup ();

      return geometryNode;
   },
   createIndexedTriangleStripSet ({ attributes, indices, material, targets }, weights, skin)
   {
      const
         scene        = this .getExecutionContext (),
         geometryNode = scene .createNode ("IndexedTriangleStripSet", false);

      geometryNode ._solid           = !material ?.doubleSided;
      geometryNode ._index           = indices .array;
      geometryNode ._color           = this .createColor (attributes .COLOR [0], material);
      geometryNode ._texCoord        = this .createMultiTextureCoordinate (attributes .TEXCOORD, material);
      geometryNode ._normal          = this .createNormal (attributes .NORMAL, targets, weights);
      geometryNode ._coord           = this .createCoordinate (attributes .POSITION, targets, weights);
      geometryNode ._normalPerVertex = !! geometryNode ._normal .getValue ();

      this .attributesJointsArray (skin, attributes .JOINTS, attributes .WEIGHTS);
      this .skinGeometry (skin, geometryNode);

      geometryNode .setup ();

      return geometryNode;
   },
   createTriangleStripSet ({ attributes, material, targets }, weights, skin)
   {
      const
         scene        = this .getExecutionContext (),
         geometryNode = scene .createNode ("TriangleStripSet", false);

      geometryNode ._solid           = !material ?.doubleSided;
      geometryNode ._color           = this .createColor (attributes .COLOR [0], material);
      geometryNode ._texCoord        = this .createMultiTextureCoordinate (attributes .TEXCOORD, material);
      geometryNode ._normal          = this .createNormal (attributes .NORMAL, targets, weights);
      geometryNode ._coord           = this .createCoordinate (attributes .POSITION, targets, weights);
      geometryNode ._normalPerVertex = !! geometryNode ._normal .getValue ();

      const coord = geometryNode ._coord;

      if (coord)
      {
         if (coord .point .length)
            geometryNode ._stripCount = [coord .point .length];
      }

      this .attributesJointsArray (skin, attributes .JOINTS, attributes .WEIGHTS);
      this .skinGeometry (skin, geometryNode);

      geometryNode .setup ();

      return geometryNode;
   },
   createIndexedTriangleFanSet ({ attributes, indices, material, targets }, weights, skin)
   {
      const
         scene        = this .getExecutionContext (),
         geometryNode = scene .createNode ("IndexedTriangleFanSet", false);

      geometryNode ._solid           = !material ?.doubleSided;
      geometryNode ._index           = indices .array;
      geometryNode ._color           = this .createColor (attributes .COLOR [0], material);
      geometryNode ._texCoord        = this .createMultiTextureCoordinate (attributes .TEXCOORD, material);
      geometryNode ._normal          = this .createNormal (attributes .NORMAL, targets, weights);
      geometryNode ._coord           = this .createCoordinate (attributes .POSITION, targets, weights);
      geometryNode ._normalPerVertex = !! geometryNode ._normal .getValue ();

      this .attributesJointsArray (skin, attributes .JOINTS, attributes .WEIGHTS);
      this .skinGeometry (skin, geometryNode);

      geometryNode .setup ();

      return geometryNode;
   },
   createTriangleFanSet ({ attributes, material, targets }, weights, skin)
   {
      const
         scene        = this .getExecutionContext (),
         geometryNode = scene .createNode ("TriangleFanSet", false);

      geometryNode ._solid           = !material ?.doubleSided;
      geometryNode ._color           = this .createColor (attributes .COLOR [0], material);
      geometryNode ._texCoord        = this .createMultiTextureCoordinate (attributes .TEXCOORD, material);
      geometryNode ._normal          = this .createNormal (attributes .NORMAL, targets, weights);
      geometryNode ._coord           = this .createCoordinate (attributes .POSITION, targets, weights);
      geometryNode ._normalPerVertex = !! geometryNode ._normal .getValue ();

      const coord = geometryNode ._coord;

      if (coord)
      {
         if (coord .point .length)
            geometryNode ._fanCount = [coord .point .length];
      }

      this .attributesJointsArray (skin, attributes .JOINTS, attributes .WEIGHTS);
      this .skinGeometry (skin, geometryNode);

      geometryNode .setup ();

      return geometryNode;
   },
   createColor: (() =>
   {
      const TypeNames = new Map ([
         ["VEC3", "Color"],
         ["VEC4", "ColorRGBA"],
      ]);

      return function (color, material)
      {
         if (!(color instanceof Object))
            return null;

         const typeName = TypeNames .get (color .type);

         if (!typeName)
            return null;

         if (color .colorNode)
            return color .colorNode;

         const
            scene          = this .getExecutionContext (),
            appearanceNode = this .materialObject ({ material }),
            opaque         = appearanceNode ._alphaMode .getValue () === "OPAQUE",
            colorNode      = scene .createNode (opaque ? "Color" : typeName, false);

         colorNode ._color = opaque && typeName !== "Color"
            ? color .normalizedArray .filter ((_, i) => (i + 1) % 4)
            : color .normalizedArray;

         colorNode .setup ();

         return color .colorNode = colorNode;
      };
   })(),
   createMultiTextureCoordinate (texCoords, material)
   {
      const appearanceNode = this .materialObject ({ material });

      if (!+appearanceNode ._material .getValue () .getTextureBits ())
         return null;

      if (texCoords .textureCoordinateNode)
         return texCoords .textureCoordinateNode;

      switch (material .texCoordMappings .size)
      {
         case 0:
         {
            return null;
         }
         case 1:
         {
            return texCoords .textureCoordinateNode = Array .from (material .texCoordMappings .entries (), ([mapping, i]) => this .createTextureCoordinate (texCoords [i], mapping)) [0];
         }
         default:
         {
            const textureCoordinateNodes = Array .from (material .texCoordMappings .entries (), ([mapping, i]) => this .createTextureCoordinate (texCoords [i], mapping))
               .filter (node => node)
               .sort ((a, b) => Math_Algorithm .cmp (a ._mapping .getValue (), b ._mapping .getValue ()));

            if (!textureCoordinateNodes .length)
               return null;

            const
               scene                 = this .getExecutionContext (),
               textureCoordinateNode = scene .createNode ("MultiTextureCoordinate", false);

            textureCoordinateNode ._texCoord = textureCoordinateNodes;

            textureCoordinateNode .setup ();

            return texCoords .textureCoordinateNode = textureCoordinateNode;
         }
      }
   },
   createTextureCoordinate (texCoord, mapping)
   {
      if (texCoord ?.type !== "VEC2")
         return null;

      if (texCoord [mapping])
         return texCoord [mapping];

      const
         scene                 = this .getExecutionContext (),
         textureCoordinateNode = scene .createNode ("TextureCoordinate", false);

      textureCoordinateNode ._mapping = mapping;
      textureCoordinateNode ._point   = texCoord .normalizedArray;

      textureCoordinateNode .setup ();

      return texCoord [mapping] = textureCoordinateNode;
   },
   createNormal (normal, targets, weights)
   {
      if (normal ?.type !== "VEC3")
         return null;

      if (normal .normalNode)
         return normal .normalNode;

      const
         scene      = this .getExecutionContext (),
         normalNode = scene .createNode ("Normal", false);

      normalNode ._vector = normal .normalizedArray;

      if ((targets instanceof Array) && (weights instanceof Array))
      {
         normal .field = normalNode ._vector .copy ();

         const vectors = this .applyMorphTargets (normalNode ._vector, targets, "NORMAL", weights);

         normalNode ._vector .length = 0;

         for (const vector of vectors)
            normalNode ._vector .push (vector);
      }
      else
      {
         normal .field = normalNode ._vector;
      }

      normalNode .setup ();

      return normal .normalNode = normalNode;
   },
   createCoordinate (position, targets, weights)
   {
      if (position ?.type !== "VEC3")
         return null;

      if (position .coordinateNode)
         return position .coordinateNode;

      const
         scene          = this .getExecutionContext (),
         coordinateNode = scene .createNode ("Coordinate", false);

      coordinateNode ._point = position .array;

      if ((targets instanceof Array) && (weights instanceof Array))
      {
         position .field = coordinateNode ._point .copy ();

         const points = this .applyMorphTargets (coordinateNode ._point, targets, "POSITION", weights);

         coordinateNode ._point .length = 0;

         for (const point of points)
            coordinateNode ._point .push (point);
      }
      else
      {
         position .field = coordinateNode ._point;
      }

      coordinateNode .setup ();

      return position .coordinateNode = coordinateNode;
   },
   attributesJointsArray: function (skin, joints, weights)
   {
      if (!(skin instanceof Object))
         return;

      if (!(joints instanceof Array))
         return;

      if (!(weights instanceof Array))
         return;

      for (let i = 0, length = joints .length; i < length; ++ i)
         this .attributesJointsObject (skin, joints [i], weights [i]);
   },
   attributesJointsObject: function (skin, joints, weights)
   {
      if (joints ?.type !== "VEC4")
         return;

      if (weights ?.type !== "VEC4")
         return;

      const
         start        = skin .coordinateNode ._point .length,
         jointsArray  = joints .array,
         weightsArray = weights .normalizedArray,
         numVertices  = jointsArray .length / 4;

      for (let v = 0; v < numVertices; ++ v)
      {
         for (let i = 0; i < 4; ++ i)
         {
            const w = weightsArray [v * 4 + i];

            if (w === 0)
               continue;

            const
               index     = skin .joints [jointsArray [v * 4 + i]],
               jointNode = this .nodes [index] ?.transformNode;

            if (!jointNode)
               continue;

            jointNode ._skinCoordIndex  .push (v + start);
            jointNode ._skinCoordWeight .push (w);
         }
      }
   },
   skinGeometry: function (skin, geometryNode)
   {
      if (!(skin instanceof Object))
         return;

      const
         skinCoordinateNode    = skin .coordinateNode,
         start                 = skinCoordinateNode ._point .length,
         textureCoordinateNode = geometryNode ._texCoord ?.getValue (),
         normalNode            = geometryNode ._normal ?.getValue (),
         coordinateNode        = geometryNode ._coord ?.getValue ();

      if (geometryNode ._coordIndex)
         geometryNode ._coordIndex = geometryNode ._coordIndex .map (index => index < 0 ? -1 : index + start);

      if (geometryNode ._index)
         geometryNode ._index = geometryNode ._index .map (index => index < 0 ? -1 : index + start);

      if (textureCoordinateNode)
      {
         switch (textureCoordinateNode .getTypeName ())
         {
            case "TextureCoordinate":
            {
               const
                  skinTextureCoordinateNode = skin .textureCoordinateNode,
                  point                     = skinTextureCoordinateNode ._point;

               textureCoordinateNode ._point .forEach ((p, i) => point [i + start] = p);
               geometryNode ._texCoord = skinTextureCoordinateNode;

               break;
            }
            case "MultiTextureCoordinate":
            {
               const skinMultiTextureCoordinateNode = skin .multiTextureCoordinateNode;

               for (const t of textureCoordinateNode ._texCoord)
               {
                  let s = skinMultiTextureCoordinateNode ._texCoord .find (s => s .mapping === t .mapping) ?.getValue ();

                  if (!s)
                  {
                     if (t .mapping === "TEXCOORD_0")
                     {
                        s = skin .textureCoordinateNode;
                     }
                     else
                     {
                        s           = this .getScene () .createNode ("TextureCoordinate", false);
                        s ._mapping = t .mapping;

                        s .setup ();
                     }

                     skinMultiTextureCoordinateNode ._texCoord .push (s);
                  }

                  const point = s ._point;

                  t .point .forEach ((p, i) => point [i + start] = p);
               }

               geometryNode ._texCoord = skinMultiTextureCoordinateNode;
               break;
            }
         }
      }

      if (normalNode)
      {
         const
            skinNormalNode = skin .normalNode,
            vector         = skinNormalNode ._vector;

         normalNode ._vector .forEach ((v, i) => vector [i + start] = v);
         geometryNode ._normal = skinNormalNode;
      }

      if (coordinateNode)
      {
         const point = skinCoordinateNode ._point;
         coordinateNode ._point .forEach ((p, i) => point [i + start] = p);
         geometryNode ._coord = skinCoordinateNode;
      }
   },
   createInterpolator (timeSensorNode, node, target, interpolation, times, keyValues, cycleInterval)
   {
      const scene = this .getExecutionContext ();

      switch (target .path)
      {
         case "translation":
         {
            const interpolatorNode = this .createPositionInterpolator (interpolation, times, keyValues .array, cycleInterval);

            scene .addNamedNode (scene .getUniqueName ("TranslationInterpolator"), interpolatorNode);

            scene .addRoute (timeSensorNode, "fraction_changed", interpolatorNode, "set_fraction");
            scene .addRoute (interpolatorNode, "value_changed", node, "set_translation");

            return interpolatorNode;
         }
         case "rotation":
         {
            const interpolatorNode = this .createOrientationInterpolator (interpolation, times, keyValues .normalizedArray, cycleInterval);

            scene .addNamedNode (scene .getUniqueName ("RotationInterpolator"), interpolatorNode);

            scene .addRoute (timeSensorNode, "fraction_changed", interpolatorNode, "set_fraction");
            scene .addRoute (interpolatorNode, "value_changed", node, "set_rotation");

            return interpolatorNode;
         }
         case "scale":
         {
            const interpolatorNode = this .createPositionInterpolator (interpolation, times, keyValues .array, cycleInterval);

            scene .addNamedNode (scene .getUniqueName ("ScaleInterpolator"), interpolatorNode);

            scene .addRoute (timeSensorNode, "fraction_changed", interpolatorNode, "set_fraction");
            scene .addRoute (interpolatorNode, "value_changed", node, "set_scale");

            return interpolatorNode;
         }
         case "weights":
         {
            const
               node              = this .nodes [target .node],
               mesh              = this .meshes [node .mesh],
               primitives        = mesh ?.primitives,
               interpolatorNodes = [ ];

            if (!(primitives instanceof Array))
               return null;

            for (const { shapeNode, targets, attributes } of primitives)
            {
               const geometryNode = shapeNode ._geometry .getValue ();

               if (!geometryNode)
                  continue;

               const coordinateInterpolatorNode = this .createArrayInterpolator ("CoordinateInterpolator", interpolation, times, keyValues .normalizedArray, cycleInterval, targets, attributes, "POSITION", false);

               if (coordinateInterpolatorNode)
               {
                  interpolatorNodes .push (coordinateInterpolatorNode);

                  scene .addRoute (timeSensorNode, "fraction_changed", coordinateInterpolatorNode, "set_fraction");
                  scene .addRoute (coordinateInterpolatorNode, "value_changed", geometryNode ._coord, "set_point");
               }

               const normalInterpolatorNode = this .createArrayInterpolator ("NormalInterpolator", interpolation, times, keyValues .normalizedArray, cycleInterval, targets, attributes, "NORMAL", true);

               if (normalInterpolatorNode)
               {
                  interpolatorNodes .push (normalInterpolatorNode);

                  scene .addRoute (timeSensorNode, "fraction_changed", normalInterpolatorNode, "set_fraction");
                  scene .addRoute (normalInterpolatorNode, "value_changed", geometryNode ._normal, "set_vector");
               }
            }

            return interpolatorNodes;
         }
         default:
         {
            return [ ];
         }
      }
   },
   createPositionInterpolator (interpolation, times, keyValues, cycleInterval)
   {
      const scene = this .getExecutionContext ();

      switch (interpolation)
      {
         case "STEP":
         {
            const interpolatorNode = scene .createNode ("PositionInterpolator", false);

            // Key

            interpolatorNode ._key .push (times [0] / cycleInterval);

            for (let i = 1, length = times .length; i < length; ++ i)
               interpolatorNode ._key .push (times [i] / cycleInterval, times [i] / cycleInterval);

            // KeyValue

            interpolatorNode ._keyValue .push (new Numbers_Vector3 (keyValues [0], keyValues [1], keyValues [2]));

            for (let i = 0, length = keyValues .length - 3; i < length; i += 3)
            {
               interpolatorNode ._keyValue .push (new Numbers_Vector3 (keyValues [i + 0], keyValues [i + 1], keyValues [i + 2]),
                                                  new Numbers_Vector3 (keyValues [i + 3], keyValues [i + 4], keyValues [i + 5]));
            }

            // Finish

            interpolatorNode .setup ();

            return interpolatorNode;
         }
         default:
         case "LINEAR":
         {
            const interpolatorNode = scene .createNode ("PositionInterpolator", false);

            interpolatorNode ._key      = times .map (t => t / cycleInterval);
            interpolatorNode ._keyValue = keyValues;

            interpolatorNode .setup ();

            return interpolatorNode;
         }
         case "CUBICSPLINE":
         {
            const
               interpolatorNode = scene .createNode ("PositionInterpolator", false),
               vectors          = [ ];

            for (let i = 0, length = keyValues .length; i < length; i += 3)
            {
               vectors .push (new Numbers_Vector3 (keyValues [i + 0],
                                           keyValues [i + 1],
                                           keyValues [i + 2]));
            }

            const
               length  = Math .floor (times .at (-1) * SAMPLES_PER_SECOND),
               samples = Array .from ({ length: length }, (_, i) => i / (length - 1) * times .at (-1))

            for (const t of samples)
            {
               interpolatorNode ._key      .push (t / cycleInterval);
               interpolatorNode ._keyValue .push (this .cubicSplineVector (t, times, vectors));
            }

            interpolatorNode .setup ();

            return interpolatorNode;
         }
      }
   },
   createOrientationInterpolator (interpolation, times, keyValues, cycleInterval)
   {
      const scene = this .getExecutionContext ();

      switch (interpolation)
      {
         case "STEP":
         {
            const interpolatorNode = scene .createNode ("OrientationInterpolator", false);

            // Key

            interpolatorNode ._key .push (times [0] / cycleInterval);

            for (let i = 1, length = times .length; i < length; ++ i)
               interpolatorNode ._key .push (times [i] / cycleInterval, times [i] / cycleInterval);

            // KeyValue

            interpolatorNode ._keyValue .push (new Numbers_Rotation4 (new Numbers_Quaternion (keyValues [0],
                                                                              keyValues [1],
                                                                              keyValues [2],
                                                                              keyValues [3])));

            for (let i = 0, length = keyValues .length - 4; i < length; i += 4)
            {
               interpolatorNode ._keyValue .push (new Numbers_Rotation4 (new Numbers_Quaternion (keyValues [i + 0],
                                                                                 keyValues [i + 1],
                                                                                 keyValues [i + 2],
                                                                                 keyValues [i + 3])),
                                                  new Numbers_Rotation4 (new Numbers_Quaternion (keyValues [i + 4],
                                                                                 keyValues [i + 5],
                                                                                 keyValues [i + 6],
                                                                                 keyValues [i + 7])));
            }

            // Finish

            interpolatorNode .setup ();

            return interpolatorNode;
         }
         default:
         case "LINEAR":
         {
            const interpolatorNode = scene .createNode ("OrientationInterpolator", false);

            interpolatorNode ._key = times .map (t => t / cycleInterval);

            for (let i = 0, length = keyValues .length; i < length; i += 4)
            {
               interpolatorNode ._keyValue .push (new Numbers_Rotation4 (new Numbers_Quaternion (keyValues [i + 0],
                                                                                 keyValues [i + 1],
                                                                                 keyValues [i + 2],
                                                                                 keyValues [i + 3])));
            }

            interpolatorNode .setup ();

            return interpolatorNode;
         }
         case "CUBICSPLINE":
         {
            const
               interpolatorNode = scene .createNode ("OrientationInterpolator", false),
               quaternions      = [ ];

            for (let i = 0, length = keyValues .length; i < length; i += 4)
            {
               quaternions .push (new Numbers_Quaternion (keyValues [i + 0],
                                                  keyValues [i + 1],
                                                  keyValues [i + 2],
                                                  keyValues [i + 3]));
            }

            const
               length  = Math .floor (times .at (-1) * SAMPLES_PER_SECOND),
               samples = Array .from ({ length: length }, (_, i) => i / (length - 1) * times .at (-1))

            for (const t of samples)
            {
               const q = this .cubicSplineVector (t, times, quaternions) .normalize ();

               interpolatorNode ._key      .push (t / cycleInterval);
               interpolatorNode ._keyValue .push (new Numbers_Rotation4 (q));
            }

            interpolatorNode .setup ();

            return interpolatorNode;
         }
      }
   },
   createArrayInterpolator (typeName, interpolation, times, weights, cycleInterval, targets, accessors, key, normalized)
   {
      const
         scene    = this .getExecutionContext (),
         accessor = accessors [key];

      if (!accessor)
         return null;

      switch (interpolation)
      {
         case "STEP":
         {
            const interpolatorNode = scene .createNode (typeName, false);

            // Key

            interpolatorNode ._key .push (times [0] / cycleInterval);

            for (let i = 1, length = times .length; i < length; ++ i)
               interpolatorNode ._key .push (times [i] / cycleInterval, times [i] / cycleInterval);

            // KeyValue

            const w = Array .from (targets .keys (), i => weights [i]);

            for (const value of this .applyMorphTargets (accessor .field, targets, key, w, normalized))
               interpolatorNode ._keyValue .push (value);

            for (let t = 1, length = times .length; t < length; ++ t)
            {
               const
                  w      = Array .from (targets .keys (), i => weights [t * targets .length + i]),
                  values = this .applyMorphTargets (accessor .field, targets, key, w, normalized);

               for (const value of values)
                  interpolatorNode ._keyValue .push (value);

               for (const value of values)
                  interpolatorNode ._keyValue .push (value);
            }

            // Finish

            interpolatorNode .setup ();

            return interpolatorNode;
         }
         default:
         case "LINEAR":
         {
            const interpolatorNode = scene .createNode (typeName, false);

            // Key

            interpolatorNode ._key = times .map (t => t / cycleInterval);

            // KeyValue

            for (const t of times .keys ())
            {
               const w = Array .from (targets .keys (), i => weights [t * targets .length + i]);

               for (const value of this .applyMorphTargets (accessor .field, targets, key, w, normalized))
                  interpolatorNode ._keyValue .push (value);
            }

            // Finish

            interpolatorNode .setup ();

            return interpolatorNode;
         }
         case "CUBICSPLINE":
         {
            const interpolatorNode = scene .createNode (typeName, false);

            // Key

            const
               length  = Math .floor (times .at (-1) * SAMPLES_PER_SECOND),
               samples = Array .from ({ length: length }, (_, i) => i / (length - 1) * times .at (-1))

            // KeyValue

            for (const t of samples)
            {
               interpolatorNode ._key .push (t / cycleInterval);

               const w = Array .from (targets .keys (), i => this .cubicSplineScalarArray (t, times, weights, targets .length, i));

               for (const value of this .applyMorphTargets (accessor .field, targets, key, w, normalized))
                  interpolatorNode ._keyValue .push (value);
            }

            // Finish

            interpolatorNode .setup ();

            return interpolatorNode;
         }
      }
   },
   applyMorphTargets: (function ()
   {
      const value = new Numbers_Vector3 (0, 0, 0);

      return function (array, targets, key, weights, normalized)
      {
         const vectors = Array .from (array, v => v .getValue () .copy ());

         for (const [i, target] of targets .entries ())
         {
            const weight = weights [i];

            if (!weight)
               continue;

            const accessor = this .accessors [target [key]];

            if (accessor ?.type !== "VEC3")
               continue;

            const
               array  = accessor [normalized ? "normalizedArray" : "array"],
               length = array .length;

            for (let a = 0, p = 0; a < length; a += 3, ++ p)
               vectors [p] .add (value .set (array [a], array [a + 1], array [a + 2]) .multiply (weight));
         }

         return vectors;
      };
   })(),
   cubicSplineVector (time, times, values)
   {
      const
         index1 = Math_Algorithm .clamp (Math_Algorithm .upperBound (times, 0, times .length, time), 1, times .length - 1),
         index0 = index1 - 1,
         td     = times [index1] - times [index0],
         t1     = (time - times [index0]) / td,
         t2     = t1 * t1,
         t3     = t2 * t1,
         v0     = values [index0 * 3 + 1] .copy (),
         b0     = values [index0 * 3 + 2] .copy (),
         v1     = values [index1 * 3 + 1] .copy (),
         a1     = values [index1 * 3 + 0] .copy ();

      v0 .multiply (2 * t3 - 3 * t2 + 1);
      b0 .multiply (td * (t3 - 2 * t2 + t1));
      v1 .multiply (-2 * t3 + 3 * t2);
      a1 .multiply (td * (t3 - t2));

      return v0 .add (b0) .add (v1) .add (a1);
   },
   cubicSplineScalarArray (time, times, values, length, i)
   {
      const
         index1 = Math_Algorithm .clamp (Math_Algorithm .upperBound (times, 0, times .length, time), 1, times .length - 1),
         index0 = index1 - 1,
         td     = times [index1] - times [index0],
         t1     = (time - times [index0]) / td,
         t2     = t1 * t1,
         t3     = t2 * t1,
         v0     = values [(index0 + 1) * length + i],
         b0     = values [(index0 + 2) * length + i],
         v1     = values [(index1 + 1) * length + i],
         a1     = values [(index1 + 0) * length + i];

      v0 *= 2 * t3 - 3 * t2 + 1;
      b0 *= td * (t3 - 2 * t2 + t1);
      v1 *= -2 * t3 + 3 * t2;
      a1 *= td * (t3 - t2);

      return v0 + b0 + v1 + a1;
   },
   vectorValue (array, vector)
   {
      if (!(array instanceof Array))
         return false;

      if (array .length !== vector .length)
         return false;

      vector .set (... array);

      return true;
   },
   numberValue (value, defaultValue)
   {
      if (typeof value !== "number")
         return defaultValue;

      return value;
   },
   stringValue (value, defaultValue)
   {
      if (typeof value !== "string")
         return defaultValue;

      return value;
   },
   description (string)
   {
      return string ?.replace (/_+/g, " ") .trim () ?? "";
   },
});

const GLTF2Parser_default_ = GLTF2Parser;
;

x_ite_Namespace .add ("GLTF2Parser", "x_ite/Parser/GLTF2Parser", GLTF2Parser_default_);
/* harmony default export */ const Parser_GLTF2Parser = (GLTF2Parser_default_);
;// CONCATENATED MODULE: ./src/x_ite/Parser/GLB2Parser.js
/* provided dependency */ var GLB2Parser_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function GLB2Parser (scene)
{
   Parser_X3DParser .call (this, scene);

   this .json    = [ ];
   this .buffers = [ ];
}

Object .assign (Object .setPrototypeOf (GLB2Parser .prototype, Parser_X3DParser .prototype),
{
   getEncoding ()
   {
      return "ARRAY_BUFFER";
   },
   setInput (input)
   {
      this .arrayBuffer = input;
      this .dataView    = new DataView (input);
   },
   isValid ()
   {
      if (!(this .arrayBuffer instanceof ArrayBuffer))
         return false;

      if (this .dataView .byteLength < 12)
         return false;

      if (this .dataView .getUint32 (0, true) !== 0x46546C67)
         return false;

      if (this .dataView .getUint32 (4, true) !== 2)
         return false;

      if (this .dataView .getUint32 (8, true) !== this .dataView .byteLength)
         return false;

      return true;
   },
   parseIntoScene (resolve, reject)
   {
      this .glb ()
         .then (resolve)
         .catch (reject);
   },
   glb: async function ()
   {
      this .chunks ();

      const parser = new Parser_GLTF2Parser (this .getScene ());

      parser .setBuffers (this .buffers);

      for (const json of this .json)
      {
         parser .setInput (json);

         if (!parser .isValid ())
            continue;

         await parser .rootObject (parser .input);
      }

      return this .getScene ();
   },
   chunks ()
   {
      for (let i = 12; i < this .dataView .byteLength;)
      {
         const
            length = this .dataView .getUint32 (i, true),
            type   = this .dataView .getUint32 (i + 4, true);

         i += 8;

         switch (type)
         {
            case 0x4e4f534a: // Structured JSON content
            {
               this .json .push (GLB2Parser_$.decodeText (this .arrayBuffer .slice (i, i + length)));
               break;
            }
            case 0x004e4942: // Binary buffer
            {
               this .buffers .push (this .arrayBuffer .slice (i, i + length));
               break;
            }
         }

         i += length;
      }

      return this .getScene ();
   },
});

const GLB2Parser_default_ = GLB2Parser;
;

x_ite_Namespace .add ("GLB2Parser", "x_ite/Parser/GLB2Parser", GLB2Parser_default_);
/* harmony default export */ const Parser_GLB2Parser = (GLB2Parser_default_);
;// CONCATENATED MODULE: ./src/x_ite/Parser/OBJParser.js
/* provided dependency */ var OBJParser_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









// http://paulbourke.net/dataformats/obj/
// https://people.sc.fsu.edu/~jburkardt/data/obj/obj.html

/*
 *  Grammar
 */

// Lexical elements
const OBJParser_Grammar = Parser_Expressions ({
   // General
   whitespaces: /[\x20\n\t\r]+/gy,
   whitespacesNoLineTerminator: /[\x20\t]+/gy,
   comment: /#.*?(?=[\n\r])/gy,
   untilEndOfLine: /([^\r\n]+)/gy,

   // Keywords
   mtllib: /\bmtllib\b/gy,
   usemtl: /\busemtl\b/gy,
   newmtl: /\bnewmtl\b/gy,
   Ka: /\bKa\b/gy,
   Kd: /\bKd\b/gy,
   Ks: /\bKs\b/gy,
   Ns: /\bNs\b/gy,
   d: /\bd\b/gy,
   Tr: /\bTr\b/gy,
   illum: /\billum\b/gy,
   map_Kd: /\bmap_Kd\b/gy,
   o: /\bo\b/gy,
   v: /\bv\b/gy,
   vt: /\bvt\b/gy,
   vn: /\bvn\b/gy,
   g: /\bg\b/gy,
   s: /\bs\b/gy,
   off: /\boff\b/gy,
   f: /\bf\b/gy,
   slash: /\//gy,

   // Values
   int32:  /((?:0[xX][\da-fA-F]+)|(?:[+-]?\d+))/gy,
   double: /([+-]?(?:(?:(?:\d*\.\d+)|(?:\d+(?:\.)?))(?:[eE][+-]?\d+)?))/gy,
   constants: /([+-])((?:NAN|INF|INFINITY))/igy,
});

/*
 * Parser
 */

function OBJParser (scene)
{
   Parser_X3DParser    .call (this, scene);
   Parser_X3DOptimizer .call (this);

   // Optimizer

   this .removeGroups         = true;
   this .removeEmptyGroups    = true;
   this .combineGroupingNodes = false;

   // Globals

   this .smoothingGroup  = 0;
   this .smoothingGroups = new Map ();
   this .groups          = new Map ();
   this .materials       = new Map ();
   this .textures        = new Map ();
   this .point2          = new Numbers_Vector2 ();
   this .point3          = new Numbers_Vector3 ();
   this .lastIndex       = 0;
}

Object .assign (Object .setPrototypeOf (OBJParser .prototype, Parser_X3DParser .prototype),
   Parser_X3DOptimizer .prototype,
{
   CONSTANTS: new Map ([
      ["NAN", NaN],
      ["INF", Infinity],
      ["INFINITY", Infinity],
   ]),
   getEncoding ()
   {
      return "STRING";
   },
   setInput (string)
   {
      this .input = string;
   },
   isValid ()
   {
      if (!(typeof this .input === "string"))
         return false;

      return !! this .input .match (/^(?:[\x20\n\t\r]+|#.*?[\r\n])*\b(?:mtllib|usemtl|o|g|s|vt|vn|v|f)\b/);
   },
   parseIntoScene (resolve, reject)
   {
      this .obj ()
         .then (resolve)
         .catch (reject);
   },
   obj: async function ()
   {
      // Set profile and components.

      const
         browser = this .getBrowser (),
         scene   = this .getScene ();

      scene .setEncoding ("OBJ");
      scene .setProfile (browser .getProfile ("Interchange"));

      await this .loadComponents ();

      // Init nodes.

      this .object          = scene .createNode ("Transform");
      this .group           = scene .createNode ("Group");
      this .defaultMaterial = scene .createNode ("Material");
      this .texCoord        = scene .createNode ("TextureCoordinate");
      this .normal          = scene .createNode ("Normal");
      this .coord           = scene .createNode ("Coordinate");

      this .object .children .push (this .group);

      scene .getRootNodes () .push (this .object);

      // Parse scene.

      await this .statements ();

      this .optimizeSceneGraph (scene .getRootNodes ());

      return this .getScene ();
   },
   comments ()
   {
      while (this .comment ())
         ;
   },
   comment ()
   {
      this .whitespaces ();

      if (OBJParser_Grammar .comment .parse (this))
         return true;

      return false;
   },
   whitespaces ()
   {
      OBJParser_Grammar .whitespaces .parse (this);
   },
   whitespacesNoLineTerminator ()
   {
      OBJParser_Grammar .whitespacesNoLineTerminator .parse (this);
   },
   statements: async function ()
   {
      while (await this .statement ())
         ;
   },
   statement: async function ()
   {
      if (await this .mtllibs ())
         return true;

      if (this .usemtl ())
         return true;

      if (this .o ())
         return true;

      if (this .g ())
         return true;

      if (this .s ())
         return true;

      if (this .vts ())
         return true;

      if (this .vns ())
         return true;

      if (this .vs ())
         return true;

      if (this .fs ())
         return true;

      // Skip empty and unknown lines.

      if (OBJParser_Grammar .untilEndOfLine .parse (this))
         return true;

      return false;
   },
   mtllibs: async function ()
   {
      this .comments ();

      if (OBJParser_Grammar .mtllib .parse (this))
      {
         this .whitespacesNoLineTerminator ();

         if (OBJParser_Grammar .untilEndOfLine .parse (this))
         {
            const mtllibs = this .result [1] .trim () .split (/\s+/);

            await Promise .all (mtllibs .map (path => this .mtllib (path)));
         }

         return true;
      }

      return false;
   },
   mtllib: async function (path)
   {
      try
      {
         const
            scene       = this .getExecutionContext (),
            url         = new URL (path, scene .getBaseURL ()),
            response    = await fetch (url),
            arrayBuffer = await response .arrayBuffer (),
            input       = OBJParser_$.decodeText (OBJParser_$.ungzip (arrayBuffer)),
            parser      = new MaterialParser (scene, input);

         parser .parse ();

         for (const [id, material] of parser .materials)
         {
            const name = this .sanitizeName (id);

            if (name)
            {
               scene .addNamedNode (scene .getUniqueName (name), material);
               scene .addExportedNode (scene .getUniqueExportName (name), material);
            }

            this .materials .set (id, material);
         }

         for (const [id, texture] of parser .textures)
         {
            const name = this .sanitizeName (id);

            if (name)
            {
               scene .addNamedNode (scene .getUniqueName (name), texture);
               scene .addExportedNode (scene .getUniqueExportName (name), texture);
            }

            this .textures .set (id, texture);
         }
      }
      catch (error)
      {
         console .warn (error);
      }
   },
   usemtl ()
   {
      this .comments ();

      if (OBJParser_Grammar .usemtl .parse (this))
      {
         this .whitespacesNoLineTerminator ();

         if (OBJParser_Grammar .untilEndOfLine .parse (this))
         {
            const id = this .result [1];

            this .material = this .materials .get (id) || this .defaultMaterial;
            this .texture  = this .textures .get (id);

            const smoothingGroup = this .smoothingGroups .get (this .group .getNodeName ());

            if (smoothingGroup)
               smoothingGroup .delete (this .smoothingGroup);
         }

         return true;
      }

      return false;
   },
   o ()
   {
      this .comments ();

      if (OBJParser_Grammar .o .parse (this))
      {
         this .whitespacesNoLineTerminator ();

         if (OBJParser_Grammar .untilEndOfLine .parse (this))
         {
            const
               scene = this .getExecutionContext (),
               name  = this .sanitizeName (this .result [1]);

            if (this .group .children .length)
            {
               this .object = scene .createNode("Transform");
               this .group  = scene .createNode ("Group");

               this .object .children .push (this .group);
               scene .getRootNodes () .push (this .object);
            }

            if (name)
            {
               scene .addNamedNode (scene .getUniqueName (name), this .object);
               scene .addExportedNode (scene .getUniqueExportName (name), this .object);
            }
         }

         return true;
      }

      return false;
   },
   g ()
   {
      this .comments ();

      if (OBJParser_Grammar .g .parse (this))
      {
         this .whitespacesNoLineTerminator ();

         if (OBJParser_Grammar .untilEndOfLine .parse (this))
         {
            const
               scene = this .getExecutionContext (),
               id    = this .result [1],
               name  = this .sanitizeName (id),
               group = this .groups .get (id);

            if (group)
            {
               this .group = group;
            }
            else
            {
               if (this .group .children .length)
               {
                  this .group = scene .createNode ("Group");

                  this .object .children .push (this .group);
               }
            }

            this .groups .set (id, this .group);

            if (name)
            {
               scene .addNamedNode (scene .getUniqueName (name), this .group);
               scene .addExportedNode (scene .getUniqueExportName (name), this .group);
            }

            this .smoothingGroup = 0;
         }

         return true;
      }

      return false;
   },
   s ()
   {
      this .comments ();

      if (OBJParser_Grammar .s .parse (this))
      {
         this .whitespacesNoLineTerminator ();

         if (OBJParser_Grammar .off .parse (this))
         {
            this .smoothingGroup = 0;
            return true;
         }

         if (this .int32 ())
         {
            this .smoothingGroup = this .value;
            return true;
         }

         return true;
      }

      return false;
   },
   vts ()
   {
      const point = this .texCoord .point;

      let result = false;

      while (this .vt (point))
         result = true;

      return result;
   },
   vt (point)
   {
      this .comments ();

      if (OBJParser_Grammar .vt .parse (this))
      {
         if (this .vec2 ())
         {
            point .push (this .point2);

            return true;
         }

         throw new Error ("Expected a texture coordinate.");
      }

      return false;
   },
   vns ()
   {
      const vector = this .normal .vector;

      let result = false;

      while (this .vn (vector))
         result = true;

      return result;
   },
   vn (vector)
   {
      this .comments ();

      if (OBJParser_Grammar .vn .parse (this))
      {
         if (this .vec3 ())
         {
            vector .push (this .point3);

            return true;
         }

         throw new Error ("Expected a normal vector.");
      }

      return false;
   },
   vs ()
   {
      const point = this .coord .point;

      let result = false;

      while (this .v (point))
         result = true;

      return result;
   },
   v (point)
   {
      this .comments ();

      if (OBJParser_Grammar .v .parse (this))
      {
         if (this .vec3 ())
         {
            point .push (this .point3);

            return true;
         }

         throw new Error ("Expected a vertex coordinate.");
      }

      return false;
   },
   fs ()
   {
      this .comments ();

      if (OBJParser_Grammar .f .lookahead (this))
      {
         try
         {
            this .shape    = this .smoothingGroups .get (this .group .getNodeName ()) .get (this .smoothingGroup);
            this .geometry = this .shape .geometry;
         }
         catch
         {
            const
               scene      = this .getExecutionContext (),
               appearance = scene .createNode ("Appearance");

            this .geometry = scene .createNode ("IndexedFaceSet");
            this .shape    = scene .createNode ("Shape");

            appearance .material        = this .material;
            appearance .texture         = this .texture;
            this .geometry .creaseAngle = this .smoothingGroup ? Math .PI : 0;
            this .shape .appearance     = appearance;
            this .shape .geometry       = this .geometry;

            this .group .children .push (this .shape);

            if (!this .smoothingGroups .has (this .group .getNodeName ()))
               this .smoothingGroups .set (this .group .getNodeName (), new Map ());

            this .smoothingGroups .get (this .group .getNodeName ()) .set (this .smoothingGroup, this .shape);
         }

         while (this .f ())
            ;

         if (this .geometry .texCoordIndex .length)
            this .geometry .texCoord = this .texCoord;

         if (this .geometry .normalIndex .length)
            this .geometry .normal = this .normal;

         this .geometry .coord = this .coord;

         return true;
      }

      return false;
   },
   f ()
   {
      this .comments ();

      if (OBJParser_Grammar .f .parse (this))
      {
         const
            geometry           = this .geometry,
            texCoordIndex      = geometry .texCoordIndex,
            normalIndex        = geometry .normalIndex,
            coordIndex         = geometry .coordIndex,
            numTexCoordIndices = texCoordIndex .length,
            numNormalIndices   = normalIndex .length,
            numTexCoords       = this .texCoord .point .length,
            numNormals         = this .normal .vector .length,
            numCoords          = this .coord .point .length;

         while (this .indices (texCoordIndex, normalIndex, coordIndex, numTexCoords, numNormals, numCoords))
            ;

         if (texCoordIndex .length !== numTexCoordIndices)
            texCoordIndex .push (-1);

         if (normalIndex .length !== numNormalIndices)
            normalIndex .push (-1);

         coordIndex .push (-1);

         return true;
      }

      return false;
   },
   indices (texCoordIndex, normalIndex, coordIndex, numTexCoords, numNormals, numCoords)
   {
      if (this .int32 ())
      {
         coordIndex .push (this .index (this .value, numCoords));

         if (OBJParser_Grammar .slash .parse (this))
         {
            if (this .int32 ())
            {
               texCoordIndex .push (this .index (this .value, numTexCoords));
            }

            if (OBJParser_Grammar .slash .parse (this))
            {
               if (this .int32 ())
               {
                  normalIndex .push (this .index (this .value, numNormals));
               }
            }
         }

         return true;
      }

      return false;
   },
   index (index, length)
   {
      if (index === 0)
         throw new Error ("Invalid index.");

      if (index < 0)
         return length + index;

      return index - 1;
   },
   int32 ()
   {
      this .whitespaces ();

      if (OBJParser_Grammar .int32 .parse (this))
      {
         this .value = parseInt (this .result [1]);

         return true;
      }

      return false;
   },
   double ()
   {
      this .whitespaces ();

      if (OBJParser_Grammar .double .parse (this))
      {
         this .value = parseFloat (this .result [1]);

         return true;
      }

      if (OBJParser_Grammar .constants .parse (this))
      {
         this .value = this .CONSTANTS .get (this .result [2] .toUpperCase ());

         if (this .result [1] === "-")
            this .value = - this .value;

         return true;
      }

      return false;
   },
   vec2 ()
   {
      if (this .double ())
      {
         this .point2 .x = this .value;

         if (this .double ())
         {
            this .point2 .y = this .value;

            return true;
         }
      }

      return false;
   },
   vec3 ()
   {
      if (this .double ())
      {
         this .point3 .x = this .value;

         if (this .double ())
         {
            this .point3 .y = this .value;

            if (this .double ())
            {
               this .point3 .z = this .value;

               return true;
            }
         }
      }

      return false;
   },
});

function MaterialParser (scene, input)
{
   this .executionContext = scene;
   this .input            = input;
   this .material         = scene .createNode ("Material");
   this .materials        = new Map ();
   this .textures         = new Map ();
   this .color3           = new Numbers_Color3 (0, 0, 0);
   this .id               = "";
}

Object .assign (MaterialParser .prototype,
{
   CONSTANTS: new Map ([
      ["NAN", NaN],
      ["INF", Infinity],
      ["INFINITY", Infinity],
   ]),
   parse ()
   {
      try
      {
         this .statements ();
      }
      catch (error)
      {
         if (DEVELOPMENT)
            console .log (error);
      }
   },
   comments ()
   {
      while (this .comment ())
         ;
   },
   comment ()
   {
      this .whitespaces ();

      if (OBJParser_Grammar .comment .parse (this))
         return true;

      return false;
   },
   whitespaces ()
   {
      OBJParser_Grammar .whitespaces .parse (this);
   },
   whitespacesNoLineTerminator ()
   {
      OBJParser_Grammar .whitespacesNoLineTerminator .parse (this);
   },
   statements ()
   {
      while (this .statement ())
		   ;
   },
   statement ()
   {
      if (this .newmtl ())
         return true;

      if (this .Ka ())
         return true;

      if (this .Kd ())
         return true;

      if (this .Ks ())
         return true;

      if (this .Ns ())
         return true;

      if (this .d ())
         return true;

      if (this .Tr ())
         return true;

      if (this .illum ())
         return true;

      if (this .map_Kd ())
         return true;

      // Skip empty and unknown lines.

      if (OBJParser_Grammar .untilEndOfLine .parse (this))
         return true;

      return false;
   },
   newmtl ()
   {
      this .comments ();

      if (OBJParser_Grammar .newmtl .parse (this))
      {
         this .whitespacesNoLineTerminator ();

         this .id = "";

         if (OBJParser_Grammar .untilEndOfLine .parse (this))
         {
            this .id = this .result [1];

            this .material = this .executionContext .createNode ("Material");

            this .materials .set (this .id, this .material);

            return true;
         }

         OBJParser_Grammar .untilEndOfLine .parse (this);

         return true;
      }

      return false;
   },
   Ka ()
   {
      this .comments ();

      if (OBJParser_Grammar .Ka .parse (this))
      {
         if (this .col3 ())
         {
            const hsv = this .color3 .getHSV ([ ]);

            this .material .ambientIntensity = hsv [2];

            return true;
         }

         OBJParser_Grammar .untilEndOfLine .parse (this);

         return true;
      }

      return false;
   },
   Kd ()
   {
      this .comments ();

      if (OBJParser_Grammar .Kd .parse (this))
      {
         if (this .col3 ())
         {
            this .material .diffuseColor = this .color3;

            return true;
         }

         OBJParser_Grammar .untilEndOfLine .parse (this);

         return true;
      }

      return false;
   },
   Ks ()
   {
      this .comments ();

      if (OBJParser_Grammar .Ks .parse (this))
      {
         if (this .col3 ())
         {
            this .material .specularColor = this .color3;

            return true;
         }

         OBJParser_Grammar .untilEndOfLine .parse (this);

         return true;
      }

      return false;
   },
   Ns ()
   {
      this .comments ();

      if (OBJParser_Grammar .Ns .parse (this))
      {
         if (this .double ())
         {
            this .material .shininess = this .value / 1000;

            return true;
         }

         OBJParser_Grammar .untilEndOfLine .parse (this);

         return true;
      }

      return false;
   },
   d ()
   {
      this .comments ();

      if (OBJParser_Grammar .d .parse (this))
      {
         if (this .double ())
         {
            this .material .transparency = 1 - this .value;

            return true;
         }

         OBJParser_Grammar .untilEndOfLine .parse (this);

         return true;
      }

      return false;
   },
   Tr ()
   {
      this .comments ();

      if (OBJParser_Grammar .Tr .parse (this))
      {
         if (this .double ())
         {
            this .material .transparency = this .value;

            return true;
         }

         OBJParser_Grammar .untilEndOfLine .parse (this);

         return true;
      }

      return false;
   },
   illum ()
   {
      this .comments ();

      if (OBJParser_Grammar .illum .parse (this))
      {
         if (this .int32 ())
         {
            // Don't know what to do with illum value in X3D.
            return true;
         }

         OBJParser_Grammar .untilEndOfLine .parse (this);

         return true;
      }

      return false;
   },
   map_Kd ()
   {
      this .comments ();

      if (OBJParser_Grammar .map_Kd .parse (this))
      {
         this .whitespacesNoLineTerminator ();

         if (OBJParser_Grammar .untilEndOfLine .parse (this))
         {
            const string = this .result [1];

            if (string .length && this .id .length)
            {
               const paths = string .trim () .split (/\s+/);

               if (paths .length)
               {
                  const
                     scene   = this .executionContext,
                     texture = scene .createNode ("ImageTexture"),
                     path    = paths .at (-1) .replace (/\\/g, "/");

                  texture .url = [path];

                  this .textures .set (this .id, texture);
               }
            }

            return true;
         }

         OBJParser_Grammar .untilEndOfLine .parse (this);

         return true;
      }

      return false;
   },
   int32 ()
   {
      this .whitespaces ();

      if (OBJParser_Grammar .int32 .parse (this))
      {
         this .value = parseInt (this .result [1]);

         return true;
      }

      return false;
   },
   double ()
   {
      this .whitespaces ();

      if (OBJParser_Grammar .double .parse (this))
      {
         this .value = parseFloat (this .result [1]);

         return true;
      }

      if (OBJParser_Grammar .constants .parse (this))
      {
         this .value = this .CONSTANTS .get (this .result [2] .toUpperCase ());

         if (this .result [1] === "-")
            this .value = - this .value;

         return true;
      }

      return false;
   },
   col3 ()
   {
      if (this .double ())
      {
         this .color3 .r = this .value;

         if (this .double ())
         {
            this .color3 .g = this .value;

            if (this .double ())
            {
               this .color3 .b = this .value;

               return true;
            }
         }
      }

      return false;
   },
});

const OBJParser_default_ = OBJParser;
;

x_ite_Namespace .add ("OBJParser", "x_ite/Parser/OBJParser", OBJParser_default_);
/* harmony default export */ const Parser_OBJParser = (OBJParser_default_);
;// CONCATENATED MODULE: ./src/x_ite/Parser/STLAParser.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





// http://paulbourke.net/dataformats/stl/
// https://people.sc.fsu.edu/~jburkardt/data/obj/obj.html

/*
 *  Grammar
 */

// Lexical elements
const STLAParser_Grammar = Parser_Expressions ({
   // General
   whitespaces: /[\x20\n\t\r]+/gy,
   whitespacesNoLineTerminator: /[\x20\t]+/gy,
   comment: /;.*?(?=[\n\r])/gy,
   untilEndOfLine: /([^\r\n]+)/gy,

   // Keywords
   solid: /solid/gy,
   facet: /facet/gy,
   normal: /normal/gy,
   outer: /outer/gy,
   loop: /loop/gy,
   vertex: /vertex/gy,
   endloop: /endloop/gy,
   endfacet: /endfacet/gy,
   endsolid: /endsolid/gy,

   // Values
   name: /(\w+)/gy,
   double: /([+-]?(?:(?:(?:\d*\.\d+)|(?:\d+(?:\.)?))(?:[eE][+-]?\d+)?))/gy,
   constants: /([+-])((?:NAN|INF|INFINITY))/igy,
});

/*
 * Parser
 */

function STLAParser (scene)
{
   Parser_X3DParser .call (this, scene);

   // Globals

   this .vector = [ ];
   this .point  = [ ];
}

Object .assign (Object .setPrototypeOf (STLAParser .prototype, Parser_X3DParser .prototype),
{
   CONSTANTS: new Map ([
      ["NAN", NaN],
      ["INF", Infinity],
      ["INFINITY", Infinity],
   ]),
   getEncoding ()
   {
      return "STRING";
   },
   setInput (string)
   {
      this .input = string;
   },
   isValid ()
   {
      if (!(typeof this .input === "string"))
         return false;

      return !! this .input .match (/^(?:[\x20\n\t\r]+|;.*?[\r\n])*\b(?:solid)\b/);
   },
   parseIntoScene (resolve, reject)
   {
      this .stl ()
         .then (resolve)
         .catch (reject);
   },
   stl: async function ()
   {
      // Set profile and components.

      const
         browser = this .getBrowser (),
         scene   = this .getScene ();

      scene .setEncoding ("STL");
      scene .setProfile (browser .getProfile ("Interchange"));

      await this .loadComponents ();

      // Create nodes.

      this .material   = scene .createNode ("Material");
      this .appearance = scene .createNode ("Appearance");

      this .material .diffuseColor = Numbers_Color3 .White;
      this .appearance .material   = this .material;

      // Parse scene.

      this .statements ();

      return this .getScene ();
   },
   comments ()
   {
      while (this .comment ())
         ;
   },
   comment ()
   {
      this .whitespaces ();

      if (STLAParser_Grammar .comment .parse (this))
         return true;

      return false;
   },
   whitespaces ()
   {
      STLAParser_Grammar .whitespaces .parse (this);
   },
   whitespacesNoLineTerminator ()
   {
      STLAParser_Grammar .whitespacesNoLineTerminator .parse (this);
   },
   statements ()
   {
      while (this .solid ())
         ;
   },
   solid ()
   {
      this .comments ();

      if (STLAParser_Grammar .solid .parse (this))
      {
         this .whitespacesNoLineTerminator ();

         const
            scene      = this .getExecutionContext (),
            shape      = scene .createNode ("Shape"),
            geometry   = scene .createNode ("TriangleSet"),
            normal     = scene .createNode ("Normal"),
            coordinate = scene .createNode ("Coordinate"),
            name       = this .sanitizeName (STLAParser_Grammar .name .parse (this) ? this .result [1] : "");

         STLAParser_Grammar .untilEndOfLine .parse (this);

         this .facets ();

         shape .appearance         = this .appearance;
         shape .geometry           = geometry;
         geometry .normalPerVertex = false;
         geometry .normal          = normal;
         geometry .coord           = coordinate;
         normal .vector            = this .vector;
         coordinate .point         = this .point;

         if (name)
         {
            scene .addNamedNode (scene .getUniqueName (name), shape);
            scene .addExportedNode (scene .getUniqueExportName (name), shape);
         }

         scene .getRootNodes () .push (shape);

         this .comments ();

         if (STLAParser_Grammar .endsolid .parse (this))
            return true;

         throw new Error ("Expected 'endsolid' statement.");
      }

      return false;
   },
   facets ()
   {
      this .vector .length = 0;
      this .point  .length = 0;

      while (this .facet ())
         ;
   },
   facet ()
   {
      this .comments ()

      if (STLAParser_Grammar .facet .parse (this))
      {
         if (this .normal ())
         {
            if (this .loop ())
            {
               this .comments ();

               if (STLAParser_Grammar .endfacet .parse (this))
                  return true;

               throw new Error ("Expected 'endfacet' statement.");
            }
         }
      }

      return false;
   },
   normal ()
   {
      this .whitespacesNoLineTerminator ();

      if (STLAParser_Grammar .normal .parse (this))
      {
         if (this .double ())
         {
            this .vector .push (this .value);

            if (this .double ())
            {
               this .vector .push (this .value);

               if (this .double ())
               {
                  this .vector .push (this .value);

                  return true;
               }

               throw new Error ("Expected a double.");
            }

            throw new Error ("Expected a double.");
         }

         throw new Error ("Expected a double.");
      }

      throw new Error ("Expected 'normal' statement.");
   },
   loop ()
   {
      this .comments ();

      if (STLAParser_Grammar .outer .parse (this))
      {
         this .whitespacesNoLineTerminator ();

         if (STLAParser_Grammar .loop .parse (this))
         {
            if (this .vertex ())
            {
               if (this .vertex ())
               {
                  if (this .vertex ())
                  {
                     this .comments ();

                     if (STLAParser_Grammar .endloop .parse (this))
                        return true;

                     throw new Error ("Expected 'endloop' statement.");
                  }
               }
            }
         }

         throw new Error ("Expected 'loop' statement.");
      }

      throw new Error ("Expected 'outer' statement.");
   },
   vertex ()
   {
      this .comments ();

      if (STLAParser_Grammar .vertex .parse (this))
      {
         if (this .double ())
         {
            this .point .push (this .value);

            if (this .double ())
            {
               this .point .push (this .value);

               if (this .double ())
               {
                  this .point .push (this .value);

                  return true;
               }

               throw new Error ("Expected a double.");
            }

            throw new Error ("Expected a double.");
         }

         throw new Error ("Expected a double.");
      }

      throw new Error ("Expected 'vertex' statement.");
   },
   double ()
   {
      this .whitespacesNoLineTerminator ();

      if (STLAParser_Grammar .double .parse (this))
      {
         this .value = parseFloat (this .result [1]);

         return true;
      }

      if (STLAParser_Grammar .constants .parse (this))
      {
         this .value = this .CONSTANTS .get (this .result [2] .toUpperCase ());

         if (this .result [1] === "-")
            this .value = - this .value;

         return true;
      }

      return false;
   },
});

const STLAParser_default_ = STLAParser;
;

x_ite_Namespace .add ("STLAParser", "x_ite/Parser/STLAParser", STLAParser_default_);
/* harmony default export */ const Parser_STLAParser = (STLAParser_default_);
;// CONCATENATED MODULE: ./src/x_ite/Parser/STLBParser.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




// http://paulbourke.net/dataformats/stl/
// https://people.sc.fsu.edu/~jburkardt/data/obj/obj.html

/*
 * Parser
 */

function STLBParser (scene)
{
   Parser_X3DParser .call (this, scene);
}

Object .assign (Object .setPrototypeOf (STLBParser .prototype, Parser_X3DParser .prototype),
{
   getEncoding ()
   {
      return "ARRAY_BUFFER";
   },
   setInput (input)
   {
      this .arrayBuffer = input;
      this .dataView    = new DataView (input);
   },
   isValid ()
   {
      if (!(this .arrayBuffer instanceof ArrayBuffer))
         return false;

      if (this .dataView .byteLength < 84)
         return false;

      const
         numFaces   = this .dataView .getUint32 (80, true),
         byteLength = numFaces * 50 + 84;

      return byteLength === this .dataView .byteLength;
   },
   parseIntoScene (resolve, reject)
   {
      this .stl ()
         .then (resolve)
         .catch (reject);
   },
   stl: async function ()
   {
      // Set profile and components.

      const
         browser = this .getBrowser (),
         scene   = this .getScene ();

      scene .setEncoding ("STL");
      scene .setProfile (browser .getProfile ("Interchange"));

      await this .loadComponents ();

      // Create nodes.

      this .material   = scene .createNode ("Material");
      this .appearance = scene .createNode ("Appearance");

      this .material .diffuseColor = Numbers_Color3 .White;
      this .appearance .material   = this .material;

      // Parse scene.

      this .shape ();

      return this .getScene ();
   },
   shape ()
   {
      const
         scene      = this .getExecutionContext (),
         shape      = scene .createNode ("Shape"),
         geometry   = scene .createNode ("TriangleSet"),
         normal     = scene .createNode ("Normal"),
         coordinate = scene .createNode ("Coordinate"),
         dataView   = this .dataView,
         byteLength = this .dataView .byteLength,
         vector     = [ ],
         point      = [ ];

      for (let i = 84; i < byteLength; i += 50)
      {
         for (let f = 0; f < 3; ++ f)
            vector .push (dataView .getFloat32 (i + f * 4, true));

         for (let f = 3; f < 12; ++ f)
            point .push (dataView .getFloat32 (i + f * 4, true));
      }

      shape .appearance         = this .appearance;
      shape .geometry           = geometry;
      geometry .normalPerVertex = false;
      geometry .normal          = normal;
      geometry .coord           = coordinate;
      normal .vector            = vector;
      coordinate .point         = point;

      scene .getRootNodes () .push (shape);
   },
});

const STLBParser_default_ = STLBParser;
;

x_ite_Namespace .add ("STLBParser", "x_ite/Parser/STLBParser", STLBParser_default_);
/* harmony default export */ const Parser_STLBParser = (STLBParser_default_);
;// CONCATENATED MODULE: ./src/x_ite/Parser/PLYAParser.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




/*
 *  Grammar
 */

// Lexical elements
const PLYAParser_Grammar = Parser_Expressions ({
   // General
   whitespaces: /[\x20\n\t\r]+/gy,
   whitespacesNoLineTerminator: /[\x20\t]+/gy,
   untilEndOfLine: /([^\r\n]+)/gy,
   line: /.*?\r?\n/gy,

   // Keywords
   ply: /ply/gy,
   format: /format ascii 1.0/gy,
   comment: /\bcomment\b/gy,
   element: /\belement\b/gy,
   elementName: /\b(\S+)\b/gy,
   property: /\bproperty\b/gy,
   propertyList: /\blist\b/gy,
   propertyType: /\b(char|uchar|short|ushort|int|uint|float|double|int8|uint8|int16|uint16|int32|uint32|float32|float64)\b/gy,
   propertyName: /\b(\S+)\b/gy,
   endHeader: /\bend_header\b/gy,

   double: /([+-]?(?:(?:(?:\d*\.\d+)|(?:\d+(?:\.)?))(?:[eE][+-]?\d+)?))/gy,
   int32:  /((?:0[xX][\da-fA-F]+)|(?:[+-]?\d+))/gy,
});

/*
 * Parser
 */

function PLYAParser (scene)
{
   Parser_X3DParser .call (this, scene);

   this .comments = [ ];
   this .attrib   = [ ];

   this .typeMapping = new Map ([
      ["char",    this .int32],
      ["uchar",   this .int32],
      ["short",   this .int32],
      ["ushort",  this .int32],
      ["int",     this .int32],
      ["uint",    this .int32],
      ["float",   this .double],
      ["double",  this .double],
      ["int8",    this .int32],
      ["uint8",   this .int32],
      ["int16",   this .int32],
      ["uint16",  this .int32],
      ["int32",   this .int32],
      ["uint32",  this .int32],
      ["float32", this .double],
      ["float64", this .double],
   ]);
}

Object .assign (Object .setPrototypeOf (PLYAParser .prototype, Parser_X3DParser .prototype),
{
   getEncoding ()
   {
      return "STRING";
   },
   setInput (input)
   {
      this .input = input;
   },
   isValid ()
   {
      return this .input .match (/^ply\r?\nformat ascii 1.0/);
   },
   parseIntoScene (resolve, reject)
   {
      this .ply ()
         .then (resolve)
         .catch (reject);
   },
   ply: async function ()
   {
      // Set profile and components.

      const
         browser = this .getBrowser (),
         scene   = this .getScene ();

      scene .setEncoding ("PLY");
      scene .setProfile (browser .getProfile ("Interchange"));

      await this .loadComponents ();
      await this .processElements (this .header ([ ]))

      // Create nodes.

      return this .getScene ();
   },
   whitespacesOrComments ()
   {
      while (this .whitespaces () || this .comment ())
         ;
   },
   whitespaces ()
   {
      return PLYAParser_Grammar .whitespaces .parse (this);
   },
   whitespacesNoLineTerminator ()
   {
      PLYAParser_Grammar .whitespacesNoLineTerminator .parse (this);
   },
   comment ()
   {
      if (PLYAParser_Grammar .comment .parse (this) && PLYAParser_Grammar .untilEndOfLine .parse (this))
      {
         this .comments .push (this .result [1] .trim ());
         return true;
      }

      return false;
   },
   double ()
   {
      this .whitespacesNoLineTerminator ();

      if (PLYAParser_Grammar .double .parse (this))
      {
         this .value = parseFloat (this .result [1]);

         return true;
      }

      return false;
   },
   int32 ()
   {
      this .whitespacesNoLineTerminator ();

      if (PLYAParser_Grammar .int32 .parse (this))
      {
         this .value = parseInt (this .result [1]);

         return true;
      }

      return false;
   },
   convertColor (value, type)
   {
      switch (type)
      {
         case "uchar":
         case "uint8":
            return value / 0xff;
         case "ushort":
         case "uint16":
            return value / 0xfffff;
         case "uint":
         case "uint32":
            return value / 0xffffffff;
         case "float":
         case "float32":
         case "double":
         case "float64":
            return value;
      }
   },
   header (elements)
   {
      PLYAParser_Grammar .ply .parse (this);
      PLYAParser_Grammar .whitespaces .parse (this);
      PLYAParser_Grammar .format .parse (this);

      this .headings (elements);

      const
         scene     = this .getScene (),
         worldInfo = scene .createNode ("WorldInfo");

      worldInfo .title = new URL (scene .worldURL) .pathname .split ('/') .at (-1);
      worldInfo .info  = this .comments;

      scene .rootNodes .push (worldInfo);

      return elements;
   },
   headings (elements)
   {
      while (this .head (elements))
         ;
   },
   head (elements)
   {
      if (this .element (elements))
         return true;

      if (PLYAParser_Grammar .endHeader .parse (this))
         return false;

      if (PLYAParser_Grammar .untilEndOfLine .parse (this))
         return true;

      return false;
   },
   element (elements)
   {
      this .whitespacesOrComments ();

      if (PLYAParser_Grammar .element .parse (this))
      {
         this .whitespacesNoLineTerminator ();

         if (PLYAParser_Grammar .elementName .parse (this))
         {
            const name = this .result [1];

            if (this .int32 ())
            {
               const element =
               {
                  name: name,
                  count: this .value,
                  properties: [ ],
               };

               this .properties (element .properties);

               elements .push (element);
               return true;
            }
         }
      }

      return false;
   },
   properties (properties)
   {
      while (this .property (properties))
         ;
   },
   property (properties)
   {
      this .whitespacesOrComments ();

      if (PLYAParser_Grammar .property .parse (this))
      {
         this .whitespacesNoLineTerminator ();

         if (PLYAParser_Grammar .propertyType .parse (this))
         {
            const
               type  = this .result [1],
               value = this .typeMapping .get (type);

            this .whitespacesNoLineTerminator ();

            if (PLYAParser_Grammar .propertyName .parse (this))
            {
               const name = this .result [1];

               properties .push ({ type, value, name });
               return true;
            }
         }

         if (PLYAParser_Grammar .propertyList .parse (this))
         {
            this .whitespacesNoLineTerminator ();

            if (PLYAParser_Grammar .propertyType .parse (this))
            {
               const count = this .typeMapping .get (this .result [1]);

               this .whitespacesNoLineTerminator ();

               if (PLYAParser_Grammar .propertyType .parse (this))
               {
                  const
                     type  = this .result [1],
                     value = this .typeMapping .get (type);

                  this .whitespacesNoLineTerminator ();

                  if (PLYAParser_Grammar .propertyName .parse (this))
                  {
                     const name = this .result [1];

                     properties .push ({ count, type, value, name });
                     return true;
                  }
               }
            }
         }
      }

      return false;
   },
   async processElements (elements)
   {
      // console .log (elements)

      for (const element of elements)
         await this .processElement (element);

      if (!this .coord)
         return;

      const
         scene      = this .getScene (),
         shape      = scene .createNode ("Shape"),
         appearance = scene .createNode ("Appearance"),
         material   = scene .createNode (this .geometry ? "Material" : "UnlitMaterial"),
         geometry   = this .geometry ?? scene .createNode ("PointSet");

      appearance .material = material;

      if (this .texCoord)
      {
         const textureTransform = scene .createNode ("TextureTransform");

         textureTransform .translation .y = -1;
         textureTransform .scale .y       = -1;

         appearance .textureTransform = textureTransform;
      }

      if (geometry .getNodeTypeName () !== "PointSet")
      {
         geometry .solid    = false;
         geometry .texCoord = this .texCoord;
      }

      geometry .attrib = this .attrib;
      geometry .color  = this .color;
      geometry .normal = this .normal;
      geometry .coord  = this .coord;

      shape .appearance = appearance;
      shape .geometry   = geometry;

      scene .rootNodes .push (shape);
   },
   async processElement (element)
   {
      switch (element .name)
      {
         case "vertex":
            await this .parseVertices (element);
            break;
         case "face":
            this .parseFaces (element);
            break;
         case "multi_texture_vertex":
            this .parseMultiTextureVertices (element);
            break;
         case "multi_texture_face":
            this .parseMultiTextureFaces (element);
            break;
         default:
            this .parseUnknown (element);
            break;
      }
   },
   async parseVertices ({ count, properties })
   {
      const
         scene      = this .getScene (),
         colors     = [ ],
         texCoord   = scene .createNode ("TextureCoordinate"),
         texCoords  = [ ],
         normal     = scene .createNode ("Normal"),
         normals    = [ ],
         coord      = scene .createNode ("Coordinate"),
         points     = [ ],
         attributes = new Map ();

      for (const { name } of properties)
      {
         if (name .match (/^(?:red|green|blue|alpha|r|g|b|a|s|t|u|v|nx|ny|nz|x|y|z)$/))
            continue;

         attributes .set (name, [ ]);
      }

      // console .time ("vertices")

      for (let i = 0; i < count; ++ i)
      {
         this .whitespaces ();

         for (const { value, name, type } of properties)
         {
            if (!value .call (this))
               throw new Error (`Couldn't parse value for property ${name}.`);

            switch (name)
            {
               default:
                  attributes .get (name) .push (this .value);
                  break;
               case "red": case "green": case "blue": case "alpha":
               case "r": case "g": case "b": case "a":
                  colors .push (this .convertColor (this .value, type));
                  break;
               case "s": case "t":
               case "u": case "v":
                  texCoords .push (this .value);
                  break;
               case "nx": case "ny": case "nz":
                  normals .push (this .value);
                  break;
               case "x": case "y": case "z":
                  points .push (this .value);
                  break;
            }
         }
      }

      // console .timeEnd ("vertices")

      // Attributes

      if (attributes .size)
      {
         scene .addComponent (this .getBrowser () .getComponent ("Shaders", 1));

         await this .loadComponents ();

         for (const [name, value] of attributes)
         {
            const floatVertexAttribute = scene .createNode ("FloatVertexAttribute");

            floatVertexAttribute .name          = name;
            floatVertexAttribute .numComponents = 1;
            floatVertexAttribute .value         = value;

            this .attrib .push (floatVertexAttribute);
         }
      }

      // Geometric properties

      const
         pAlpha = properties .some (p => p .name .match (/^(?:alpha|a)$/)),
         alpha  = pAlpha && colors .some ((v, i) => i % 4 === 3 && v < 1),
         color  = scene .createNode (alpha ? "ColorRGBA" : "Color");

      color    .color  = alpha || !pAlpha ? colors : colors .filter ((v, i) => i % 4 !== 3);
      texCoord .point  = texCoords;
      normal   .vector = normals;
      coord    .point  = points;

      this .color    = colors    .length ? color    : null;
      this .texCoord = texCoords .length ? texCoord : null;
      this .normal   = normals   .length ? normal   : null;
      this .coord    = coord;
   },
   parseFaces ({ count, properties })
   {
      const
         scene      = this .getScene (),
         geometry   = scene .createNode ("IndexedFaceSet"),
         coordIndex = [ ];

      for (let i = 0; i < count; ++ i)
      {
         this .whitespaces ();

         for (const { count, value, name } of properties)
         {
            if (!count .call (this))
               throw new Error (`Couldn't parse property count for ${name}.`);

            const length = this .value;

            for (let i = 0; i < length; ++ i)
            {
               if (!value .call (this))
                  throw new Error (`Couldn't parse a property value for ${name}.`);

               coordIndex .push (this .value);
            }

            coordIndex .push (-1);
         }
      }

      geometry .coordIndex = coordIndex;
      this .geometry       = geometry;
   },
   parseMultiTextureVertices ({ count, properties })
   {
      const
         scene     = this .getScene (),
         texCoord  = scene .createNode ("TextureCoordinate"),
         texCoords = [ ];

      for (let i = 0; i < count; ++ i)
      {
         this .whitespaces ();

         for (const { value, name } of properties)
         {
            if (!value .call (this))
               throw new Error (`Couldn't parse value for property ${name}.`);

            switch (name)
            {
               case "s": case "t":
               case "u": case "v":
                  texCoords .push (this .value);
                  break;
            }
         }
      }

      texCoord .point = texCoords;

      this .texCoord = texCoords .length ? texCoord : null;
   },
   parseMultiTextureFaces ({ count, properties })
   {
      const texCoordIndex = [ ];

      for (let i = 0; i < count; ++ i)
      {
         for (const { count, value, name } of properties)
         {
            if (count)
            {
               if (!count .call (this))
                  throw new Error (`Couldn't parse property count for ${name}.`);

               const length = this .value;

               for (let i = 0; i < length; ++ i)
               {
                  if (!value .call (this))
                     throw new Error (`Couldn't parse value for property ${name}.`);

                  texCoordIndex .push (this .value);
               }

               texCoordIndex .push (-1);
            }
            else
            {
               if (!value .call (this))
                  throw new Error (`Couldn't parse value for property ${name}.`);
            }
         }
      }

      if (this .geometry)
         this .geometry .texCoordIndex = texCoordIndex;
   },
   parseUnknown ({ count })
   {
      this .whitespaces ();

      for (let i = 0; i < count; ++ i)
         PLYAParser_Grammar .line .parse (this);
   },
});

const PLYAParser_default_ = PLYAParser;
;

x_ite_Namespace .add ("PLYAParser", "x_ite/Parser/PLYAParser", PLYAParser_default_);
/* harmony default export */ const Parser_PLYAParser = (PLYAParser_default_);
;// CONCATENATED MODULE: ./src/x_ite/Parser/PLYBParser.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function PLYBParser (scene)
{
   Parser_PLYAParser .call (this, scene);

   this .typeMapping = new Map ([
      ["char",    this .binaryInt8],
      ["uchar",   this .binaryUint8],
      ["short",   this .binaryInt16],
      ["ushort",  this .binaryUint16],
      ["int",     this .binaryInt32],
      ["uint",    this .binaryUint32],
      ["float",   this .binaryFloat32],
      ["double",  this .binaryFloat64],
      ["int8",    this .binaryInt8],
      ["uint8",   this .binaryUint8],
      ["int16",   this .binaryInt16],
      ["uint16",  this .binaryUint16],
      ["int32",   this .binaryInt32],
      ["uint32",  this .binaryUint32],
      ["float32", this .binaryFloat32],
      ["float64", this .binaryFloat64],
   ]);

   this .binaryInt8    .bytes = 1;
   this .binaryUint8   .bytes = 1;
   this .binaryInt16   .bytes = 2;
   this .binaryUint16  .bytes = 2;
   this .binaryInt32   .bytes = 4;
   this .binaryUint32  .bytes = 4;
   this .binaryFloat32 .bytes = 4;
   this .binaryFloat64 .bytes = 8;
}

Object .assign (Object .setPrototypeOf (PLYBParser .prototype, Parser_PLYAParser .prototype),
{
   getEncoding ()
   {
      return ["ARRAY_BUFFER", "STRING"];
   },
   setInput (inputs)
   {
      this .arrayBuffer  = inputs [0];
      this .dataView     = new DataView (this .arrayBuffer);
      this .input        = inputs [1];
      this .magic        = this .input .match (/^ply\r?\nformat (binary_(?:little|big)_endian) 1.0.*?end_header\r?\n/s);
      this .byteOffset   = this .magic ?.[0] .length;
      this .littleEndian = this .magic ?.[1] === "binary_little_endian";
   },
   isValid ()
   {
      if (!(this .arrayBuffer instanceof ArrayBuffer))
         return false;

      return !! this .magic;
   },
   binaryInt8 ()
   {
      this .value       = this .dataView .getInt8 (this .byteOffset, this .littleEndian);
      this .byteOffset += 1;

      return true;
   },
   binaryUint8 ()
   {
      this .value       = this .dataView .getUint8 (this .byteOffset, this .littleEndian);
      this .byteOffset += 1;

      return true;
   },
   binaryInt16 ()
   {
      this .value       = this .dataView .getInt16 (this .byteOffset, this .littleEndian);
      this .byteOffset += 2;

      return true;
   },
   binaryUint16 ()
   {
      this .value       = this .dataView .getUint16 (this .byteOffset, this .littleEndian);
      this .byteOffset += 2;

      return true;
   },
   binaryInt32 ()
   {
      this .value       = this .dataView .getInt32 (this .byteOffset, this .littleEndian);
      this .byteOffset += 4;

      return true;
   },
   binaryUint32 ()
   {
      this .value       = this .dataView .getUint32 (this .byteOffset, this .littleEndian);
      this .byteOffset += 4;

      return true;
   },
   binaryFloat32 ()
   {
      this .value       = this .dataView .getFloat32 (this .byteOffset, this .littleEndian);
      this .byteOffset += 4;

      return true;
   },
   binaryFloat64 ()
   {
      this .value       = this .dataView .getFloat64 (this .byteOffset, this .littleEndian);
      this .byteOffset += 8;

      return true;
   },
   processElements (elements)
   {
      this .whitespaces = Function .prototype;

      return Parser_PLYAParser .prototype .processElements .call (this, elements);
   },
   parseUnknown ({ count, properties })
   {
      for (let i = 0; i < count; ++ i)
      {
         for (const { count, type } of properties)
         {
            if (count)
            {
               count .call (this);

               this .byteOffset += this .value * this .typeMapping .get (type) .bytes;
            }
            else
            {
               this .byteOffset += this .typeMapping .get (type) .bytes;
            }
         }
      }
   },
   // parseUnknown ({ count, properties })
   // {
   //    let string = "";

   //    for (let i = 0; i < count; ++ i)
   //    {
   //       for (const { count, type, value } of properties)
   //       {
   //          if (count === undefined)
   //          {
   //             value .call (this);

   //             string += this .value + " "
   //          }
   //          else
   //          {
   //             count .call (this);

   //             string += this .value + " "

   //             for (let i = 0, l = this .value; i < l; ++ i)
   //             {
   //                value .call (this);

   //                string += this .value + " "
   //             }
   //          }
   //       }

   //       string += "\n"
   //    }

   //    console .log (string .substring (0, 1000))
   // },
});

const PLYBParser_default_ = PLYBParser;
;

x_ite_Namespace .add ("PLYBParser", "x_ite/Parser/PLYBParser", PLYBParser_default_);
/* harmony default export */ const Parser_PLYBParser = (PLYBParser_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Numbers/Complex.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

function Complex (real, imag)
{
   this .real = real;
   this .imag = imag;
}

Object .assign (Complex .prototype,
{
   *[Symbol .iterator] ()
   {
      yield this .real;
      yield this .imag;
   },
   copy ()
   {
      const copy = Object .create (Complex .prototype);
      copy .real = this .real;
      copy .imag = this .imag;
      return copy;
   },
   assign (complex)
   {
      this .real = complex .real;
      this .imag = complex .imag;
      return this;
   },
   equals (complex)
   {
      return this .real === complex .real &&
             this .imag === complex .imag;
   },
   set (real, imag)
   {
      this .real = real;
      this .imag = imag;
      return this;
   },
   setPolar (magnitude, angle)
   {
      this .real = magnitude * Math .cos (angle);
      this .imag = magnitude * Math .sin (angle);
      return this;
   },
   conjugate ()
   {
      this .imag = -this .imag;
      return this;
   },
   negate ()
   {
      this .real = -this .real;
      this .imag = -this .imag;
      return this;
   },
   inverse ()
   {
      const d = this .real * this .real + this .imag * this .imag;

      this .real /=  d;
      this .imag /= -d;
      return this;
   },
   add (value)
   {
      this .real += value .real;
      this .imag += value .imag;
      return this;
   },
   subtract (value)
   {
      this .real -= value .real;
      this .imag -= value .imag;
      return this;
   },
   multiply (value)
   {
      this .real *= value;
      this .imag *= value;
      return this;
   },
   multComp (value)
   {
      const
         { real: ar, imag: ai } = this,
         { real: br, imag: bi } = value;

      this .real = ar * br - ai * bi;
      this .imag = ar * bi + ai * br;
      return this;
   },
   divide (value)
   {
      this .real /= value;
      this .imag /= value;
      return this;
   },
   divComp (value)
   {
      const
         { real: ar, imag: ai } = this,
         { real: br, imag: bi } = value,
         d = br * br + bi * bi;

      this .real = (ar * br + ai * bi) / d;
      this .imag = (ai * br - ar * bi) / d;
      return this;
   },
   toString ()
   {
      let string = "";

      string += this .real;

      if (this .imag < 0)
      {
         string += this .imag;
         string += "i";
      }
      else if (this .imag > 0)
      {
         string += "+";
         string += this .imag;
         string += "i";
      }

      return string;
   },
});

Object .defineProperties (Complex .prototype,
{
   length: { value: 2 },
   0:
   {
      get ()
      {
         return this .real;
      },
      set (value)
      {
         this .real = value;
      },
   },
   1:
   {
      get ()
      {
         return this .imag;
      },
      set (value)
      {
         this .imag = value;
      },
   },
   magnitude:
   {
      get ()
      {
         if (this .real)
         {
            if (this .imag)
               return Math .hypot (this .real, this .imag);

            return Math .abs (this .real);
         }

         return Math .abs (this .imag);
      },
      set (magnitude)
      {
         this .setPolar (magnitude, this .angle);
      },
   },
   angle:
   {
      get ()
      {
         return Math .atan2 (this .imag, this .real);
      },
      set (angle)
      {
         this .setPolar (this .magnitude, angle);
      },
   },
});

Object .assign (Complex,
{
   Polar (magnitude, angle)
   {
      return Object .create (Complex .prototype) .setPolar (magnitude, angle);
   },
   multiply (lhs, rhs)
   {
      return lhs .copy () .multiply (rhs);
   },
});

const Complex_default_ = Complex;
;

x_ite_Namespace .add ("Complex", "standard/Math/Numbers/Complex", Complex_default_);
/* harmony default export */ const Numbers_Complex = (Complex_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Geometry/Box2.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function Box2 (/* size, center */)
{
   this .matrix = new Numbers_Matrix3 ();

   this .set (... arguments);
}

Object .assign (Box2 .prototype,
{
   copy ()
   {
      const copy = Object .create (Box2 .prototype);
      copy .matrix = this .matrix .copy ();
      return copy;
   },
   assign (box)
   {
      this .matrix .assign (box .matrix);
      return this;
   },
   equals (box)
   {
      return this .matrix .equals (box .matrix);
   },
   set (size, center)
   {
      switch (arguments .length)
      {
         case 0:
         {
            this .matrix .set (0, 0, 0,
                               0, 0, 0,
                               0, 0, 0);

            return this;
         }
         case 2:
         {
            this .matrix .set (size .x / 2, 0, 0,
                               0, size .y / 2, 0,
                               center .x, center .y, 1);

            return this;
         }
         // case 3:
         // {
         //    console .trace ()
         //    return this .setExtents (arguments [0], arguments [1]);
         // }
      }
   },
   setExtents (min, max)
   {
      const
         sx = (max .x - min .x) / 2,
         sy = (max .y - min .y) / 2,
         cx = (max .x + min .x) / 2,
         cy = (max .y + min .y) / 2;

      this .matrix .set (sx,  0, 0,
                          0, sy, 0,
                         cx, cy, 1);

      return this;
   },
   isEmpty ()
   {
      return this .matrix [8] === 0;
   },
   add: (() =>
   {
      const
         lhs_min = new Numbers_Vector2 (0, 0),
         lhs_max = new Numbers_Vector2 (0, 0),
         rhs_min = new Numbers_Vector2 (0, 0),
         rhs_max = new Numbers_Vector2 (0, 0);

      return function (box)
      {
         if (this .isEmpty ())
            return this .assign (box);

         if (box .isEmpty ())
            return this;

         this .getExtents (lhs_min, lhs_max);
         box  .getExtents (rhs_min, rhs_max);

         return this .setExtents (lhs_min .min (rhs_min), lhs_max .max (rhs_max));
      };
   })(),
   multLeft (matrix)
   {
      this .matrix .multLeft (matrix);
      return this;
   },
   multRight (matrix)
   {
      this .matrix .multRight (matrix);
      return this;
   },
   getExtents (min, max)
   {
      this .getAbsoluteExtents (min, max);

      min .add (this .center);
      max .add (this .center);
   },
   getAbsoluteExtents: (() =>
   {
      const p1 = new Numbers_Vector2 (0, 0);

      return function (min, max)
      {
         const
            m = this .matrix,
            x = m .xAxis,
            y = m .yAxis;

         p1 .assign (x) .add (y);

         const p2 = y .subtract (x);

         min .assign (p1) .min (p2);
         max .assign (p1) .max (p2);

         p1 .negate ();
         p2 .negate ();

         min .min (p1, p2);
         max .max (p1, p2);
      };
   })(),
   containsPoint: (() =>
   {
      const
         min = new Numbers_Vector2 (0, 0),
         max = new Numbers_Vector2 (0, 0);

      return function (point)
      {
         this .getExtents (min, max);

         return min .x <= point .x &&
                max .x >= point .x &&
                min .y <= point .y &&
                max .y >= point .y;
      };
   })(),
   toString ()
   {
      return `${this .size}, ${this .center}`;
   },
});

Object .assign (Box2,
{
   Extents (min, max)
   {
      return new Box2 () .setExtents (min, max);
   },
   Points (points)
   {
      const
         min = new Numbers_Vector2 (Number .POSITIVE_INFINITY, Number .POSITIVE_INFINITY),
         max = new Numbers_Vector2 (Number .NEGATIVE_INFINITY, Number .NEGATIVE_INFINITY);

      for (const point of points)
      {
         min .min (point);
         max .max (point);
      }

      return new Box2 () .setExtents (min, max);
   },
});

Object .defineProperties (Box2 .prototype,
{
   size:
   {
      get: (() =>
      {
         const
            min = new Numbers_Vector2 (0, 0),
            max = new Numbers_Vector2 (0, 0);

         return function ()
         {
            this .getAbsoluteExtents (min, max);

            return max .subtract (min);
         };
      })(),
      enumerable: true,
   },
   center:
   {
      get ()
      {
         return this .matrix .origin;
      },
      enumerable: true,
   },
});

const Box2_default_ = Box2;
;

x_ite_Namespace .add ("Box2", "standard/Math/Geometry/Box2", Box2_default_);
/* harmony default export */ const Geometry_Box2 = (Box2_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Algorithms/Bezier.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








const { interval: Bezier_interval } = Math_Algorithm;

// https://pomax.github.io/bezierinfo/

const Bezier =
{
   quadric: (() =>
   {
      const
         c = new Numbers_Matrix3 (1, 0, 0, -2, 2, 0, 1, -2, 1),
         p = new Numbers_Matrix3 ();

      return function (x0, y0, z0, x1, y1, z1, x2, y2, z2, steps, points)
      {
         p .set (x0, y0, z0, x1, y1, z1, x2, y2, z2)
            .multLeft (c);

         for (let i = 0, d = steps - 1; i < steps; ++ i)
         {
            const t = i / d;

            points .push (p .multVecMatrix (new Numbers_Vector3 (1, t, t * t)));
         }
      };
   })(),
   cubic: (() =>
   {
      const
         v = new Numbers_Vector4 (0, 0, 0, 0),
         c = new Numbers_Matrix4 (1, 0, 0, 0, -3, 3, 0, 0, 3, -6, 3, 0, -1, 3, -3, 1),
         p = new Numbers_Matrix4 ();

      return function (x0, y0, z0, x1, y1, z1, x2, y2, z2, x3, y3, z3, steps, points)
      {
         p .set (x0, y0, z0, 0, x1, y1, z1, 0, x2, y2, z2, 0, x3, y3, z3, 0)
            .multLeft (c);

         for (let i = 0, d = steps - 1; i < steps; ++ i)
         {
            const t = i / d;

            p .multVecMatrix (v .set (1, t, t * t, t * t * t));

            points .push (new Numbers_Vector3 (v .x, v .y, v .z));
         }
      };
   })(),
   arc (ax, ay, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y, steps, points)
   {
      // https://ericeastwood.com/blog/25/curves-and-arcs-quadratic-cubic-elliptical-svg-implementations
      // See https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes.

      // If the endpoints are identical, then this is equivalent to omitting the elliptical arc segment entirely.
      if (ax === x && ay === y)
      {
         points .push (new Numbers_Vector3 (x, y, 0));
         return;
      }

      // In accordance to: http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters

      rx = Math .abs (rx);
      ry = Math .abs (ry);

      // If rx = 0 or ry = 0 then this arc is treated as a straight line segment joining the endpoints.
      if (rx === 0 || ry === 0)
      {
         points .push (new Numbers_Vector3 (ax, ay, 0), new Numbers_Vector3 (x, y, 0));
         return;
      }

      const
         rx2 = rx * rx,
         ry2 = ry * ry;

      // In accordance to: http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters

      xAxisRotation = Bezier_interval (xAxisRotation, 0, 2 * Math .PI);

      const
         sinRotation = Math .sin (xAxisRotation),
         cosRotation = Math .cos (xAxisRotation);

      // Following "Conversion from endpoint to center parameterization"
      // http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter

      // Step #1: Compute transformedPoint
      const d = new Numbers_Vector2 (ax - x, ay - y) .divide (2);

      const transformedPoint = new Numbers_Vector2 ( cosRotation * d .x + sinRotation * d .y,
                                             -sinRotation * d .x + cosRotation * d .y);

      const transformedPoint2 = transformedPoint .copy () .multVec (transformedPoint);

      // Ensure radii are large enough
      const radiiCheck = transformedPoint2 .x / rx2 + transformedPoint2 .y / ry2;

      if (radiiCheck > 1)
      {
         rx = Math .sqrt (radiiCheck) * rx;
         ry = Math .sqrt (radiiCheck) * ry;
      }

      // Step #2: Compute transformedCenter
      const cSquareNumerator = rx2 * ry2 - rx2 * transformedPoint2 .y - ry2 * transformedPoint2 .x;
      const cSquareRootDenom =             rx2 * transformedPoint2 .y + ry2 * transformedPoint2 .x;
      let   cRadicand        = cSquareNumerator / cSquareRootDenom;

      // Make sure this never drops below zero because of precision
      cRadicand = Math .max (0, cRadicand);

      const cCoef = (largeArcFlag !== sweepFlag ? 1 : -1) * Math .sqrt (cRadicand);

      const transformedCenter = new Numbers_Vector2 ( cCoef * rx * transformedPoint .y / ry,
                                             -cCoef * ry * transformedPoint .x / rx);

      // Step #3: Compute center
      const center = new Numbers_Vector2 (cosRotation * transformedCenter .x - sinRotation * transformedCenter .y + ((ax + x) / 2),
                                  sinRotation * transformedCenter .x + cosRotation * transformedCenter .y + ((ay + y) / 2));

      // Step #4: Compute start/sweep angles
      const startVector = new Numbers_Vector2 ((transformedPoint .x - transformedCenter .x) / rx,
                                       (transformedPoint .y - transformedCenter .y) / ry);

      const endVector = new Numbers_Vector2 ((-transformedPoint .x - transformedCenter .x) / rx,
                                     (-transformedPoint .y - transformedCenter .y) / ry);

      const get_angle  = (x) => { return x > 0 ? x : 2 * Math .PI + x; }; // transform angle to range [0, 2pi]
      const startAngle = get_angle (Math .atan2 (startVector .y, startVector .x));
      const endAngle   = get_angle (Math .atan2 (endVector   .y, endVector   .x));

      let sweepAngle = endAngle - startAngle;

      if (largeArcFlag)
      {
         // sweepAngle must be positive
         if (sweepAngle < 0)
            sweepAngle += 2 * Math .PI;
      }
      else
      {
         // sweepAngle must be negative
         if (sweepAngle > 0)
            sweepAngle -= 2 * Math .PI;
      }

      if (sweepFlag && sweepAngle < 0)
         sweepAngle += 2 *Math .PI;

      else if (!sweepFlag && sweepAngle > 0)
         sweepAngle -= 2 * Math .PI;

      // Interpolate:

      const bezier_steps   = Math .max (4, Math .abs (sweepAngle) * steps / (2 * Math .PI));
      const bezier_steps_1 = bezier_steps - 1;

      points .push (new Numbers_Vector3 (ax, ay, 0));

      for (let i = 1; i < bezier_steps_1; ++ i)
      {
         const t = i / bezier_steps_1;

         // From http://www.w3.org/TR/SVG/implnote.html#ArcParameterizationAlternatives
         const angle = startAngle + (sweepAngle * t);
         const x     = rx * Math .cos (angle);
         const y     = ry * Math .sin (angle);

         points .push (new Numbers_Vector3 (cosRotation * x - sinRotation * y + center .x,
                                    sinRotation * x + cosRotation * y + center .y,
                                    0));
      }

      points .push (new Numbers_Vector3 (x, y, 0));
   },
};

const Bezier_default_ = Bezier;
;

x_ite_Namespace .add ("Bezier", "standard/Math/Algorithms/Bezier", Bezier_default_);
/* harmony default export */ const Algorithms_Bezier = (Bezier_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Utility/MatrixStack.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

function MatrixStack (Type)
{
   return Object .assign ([ new Type () ],
   {
      top: 0,
      set (matrix)
      {
         this [this .top] .assign (matrix);
      },
      get ()
      {
         return this [this .top];
      },
      push ()
      {
         const top = ++ this .top;

         if (top < this .length)
            this [top] .assign (this [top - 1]);
         else
            this [top] = this [top - 1] .copy ();
      },
      pushMatrix (matrix)
      {
         const top = ++ this .top;

         if (top < this .length)
            this [top] .assign (matrix);
         else
            this [top] = matrix .copy ();
      },
      pop ()
      {
         -- this .top;
      },
      clear ()
      {
         this .top = 0;
      },
      size ()
      {
         return this .top + 1;
      },
      identity ()
      {
         this [this .top] .identity ();
      },
      multLeft (matrix)
      {
         this [this .top] .multLeft (matrix);
      },
      translate (vector)
      {
         this [this .top] .translate (vector);
      },
      rotate (rotation)
      {
         this [this .top] .rotate (rotation);
      },
      scale (vector)
      {
         this [this .top] .scale (vector);
      },
   });
}

const MatrixStack_default_ = MatrixStack;
;

x_ite_Namespace .add ("MatrixStack", "standard/Math/Utility/MatrixStack", MatrixStack_default_);
/* harmony default export */ const Utility_MatrixStack = (MatrixStack_default_);
;// CONCATENATED MODULE: ./src/x_ite/Parser/SVGParser.js
/* provided dependency */ var SVGParser_$ = __webpack_require__(659);
/* provided dependency */ var libtess = __webpack_require__(793);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/


















/*
 *  Grammar
 */

// Lexical elements
const SVGParser_Grammar = Parser_Expressions ({
   // General
   whitespaces: /[\x20\n\t\r]+/gy,
   comma: /,/gy,
   openParenthesis: /\(/gy,
   closeParenthesis: /\)/gy,

   // Units
   length: /(em|ex|px|in|cm|mm|pt|pc|%)/gy,
   percent: /%/gy,

   // Values
   int32: /((?:0[xX][\da-fA-F]+)|(?:[+-]?\d+))/gy,
   double: /([+-]?(?:(?:(?:\d*\.\d+)|(?:\d+(?:\.)?))(?:[eE][+-]?\d+)?))/gy,
   constants: /([+-])((?:NAN|INF|INFINITY))/igy,
   matrix: /matrix/gy,
   translate: /translate/gy,
   rotate: /rotate/gy,
   scale: /scale/gy,
   skewX: /skewX/gy,
   skewY: /skewY/gy,
   color: /([a-zA-Z]+|#[\da-fA-F]+|rgba?\(.*?\))/gy,
   url: /url\("?(.*?)"?\)/gy,
   path: /([mMlLhHvVqQtTcCsSaAzZ])/gy,
});

/*
 *  Constants
 */

const
   MM     = 0.001,     // One mm in meters.
   CM     = 0.01,      // One cm in meters.
   INCH   = 0.0254,    // One inch in meters.
   POINT  = INCH / 72, // One point in meters.
   PICA   = INCH / 6,  // One pica in meters.
   PIXEL  = INCH / 90, // One pixel in meters.
   EM     = 16,        // One em in pixels.
   SPREAD = 16;        // Spread factor, Integer.

/*
 *  Parser
 */

function SVGParser (scene)
{
   Parser_X3DParser    .call (this, scene);
   Parser_X3DOptimizer .call (this);

   // Optimizer

   this .removeGroups         = true;
   this .removeEmptyGroups    = true;
   this .combineGroupingNodes = false;

   // Options

   this .solid = false; // Are 2D primitives solid?

   // Globals

   this .viewBox          = new Numbers_Vector4 (0, 0, 100, 100);
   this .modelMatrix      = new Utility_MatrixStack (Numbers_Matrix4);
   this .fillGeometries   = new Map ();
   this .strokeGeometries = new Map ();
   this .lineProperties   = new Map ();
   this .tessy            = this .createTesselator ();
   this .canvas           = document .createElement ("canvas");
   this .context          = this .canvas .getContext ("2d");

   this .styles = [{
      display: "inline",
      fillType: "COLOR",
      fillColor: Numbers_Color4 .Black,
      fillURL: "",
      fillOpacity: 1,
      fillRule: "nonzero",
      strokeType: "none",
      strokeColor: Numbers_Color4 .Black,
      strokeURL: "",
      strokeOpacity: 1,
      strokeWidth: 1,
      opacity: 1,
      stopColor: Numbers_Color4 .Black,
      stopOpacity: 1,
      vectorEffect: "none",
   }];

   // Constants

   const browser = scene .getBrowser ()

   switch (browser .getBrowserOption ("PrimitiveQuality"))
   {
      case "LOW":
         this .BEZIER_STEPS = 6;  // Subdivisions of a span.
         this .CIRCLE_STEPS = 20; // Subdivisions of a circle, used for arc and rounded rect.
         break;
      case "HIGH":
         this .BEZIER_STEPS = 10; // Subdivisions of a span.
         this .CIRCLE_STEPS = 64; // Subdivisions of a circle, used for arc and rounded rect.
         break;
      default:
         this .BEZIER_STEPS = 8;  // Subdivisions of a span.
         this .CIRCLE_STEPS = 32; // Subdivisions of a circle, used for arc and rounded rect.
         break;
   }

   switch (browser .getBrowserOption ("TextureQuality"))
   {
      case "LOW":
         this .GRADIENT_SIZE = 128; // In pixels.
         break;
      case "HIGH":
         this .GRADIENT_SIZE = 512; // In pixels.
         break;
      default:
         this .GRADIENT_SIZE = 256; // In pixels.
         break;
   }

   this .canvas .width  = this .GRADIENT_SIZE;
   this .canvas .height = this .GRADIENT_SIZE;
}

Object .assign (Object .setPrototypeOf (SVGParser .prototype, Parser_X3DParser .prototype),
   Parser_X3DOptimizer .prototype,
{
   CONSTANTS: new Map ([
      ["NAN", NaN],
      ["INF", Infinity],
      ["INFINITY", Infinity],
   ]),
   getEncoding ()
   {
      return "XML";
   },
   setInput (xmlElement)
   {
      try
      {
         if (typeof xmlElement === "string")
            xmlElement = SVGParser_$.parseXML (xmlElement);

         this .input = xmlElement;
      }
      catch
      {
         this .input = undefined;
      }
   },
   isValid ()
   {
      if (!(this .input instanceof XMLDocument))
         return false;

      if (SVGParser_$(this .input) .children ("svg") .length)
         return true;

      if (this .input .nodeName === "svg")
         return true;

      return false;
   },
   parseIntoScene (resolve, reject)
   {
      this .xmlElement (this .input)
         .then (resolve)
         .catch (reject);
   },
   xmlElement: async function (xmlElement)
   {
      switch (xmlElement .nodeName)
      {
         case "#document":
         {
            const svg = SVGParser_$(xmlElement) .children ("svg");

            for (const xmlElement of svg)
               await this .svgElement (xmlElement);

            break;
         }
         case "svg":
         {
            await this .svgElement (xmlElement);
            break;
         }
      }

      return this .getScene ();
   },
   svgElement: async function (xmlElement)
   {
      const
         browser = this .getBrowser (),
         scene   = this .getScene ();

      scene .setEncoding ("SVG");
      scene .setProfile (browser .getProfile ("Interchange"));
      scene .addComponent (browser .getComponent ("Geometry2D", 2));

      await this .loadComponents ();

      // Init nodes.

      this .document              = this .input;
      this .rootTransform         = scene .createNode ("Transform");
      this .groupNodes            = [this .rootTransform];
      this .texturePropertiesNode = this .createTextureProperties ();

      // Create background.

      const background = scene .createNode ("Background");

      background .skyColor = [1, 1, 1];

      scene .getRootNodes () .push (background);

      // Create navigation info.

      const navigationInfo = scene .createNode ("NavigationInfo");

      navigationInfo .type = ["PLANE_create3000.github.io", "PLANE", "EXAMINE", "ANY"];

      scene .getRootNodes () .push (navigationInfo);

      // Get attributes of svg element.

      const
         defaultWidth   = this .lengthAttribute (xmlElement .getAttribute ("width"),  300, "width"),
         defaultHeight  = this .lengthAttribute (xmlElement .getAttribute ("height"), 150, "height"),
         defaultViewBox = this .viewBox .set (0, 0, defaultWidth, defaultHeight),
         viewBox        = this .viewBoxAttribute (xmlElement .getAttribute ("viewBox"), defaultViewBox),
         width          = this .lengthAttribute (xmlElement .getAttribute ("width"),  viewBox [2], "width"),
         height         = this .lengthAttribute (xmlElement .getAttribute ("height"), viewBox [3], "height");

      if (true) // default
      {
         // preserveAspectRatio = "xMidYMid meet"

         const
            r  = width / height,
            rv = viewBox [2] / viewBox [3];

         if (rv > r)
            viewBox [3] += viewBox [2] / r - viewBox [3];
         else
            viewBox [2] += viewBox [3] * r - viewBox [2];
      }

      // Create viewpoint.

      const
         viewpoint = scene .createNode ("OrthoViewpoint"),
         x         =  (viewBox .x + width  / 2) * PIXEL,
         y         = -(viewBox .y + height / 2) * PIXEL;

      viewpoint .position         = new Numbers_Vector3 (x, y, 10);
      viewpoint .centerOfRotation = new Numbers_Vector3 (x, y, 0);

      viewpoint .fieldOfView = [
         -width  / 2 * PIXEL,
         -height / 2 * PIXEL,
          width  / 2 * PIXEL,
          height / 2 * PIXEL,
      ];

      scene .getRootNodes () .push (viewpoint);

      // Create view matrix.

      const
         scale       = new Numbers_Vector3 (width * PIXEL / viewBox [2], -height * PIXEL / viewBox [3], 1),
         translation = new Numbers_Vector3 (-viewBox .x, viewBox .y, 0) .multVec (scale);

      this .rootTransform .translation = translation;
      this .rootTransform .scale       = scale;

      // Parse elements.

      this .elements (xmlElement);

      // Add root Transform node.

      scene .addNamedNode (scene .getUniqueName ("ViewBox"), this .rootTransform);
      scene .addExportedNode (scene .getUniqueExportName ("ViewBox"), this .rootTransform);
      scene .getRootNodes () .push (this .rootTransform);

      // Optimize scene graph.

      this .optimizeSceneGraph (scene .getRootNodes ());
   },
   elements (xmlElement)
   {
      for (const childNode of xmlElement .childNodes)
		   this .element (childNode);
   },
   element (xmlElement)
   {
      switch (xmlElement .nodeName)
      {
         case "use":
            return this .useElement (xmlElement);
         case "g":
            return this .gElement (xmlElement);
         case "switch":
            return this .switchElement (xmlElement);
         case "a":
            return this .aElement (xmlElement);
         case "rect":
            return this .rectElement (xmlElement);
         case "circle":
            return this .circleElement (xmlElement);
         case "ellipse":
            return this .ellipseElement (xmlElement);
         case "text":
            return this .textElement (xmlElement);
         case "image":
            return this .imageElement (xmlElement);
         case "polyline":
            return this .polylineElement (xmlElement);
         case "polygon":
            return this .polygonElement (xmlElement);
         case "path":
            return this .pathElement (xmlElement);
      }
   },
   useElement (xmlElement)
   {
      // Get href.

      const usedElement = this .hrefAttribute (xmlElement .getAttribute ("href") || xmlElement .getAttribute ("xlink:href"));

      if (!usedElement)
         return;

      // Determine style.

      if (!this .styleAttributes (xmlElement))
         return;

      // Create Transform node.

      const
         x      = this .lengthAttribute (xmlElement .getAttribute ("x"),      0, "width"),
         y      = this .lengthAttribute (xmlElement .getAttribute ("y"),      0, "height"),
         width  = this .lengthAttribute (xmlElement .getAttribute ("width"),  0, "width"),
         height = this .lengthAttribute (xmlElement .getAttribute ("height"), 0, "height");

      const transformNode = this .createTransform (xmlElement, new Numbers_Vector2 (x, y));

      this .groupNodes .push (transformNode);

      this .element (usedElement);

      this .popAll ();
   },
   gElement (xmlElement)
   {
      // Determine style.

      if (!this .styleAttributes (xmlElement))
         return;

      // Create Transform node.

      const transformNode = this .createTransform (xmlElement);

      // Get child elements.

      this .groupNodes .push (transformNode);

      this .elements (xmlElement);

      this .popAll ();
   },
   switchElement (xmlElement)
   {
      // Determine style.

      if (!this .styleAttributes (xmlElement))
         return;

      // Create Transform node.

      const
         scene         = this .getExecutionContext (),
         transformNode = this .createTransform (xmlElement),
         switchNode    = scene .createNode ("Switch");

      transformNode .children .push (switchNode);
      switchNode .whichChoice = 0;

      // Get child elements.

      this .groupNodes .push (switchNode);

      this .elements (xmlElement);

      this .popAll ();
   },
   aElement (xmlElement)
   {
      // Determine style.

      if (!this .styleAttributes (xmlElement))
         return;

      // Get attributes.

      const
         href   = xmlElement .getAttribute ("href") || xmlElement .getAttribute ("xlink:href"),
         title  = xmlElement .getAttribute ("title") || xmlElement .getAttribute ("xlink:title"),
         target = xmlElement .getAttribute ("target");

      // Create Transform node.

      const
         scene         = this .getExecutionContext (),
         transformNode = this .createTransform (xmlElement),
         anchorNode    = scene .createNode ("Anchor");

      transformNode .children .push (anchorNode);

      anchorNode .description = title;
      anchorNode .url         = [href];

      if (target)
         anchorNode .parameter = [`target=${target}`];

      // Get child elements.

      this .groupNodes .push (anchorNode);

      this .elements (xmlElement);

      this .popAll ();
   },
   rectElement (xmlElement)
   {
      // Create Transform node.

      const
         x      = this .lengthAttribute (xmlElement .getAttribute ("x"),      0, "width"),
         y      = this .lengthAttribute (xmlElement .getAttribute ("y"),      0, "height"),
         width  = this .lengthAttribute (xmlElement .getAttribute ("width"),  0, "width"),
         height = this .lengthAttribute (xmlElement .getAttribute ("height"), 0, "height");

      let
         rx = Math .max (0, this .lengthAttribute (xmlElement .getAttribute ("rx"), 0, "width")),
         ry = Math .max (0, this .lengthAttribute (xmlElement .getAttribute ("ry"), 0, "height"));

      if (rx === 0 && ry === 0)
      {
         // Determine style.

         if (!this .styleAttributes (xmlElement))
            return;

         // Create Transform node.

         const
            scene         = this .getExecutionContext (),
            size          = new Numbers_Vector2 (width, height),
            center        = new Numbers_Vector2 (x + width / 2, y + height / 2),
            bbox          = new Geometry_Box2 (size, center),
            transformNode = this .createTransform (xmlElement, center);

         this .groupNodes .push (transformNode);

         // Create nodes.

         if (this .style .fillType !== "none")
         {
            const
               shapeNode     = scene .createNode ("Shape"),
               rectangleNode = this .fillGeometries .get (xmlElement);

            transformNode .children .push (shapeNode);
            shapeNode .appearance = this .createFillAppearance (bbox);

            if (rectangleNode)
            {
               shapeNode .geometry = rectangleNode;
            }
            else
            {
               const rectangleNode = scene .createNode ("Rectangle2D");

               this .fillGeometries .set (xmlElement, rectangleNode);

               shapeNode .geometry  = rectangleNode;
               rectangleNode .solid = this .solid;
               rectangleNode .size  = size;
            }
         }

         if (this .style .strokeType !== "none")
         {
            const
               shapeNode    = scene .createNode ("Shape"),
               polylineNode = this .strokeGeometries .get (xmlElement);

            transformNode .children .push (shapeNode);
            shapeNode .appearance = this .createStrokeAppearance ();

            if (polylineNode)
            {
               shapeNode .geometry = polylineNode;
            }
            else
            {
               const
                  polylineNode = scene .createNode ("Polyline2D"),
                  width1_2     = width / 2,
                  height1_2    = height / 2;

               this .strokeGeometries .set (xmlElement, polylineNode);

               shapeNode .geometry = polylineNode;

               polylineNode .lineSegments = [ width1_2,  height1_2,
                                             -width1_2,  height1_2,
                                             -width1_2, -height1_2,
                                              width1_2, -height1_2,
                                              width1_2,  height1_2];
            }
         }

         this .popAll ();
      }
      else
      {
         // Create points.

         if (rx && !ry) ry = rx;
         if (ry && !rx) rx = ry;

         rx = Math .min (rx, width / 2);
         ry = Math .min (ry, height / 2);

         const
            xOffsets = [x + width - rx, x + rx , x + rx, x + width - rx],
            yOffsets = [y + height - ry, y + height - ry, y + ry, y + ry],
            points   = Object .assign ([ ], { closed: true });

         for (let c = 0; c < 4; ++ c)
         {
            const s = c * Math .PI / 2;

            for (let i = 0, N = this .CIRCLE_STEPS / 4; i < N; ++ i)
            {
               const p = Numbers_Complex .Polar (1, s + Math .PI / 2 * i / (N - 1));

               points .push (new Numbers_Vector3 (xOffsets [c] + p .real * rx, yOffsets [c] + p .imag * ry, 0));
            }
         }

         points .pop ();

         // Create nodes.

         this .pathLikeElement (xmlElement, [points]);
      }
   },
   circleElement (xmlElement)
   {
      // Determine style.

      if (!this .styleAttributes (xmlElement))
         return;

      // Create Transform node.

      const
         cx = this .lengthAttribute (xmlElement .getAttribute ("cx"), 0, "width"),
         cy = this .lengthAttribute (xmlElement .getAttribute ("cy"), 0, "height"),
         r  = this .lengthAttribute (xmlElement .getAttribute ("r"),  0);

      const
         scene         = this .getExecutionContext (),
         bbox          = new Geometry_Box2 (new Numbers_Vector2 (r * 2, r * 2), new Numbers_Vector2 (cx, cy)),
         transformNode = this .createTransform (xmlElement, new Numbers_Vector2 (cx, cy));

      this .groupNodes .push (transformNode);

      // Create nodes.

      if (this .style .fillType !== "none")
      {
         const
            shapeNode = scene .createNode ("Shape"),
            diskNode  = this .fillGeometries .get (xmlElement);

         transformNode .children .push (shapeNode);
         shapeNode .appearance = this .createFillAppearance (bbox);

         if (diskNode)
         {
            shapeNode .geometry = diskNode;
         }
         else
         {
            const diskNode = scene .createNode ("Disk2D");

            this .fillGeometries .set (xmlElement, diskNode);

            shapeNode .geometry   = diskNode;
            diskNode .solid       = this .solid;
            diskNode .outerRadius = r;
         }
      }

      if (this .style .strokeType !== "none")
      {
         const
            shapeNode  = scene .createNode ("Shape"),
            circleNode = this .strokeGeometries .get (xmlElement);

         transformNode .children .push (shapeNode);
         shapeNode .appearance = this .createStrokeAppearance ();

         if (circleNode)
         {
            shapeNode .geometry = circleNode;
         }
         else
         {
            const circleNode = scene .createNode ("Circle2D");

            this .strokeGeometries .set (xmlElement, circleNode);

            shapeNode .geometry = circleNode;
            circleNode .radius  = r;
         }
      }

      this .popAll ();
   },
   ellipseElement (xmlElement)
   {
      // Determine style.

      if (!this .styleAttributes (xmlElement))
         return;

      // Create Transform node.

      const
         cx = this .lengthAttribute (xmlElement .getAttribute ("cx"), 0, "width"),
         cy = this .lengthAttribute (xmlElement .getAttribute ("cy"), 0, "height"),
         rx = this .lengthAttribute (xmlElement .getAttribute ("rx"), 0, "width"),
         ry = this .lengthAttribute (xmlElement .getAttribute ("ry"), 0, "height");

      const
         scene         = this .getExecutionContext (),
         rMin          = Math .min (rx, ry),
         bbox          = new Geometry_Box2 (new Numbers_Vector2 (rx * 2, ry * 2), new Numbers_Vector2 (cx, cy)),
         transformNode = this .createTransform (xmlElement, new Numbers_Vector2 (cx, cy), new Numbers_Vector2 (rx / rMin, ry / rMin));

      this .groupNodes .push (transformNode);

      // Create nodes.

      if (this .style .fillType !== "none")
      {
         const
            shapeNode = scene .createNode ("Shape"),
            diskNode  = this .fillGeometries .get (xmlElement);

         transformNode .children .push (shapeNode);
         shapeNode .appearance = this .createFillAppearance (bbox);

         if (diskNode)
         {
            shapeNode .geometry = diskNode;
         }
         else
         {
            const diskNode = scene .createNode ("Disk2D");

            this .fillGeometries .set (xmlElement, diskNode);

            shapeNode .geometry   = diskNode;
            diskNode .solid       = this .solid;
            diskNode .outerRadius = rMin;
         }
      }

      if (this .style .strokeType !== "none")
      {
         const
            shapeNode  = scene .createNode ("Shape"),
            circleNode = this .strokeGeometries .get (xmlElement);

         transformNode .children .push (shapeNode);
         shapeNode .appearance = this .createStrokeAppearance ();

         if (circleNode)
         {
            shapeNode .geometry = circleNode;
         }
         else
         {
            const circleNode = scene .createNode ("Circle2D");

            this .strokeGeometries .set (xmlElement, circleNode);

            shapeNode .geometry = circleNode;
            circleNode .radius  = rMin;
         }
      }

      this .popAll ();
   },
   textElement (xmlElement)
   {

   },
   imageElement (xmlElement)
   {
      const transformNode = this .fillGeometries .get (xmlElement);

      if (transformNode)
      {
         this .groupNodes .at (-1) .children .push (transformNode);
      }
      else
      {
         // Determine style.

         if (!this .styleAttributes (xmlElement))
            return;

         // Create Transform node.

         const
            x      = this .lengthAttribute (xmlElement .getAttribute ("x"),      0, "width"),
            y      = this .lengthAttribute (xmlElement .getAttribute ("y"),      0, "height"),
            width  = this .lengthAttribute (xmlElement .getAttribute ("width"),  0, "width"),
            height = this .lengthAttribute (xmlElement .getAttribute ("height"), 0, "height"),
            href   = xmlElement .getAttribute ("href") || xmlElement .getAttribute ("xlink:href");

         const
            scene         = this .getExecutionContext (),
            transformNode = this .createTransform (xmlElement, new Numbers_Vector2 (x + width / 2, y + height / 2), new Numbers_Vector2 (1, -1));

         this .fillGeometries .set (xmlElement, transformNode);
         this .groupNodes .push (transformNode);

         // Create nodes.

         const
            shapeNode      = scene .createNode ("Shape"),
            appearanceNode = scene .createNode ("Appearance"),
            textureNode    = scene .createNode ("ImageTexture"),
            rectangleNode  = scene .createNode ("Rectangle2D");

         shapeNode .appearance          = appearanceNode;
         shapeNode .geometry            = rectangleNode;
         appearanceNode .texture        = textureNode;
         textureNode .url               = [href];
         textureNode .textureProperties = this .texturePropertiesNode;
         rectangleNode .solid           = this .solid;
         rectangleNode .size            = new Numbers_Vector2 (width, height);

         transformNode .children .push (shapeNode);

         this .popAll ();
      }
   },
   polylineElement (xmlElement)
   {
      // Get points.

      const points = [ ];

      if (!this .pointsAttribute (xmlElement .getAttribute ("points"), points))
         return;

      // Create nodes.

      this .pathLikeElement (xmlElement, [points]);
   },
   polygonElement (xmlElement)
   {
      // Get points.

      const points = Object .assign ([ ], { closed: true });

      if (!this .pointsAttribute (xmlElement .getAttribute ("points"), points))
         return;

      // Create nodes.

      this .pathLikeElement (xmlElement, [points]);
   },
   pathElement (xmlElement)
   {
      // Get path points.

      const contours = [ ];

      if (!this .dAttribute (xmlElement .getAttribute ("d"), contours))
         return;

      // Create nodes.

      this .pathLikeElement (xmlElement, contours);
   },
   pathLikeElement (xmlElement, contours)
   {
      // Determine style.

      if (!this .styleAttributes (xmlElement))
         return;

      // Filter consecutive equal points.

      const EPSILON = 1e-9; // Min point distance.

      contours = contours .map (points =>
      {
         if (points .closed)
         {
            return Object .assign (points .filter ((p, i, a) => p .distance (a [(i + 1) % a .length]) > EPSILON),
            {
               closed: true,
            });
         }
         else
         {
            return points .filter ((p, i, a) => !i || p .distance (a [i - 1]) > EPSILON);
         }
      })
      .filter (points => points .length > 2);

      // Add index property to points.

      contours .forEach ((points, i, a) => points .index = i ? a [i - 1] .index + a [i - 1] .length : 0);

      // Create Transform node.

      const
         scene         = this .getExecutionContext (),
         transformNode = this .createTransform (xmlElement),
         bbox          = new Geometry_Box2 ();

      for (const points of contours)
         bbox .add (Geometry_Box2 .Points (points));

      this .groupNodes .push (transformNode);

      // Create nodes.

      const coordinateNode = scene .createNode ("Coordinate");

      for (const points of contours)
         coordinateNode .point .push (... points);

      if (this .style .fillType !== "none")
      {
         const
            shapeNode    = scene .createNode ("Shape"),
            geometryNode = this .fillGeometries .get (xmlElement);

         transformNode .children .push (shapeNode);
         shapeNode .appearance = this .createFillAppearance (bbox);

         if (geometryNode)
         {
            shapeNode .geometry = geometryNode;
         }
         else
         {
            const geometryNode = scene .createNode ("IndexedTriangleSet");

            this .fillGeometries .set (xmlElement, geometryNode);

            shapeNode .geometry    = geometryNode;
            geometryNode .solid    = this .solid;
            geometryNode .index    = this .triangulatePolygon (contours, coordinateNode);
            geometryNode .texCoord = this .createTextureCoordinate (coordinateNode, bbox, shapeNode .appearance);
            geometryNode .coord    = coordinateNode;
         }
      }

      if (this .style .strokeType !== "none")
      {
         const
            shapeNode    = scene .createNode ("Shape"),
            geometryNode = this .strokeGeometries .get (xmlElement);

         transformNode .children .push (shapeNode);
         shapeNode .appearance = this .createStrokeAppearance ();

         if (geometryNode)
         {
            shapeNode .geometry = geometryNode;
         }
         else
         {
            const geometryNode = scene .createNode ("IndexedLineSet");

            this .strokeGeometries .set (xmlElement, geometryNode);

            shapeNode .geometry = geometryNode;
            geometryNode .coord = coordinateNode;

            // Create contour indices.

            const indices = geometryNode .coordIndex;

            for (const points of contours)
            {
               for (const i of points .keys ())
                  indices .push (points .index + i);

               if (points .closed)
                  indices .push (points .index);

               indices .push (-1);
            }
         }
      }

      this .popAll ();
   },
   linearGradientElementUrl (xmlElement, bbox)
   {
      const
         g        = this .linearGradientElement (xmlElement, bbox, { stops: [ ] }),
         gradient = this .context .createLinearGradient (g .x1, g .y1, g .x2, g .y2);

      return this .drawGradient (gradient, g, bbox);
   },
   linearGradientElement (xmlElement, bbox, gradient)
   {
      if (xmlElement .nodeName !== "linearGradient")
         return;

      // Attribute xlink:href

      const refElement = this .hrefAttribute (xmlElement .getAttribute ("href") || xmlElement .getAttribute ("xlink:href"));

      if (refElement)
         this .gradientElement (refElement, bbox, gradient);

      // Attributes

      gradient .x1        = this .lengthAttribute (xmlElement .getAttribute ("x1"), gradient .x1 || 0, "width");
      gradient .y1        = this .lengthAttribute (xmlElement .getAttribute ("y1"), gradient .y1 || 0, "height");
      gradient .x2        = this .lengthAttribute (xmlElement .getAttribute ("x2"), gradient .x2 || 1, "width");
      gradient .y2        = this .lengthAttribute (xmlElement .getAttribute ("y2"), gradient .y2 || 0, "height");
      gradient .units     = xmlElement .getAttribute ("gradientUnits") || "objectBoundingBox";
      gradient .transform = this .transformAttribute (xmlElement .getAttribute ("gradientTransform"));

      // Spread matrix

      const
         s = new Numbers_Matrix3 (),
         c = new Numbers_Vector2 (gradient .x1, gradient .y1);

      s .translate (c);
      s .scale (new Numbers_Vector2 (SPREAD, SPREAD));
      s .translate (c .negate ());

      gradient .spreadMatrix = s;

      // Stops

      for (const childNode of xmlElement .childNodes)
         this .gradientChild (childNode, gradient);

      return gradient;
   },
   radialGradientElementUrl (xmlElement, bbox)
   {
      const
         g        = this .radialGradientElement (xmlElement, bbox, { stops: [ ] }),
         gradient = this .context .createRadialGradient (g .fx, g .fy, g. fr, g .cx, g .cy, g .r);

      return this .drawGradient (gradient, g, bbox);
   },
   radialGradientElement (xmlElement, bbox, gradient)
   {
      // Attribute xlink:href

      const refElement = this .hrefAttribute (xmlElement .getAttribute ("href") || xmlElement .getAttribute ("xlink:href"));

      if (refElement)
         this .gradientElement (refElement, bbox, gradient);

      // Attributes

      gradient .cx           = this .lengthAttribute (xmlElement .getAttribute ("cx"), gradient .cx || 0.5, "width"),
      gradient .cy           = this .lengthAttribute (xmlElement .getAttribute ("cy"), gradient .cy || 0.5, "height"),
      gradient .r            = this .lengthAttribute (xmlElement .getAttribute ("r"),  gradient .r  || 0.5),
      gradient .fx           = this .lengthAttribute (xmlElement .getAttribute ("fx"), gradient .fx || gradient .cx, "width"),
      gradient .fy           = this .lengthAttribute (xmlElement .getAttribute ("fy"), gradient .fy || gradient .cy, "height"),
      gradient .fr           = this .lengthAttribute (xmlElement .getAttribute ("fr"), gradient .fr || 0),
      gradient .units        = xmlElement .getAttribute ("gradientUnits") || "objectBoundingBox";
      gradient .spreadMethod = xmlElement .getAttribute ("spreadMethod");
      gradient .transform    = this .transformAttribute (xmlElement .getAttribute ("gradientTransform"));

      // Spread matrix

      const
         s = new Numbers_Matrix3 (),
         c = new Numbers_Vector2 (gradient .fx, gradient .fy);

      s .translate (c);
      s .scale (new Numbers_Vector2 (SPREAD, SPREAD));
      s .translate (c .negate ());

      gradient .spreadMatrix = s;

      // Stops

      for (const childNode of xmlElement .childNodes)
         this .gradientChild (childNode, gradient);

      return gradient;
   },
   gradientElement (xmlElement, bbox, gradient)
   {
      if (!xmlElement)
         return;

      switch (xmlElement .nodeName)
      {
         case "linearGradient":
            return this .linearGradientElement (xmlElement, bbox, gradient);
         case "radialGradient":
            return this .radialGradientElement (xmlElement, bbox, gradient);
      }
   },
   gradientChild (xmlElement, gradient)
   {
      if (xmlElement .nodeName === "stop")
		   return this .stopElement (xmlElement, gradient);
   },
   stopElement (xmlElement, gradient)
   {
      if (!this .styleAttributes (xmlElement))
         return;

      const offset = this .percentAttribute (xmlElement .getAttribute ("offset"), 0);

      if (offset < 0 || offset > 1)
         return;

      const { stopColor, stopOpacity } = this .style;

      gradient .stops .push ([offset, stopColor, stopOpacity]);

      this .styles .pop ();
   },
   drawGradient (gradient, g, bbox)
   {
      // Add color stops.

      switch (g .spreadMethod)
      {
         default: // pad
         {
            g .spreadMatrix .identity ();

            for (const [o, c, a] of g .stops)
               gradient .addColorStop (o, this .cssColor (c, a));

            break;
         }
         case "repeat":
         {
            for (let i = 0; i < SPREAD; ++ i)
            {
               const s = i / SPREAD;

               for (const [o, c, a] of g .stops)
                  gradient .addColorStop (s + o / SPREAD, this .cssColor (c, a));
            }

            break;
         }
         case "reflect":
         {
            for (let i = 0; i < SPREAD; ++ i)
            {
               const s = i / SPREAD;

               for (const [o, c, a] of g .stops)
                  gradient .addColorStop (s + (i % 2 ? 1 - o : o) / SPREAD, this .cssColor (c, a));
            }

            break;
         }
      }

      // Create Matrix.

      const m = new Numbers_Matrix3 ();

      m .scale (new Numbers_Vector2 (this .GRADIENT_SIZE / 2, this .GRADIENT_SIZE / 2));
      m .translate (Numbers_Vector2 .One);
      m .scale (new Numbers_Vector2 (1, -1));

      if (g .units === "userSpaceOnUse")
         m .multLeft (bbox .matrix .copy () .inverse ());
      else
         m .multLeft (new Numbers_Matrix3 (2, 0, 0, 0, 2, 0, -1, -1, 1));

      m .multLeft (g .transform);
      m .multLeft (g .spreadMatrix);

      // Paint.

      const cx = this .context;

      cx .fillStyle = gradient;
      cx .save ();
      cx .clearRect (0, 0, this .GRADIENT_SIZE, this .GRADIENT_SIZE);
      cx .rect (0, 0, this .GRADIENT_SIZE, this .GRADIENT_SIZE);
      cx .transform (m [0], m [1], m [3], m [4], m [6], m [7]);
      cx .fill ();
      cx .restore ();

      // Use PNG because image can have alpha channel.
      return this .canvas .toDataURL ("image/png");
   },
   patternUrl (xmlElement)
   {
      //console .debug ("pattern");
   },
   idAttribute (attribute, node)
   {
      if (attribute === null)
         return;

      const
         scene = this .getExecutionContext (),
         name  = this .sanitizeName (attribute);

      if (name)
      {
		   scene .addNamedNode (scene .getUniqueName (name), node);
		   scene .addExportedNode (scene .getUniqueExportName (name), node);
      }
   },
   viewBoxAttribute (attribute, defaultValue)
   {
      if (attribute === null)
         return defaultValue;

      this .parseValue (attribute);

      if (this .double ())
      {
         const x = this .value;

         if (this .double ())
         {
            const y = this .value;

            if (this .double ())
            {
               const width = this .value;

               if (this .double ())
               {
                  const height = this .value;

                  return new Numbers_Vector4 (x, y, width, height);
               }
            }
         }
      }

      return defaultValue;
   },
   hrefAttribute (attribute)
   {
      if (!attribute)
         return;

      const
         scene = this .getExecutionContext (),
         hash  = new URL (attribute, scene .getBaseURL ()) .hash .slice (1);

      return this .document .getElementById (hash);
   },
   lengthAttribute (attribute, defaultValue, percent)
   {
      // Returns length in pixel.

      if (attribute === null)
         return defaultValue;

      this .parseValue (attribute);

      if (this .double ())
      {
         let value = this .value;

         // Parse unit

         if (SVGParser_Grammar .length .parse (this))
         {
            switch (this .result [1])
            {
               case "em":
                  value *= EM;
                  break;
               case "ex":
                  // TODO
                  break;
               case "px":
                  // We are pixels :)
                  break;
               case "in":
                  value *= INCH / PIXEL;
                  break;
               case "cm":
                  value *= CM / PIXEL;
                  break;
               case "mm":
                  value *= MM / PIXEL;
                  break;
               case "pt":
                  value *= POINT / PIXEL;
                  break;
               case "pc":
                  value *= PICA / PIXEL;
                  break;
               case "%":
               {
                  switch (percent)
                  {
                     case "width":
                        value *= this .viewBox [2] / 100;
                        break;
                     case "height":
                        value *= this .viewBox [3] / 100;
                        break;
                     default:
                        value *= Math .hypot (this .viewBox [2], this .viewBox [3]) / 100;
                        break;
                     }

                  break;
               }
            }
         }

         return value;
      }

      return defaultValue;
   },
   percentAttribute (attribute, defaultValue)
   {
      this .parseValue (attribute);

      if (this .double ())
      {
         let value = this .value;

         // Parse unit

         if (SVGParser_Grammar .percent .parse (this))
            value /= 100;

         return Math_Algorithm .clamp (value, 0, 1);
      }

      return defaultValue;
   },
   pointsAttribute (attribute, points)
   {
      if (attribute === null)
         return false;

      this .parseValue (attribute);

      while (true)
      {
         if (this .double ())
         {
            const x = this .value;

            if (this .comma ())
            {
               if (this .double ())
               {
                  const y = this .value;

                  points .push (new Numbers_Vector3 (x, y, 0));

                  if (this .comma ())
                     continue;
               }
            }
         }

         break;
      }

      return !! points .length;
   },
   dAttribute (attribute, contours)
   {
      if (attribute === null)
         return false;

      this .parseValue (attribute);

      let
         points   = [ ],
         previous = "",
         command  = "",
         relative = false,
         ax       = 0,
         ay       = 0,
         px       = 0,
         py       = 0;

      while (true)
      {
         this .whitespaces ();

         if (!SVGParser_Grammar .path .parse (this))
            break;

         previous = command;
         command  = this .result [1];
         relative = command === command .toLowerCase ();

         switch (command)
         {
            case "m":
            case "M":
            {
               // moveto

               if (points .length > 2)
                  contours .push (Object .assign (points, { closed: false }));

               points = [ ];

               while (true)
               {
                  if (this .double ())
                  {
                     let x = this .value;

                     this .comma ();

                     if (this .double ())
                     {
                        let y = this .value;

                        if (relative)
                        {
                           x += ax;
                           y += ay;
                        }

                        points .push (new Numbers_Vector3 (x, y, 0));

                        ax = x;
                        ay = y;

                        this .comma ();
                        continue;
                     }
                  }

                  break;
               }

               continue;
            }
            case "l":
            case "L":
            {
               // lineto

               while (true)
               {
                  if (this .double ())
                  {
                     let x = this .value;

                     this .comma ();

                     if (this .double ())
                     {
                        let y = this .value;

                        if (relative)
                        {
                           x += ax;
                           y += ay;
                        }

                        points .push (new Numbers_Vector3 (x, y, 0));

                        ax = x;
                        ay = y;

                        this .comma ();
                        continue;
                     }
                  }

                  break;
               }

               continue;
            }
            case "h":
            case "H":
            {
               // horizontal lineto

               while (true)
               {
                  if (this .double ())
                  {
                     let x = this .value;

                     if (relative)
                        x += ax;

                     points .push (new Numbers_Vector3 (x, ay, 0));

                     ax = x;

                     this .comma ();
                     continue;
                  }

                  break;
               }

               continue;
            }
            case "v":
            case "V":
            {
               // vertical lineto

               while (this)
               {
                  if (this .double ())
                  {
                     let y = this .value;

                     if (relative)
                        y += ay;

                     points .push (new Numbers_Vector3 (ax, y, 0));

                     ay = y;

                     this .comma ();
                     continue;
                  }

                  break;
               }

               continue;
            }
            case "q":
            case "Q":
            {
               // quadratic Bézier curveto

               while (true)
               {
                  if (this .double ())
                  {
                     let x1 = this .value;

                     this .comma ();

                     if (this .double ())
                     {
                        let y1 = this .value;

                        this .comma ();

                        if (this .double ())
                        {
                           let x = this .value;

                           this .comma ();

                           if (this .double ())
                           {
                              let y = this .value;

                              if (relative)
                              {
                                 x1 += ax;
                                 y1 += ay;
                                 x  += ax;
                                 y  += ay;
                              }

                              Algorithms_Bezier .quadric (ax, ay, 0, x1, y1, 0, x, y, 0, this .BEZIER_STEPS, points);

                              ax = x;
                              ay = y;
                              px = x1;
                              py = y1;

                              this .comma ();
                              continue;
                           }
                        }
                     }
                  }

                  break;
               }

               continue;
            }
            case "t":
            case "T":
            {
               // Shorthand/smooth quadratic Bézier curveto

               while (true)
               {
                  if (this .double ())
                  {
                     let x = this .value;

                     this .comma ();

                     if (this .double ())
                     {
                        let y = this .value;

                        if (relative)
                        {
                           x += ax;
                           y += ay;
                        }

                        switch (previous)
                        {
                           case 'Q':
                           case 'q':
                           case 'T':
                           case 't':
                           {
                              x1 = ax + (ax - px);
                              y1 = ay + (ay - py);
                              break;
                           }
                           default:
                           {
                              x1 = ax;
                              y1 = ay;
                              break;
                           }
                        }

                        Algorithms_Bezier .quadric (ax, ay, 0, x1, y1, 0, x, y, 0, this .BEZIER_STEPS, points);

                        ax = x;
                        ay = y;

                        this .comma ();
                        continue;
                     }
                  }

                  break;
               }

               continue;
            }
            case "c":
            case "C":
            {
               // curveto, cubic Bézier curve

               while (true)
               {
                  if (this .double ())
                  {
                     let x1 = this .value;

                     this .comma ();

                     if (this .double ())
                     {
                        let y1 = this .value;

                        this .comma ();

                        if (this .double ())
                        {
                           let x2 = this .value;

                           this .comma ();

                           if (this .double ())
                           {
                              let y2 = this .value;

                              this .comma ();

                              if (this .double ())
                              {
                                 let x = this .value;

                                 this .comma ();

                                 if (this .double ())
                                 {
                                    let y = this .value;

                                    if (relative)
                                    {
                                       x1 += ax;
                                       y1 += ay;
                                       x2 += ax;
                                       y2 += ay;
                                       x  += ax;
                                       y  += ay;
                                    }

                                    Algorithms_Bezier .cubic (ax, ay, 0, x1, y1, 0, x2, y2, 0, x, y, 0, this .BEZIER_STEPS, points);

                                    ax = x;
                                    ay = y;
                                    px = x2;
                                    py = y2;

                                    this .comma ();
                                    continue;
                                 }
                              }
                           }
                        }
                     }
                  }

                  break;
               }

               continue;
            }
            case "s":
            case "S":
            {
               // shorthand/smooth curveto, cubic Bézier curve

               while (true)
               {
                  if (this .double ())
                  {
                     let x2 = this .value;

                     this .comma ();

                     if (this .double ())
                     {
                        let y2 = this .value;

                        this .comma ();

                        if (this .double ())
                        {
                           let x = this .value;

                           this .comma ();

                           if (this .double ())
                           {
                              let y = this .value;

                              if (relative)
                              {
                                 x2 += ax;
                                 y2 += ay;
                                 x  += ax;
                                 y  += ay;
                              }

                              switch (previous)
                              {
                                 case 'C':
                                 case 'c':
                                 case 'S':
                                 case 's':
                                 {
                                    var x1 = ax + (ax - px);
                                    var y1 = ay + (ay - py);
                                    break;
                                 }
                                 default:
                                 {
                                    var x1 = ax;
                                    var y1 = ay;
                                    break;
                                 }
                              }

                              Algorithms_Bezier .cubic (ax, ay, 0, x1, y1, 0, x2, y2, 0, x, y, 0, this .BEZIER_STEPS, points);

                              ax = x;
                              ay = y;
                              px = x2;
                              py = y2;

                              this .comma ();
                              continue;
                           }
                        }
                     }
                  }

                  break;
               }

               continue;
            }
            case "a":
            case "A":
            {
               // elliptical arc

               while (true)
               {
                  if (this .double ())
                  {
                     let rx = this .value;

                     this .comma ();

                     if (this .double ())
                     {
                        let ry = this .value;

                        this .comma ();

                        if (this .double ())
                        {
                           let xAxisRotation = Math_Algorithm .radians (this .value);

                           this .comma ();

                           if (this .int32 ())
                           {
                              let largeArcFlag = this .value;

                              this .comma ();

                              if (this .int32 ())
                              {
                                 let sweepFlag = this .value;

                                 this .comma ();

                                 if (this .double ())
                                 {
                                    let x = this .value;

                                    this .comma ();

                                    if (this .double ())
                                    {
                                       let y = this .value;

                                       if (relative)
                                       {
                                          x += ax;
                                          y += ay;
                                       }

                                       Algorithms_Bezier .arc (ax, ay, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y, this .CIRCLE_STEPS, points);

                                       ax = x;
                                       ay = y;

                                       this .comma ();
                                       continue;
                                    }
                                 }
                              }
                           }
                        }
                     }
                  }

                  break;
               }

               continue;
            }
            case "z":
            case "Z":
            {
               // closepath

               if (points .length > 2)
               {
                  ax = points [0] .x;
                  ay = points [0] .y;

                  contours .push (Object .assign (points, { closed: true }));
               }

               points = [ ];

               this .comma ();
               continue;
            }
         }

         break;
      }

      if (points .length > 2)
		   contours .push (Object .assign (points, { closed: false }));

      return !! contours .length;
   },
   transformAttribute (attribute)
   {
      const matrix = new Numbers_Matrix3 ();

      if (attribute === null)
         return matrix;

      this .parseValue (attribute);

      while (true)
      {
         this .comma ();
         this .whitespaces ();

         if (SVGParser_Grammar .matrix .parse (this))
         {
            this .whitespaces ();

            if (SVGParser_Grammar .openParenthesis .parse (this))
            {
               if (this .double ())
               {
                  const a = this .value;

                  if (this .comma ())
                  {
                     if (this .double ())
                     {
                        const b = this .value;

                        if (this .comma ())
                        {
                           if (this .double ())
                           {
                              const c = this .value;

                              if (this .comma ())
                              {
                                 if (this .double ())
                                 {
                                    const d = this .value;

                                    if (this .comma ())
                                    {
                                       if (this .double ())
                                       {
                                          const e = this .value;

                                          if (this .comma ())
                                          {
                                             if (this .double ())
                                             {
                                                const f = this .value;

                                                this .whitespaces ();

                                                if (SVGParser_Grammar .closeParenthesis .parse (this))
                                                {
                                                   matrix .multLeft (new Numbers_Matrix3 (a, b, 0, c, d, 0, e, f, 1));
                                                   continue;
                                                }
                                             }
                                          }
                                       }
                                    }
                                 }
                              }
                           }
                        }
                     }
                  }
               }
            }
         }
         else if (SVGParser_Grammar .translate .parse (this))
         {
            this .whitespaces ();

            if (SVGParser_Grammar .openParenthesis .parse (this))
            {
               if (this .double ())
               {
                  const tx = this .value;

                  if (this .comma ())
                  {
                     if (this .double ())
                     {
                        var ty = this .value;
                     }
                  }
                  else
                  {
                     var ty = 0;
                  }

                  this .whitespaces ();

                  if (SVGParser_Grammar .closeParenthesis .parse (this))
                  {
                     matrix .translate (new Numbers_Vector2 (tx, ty));
                     continue;
                  }
               }
            }
         }
         else if (SVGParser_Grammar .rotate .parse (this))
         {
            this .whitespaces ();

            if (SVGParser_Grammar .openParenthesis .parse (this))
            {
               if (this .double ())
               {
                  const angle = this .value;

                  this .whitespaces ();

                  if (SVGParser_Grammar .closeParenthesis .parse (this))
                  {
                     matrix .rotate (Math_Algorithm .radians (angle));
                     continue;
                  }
                  else
                  {
                     if (this .comma ())
                     {
                        if (this .double ())
                        {
                           const cx = this .value;

                           if (this .comma ())
                           {
                              if (this .double ())
                              {
                                 const cy = this .value;

                                 this .whitespaces ();

                                 if (SVGParser_Grammar .closeParenthesis .parse (this))
                                 {
                                    matrix .translate (new Numbers_Vector2 (cx, cy));
                                    matrix .rotate (Math_Algorithm .radians (angle));
                                    matrix .translate (new Numbers_Vector2 (-cx, -cy));
                                    continue;
                                 }
                              }
                           }
                        }
                     }
                  }
               }
            }
         }
         else if (SVGParser_Grammar .scale .parse (this))
         {
            this .whitespaces ();

            if (SVGParser_Grammar .openParenthesis .parse (this))
            {
               if (this .double ())
               {
                  const sx = this .value;

                  if (this .comma ())
                  {
                     if (this .double ())
                     {
                        var sy = this .value;
                     }
                  }
                  else
                  {
                     var sy = sx;
                  }

                  this .whitespaces ();

                  if (SVGParser_Grammar .closeParenthesis .parse (this))
                  {
                     matrix .scale (new Numbers_Vector2 (sx, sy));
                     continue;
                  }
               }
            }
         }
         else if (SVGParser_Grammar .skewX .parse (this))
         {
            this .whitespaces ();

            if (SVGParser_Grammar .openParenthesis .parse (this))
            {
               if (this .double ())
               {
                  const angle = this .value;

                  this .whitespaces ();

                  if (SVGParser_Grammar .closeParenthesis .parse (this))
                  {
                     matrix .skewX (Math_Algorithm .radians (angle));
                     continue;
                  }
               }
            }
         }
         else if (SVGParser_Grammar .skewY .parse (this))
         {
            this .whitespaces ();

            if (SVGParser_Grammar .openParenthesis .parse (this))
            {
               if (this .double ())
               {
                  const angle = this .value;

                  this .whitespaces ();

                  if (SVGParser_Grammar .closeParenthesis .parse (this))
                  {
                     matrix .skewY (Math_Algorithm .radians (angle));
                     continue;
                  }
               }
            }
         }

         break;
      }

      return matrix;
   },
   styleAttributes (xmlElement)
   {
      const style = Object .assign ({ }, this .styles .at (-1));

      if (this .style .display === "none")
         return false;

      this .styles .push (style);

      for (const attribute of xmlElement .attributes)
         this .parseStyle (attribute .name, attribute .value)

      // Style attribute has higher precedence.

      this .styleAttribute (xmlElement .getAttribute ("style"));

      return true;
   },
   styleAttribute (attribute)
   {
      if (attribute === null)
         return;

      const values = attribute .split (";");

      for (const value of values)
      {
         const pair = value .split (":");

         if (pair .length !== 2)
            continue;

         this .parseStyle (pair [0] .trim (), pair [1] .trim ());
      }
   },
   parseStyle (style, value)
   {
      if (value === "inherit" || value == "unset")
         return;

      this .parseValue (value);

      switch (style)
      {
         case "display":
            this .displayStyle (value);
            break;
         case "fill":
            this .fillStyle (value);
            break;
         case "fill-opacity":
            this .fillOpacityStyle (value);
            break;
         case "fill-rule":
            this .fillRuleStyle (value);
            break;
         case "stroke":
            this .strokeStyle (value);
            break;
         case "stroke-opacity":
            this .strokeOpacityStyle (value);
            break;
         case "stroke-width":
            this .strokeWidthStyle (value);
            break;
         case "opacity":
            this .opacityStyle (value);
            break;
         case "stop-color":
            this .stopColorStyle (value);
            break;
         case "stop-opacity":
            this .stopOpacityStyle (value);
            break;
         case "vector-effect":
            this .vectorEffectStyle (value);
            break;
      }
   },
   displayStyle (value)
   {
      if (value === "default")
      {
         this .style .display = "inline";
         return;
      }

      this .style .display = value;
   },
   fillStyle (value)
   {
      if (value === "default")
      {
         this .style .fillType  = this .styles [0] .fillType;
         this .style .fillColor = this .styles [0] .fillColor;
         this .style .fillURL   = this .styles [0] .fillURL;
         return;
      }

      if (value === "transparent")
      {
         this .style .fillType = "none";
         return;
      }

      if (value === "none")
      {
         this .style .fillType = "none";
         return;
      }

      if (this .urlValue ())
      {
         this .style .fillType = "URL";
         this .style .fillURL  = this .result [1] .trim ();
         return;
      }

      if (this .colorValue (this .styles .at (-1) .fillColor))
      {
         this .style .fillType  = "COLOR";
         this .style .fillColor = this .value .copy ();
         return;
      }
   },
   fillOpacityStyle (value)
   {
      if (value === "default")
      {
         this .style .fillOpacity = this .styles [0] .fillOpacity;
         return;
      }

      if (value === "transparent")
      {
         this .style .fillOpacity = 0;
         return;
      }

      if (this .double ())
      {
         this .style .fillOpacity = Math_Algorithm .clamp (this .value, 0, 1);
         return;
      }
   },
   fillRuleStyle (value)
   {
      if (value === "default")
      {
         this .style .fillRule = this .styles [0] .fillRule;
         return;
      }

      this .style .fillRule = value;
   },
   strokeStyle (value)
   {
      if (value === "default")
      {
         this .style .strokeType  = this .styles [0] .strokeType;
         this .style .strokeColor = this .styles [0] .strokeColor;
         this .style .strokeURL   = this .styles [0] .strokeURL;
         return;
      }

      if (value === "transparent")
      {
         this .style .strokeType = "none";
         return;
      }

      if (value === "none")
      {
         this .style .strokeType = "none";
         return;
      }

      if (this .urlValue ())
      {
         this .style .strokeType = "URL";
         this .style .strokeURL  = this .result [1] .trim ();
         return;
      }

      if (this .colorValue (this .styles .at (-1) .strokeColor))
      {
         this .style .strokeType  = "COLOR";
         this .style .strokeColor = this .value .copy ();
         return;
      }
   },
   strokeOpacityStyle (value)
   {
      if (value === "default")
      {
         this .style .strokeOpacity = this .styles [0] .strokeOpacity;
         return;
      }

      if (value === "transparent")
      {
         this .style .strokeOpacity = 0;
         return;
      }

      if (this .double ())
      {
         this .style .strokeOpacity = Math_Algorithm .clamp (this .value, 0, 1);
         return;
      }
   },
   strokeWidthStyle (value)
   {
      if (value === "default")
      {
         this .style .strokeWidth = this .styles [0] .strokeWidth;
         return;
      }

      if (value === "none")
      {
         this .style .strokeWidth = 0;
         return;
      }

      if (this .double ())
      {
         this .style .strokeWidth = this .lengthAttribute (this .value, 1);
         return;
      }
   },
   opacityStyle (value)
   {
      if (value === "default")
      {
         this .style .opacity = this .styles [0] .opacity;
         return;
      }

      if (value === "transparent")
      {
         this .style .opacity = 0;
         return;
      }

      if (this .double ())
      {
         this .style .opacity = Math_Algorithm .clamp (this .value, 0, 1) * this .styles .at (-1) .opacity;
         return;
      }
   },
   stopColorStyle (value)
   {
      if (value === "default")
      {
         this .style .stopColor = this .styles [0] .stopColor;
         return;
      }

      if (this .colorValue (Numbers_Color4 .Black))
      {
         this .style .stopColor = this .value .copy ();
         return;
      }
   },
   stopOpacityStyle (value)
   {
      if (value === "default")
      {
         this .style .stopOpacity = this .styles [0] .stopOpacity;
         return;
      }

      if (value === "transparent")
      {
         this .style .stopOpacity = 0;
         return;
      }

      if (this .double ())
      {
         this .style .stopOpacity = Math_Algorithm .clamp (this .value, 0, 1);
         return;
      }
   },
   vectorEffectStyle (value)
   {
      if (value === "default")
      {
         this .style .vectorEffect = this .styles [0] .vectorEffect;
         return;
      }

      this .style .vectorEffect = value;
   },
   parseValue (value)
   {
      this .input     = value;
      this .lastIndex = 0;
      this .value     = undefined;
   },
   whitespaces ()
   {
      return SVGParser_Grammar .whitespaces .parse (this);
   },
   comma ()
   {
      return !! (this .whitespaces () | SVGParser_Grammar .comma .parse (this));
   },
   int32 ()
   {
      this .whitespaces ();

      if (SVGParser_Grammar .int32 .parse (this))
      {
         this .value = parseInt (this .result [1]);

         return true;
      }

      return false;
   },
   double ()
   {
      this .whitespaces ();

      if (SVGParser_Grammar .double .parse (this))
      {
         this .value = parseFloat (this .result [1]);

         return true;
      }

      if (SVGParser_Grammar .constants .parse (this))
      {
         this .value = this .CONSTANTS .get (this .result [2] .toUpperCase ());

         if (this .result [1] === "-")
            this .value = - this .value;

         return true;
      }

      return false;
   },
   colorValue: (() =>
   {
      const color = new Numbers_Color4 (0, 0, 0, 0);

      return function (c)
      {
         if (!SVGParser_Grammar .color .parse (this))
            return false;

         const defaultColor = this .cssColor (c);

         this .value = color .set (... this .convertColor (this .result [1], defaultColor));

         return true;
      };
   })(),
   urlValue ()
   {
      return SVGParser_Grammar .url .parse (this);
   },
   cssColor (c, a = c .a)
   {
      return `rgba(${c .r * 255},${c .g * 255},${c .b * 255},${a})`;
   },
   createTransform (xmlElement, t = Numbers_Vector2 .Zero, s = Numbers_Vector2 .One)
   {
      // Determine matrix.

      const
         scene = this .getExecutionContext (),
         m     = this .transformAttribute (xmlElement .getAttribute ("transform"));

      this .modelMatrix .push ();
      this .modelMatrix .multLeft (Numbers_Matrix4 .Matrix3 (m));

      m .translate (t);
      m .scale (s);

      // Create node.

      const
         transformNode    = scene .createNode ("Transform"),
         matrix           = Numbers_Matrix4 .Matrix3 (m),
         translation      = new Numbers_Vector3 (0, 0, 0),
         rotation         = new Numbers_Rotation4 (),
         scale            = new Numbers_Vector3 (1, 1, 1),
         scaleOrientation = new Numbers_Rotation4 ();

      matrix .get (translation, rotation, scale, scaleOrientation);

      transformNode .translation      = translation;
      transformNode .rotation         = rotation;
      transformNode .scale            = scale;
      transformNode .scaleOrientation = scaleOrientation;

      // Set name.

      this .idAttribute (xmlElement .getAttribute ("id"), transformNode);

      // Add node to parent.

      this .groupNodes .at (-1) .children .push (transformNode);

      return transformNode;
   },
   popAll ()
   {
      this .groupNodes  .pop ();
      this .modelMatrix .pop ();
      this .styles      .pop ();
   },
   createFillAppearance (bbox)
   {
      const
         scene          = this .getExecutionContext (),
         appearanceNode = scene .createNode ("Appearance");

      switch (this .style .fillType)
      {
         case "none":
         {
            return null;
         }
         case "COLOR":
         {
            const materialNode = scene .createNode ("UnlitMaterial");

            appearanceNode .material    = materialNode;
            materialNode .emissiveColor = new Numbers_Color3 (... this .style .fillColor);
            materialNode .transparency  = 1 - this .style .fillOpacity * this .style .opacity;

            break;
         }
         case "URL":
         {
            // Gradient

            const
               scene       = this .getExecutionContext (),
               textureNode = scene .createNode ("ImageTexture"),
               url         = this .getFillUrl (this .style .fillURL, bbox);

            // Get image from url.

            if (!url)
               return null;

            textureNode .url               = [url];
            textureNode .textureProperties = this .texturePropertiesNode;
            appearanceNode .texture        = textureNode;

            break;
         }
      }

      return appearanceNode;
   },
   getFillUrl (fillURL, bbox)
   {
      const xmlElement = this .hrefAttribute (fillURL);

      if (!xmlElement)
         return;

      switch (xmlElement .nodeName)
      {
         case "linearGradient":
            return this .linearGradientElementUrl (xmlElement, bbox);

         case "radialGradient":
            return this .radialGradientElementUrl (xmlElement, bbox);

         case "pattern":
            return this .patternUrl (xmlElement);
      }
   },
   createStrokeAppearance ()
   {
      const
         scene          = this .getExecutionContext (),
         appearanceNode = scene .createNode ("Appearance"),
         materialNode   = scene .createNode ("UnlitMaterial");

      appearanceNode .material    = materialNode;
      materialNode .emissiveColor = new Numbers_Color3 (... this .style .strokeColor);
      materialNode .transparency  = 1 - this .style .strokeOpacity * this .style .opacity;

      const strokeWidth = this .vectorEffect === "non-scaling-stroke"
         ? this .style .strokeWidth
         : this .getStokeWidth ();

      if (strokeWidth > 1)
         appearanceNode .lineProperties = this .getLineProperties (strokeWidth);

      return appearanceNode;
   },
   getStokeWidth ()
   {
      const
         modelMatrix = this .modelMatrix .get (),
         strokeWidth = modelMatrix .multDirMatrix (new Numbers_Vector3 (this .style .strokeWidth, this .style .strokeWidth, 0));

      return (strokeWidth .x + strokeWidth .y) / 2;
   },
   getLineProperties (strokeWidth)
   {
      const lineProperties = this .lineProperties .get (strokeWidth);

      if (lineProperties)
      {
         return lineProperties;
      }
      else
      {
         const
            scene          = this .getExecutionContext (),
            lineProperties = scene .createNode ("LineProperties");

         lineProperties .linewidthScaleFactor = strokeWidth;

         this .lineProperties .set (strokeWidth, lineProperties);

         return lineProperties;
      }
   },
   createTextureProperties ()
   {
      const
         scene                 = this .getExecutionContext (),
         texturePropertiesNode = scene .createNode ("TextureProperties");

      texturePropertiesNode .generateMipMaps     = true;
      texturePropertiesNode .minificationFilter  = "NICEST";
      texturePropertiesNode .magnificationFilter = "NICEST";
      texturePropertiesNode .boundaryModeS       = "CLAMP_TO_EDGE";
      texturePropertiesNode .boundaryModeT       = "CLAMP_TO_EDGE";
      texturePropertiesNode .boundaryModeR       = "CLAMP_TO_EDGE";
      texturePropertiesNode .textureCompression  = "DEFAULT";

      return texturePropertiesNode;
   },
   createTextureCoordinate (coordinateNode, bbox, appearance)
   {
      if (!appearance || !appearance .texture)
         return null;

      const
         scene        = this .getExecutionContext (),
         texCoordNode = scene .createNode ("TextureCoordinate"),
         invMatrix    = bbox .matrix .copy () .inverse ();

      for (const point of coordinateNode .point)
         texCoordNode .point .push (invMatrix .multVecMatrix (new Numbers_Vector2 (point .x, point .y)) .add (Numbers_Vector2 .One) .divide (2));

      return texCoordNode;
   },
   createTesselator ()
   {
      // Function called for each vertex of tessellator output.

      function vertexCallback (index, triangles)
      {
         triangles .push (index);
      }

      const tessy = new libtess .GluTesselator ();

      tessy .gluTessCallback (libtess .gluEnum .GLU_TESS_VERTEX_DATA, vertexCallback);
      tessy .gluTessNormal (0, 0, 1);

      return tessy;
   },
   triangulatePolygon (contours, coordinateNode)
   {
      // Callback for when segments intersect and must be split.

      function combineCallback (coords, data, weight)
      {
         const index = coordinateNode .point .length;

         coordinateNode .point .push (new Numbers_Vector3 (... coords));

         return index;
      }

      const
         tessy     = this .tessy,
         winding   = this .style .fillRule === "evenodd" ? "GLU_TESS_WINDING_ODD" : "GLU_TESS_WINDING_NONZERO",
         triangles = [ ];

      tessy .gluTessProperty (libtess .gluEnum .GLU_TESS_WINDING_RULE, libtess .windingRule [winding]);
      tessy .gluTessCallback (libtess .gluEnum .GLU_TESS_COMBINE,      combineCallback);
      tessy .gluTessBeginPolygon (triangles);

      for (const points of contours)
      {
         tessy .gluTessBeginContour ();

         for (const [i, point] of points .entries ())
            tessy .gluTessVertex (point, points .index + i);

         tessy .gluTessEndContour ();
      }

      tessy .gluTessEndPolygon ();

      // Array of indices of triangles.
      return triangles;
   },
});

Object .defineProperty (SVGParser .prototype, "style",
{
   get ()
   {
      return this .styles .at (-1);
   },
})

const SVGParser_default_ = SVGParser;
;

x_ite_Namespace .add ("SVGParser", "x_ite/Parser/SVGParser", SVGParser_default_);
/* harmony default export */ const Parser_SVGParser = (SVGParser_default_);
;// CONCATENATED MODULE: ./src/x_ite/Parser/GoldenGate.js
/* provided dependency */ var GoldenGate_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/














function GoldenGate (scene)
{
   Parser_X3DParser .call (this, scene);

   this .inputs = new Map ();
}

Object .assign (Object .setPrototypeOf (GoldenGate .prototype, Parser_X3DParser .prototype),
{
   parseIntoScene (x3dSyntax, resolve, reject)
   {
      for (const Parser of GoldenGate .Parser)
      {
         try
         {
            const
               parser = new Parser (this .getScene ()),
               input  = this .getInput (parser .getEncoding (), x3dSyntax);

            if (Array .isArray (input) ? input .some (i => i === undefined) : input === undefined)
               continue;

            parser .setInput (input);

            if (!parser .isValid ())
               continue;

            parser .pushExecutionContext (this .getExecutionContext ());
            parser .parseIntoScene (resolve, reject);
            return;
         }
         catch (error)
         {
            if (reject)
               reject (error);
            else
               throw error;

            return;
         }
      }

      if (this .getScene () .worldURL .startsWith ("data:"))
         throw new Error ("Couldn't parse X3D. No suitable file handler found for 'data:' URL.");
      else
         throw new Error (`Couldn't parse X3D. No suitable file handler found for '${this .getScene () .worldURL}'.`);
   },
   getInput (encoding, x3dSyntax)
   {
      if (Array .isArray (encoding))
      {
         return encoding .map (encoding => this .getInput (encoding));
      }
      else
      {
         if (this .inputs .has (encoding))
            return this .inputs .get (encoding);

         const input = this .createInput (encoding, x3dSyntax);

         this .inputs .set (encoding, input);

         return input;
      }
   },
   createInput (encoding, x3dSyntax)
   {
      try
      {
         switch (encoding)
         {
            case "STRING":
               return GoldenGate_$.decodeText (x3dSyntax);
            case "XML":
               return GoldenGate_$.parseXML (this .getInput ("STRING", x3dSyntax));
            case "JSON":
               return JSON .parse (this .getInput ("STRING", x3dSyntax));
            case "ARRAY_BUFFER":
               return x3dSyntax instanceof ArrayBuffer ? x3dSyntax : undefined;
         }
      }
      catch
      {
         return undefined;
      }
   },
});

GoldenGate .Parser = [
   Parser_SVGParser,
   Parser_XMLParser,
   Parser_GLTF2Parser,
   Parser_GLB2Parser,
   Parser_JSONParser,
   Parser_VRMLParser,
   Parser_OBJParser,
   Parser_STLAParser,
   Parser_STLBParser,
   Parser_PLYAParser,
   Parser_PLYBParser,
];

const GoldenGate_default_ = GoldenGate;
;

x_ite_Namespace .add ("GoldenGate", "x_ite/Parser/GoldenGate", GoldenGate_default_);
/* harmony default export */ const Parser_GoldenGate = (GoldenGate_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Geometry/Plane3.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




const
   normal    = new Numbers_Vector3 (0, 0, 0),
   point     = new Numbers_Vector3 (0, 0, 0),
   invMatrix = new Numbers_Matrix4 ();

function Plane3 (point, normal)
{
   this .normal             = normal .copy ();
   this .distanceFromOrigin = normal .dot (point);
}

Object .assign (Plane3 .prototype,
{
   copy ()
   {
      const copy = Object .create (Plane3 .prototype);
      copy .normal             = this .normal .copy ();
      copy .distanceFromOrigin = this .distanceFromOrigin;
      return copy;
   },
   assign (plane)
   {
      this .normal .assign (plane .normal);
      this .distanceFromOrigin = plane .distanceFromOrigin;
      return this;
   },
   set (point, normal)
   {
      this .normal .assign (normal);
      this .distanceFromOrigin = normal .dot (point);
      return this;
   },
   multRight (matrix)
   {
      // Taken from Inventor:

      // Find the point on the plane along the normal from the origin
      point .assign (this .normal) .multiply (this .distanceFromOrigin);

      // Transform the plane normal by the matrix
      // to get the new normal. Use the inverse transpose
      // of the matrix so that normals are not scaled incorrectly.
      // n' = n * !~m = ~m * n
      invMatrix .assign (matrix) .inverse ();
      invMatrix .multMatrixDir (normal .assign (this .normal)) .normalize ();

      // Transform the point by the matrix
      matrix .multVecMatrix (point);

      // The new distance is the projected distance of the vector to the
      // transformed point onto the (unit) transformed normal. This is
      // just a dot product.
      this .normal .assign (normal);
      this .distanceFromOrigin = normal .dot (point);

      return this;
   },
   multLeft (matrix)
   {
      // Taken from Inventor:

      // Find the point on the plane along the normal from the origin
      point .assign (this .normal) .multiply (this .distanceFromOrigin);

      // Transform the plane normal by the matrix
      // to get the new normal. Use the inverse transpose
      // of the matrix so that normals are not scaled incorrectly.
      // n' = !~m * n = n * ~m
      invMatrix .assign (matrix) .inverse ();
      invMatrix .multDirMatrix (normal .assign (this .normal)) .normalize ();

      // Transform the point by the matrix
      matrix .multMatrixVec (point);

      // The new distance is the projected distance of the vector to the
      // transformed point onto the (unit) transformed normal. This is
      // just a dot product.
      this .normal .assign (normal);
      this .distanceFromOrigin = normal .dot (point);

      return this;
   },
   getDistanceToPoint (point)
   {
      return point .dot (this .normal) - this .distanceFromOrigin;
   },
   intersectsLine (line, intersection)
   {
      const { point, direction } = line;

      // Check if the line is parallel to the plane.
      const theta = direction .dot (this .normal);

      // Plane and line are parallel.
      if (theta === 0)
         return false;

      // Plane and line are not parallel. The intersection point can be calculated now.
      const t = (this .distanceFromOrigin - this .normal .dot (point)) / theta;

      intersection .x = point .x + direction .x * t;
      intersection .y = point .y + direction .y * t;
      intersection .z = point .z + direction .z * t;

      return true;
   },
   toString ()
   {
      return `${this .normal} ${this .distanceFromOrigin}`;
   },
});

const Plane3_default_ = Plane3;
;

x_ite_Namespace .add ("Plane3", "standard/Math/Geometry/Plane3", Plane3_default_);
/* harmony default export */ const Geometry_Plane3 = (Plane3_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Geometry/Triangle3.js
/* provided dependency */ var Triangle3_libtess = __webpack_require__(793);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



const Triangle3 =
{
   area: (() =>
   {
      const
         B = new Numbers_Vector3 (0, 0, 0),
         C = new Numbers_Vector3 (0, 0, 0);

      return function (a, b, c)
      {
         return B .assign (b) .subtract (a) .cross (C .assign (c) .subtract (a)) .magnitude () / 2;
      };
   })(),
   normal (v1, v2, v3, normal)
   {
      const
         x1 = v3 .x - v2 .x,
         y1 = v3 .y - v2 .y,
         z1 = v3 .z - v2 .z,
         x2 = v1 .x - v2 .x,
         y2 = v1 .y - v2 .y,
         z2 = v1 .z - v2 .z;

      normal .set (y1 * z2 - z1 * y2,
                   z1 * x2 - x1 * z2,
                   x1 * y2 - y1 * x2);

      return normal .normalize ();
   },
   quadNormal (v1, v2, v3, v4, normal)
   {
      const
         x1 = v3 .x - v1 .x,
         y1 = v3 .y - v1 .y,
         z1 = v3 .z - v1 .z,
         x2 = v4 .x - v2 .x,
         y2 = v4 .y - v2 .y,
         z2 = v4 .z - v2 .z;

      normal .set (y1 * z2 - z1 * y2,
                   z1 * x2 - x1 * z2,
                   x1 * y2 - y1 * x2);

      return normal .normalize ();
   },
   triangulatePolygon: (() =>
   {
      // Function called for each vertex of tesselator output.

      function vertexCallback (index, triangles)
      {
         triangles .push (index);
      }

      // Required in case of a combine, otherwise an empty array is returned.

      function combineCallback (coords, data, weight)
      {
         return data [0];
      }

      const tessy = new Triangle3_libtess .GluTesselator ();

      tessy .gluTessCallback (Triangle3_libtess .gluEnum .GLU_TESS_VERTEX_DATA,  vertexCallback);
      tessy .gluTessCallback (Triangle3_libtess .gluEnum .GLU_TESS_COMBINE,      combineCallback);
      tessy .gluTessProperty (Triangle3_libtess .gluEnum .GLU_TESS_WINDING_RULE, Triangle3_libtess .windingRule .GLU_TESS_WINDING_ODD);

      return function (polygon, triangles)
      {
         tessy .gluTessBeginPolygon (triangles);
         tessy .gluTessBeginContour ();

         for (const point of polygon)
            tessy .gluTessVertex (point, point .index);

         tessy .gluTessEndContour ();
         tessy .gluTessEndPolygon ();

         // Return array of indices.
         return triangles;
      };
   })(),
   triangulateConvexPolygon (vertices, triangles)
   {
      // Fallback: Very simple triangulation for convex polygons.
      for (let i = 1, length = vertices .length - 1; i < length; ++ i)
         triangles .push (vertices [0], vertices [i], vertices [i + 1]);
   },
};

const Triangle3_default_ = Triangle3;
;

x_ite_Namespace .add ("Triangle3", "standard/Math/Geometry/Triangle3", Triangle3_default_);
/* harmony default export */ const Geometry_Triangle3 = (Triangle3_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Algorithms/SAT.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

const
   extents1 = { min: 0, max: 0 },
   extents2 = { min: 0, max: 0 };

/**
 *  Class to represent the Separating Axis Theorem.
 */
function SAT () { }

SAT .isSeparated = function (axes, points1, points2)
{
   // https://gamedev.stackexchange.com/questions/25397/obb-vs-obb-collision-detection

   for (const axis of axes)
   {
      project (points1, axis, extents1);
      project (points2, axis, extents2);

      if (overlaps (extents1 .min, extents1 .max, extents2 .min, extents2 .max))
         continue;

      return true;
   }

   return false;
};

///  Projects @a points to @a axis and returns the minimum and maximum bounds.
function project (points, axis, extents)
{
   extents .min = Number .POSITIVE_INFINITY;
   extents .max = Number .NEGATIVE_INFINITY;

   for (const point of points)
   {
      // Just dot it to get the min and max along this axis.
      // NOTE: the axis must be normalized to get accurate projections to calculate the MTV, but if it is only needed to
      // know whether it overlaps, every axis can be used.

      const dotVal = point .dot (axis);

      if (dotVal < extents .min)
         extents .min = dotVal;

      if (dotVal > extents .max)
         extents .max = dotVal;
   }
}

///  Returns true if both ranges overlap, otherwise false.
function overlaps (min1, max1, min2, max2)
{
   return is_between (min2, min1, max1) || is_between (min1, min2, max2);
}

///  Returns true if @a value is between @a lowerBound and @a upperBound, otherwise false.
function is_between (value, lowerBound, upperBound)
{
   return lowerBound <= value && value <= upperBound;
}

const SAT_default_ = SAT;
;

x_ite_Namespace .add ("SAT", "standard/Math/Algorithms/SAT", SAT_default_);
/* harmony default export */ const Algorithms_SAT = (SAT_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Geometry/ViewVolume.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









/*
 * p7 -------- p6  far plane
 * | \         | \
 * | p3 --------- p2
 * |  |        |  |
 * |  |        |  |
 * p4 |______ p5  |
 *  \ |         \ |
 *   \|          \|
 *    p0 -------- p1  near plane
 */

function ViewVolume (projectionMatrix, viewport, scissor)
{
   this .viewport = new Numbers_Vector4 (0, 0, 0, 0);
   this .scissor  = new Numbers_Vector4 (0, 0, 0, 0);

   this .points = [
      new Numbers_Vector3 (0, 0, 0),
      new Numbers_Vector3 (0, 0, 0),
      new Numbers_Vector3 (0, 0, 0),
      new Numbers_Vector3 (0, 0, 0),

      new Numbers_Vector3 (0, 0, 0),
      new Numbers_Vector3 (0, 0, 0),
      new Numbers_Vector3 (0, 0, 0),
      new Numbers_Vector3 (0, 0, 0),
   ];

   this .normals = [
      new Numbers_Vector3 (0, 0, 0), // front
      new Numbers_Vector3 (0, 0, 0), // left
      new Numbers_Vector3 (0, 0, 0), // right
      new Numbers_Vector3 (0, 0, 0), // top
      new Numbers_Vector3 (0, 0, 0), // bottom
      new Numbers_Vector3 (0, 0, 0), // back
   ];

   this .edges = [
      new Numbers_Vector3 (0, 0, 0),
      new Numbers_Vector3 (0, 0, 0),
      new Numbers_Vector3 (0, 0, 0),
      new Numbers_Vector3 (0, 0, 0),

      new Numbers_Vector3 (0, 0, 0),
      new Numbers_Vector3 (0, 0, 0),
      new Numbers_Vector3 (0, 0, 0),
      new Numbers_Vector3 (0, 0, 0),
   ];

   this .planes = [
      new Geometry_Plane3 (Numbers_Vector3 .Zero, Numbers_Vector3 .Zero), // front
      new Geometry_Plane3 (Numbers_Vector3 .Zero, Numbers_Vector3 .Zero), // left
      new Geometry_Plane3 (Numbers_Vector3 .Zero, Numbers_Vector3 .Zero), // right
      new Geometry_Plane3 (Numbers_Vector3 .Zero, Numbers_Vector3 .Zero), // top
      new Geometry_Plane3 (Numbers_Vector3 .Zero, Numbers_Vector3 .Zero), // bottom
      new Geometry_Plane3 (Numbers_Vector3 .Zero, Numbers_Vector3 .Zero), // back
   ];

   if (arguments .length)
      this .set (projectionMatrix, viewport, scissor);
}

Object .assign (ViewVolume .prototype,
{
   set: (() =>
   {
      const matrix = new Numbers_Matrix4 ();

      return function (projectionMatrix, viewport, scissor)
      {
         this .viewport .assign (viewport);
         this .scissor  .assign (scissor);

         const [p0, p1 ,p2, p3, p4, p5, p6, p7] = this .points;

         const
            x1 = scissor [0],
            x2 = x1 + scissor [2],
            y1 = scissor [1],
            y2 = y1 + scissor [3];

         matrix .assign (projectionMatrix) .inverse ();

         ViewVolume .unProjectPointMatrix (x1, y1, 0, matrix, viewport, p0),
         ViewVolume .unProjectPointMatrix (x2, y1, 0, matrix, viewport, p1),
         ViewVolume .unProjectPointMatrix (x2, y2, 0, matrix, viewport, p2),
         ViewVolume .unProjectPointMatrix (x1, y2, 0, matrix, viewport, p3),
         ViewVolume .unProjectPointMatrix (x1, y1, 1, matrix, viewport, p4),
         ViewVolume .unProjectPointMatrix (x2, y1, 1, matrix, viewport, p5);
         ViewVolume .unProjectPointMatrix (x2, y2, 1, matrix, viewport, p6);
         ViewVolume .unProjectPointMatrix (x1, y2, 1, matrix, viewport, p7);

         const normals = this .normals;

         Geometry_Triangle3 .normal (p0, p1, p2, normals [0]); // front
         Geometry_Triangle3 .normal (p7, p4, p0, normals [1]); // left
         Geometry_Triangle3 .normal (p6, p2, p1, normals [2]); // right
         Geometry_Triangle3 .normal (p2, p6, p7, normals [3]); // top
         Geometry_Triangle3 .normal (p1, p0, p4, normals [4]); // bottom
         Geometry_Triangle3 .normal (p4, p7, p6, normals [5]); // back

         const planes = this .planes;

         planes [0] .set (p1, normals [0]); // front
         planes [1] .set (p4, normals [1]); // left
         planes [2] .set (p2, normals [2]); // right
         planes [3] .set (p6, normals [3]); // top
         planes [4] .set (p0, normals [4]); // bottom
         planes [5] .set (p7, normals [5]); // back

         this .edges .tainted = true;

         return this;
      };
   })(),
   getViewport ()
   {
      return this .viewport;
   },
   getScissor ()
   {
      return this .scissor;
   },
   getEdges ()
   {
      // Return suitable edges for SAT theorem.

      const edges = this .edges;

      if (edges .tainted)
      {
         const [p0, p1 ,p2, p3, p4, p5, p6, p7] = this .points;

         edges [0] .assign (p0) .subtract (p1);
         edges [1] .assign (p1) .subtract (p2);
         edges [2] .assign (p2) .subtract (p3);
         edges [3] .assign (p3) .subtract (p0);

         edges [4] .assign (p0) .subtract (p4);
         edges [5] .assign (p1) .subtract (p5);
         edges [6] .assign (p2) .subtract (p6);
         edges [7] .assign (p3) .subtract (p7);

         // Edges 8 - 11 are equal to edges 0 - 3.

         edges .tainted = false;
      }

      return edges;
   },
   intersectsSphere (radius, center)
   {
      const [p0, p1 ,p2, p3, p4, p5, p6, p7] = this .planes;

      if (p0 .getDistanceToPoint (center) > radius)
         return false;

      if (p1 .getDistanceToPoint (center) > radius)
         return false;

      if (p2 .getDistanceToPoint (center) > radius)
         return false;

      if (p3 .getDistanceToPoint (center) > radius)
         return false;

      if (p4 .getDistanceToPoint (center) > radius)
         return false;

      if (p5 .getDistanceToPoint (center) > radius)
         return false;

      return true;
   },
   intersectsBox: (() =>
   {
      const points1 = [
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),

         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
      ];

      const normals1 = [
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
      ];

      const axes1 = [
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
      ];

      const axes = [ ];

      for (let i = 0; i < 3 * 8; ++ i)
         axes .push (new Numbers_Vector3 (0, 0, 0));

      return function (box)
      {
         // Get points.

         box .getPoints (points1);

         const points2 = this .points;

         // Test the three planes spanned by the normal vectors of the faces of the box.

         if (Algorithms_SAT .isSeparated (box .getNormals (normals1), points1, points2))
            return false;

         // Test the six planes spanned by the normal vectors of the faces of the view volume.

         if (Algorithms_SAT .isSeparated (this .normals, points1, points2))
            return false;

         // Test the planes spanned by the edges of each object.

         box .getAxes (axes1);

         const edges = this .getEdges ();

         for (let i1 = 0; i1 < 3; ++ i1)
         {
            for (let i2 = 0; i2 < 8; ++ i2)
               axes [i1 * 3 + i2] .assign (axes1 [i1]) .cross (edges [i2]);
         }

         if (Algorithms_SAT .isSeparated (axes, points1, points2))
            return false;

         // Both boxes intersect.

         return true;
      };
   })(),
});

Object .assign (ViewVolume,
{
   unProjectPoint: (() =>
   {
      const invModelViewProjectionMatrix = new Numbers_Matrix4 ();

      return function (winx, winy, winz, modelViewMatrix, projectionMatrix, viewport, point)
      {
         return this .unProjectPointMatrix (winx, winy, winz, invModelViewProjectionMatrix .assign (modelViewMatrix) .multRight (projectionMatrix) .inverse (), viewport, point);
      };
   })(),
   unProjectPointMatrix: (() =>
   {
      const vin = new Numbers_Vector4 (0, 0, 0, 0);

      return function (winx, winy, winz, invModelViewProjectionMatrix, viewport, point)
      {
         // Transformation of normalized coordinates between -1 and 1
         vin .set ((winx - viewport [0]) / viewport [2] * 2 - 1,
                   (winy - viewport [1]) / viewport [3] * 2 - 1,
                   2 * winz - 1,
                   1);

         //Objects coordinates
         invModelViewProjectionMatrix .multVecMatrix (vin);

         const d = 1 / vin .w;

         return point .set (vin .x * d, vin .y * d, vin .z * d, 1);
      };
   })(),
   unProjectRay: (() =>
   {
      const invModelViewProjectionMatrix = new Numbers_Matrix4 ();

      return function (winx, winy, modelViewMatrix, projectionMatrix, viewport, result)
      {
         return this .unProjectRayMatrix (winx, winy, invModelViewProjectionMatrix .assign (modelViewMatrix) .multRight (projectionMatrix) .inverse (), viewport, result);
      };
   })(),
   unProjectRayMatrix: (() =>
   {
      const
         near = new Numbers_Vector3 (0, 0, 0),
         far  = new Numbers_Vector3 (0, 0, 0);

      return function (winx, winy, invModelViewProjectionMatrix, viewport, result)
      {
         ViewVolume .unProjectPointMatrix (winx, winy, 0.0, invModelViewProjectionMatrix, viewport, near);
         ViewVolume .unProjectPointMatrix (winx, winy, 0.9, invModelViewProjectionMatrix, viewport, far);

         return result .setPoints (near, far);
      };
   })(),
   projectPoint: (() =>
   {
      const vin = new Numbers_Vector4 (0, 0, 0, 0);

      return function (point, modelViewMatrix, projectionMatrix, viewport, vout)
      {
         if (point .length === 4)
            vin .assign (point);
         else
            vin .set (point .x, point .y, point .z, 1);

         projectionMatrix .multVecMatrix (modelViewMatrix .multVecMatrix (vin));

         const d = 1 / (2 * vin .w);

         return vout .set ((vin .x * d + 0.5) * viewport [2] + viewport [0],
                           (vin .y * d + 0.5) * viewport [3] + viewport [1],
                           (vin .z * d + 0.5));
      };
   })(),
   projectPointMatrix: (() =>
   {
      const vin = new Numbers_Vector4 (0, 0, 0, 0);

      return function (point, modelViewProjectionMatrix, viewport, vout)
      {
         if (point .length === 4)
            vin .assign (point);
         else
            vin .set (point .x, point .y, point .z, 1);

         modelViewProjectionMatrix .multVecMatrix (vin);

         const d = 1 / (2 * vin .w);

         return vout .set ((vin .x * d + 0.5) * viewport [2] + viewport [0],
                           (vin .y * d + 0.5) * viewport [3] + viewport [1],
                           (vin .z * d + 0.5));
      };
   })(),
   projectLine: (() =>
   {
      const modelViewProjectionMatrix = new Numbers_Matrix4 ();

      return function (line, modelViewMatrix, projectionMatrix, viewport, result)
      {
         return this .projectLineMatrix (line, modelViewProjectionMatrix .assign (modelViewMatrix) .multRight (projectionMatrix), viewport, result);
      };
   })(),
   projectLineMatrix: (() =>
   {
      const
         near      = new Numbers_Vector2 (0, 0),
         far       = new Numbers_Vector2 (0, 0),
         direction = new Numbers_Vector3 (0, 0, 0);

      return function (line, modelViewProjectionMatrix, viewport, result)
      {
         ViewVolume .projectPointMatrix (line .point, modelViewProjectionMatrix, viewport, near);
         ViewVolume .projectPointMatrix (direction .assign (line .direction) .multiply (1e9) .add (line .point), modelViewProjectionMatrix, viewport, far);

         return result .setPoints (near, far);
      };
   })(),
});

const ViewVolume_default_ = ViewVolume;
;

x_ite_Namespace .add ("ViewVolume", "standard/Math/Geometry/ViewVolume", ViewVolume_default_);
/* harmony default export */ const Geometry_ViewVolume = (ViewVolume_default_);
;// CONCATENATED MODULE: ./src/x_ite/Rendering/TextureBuffer.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function TextureBuffer (browser, width, height, float = false)
{
   const gl = browser .getContext ();

   this .context = gl;
   this .width   = width;
   this .height  = height;

   Object .defineProperty (this, "array",
   {
      get ()
      {
         const value = float ? new Float32Array (width * height * 4) : new Uint8Array (width * height * 4);

         Object .defineProperty (this, "array", { value: value });

         return value;
      },
      configurable: true,
   });

   // Create frame buffer.

   this .lastBuffer  = gl .getParameter (gl .FRAMEBUFFER_BINDING);
   this .frameBuffer = gl .createFramebuffer ();

   gl .bindFramebuffer (gl .FRAMEBUFFER, this .frameBuffer);

   // Create color texture.

   this .colorTexture = gl .createTexture ();

   gl .bindTexture (gl .TEXTURE_2D, this .colorTexture);
   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 .texParameteri (gl .TEXTURE_2D, gl .TEXTURE_MIN_FILTER, gl .LINEAR);
   gl .texParameteri (gl .TEXTURE_2D, gl .TEXTURE_MAG_FILTER, gl .LINEAR);

   if (float)
      gl .texImage2D (gl .TEXTURE_2D, 0, gl .getVersion () > 1 ? gl .RGBA32F : gl .RGBA, width, height, 0, gl .RGBA, gl .FLOAT, null);
   else
      gl .texImage2D (gl .TEXTURE_2D, 0, gl .RGBA, width, height, 0, gl .RGBA, gl .UNSIGNED_BYTE, null);

   gl .framebufferTexture2D (gl .FRAMEBUFFER, gl .COLOR_ATTACHMENT0, gl .TEXTURE_2D, this .colorTexture, 0);

   // Create depth buffer.

   if (gl .HAS_FEATURE_DEPTH_TEXTURE)
   {
      this .depthTexture = gl .createTexture ();

      gl .bindTexture (gl .TEXTURE_2D, this .depthTexture);

      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 .texParameteri (gl .TEXTURE_2D, gl .TEXTURE_MAG_FILTER, gl .NEAREST);
      gl .texParameteri (gl .TEXTURE_2D, gl .TEXTURE_MIN_FILTER, gl .NEAREST);

      const internalFormat = gl .getVersion () >= 2 ? gl .DEPTH_COMPONENT24 : gl .DEPTH_COMPONENT;

      gl .texImage2D (gl .TEXTURE_2D, 0, internalFormat, width, height, 0, gl .DEPTH_COMPONENT, gl .UNSIGNED_INT, null);
      gl .framebufferTexture2D (gl .FRAMEBUFFER, gl .DEPTH_ATTACHMENT, gl .TEXTURE_2D, this .depthTexture, 0);
   }
   else
   {
      this .depthBuffer = gl .createRenderbuffer ();

      gl .bindRenderbuffer (gl .RENDERBUFFER, this .depthBuffer);
      gl .renderbufferStorage (gl .RENDERBUFFER, gl .DEPTH_COMPONENT16, width, height);
      gl .framebufferRenderbuffer (gl .FRAMEBUFFER, gl .DEPTH_ATTACHMENT, gl .RENDERBUFFER, this .depthBuffer);
   }

   const status = gl .checkFramebufferStatus (gl .FRAMEBUFFER) === gl .FRAMEBUFFER_COMPLETE;

   gl .bindTexture (gl .TEXTURE_2D, null);
   gl .bindFramebuffer (gl .FRAMEBUFFER, this .lastBuffer);

   // Always check that our framebuffer is ok.

   if (!status)
      throw new Error ("Couldn't create frame buffer.");
}

Object .assign (TextureBuffer .prototype,
{
   getWidth ()
   {
      return this .width;
   },
   getHeight ()
   {
      return this .height;
   },
   getColorTexture ()
   {
      return this .colorTexture;
   },
   getDepthTexture ()
   {
      return this .depthTexture;
   },
   readPixels ()
   {
      const { context: gl, array, width, height } = this;

      gl .readPixels (0, 0, width, height, gl .RGBA, gl .UNSIGNED_BYTE, array);

      return array;
   },
   readDepth: (() =>
   {
      const
         invProjectionMatrix = new Numbers_Matrix4 (),
         point               = new Numbers_Vector3 (0, 0, 0);

      return function (projectionMatrix, viewport)
      {
         const { context: gl, array, width, height } = this;

         gl .readPixels (0, 0, width, height, gl .RGBA, gl .FLOAT, array);

         let
            winX = 0,
            winY = 0,
            winZ = Number .POSITIVE_INFINITY;

         for (let wy = 0, i = 0; wy < height; ++ wy)
         {
            for (let wx = 0; wx < width; ++ wx, i += 4)
            {
               const wz = array [i];

               if (wz < winZ)
               {
                  winX = wx;
                  winY = wy;
                  winZ = wz;
               }
            }
         }

         invProjectionMatrix .assign (projectionMatrix) .inverse ();

         Geometry_ViewVolume .unProjectPointMatrix (winX, winY, winZ, invProjectionMatrix, viewport, point);

         return point .z;
      };
   })(),
   bind ()
   {
      const gl = this .context;

      this .lastBuffer = gl .getParameter (gl .FRAMEBUFFER_BINDING);

      gl .bindFramebuffer (gl .FRAMEBUFFER, this .frameBuffer);
   },
   unbind ()
   {
      const gl = this .context;

      gl .bindFramebuffer (gl .FRAMEBUFFER, this .lastBuffer);
   },
   delete ()
   {
      const gl = this .context;

      gl .deleteFramebuffer (this .frameBuffer);
      gl .deleteTexture (this .colorTexture);

      if (gl .HAS_FEATURE_DEPTH_TEXTURE)
         gl .deleteTexture (this .depthTexture);
      else
         gl .deleteRenderbuffer (this .depthBuffer);
    },
});

for (const key of Object .keys (TextureBuffer .prototype))
   Object .defineProperty (TextureBuffer .prototype, key, { enumerable: false });

const TextureBuffer_default_ = TextureBuffer;
;

x_ite_Namespace .add ("TextureBuffer", "x_ite/Rendering/TextureBuffer", TextureBuffer_default_);
/* harmony default export */ const Rendering_TextureBuffer = (TextureBuffer_default_);
;// CONCATENATED MODULE: ./src/x_ite/Rendering/TraverseType.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

let i = 0;

const TraverseType =
{
   POINTER:   i ++,
   CAMERA:    i ++,
   PICKING:   i ++,
   COLLISION: i ++,
   SHADOW:    i ++,
   DISPLAY:   i ++,
};

const TraverseType_default_ = TraverseType;
;

x_ite_Namespace .add ("TraverseType", "x_ite/Rendering/TraverseType", TraverseType_default_);
/* harmony default export */ const Rendering_TraverseType = (TraverseType_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Algorithms/MergeSort.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

function MergeSort (array, compare)
{
   this .array     = array;
   this .auxiliary = [ ];

   if (compare)
      this .compare = compare;
}

Object .assign (MergeSort .prototype,
{
   compare (lhs, rhs)
   {
      return lhs < rhs;
   },
   sort (first, last)
   {
      this .mergeSort (first, last - 1);
   },
   mergeSort (lo, hi)
   {
      if (lo < hi)
      {
         const m = (lo + hi) >>> 1;
         this .mergeSort (lo, m);   // Recursion
         this .mergeSort (m + 1, hi); // Recursion
         this .merge (lo, m, hi);
      }
   },
   merge (lo, m, hi)
   {
      const { array, auxiliary, compare } = this;

      let i, j, k;

      i = 0, j = lo;
      // Copy first half of array a to auxiliary array b.
      while (j <= m)
         auxiliary [i++] = array [j++];

      i = 0; k = lo;
      // Copy back next-greatest element at each time.
      while (k < j && j <= hi)
      {
         if (compare (array [j], auxiliary [i]))
            array [k++] = array [j++];
         else
            array [k++] = auxiliary [i++];
      }

      // Copy back remaining elements of first half (if any).
      while (k < j)
         array [k++] = auxiliary [i++];
   }
});

const MergeSort_default_ = MergeSort;
;

x_ite_Namespace .add ("MergeSort", "standard/Math/Algorithms/MergeSort", MergeSort_default_);
/* harmony default export */ const Algorithms_MergeSort = (MergeSort_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Geometry/Camera.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



const Camera =
{
   frustum (l, r, b, t, n, f, matrix)
   {
      const
         r_l = r - l,
         t_b = t - b,
         f_n = f - n,
         n_2 = 2 * n,

         A = (r + l) / r_l,
         B = (t + b) / t_b,
         C = -(f + n) / f_n,
         D = -(n_2 * f) / f_n,
         E = n_2 / r_l,
         F = n_2 / t_b;

      return matrix .set (E, 0, 0, 0,
                          0, F, 0, 0,
                          A, B, C, -1,
                          0, 0, D, 0);
   },
   perspective (fieldOfView, zNear, zFar, width, height, matrix)
   {
      const ratio = Math .tan (fieldOfView / 2) * zNear;

      if (width > height)
      {
         const aspect = width * ratio / height;
         return this .frustum (-aspect, aspect, -ratio, ratio, zNear, zFar, matrix);
      }
      else
      {
         const aspect = height * ratio / width;
         return this .frustum (-ratio, ratio, -aspect, aspect, zNear, zFar, matrix);
      }
   },
   perspective2 (fieldOfView, zNear, zFar, width, height, matrix)
   {
      const ratio = Math .tan (fieldOfView / 2) * zNear;

      return this .frustum (-ratio, ratio, -ratio, ratio, zNear, zFar, matrix);
   },
   ortho (l, r, b, t, n, f, matrix)
   {
      const
         r_l = r - l,
         t_b = t - b,
         f_n = f - n,

         A =  2 / r_l,
         B =  2 / t_b,
         C = -2 / f_n,
         D = -(r + l) / r_l,
         E = -(t + b) / t_b,
         F = -(f + n) / f_n;

      return matrix .set (A, 0, 0, 0,
                          0, B, 0, 0,
                          0, 0, C, 0,
                          D, E, F, 1);
   },
   orthoBox: (() =>
   {
      const
         min = new Numbers_Vector3 (0, 0, 0),
         max = new Numbers_Vector3 (0, 0, 0);

      return function (box, matrix)
      {
         box .getExtents (min, max);

         return this .ortho (min .x, max .x, min .y, max .y, -max .z, -min .z, matrix);
      };
   })(),
};

const Camera_default_ = Camera;
;

x_ite_Namespace .add ("Camera", "standard/Math/Geometry/Camera", Camera_default_);
/* harmony default export */ const Geometry_Camera = (Camera_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Geometry/Box3.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






function Box3 (/* size, center */)
{
   this .matrix = new Numbers_Matrix4 ();

   this .set (... arguments);
}

Object .assign (Box3 .prototype,
{
   copy ()
   {
      const copy = Object .create (Box3 .prototype);
      copy .matrix = this .matrix .copy ();
      return copy;
   },
   assign (box)
   {
      this .matrix .assign (box .matrix);
      return this;
   },
   equals (box)
   {
      return this .matrix .equals (box .matrix);
   },
   getMatrix ()
   {
      return this .matrix;
   },
   set (size, center)
   {
      switch (arguments .length)
      {
         case 0:
         {
            this .matrix .set (0, 0, 0, 0,
                               0, 0, 0, 0,
                               0, 0, 0, 0,
                               0, 0, 0, 0);

            return this;
         }
         case 2:
         {
            this .matrix .set (size .x / 2, 0, 0, 0,
                               0, size .y / 2, 0, 0,
                               0, 0, size .z / 2, 0,
                               center .x, center .y, center .z, 1);

            return this;
         }
         // case 3:
         // {
         //    console .trace ()
         //    return this .setExtents (arguments [0], arguments [1]);
         // }
      }
   },
   setExtents (min, max)
   {
      const
         sx = (max .x - min .x) / 2,
         sy = (max .y - min .y) / 2,
         sz = (max .z - min .z) / 2,
         cx = (max .x + min .x) / 2,
         cy = (max .y + min .y) / 2,
         cz = (max .z + min .z) / 2;

      this .matrix .set (sx, 0,  0,  0,
                         0,  sy, 0,  0,
                         0,  0,  sz, 0,
                         cx, cy, cz, 1);

      return this;
   },
   getExtents (min, max)
   {
      this .getAbsoluteExtents (min, max);

      min .add (this .center);
      max .add (this .center);
   },
   getAbsoluteExtents: (() =>
   {
      const
         r1 = new Numbers_Vector3 (0, 0, 0),
         p1 = new Numbers_Vector3 (0, 0, 0),
         p4 = new Numbers_Vector3 (0, 0, 0);

      return function (min, max)
      {
         const
            m = this .matrix,
            x = m .xAxis,
            y = m .yAxis,
            z = m .zAxis;

         r1 .assign (y) .add (z);

         const r2 = z .subtract (y);

         p1 .assign (x) .add (r1),
         p4 .assign (x) .add (r2);

         const
            p2 = r1 .subtract (x),
            p3 = r2 .subtract (x);

         min .assign (p1) .min (p2, p3, p4);
         max .assign (p1) .max (p2, p3, p4);

         p1 .negate ();
         p2 .negate ();
         p3 .negate ();
         p4 .negate ();

         min .min (p1, p2, p3, p4);
         max .max (p1, p2, p3, p4);
      };
   })(),
   getPoints: (() =>
   {
      const
         x  = new Numbers_Vector3 (0, 0, 0),
         y  = new Numbers_Vector3 (0, 0, 0),
         z  = new Numbers_Vector3 (0, 0, 0),
         r1 = new Numbers_Vector3 (0, 0, 0);

      return function (points)
      {
         /*
          * p6 ---------- p5
          * | \           | \
          * | p2------------ p1
          * |  |          |  |
          * |  |          |  |
          * p7 |_________ p8 |
          *  \ |           \ |
          *   \|            \|
          *    p3 ---------- p4
          */

         const m = this .matrix;

         x .assign (m .xAxis);
         y .assign (m .yAxis);
         z .assign (m .zAxis);

         r1 .assign (y) .add (z);

         const r2 = z .subtract (y);

         points [0] .assign (x)  .add (r1);
         points [1] .assign (r1) .subtract (x);
         points [2] .assign (r2) .subtract (x);
         points [3] .assign (x)  .add (r2);

         points [4] .assign (points [2]) .negate ();
         points [5] .assign (points [3]) .negate ();
         points [6] .assign (points [0]) .negate ();
         points [7] .assign (points [1]) .negate ();

         const center = this .center;

         points [0] .add (center);
         points [1] .add (center);
         points [2] .add (center);
         points [3] .add (center);

         points [4] .add (center);
         points [5] .add (center);
         points [6] .add (center);
         points [7] .add (center);

         return points;
      };
   })(),
   getAxes (axes)
   {
      const m = this .matrix;

      axes [0] .assign (m .xAxis);
      axes [1] .assign (m .yAxis);
      axes [2] .assign (m .zAxis);

      return axes;
   },
   getNormals: (() =>
   {
      const
         x = new Numbers_Vector3 (0, 0, 0),
         y = new Numbers_Vector3 (0, 0, 0),
         z = new Numbers_Vector3 (0, 0, 0);

      const axes = [ Numbers_Vector3 .xAxis, Numbers_Vector3 .yAxis, Numbers_Vector3 .zAxis ];

      return function (normals)
      {
         const m = this .matrix;

         x .assign (m .xAxis);
         y .assign (m .yAxis);
         z .assign (m .zAxis);

         if (x .norm () === 0)
         {
            x .assign (y) .cross (z);

            if (x .norm () === 0)
            {
               for (const axis of axes)
               {
                  x .assign (axis) .cross (y);

                  if (x .norm () !== 0)
                     break;
               }

               if (x .norm () === 0)
               {
                  for (const axis of axes)
                  {
                     x .assign (axis) .cross (z);

                     if (x .norm () !== 0)
                        break;
                  }

                  if (x .norm () === 0)
                     x .assign (Numbers_Vector3 .xAxis);
               }
            }
         }

         if (y .norm () === 0)
         {
            y .assign (z) .cross (x);

            if (y .norm () === 0)
            {
               for (const axis of axes)
               {
                  y .assign (axis) .cross (z);

                  if (y .norm () !== 0)
                     break;
               }

               if (y .norm () === 0)
               {
                  for (const axis of axes)
                  {
                     y .assign (axis) .cross (x);

                     if (y .norm () !== 0)
                        break;
                  }

                  if (y .norm () === 0)
                     y .assign (Numbers_Vector3 .yAxis);
               }
            }
         }

         if (z .norm () === 0)
         {
            z .assign (x) .cross (y);

            if (z .norm () === 0)
            {
               for (const axis of axes)
               {
                  z .assign (axis) .cross (x);

                  if (z .norm () !== 0)
                     break;
               }

               if (z .norm () === 0)
               {
                  for (const axis of axes)
                  {
                     z .assign (axis) .cross (y);

                     if (z .norm () !== 0)
                        break;
                  }

                  if (z .norm () === 0)
                     z .assign (Numbers_Vector3 .zAxis);
               }
            }
         }

         normals [0] .assign (y) .cross (z) .normalize ();
         normals [1] .assign (z) .cross (x) .normalize ();
         normals [2] .assign (x) .cross (y) .normalize ();

         return normals;
      };
   })(),
   isEmpty ()
   {
      return this .matrix [15] === 0;
   },
   add: (() =>
   {
      const
         lhs_min = new Numbers_Vector3 (0, 0, 0),
         lhs_max = new Numbers_Vector3 (0, 0, 0),
         rhs_min = new Numbers_Vector3 (0, 0, 0),
         rhs_max = new Numbers_Vector3 (0, 0, 0);

      return function (box)
      {
         if (this .isEmpty ())
            return this .assign (box);

         if (box .isEmpty ())
            return this;

         this .getExtents (lhs_min, lhs_max);
         box  .getExtents (rhs_min, rhs_max);

         return this .setExtents (lhs_min .min (rhs_min), lhs_max .max (rhs_max));
      };
   })(),
   multLeft (matrix)
   {
      this .matrix .multLeft (matrix);
      return this;
   },
   multRight (matrix)
   {
      this .matrix .multRight (matrix);
      return this;
   },
   containsPoint: (() =>
   {
      const
         min = new Numbers_Vector3 (0, 0, 0),
         max = new Numbers_Vector3 (0, 0, 0);

      return function (point)
      {
         this .getExtents (min, max);

         return min .x <= point .x &&
                max .x >= point .x &&
                min .y <= point .y &&
                max .y >= point .y &&
                min .z <= point .z &&
                max .z >= point .z;
      };
   })(),
   intersectsBox: (() =>
   {
      const points1 = [
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),

         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
      ];

      const points2 = [
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),

         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
      ];

      const axes1 = [
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
      ];

      const axes2 = [
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
      ];

      const axes9 = [
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),

         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),

         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
      ];

      const normals = [
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
      ];

      return function (other)
      {
         // Test special cases.

         if (this .isEmpty ())
            return false;

         if (other .isEmpty ())
            return false;

         // Get points.

         this  .getPoints (points1);
         other .getPoints (points2);

         // Test the three planes spanned by the normal vectors of the faces of the first parallelepiped.

         if (Algorithms_SAT .isSeparated (this .getNormals (normals), points1, points2))
            return false;

         // Test the three planes spanned by the normal vectors of the faces of the second parallelepiped.

         if (Algorithms_SAT .isSeparated (other .getNormals (normals), points1, points2))
            return false;

         // Test the nine other planes spanned by the edges of each parallelepiped.

         this  .getAxes (axes1);
         other .getAxes (axes2);

         for (let i1 = 0; i1 < 3; ++ i1)
         {
            for (let i2 = 0; i2 < 3; ++ i2)
               axes9 [i1 * 3 + i2] .assign (axes1 [i1]) .cross (axes2 [i2]);
         }

         if (Algorithms_SAT .isSeparated (axes9, points1, points2))
            return false;

         // Both boxes intersect.

         return true;
      };
   })(),
   intersectsTriangle: (() =>
   {
      const points1 = [
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),

         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
      ];

      const axes1 = [
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
      ];

      const axes9 = [
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),

         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),

         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
      ];

      const normals = [
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
      ];

      const triangle = [ ];

      const triangleNormal = [ new Numbers_Vector3 (0, 0, 0) ];

      const triangleEdges = [
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0),
         new Numbers_Vector3 (0, 0, 0)
      ];

      return function (a, b, c)
      {
         // Test special cases.

         if (this .isEmpty ())
            return false;

         // Get points.

         this .getPoints (points1);

         triangle [0] = a;
         triangle [1] = b;
         triangle [2] = c;

         // Test the three planes spanned by the normal vectors of the faces of the first parallelepiped.

         if (Algorithms_SAT .isSeparated (this .getNormals (normals), points1, triangle))
            return false;

         // Test the normal of the triangle.

         Geometry_Triangle3 .normal (a, b, c, triangleNormal [0]);

         if (Algorithms_SAT .isSeparated (triangleNormal, points1, triangle))
            return false;

         // Test the nine other planes spanned by the edges of each parallelepiped.

         this .getAxes (axes1);

         triangleEdges [0] .assign (a) .subtract (b);
         triangleEdges [1] .assign (b) .subtract (c);
         triangleEdges [2] .assign (c) .subtract (a);

         for (let i1 = 0; i1 < 3; ++ i1)
         {
            for (let i2 = 0; i2 < 3; ++ i2)
               axes9 [i1 * 3 + i2] .assign (axes1 [i1]) .cross (triangleEdges [i2]);
         }

         if (Algorithms_SAT .isSeparated (axes9, points1, triangle))
            return false;

         // Box and triangle intersect.

         return true;
      };
   })(),
   toString ()
   {
      return `${this .size}, ${this .center}`;
   },
});

Object .assign (Box3,
{
   Extents (min, max)
   {
      return new Box3 () .setExtents (min, max);
   },
   Points (points)
   {
      const
         min = new Numbers_Vector3 (Number .POSITIVE_INFINITY, Number .POSITIVE_INFINITY, Number .POSITIVE_INFINITY),
         max = new Numbers_Vector3 (Number .NEGATIVE_INFINITY, Number .NEGATIVE_INFINITY, Number .NEGATIVE_INFINITY);

      for (const point of points)
      {
         min .min (point);
         max .max (point);
      }

      return new Box3 () .setExtents (min, max);
   },
});

Object .defineProperties (Box3 .prototype,
{
   size:
   {
      get: (() =>
      {
         const
            min = new Numbers_Vector3 (0, 0, 0),
            max = new Numbers_Vector3 (0, 0, 0);

         return function ()
         {
            this .getAbsoluteExtents (min, max);

            return max .subtract (min);
         };
      })(),
      enumerable: true,
   },
   center:
   {
      get ()
      {
         return this .matrix .origin;
      },
      enumerable: true,
   },
});

const Box3_default_ = Box3;
;

x_ite_Namespace .add ("Box3", "standard/Math/Geometry/Box3", Box3_default_);
/* harmony default export */ const Geometry_Box3 = (Box3_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Geometry/Line3.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function Line3 (point, direction)
{
   this .point     = point     .copy ();
   this .direction = direction .copy ();
}

Object .assign (Line3 .prototype,
{
   copy ()
   {
      const copy = Object .create (Line3 .prototype);
      copy .point     = this .point .copy ();
      copy .direction = this .direction .copy ();
      return copy;
   },
   assign (line)
   {
      this .point     .assign (line .point);
      this .direction .assign (line .direction);
      return this;
   },
   set (point, direction)
   {
      this .point     .assign (point);
      this .direction .assign (direction);
      return this;
   },
   setPoints (point1, point2)
   {
      this .point .assign (point1);
      this .direction .assign (point2) .subtract (point1) .normalize ();
      return this;
   },
   multMatrixLine (matrix)
   {
      matrix .multMatrixVec (this .point);
      matrix .multMatrixDir (this .direction) .normalize ();
      return this;
   },
   multLineMatrix (matrix)
   {
      matrix .multVecMatrix (this .point);
      matrix .multDirMatrix (this .direction) .normalize ();
      return this;
   },
   getClosestPointToPoint (point, result)
   {
      const
         r = result .assign (point) .subtract (this .point),
         d = r .dot (this .direction);

      return result .assign (this .direction) .multiply (d) .add (this .point);
   },
   getClosestPointToLine: (() =>
   {
      const u = new Numbers_Vector3 (0, 0, 0);

      return function (line, point)
      {
         const
            { point: p1, direction: d1 } = this,
            { point: p2, direction: d2 } = line;

         let t = d1 .dot (d2);

         if (Math .abs (t) >= 1)
            return false;  // lines are parallel

         u .assign (p2) .subtract (p1);

         t = (u .dot (d1) - t * u .dot (d2)) / (1 - t * t);

         point .assign (d1) .multiply (t) .add (p1);
         return true;
      };
   })(),
   getPerpendicularVectorToPoint: (() =>
   {
      const t = new Numbers_Vector3 (0, 0, 0);

      return function (point, result)
      {
         result .assign (this .point) .subtract (point);

         return result .subtract (t .assign (this .direction) .multiply (result .dot (this .direction)));
      };
   })(),
   getPerpendicularVectorToLine: (() =>
   {
      const
         d  = new Numbers_Vector3 (0, 0, 0),
         ad = new Numbers_Vector3 (0, 0, 0);

      return function (line, result)
      {
         const bd = result;

         d .assign (this .point) .subtract (line .point);

         const
            re1 = d .dot (this .direction),
            re2 = d .dot (line .direction),
            e12 = this .direction .dot (line .direction),
            E12 = e12 * e12;

         const
            a =  (re1 - re2 * e12) / (1 - E12),
            b = -(re2 - re1 * e12) / (1 - E12);

         ad .assign (this .direction) .multiply (a);
         bd .assign (line .direction) .multiply (b);

         return bd .subtract (ad) .add (d);
      };
   })(),
   intersectsTriangle: (() =>
   {
      const
         pvec = new Numbers_Vector3 (0, 0, 0),
         tvec = new Numbers_Vector3 (0, 0, 0);

      return function (A, B, C, uvt)
      {
         // Find vectors for two edges sharing vert0.
         const
            edge1 = B .subtract (A),
            edge2 = C .subtract (A);

         // Begin calculating determinant - also used to calculate U parameter.
         pvec .assign (this .direction) .cross (edge2);

         // If determinant is near zero, ray lies in plane of triangle.
         const det = edge1 .dot (pvec);

         // Non culling intersection.

         if (det === 0)
            return false;

            const inv_det = 1 / det;

         // Calculate distance from vert0 to ray point.
         tvec .assign (this .point) .subtract (A);

         // Calculate U parameter and test bounds.
         const u = tvec .dot (pvec) * inv_det;

         if (u < 0 || u > 1)
            return false;

         // Prepare to test V parameter.
         const qvec = tvec .cross (edge1);

         // Calculate V parameter and test bounds.
         const v = this .direction .dot (qvec) * inv_det;

         if (v < 0 || u + v > 1)
            return false;

         //let t = edge2 .dot (qvec) * inv_det;

         uvt .u = u;
         uvt .v = v;
         uvt .t = 1 - u - v;

         return true;
      };
   })(),
   toString ()
   {
      return `${this .point}, ${this .direction}`;
   },
});

Object .assign (Line3,
{
   Points (point1, point2)
   {
      const line = Object .create (Line3 .prototype);
      line .point     = point1 .copy ();
      line .direction = point2 .copy () .subtract (point1) .normalize ();
      return line;
   },
});

const Line3_default_ = Line3;
;

x_ite_Namespace .add ("Line3", "standard/Math/Geometry/Line3", Line3_default_);
/* harmony default export */ const Geometry_Line3 = (Line3_default_);
;// CONCATENATED MODULE: ./src/standard/Time/StopWatch.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

class StopWatch
{
   #startTime = 0;
   #stopTime = 0;
   cycles = 0;
   elapsedTime = 0;

   start ()
   {
      this .#startTime = Date .now ();
   }

   stop ()
   {
      if (this .#startTime <= this .#stopTime)
         return;

      this .#stopTime    = Date .now ();
      this .cycles      += 1;
      this .elapsedTime += this .#stopTime - this .#startTime;
   }

   reset ()
   {
      this .#startTime  = 0;
      this .#stopTime   = 0;
      this .cycles      = 0;
      this .elapsedTime = 0;
   }

   get averageTime ()
   {
      return this .cycles ? this .elapsedTime / this .cycles : 0;
   }
}

const StopWatch_default_ = StopWatch;
;

x_ite_Namespace .add ("StopWatch", "standard/Time/StopWatch", StopWatch_default_);
/* harmony default export */ const Time_StopWatch = (StopWatch_default_);
;// CONCATENATED MODULE: ./src/x_ite/Rendering/X3DRenderObject.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/















const DEPTH_BUFFER_SIZE = 16;

let renderCount = 0;

function X3DRenderObject (executionContext)
{
   const browser = executionContext .getBrowser ();

   this .renderCount              = 0;
   this .viewVolumes              = [ ];
   this .cameraSpaceMatrix        = new Utility_MatrixStack (Numbers_Matrix4);
   this .viewMatrix               = new Utility_MatrixStack (Numbers_Matrix4);
   this .projectionMatrix         = new Utility_MatrixStack (Numbers_Matrix4);
   this .modelViewMatrix          = new Utility_MatrixStack (Numbers_Matrix4);
   this .viewportArray            = new Int32Array (4);
   this .projectionMatrixArray    = new Float32Array (16);
   this .cameraSpaceMatrixArray   = new Float32Array (16);
   this .hitRay                   = new Geometry_Line3 (Numbers_Vector3 .Zero, Numbers_Vector3 .Zero);
   this .sensors                  = [[ ]];
   this .viewpointGroups          = [ ];
   this .localObjectsCount        = [0, 0, 0];
   this .globalObjects            = [ ];
   this .localObjects             = [ ];
   this .lights                   = [ ];
   this .globalShadows            = [ false ];
   this .localShadows             = [ false ];
   this .localFogs                = [ null ];
   this .layouts                  = [ ];
   this .humanoids                = [ ];
   this .textureProjectors        = [ ];
   this .generatedCubeMapTextures = [ ];
   this .collisions               = [ ];
   this .collisionTime            = new Time_StopWatch ();
   this .numPointingShapes        = 0;
   this .numCollisionShapes       = 0;
   this .numShadowShapes          = 0;
   this .numOpaqueShapes          = 0;
   this .numTransparentShapes     = 0;
   this .pointingShapes           = [ ];
   this .collisionShapes          = [ ];
   this .activeCollisions         = [ ];
   this .shadowShapes             = [ ];
   this .opaqueShapes             = [ ];
   this .transparentShapes        = [ ];
   this .transparencySorter       = new Algorithms_MergeSort (this .transparentShapes, (a, b) => a .distance < b .distance);
   this .speed                    = 0;
   this .depthBuffer              = new Rendering_TextureBuffer (browser, DEPTH_BUFFER_SIZE, DEPTH_BUFFER_SIZE, true);
}

Object .assign (X3DRenderObject .prototype,
{
   initialize ()
   { },
   isIndependent ()
   {
      return true;
   },
   getRenderCount ()
   {
      return this .renderCount;
   },
   getViewVolumes ()
   {
      return this .viewVolumes;
   },
   getViewVolume ()
   {
      return this .viewVolumes .at (-1);
   },
   getCameraSpaceMatrix ()
   {
      return this .cameraSpaceMatrix;
   },
   getViewMatrix ()
   {
      return this .viewMatrix;
   },
   getProjectionMatrix ()
   {
      return this .projectionMatrix;
   },
   getModelViewMatrix ()
   {
      return this .modelViewMatrix;
   },
   getViewportArray ()
   {
      return this .viewportArray;
   },
   getProjectionMatrixArray ()
   {
      return this .projectionMatrixArray;
   },
   getCameraSpaceMatrixArray ()
   {
      return this .cameraSpaceMatrixArray;
   },
   getLogarithmicDepthBuffer ()
   {
      return this .logarithmicDepthBuffer;
   },
   getHitRay ()
   {
      return this .hitRay;
   },
   getSensors ()
   {
      return this .sensors;
   },
   getViewpointGroups ()
   {
      return this .viewpointGroups;
   },
   getGlobalObjects ()
   {
      return this .globalObjects;
   },
   getLocalObjects ()
   {
      return this .localObjects;
   },
   getLocalObjectsCount ()
   {
      return this .localObjectsCount;
   },
   getLights ()
   {
      return this .lights;
   },
   pushGlobalShadows (value)
   {
      this .globalShadows .push (value || this .globalShadows .at (-1));
   },
   getGlobalShadows ()
   {
      return this .globalShadows;
   },
   pushLocalShadows (value)
   {
      this .localShadows .push (value || this .localShadows .at (-1));
   },
   popLocalShadows ()
   {
      this .localShadows .pop ();
   },
   setGlobalFog: (() =>
   {
      const modelViewMatrix = new Numbers_Matrix4 ();

      return function (fogNode)
      {
         if (fogNode .getFogType ())
         {
            const fogContainer = this .localFogs [0] || fogNode .getFogs () .pop ();

            modelViewMatrix .assign (fogNode .getModelMatrix ()) .multRight (this .getViewMatrix () .get ());
            fogContainer .set (fogNode, modelViewMatrix);

            this .localFogs [0] = fogContainer;
         }
         else
         {
            this .localFogs [0] = null;
         }
      };
   })(),
   getLocalFogs ()
   {
      return this .localFogs;
   },
   getLayouts ()
   {
      return this .layouts;
   },
   getParentLayout ()
   {
      return this .layouts .at (-1);
   },
   getHumanoids ()
   {
      return this .humanoids;
   },
   getTextureProjectors ()
   {
      return this .textureProjectors;
   },
   getGeneratedCubeMapTextures ()
   {
      return this .generatedCubeMapTextures;
   },
   getCollisions ()
   {
      return this .collisions;
   },
   getCollisionTime ()
   {
      return this .collisionTime;
   },
   setNumPointingShapes (value)
   {
      this .numPointingShapes = value;
   },
   getNumPointingShapes ()
   {
      return this .numPointingShapes;
   },
   getPointingShapes ()
   {
      return this .pointingShapes;
   },
   setNumCollisionShapes (value)
   {
      this .numCollisionShapes = value;
   },
   getNumCollisionShapes ()
   {
      return this .numCollisionShapes;
   },
   getCollisionShapes ()
   {
      return this .collisionShapes;
   },
   setNumShadowShapes (value)
   {
      this .numShadowShapes = value;
   },
   getNumShadowShapes ()
   {
      return this .numShadowShapes;
   },
   getShadowShapes ()
   {
      return this .shadowShapes;
   },
   setNumOpaqueShapes (value)
   {
      this .numOpaqueShapes = value;
   },
   getNumOpaqueShapes ()
   {
      return this .numOpaqueShapes;
   },
   getOpaqueShapes ()
   {
      return this .opaqueShapes;
   },
   setNumTransparentShapes (value)
   {
      this .numTransparentShapes = value;
   },
   getNumTransparentShapes ()
   {
      return this .numTransparentShapes;
   },
   getTransparentShapes ()
   {
      return this .transparentShapes;
   },
   constrainTranslation (translation, stepBack)
   {
      ///  Contrains @a translation to a possible value the avatar can move.  If the avatar reaches and intersects with an
      ///  and obstacle and @a stepBack is true a translation in the opposite directiion is returned.  Future implementation will
      ///  will then return a value where the avatar slides along the wall.  Modifies translation in place.

      // Constrain translation when the viewer collides with an obstacle.

      const distance = this .getDistance (translation) - this .getNavigationInfo () .getCollisionRadius ();

      if (distance > 0)
      {
         // Move.

         const length = translation .magnitude ();

         if (length > distance)
         {
            // Collision, the avatar would intersect with the obstacle.

            return translation .normalize () .multiply (distance);
         }

         // Everything is fine.

         return translation;
      }

      // Collision, the avatar is already within an obstacle.

      if (stepBack)
         return this .constrainTranslation (translation .normalize () .multiply (distance), false);

      return translation .assign (Numbers_Vector3 .Zero);
   },
   getDistance: (() =>
   {
      const
         projectionMatrix            = new Numbers_Matrix4 (),
         cameraSpaceProjectionMatrix = new Numbers_Matrix4 (),
         localOrientation            = new Numbers_Rotation4 (),
         vector                      = new Numbers_Vector3 (0, 0, 0),
         rotation                    = new Numbers_Rotation4 ();

      return function (direction)
      {
         ///  Returns the distance to the closest object in @a direction.  The maximum determinable value is avatarHeight * 2.

         this .collisionTime .start ();

         const
            viewpoint       = this .getViewpoint (),
            navigationInfo  = this .getNavigationInfo (),
            collisionRadius = navigationInfo .getCollisionRadius (),
            bottom          = navigationInfo .getStepHeight () - navigationInfo .getAvatarHeight (),
            nearValue       = navigationInfo .getNearValue (),
            avatarHeight    = navigationInfo .getAvatarHeight ();

         // Determine width and height of camera

         // Reshape camera

         Geometry_Camera .ortho (-collisionRadius,
                        collisionRadius,
                        Math .min (bottom, -collisionRadius), /// TODO: bottom could be a positive value if stepHeight > avatarHeight.
                        collisionRadius,
                        nearValue,
                        Math .max (collisionRadius * 2, avatarHeight * 2),
                        projectionMatrix);

         // Translate camera to user position and to look in the direction of the direction.

         localOrientation .assign (viewpoint ._orientation .getValue ()) .inverse () .multRight (viewpoint .getOrientation ());
         rotation .setFromToVec (Numbers_Vector3 .zAxis, vector .assign (direction) .negate ()) .multRight (localOrientation);
         viewpoint .straightenHorizon (rotation);

         cameraSpaceProjectionMatrix .assign (viewpoint .getModelMatrix ());
         cameraSpaceProjectionMatrix .translate (viewpoint .getUserPosition ());
         cameraSpaceProjectionMatrix .rotate (rotation);
         cameraSpaceProjectionMatrix .inverse ();

         cameraSpaceProjectionMatrix .multRight (projectionMatrix);
         cameraSpaceProjectionMatrix .multLeft (viewpoint .getCameraSpaceMatrix ());

         this .getProjectionMatrix () .pushMatrix (cameraSpaceProjectionMatrix);

         const depth = this .getDepth (projectionMatrix);

         this .getProjectionMatrix () .pop ();

         this .collisionTime .stop ();
         return -depth;
      };
   })(),
   getDepth: (() =>
   {
      const
         depthBufferViewport   = new Numbers_Vector4 (0, 0, DEPTH_BUFFER_SIZE, DEPTH_BUFFER_SIZE),
         depthBufferViewVolume = new Geometry_ViewVolume ();

      depthBufferViewVolume .set (Numbers_Matrix4 .Identity, depthBufferViewport, depthBufferViewport);

      return function (projectionMatrix)
      {
         ///  Returns the depth value to the closest object.  The maximum determinable value is avatarHeight * 2.

         this .depthBuffer .bind ();
         this .viewVolumes .push (depthBufferViewVolume);

         this .depth (this .collisionShapes, this .numCollisionShapes);

         const depth = this .depthBuffer .readDepth (projectionMatrix, depthBufferViewport);

         this .viewVolumes .pop ();
         this .depthBuffer .unbind ();

         return depth;
      };
   })(),
   render (type, callback, group)
   {
      switch (type)
      {
         case Rendering_TraverseType .POINTER:
         {
            this .numPointingShapes = 0;

            callback .call (group, type, this);
            this .pointing (this .pointingShapes, this .numPointingShapes);
            break;
         }
         case Rendering_TraverseType .COLLISION:
         {
            // Collect for collide and gravite
            this .numCollisionShapes = 0;

            callback .call (group, type, this);
            this .collide ();
            this .gravite ();
            break;
         }
         case Rendering_TraverseType .SHADOW:
         {
            this .numShadowShapes = 0;

            callback .call (group, type, this);
            this .depth (this .shadowShapes, this .numShadowShapes);
            break;
         }
         case Rendering_TraverseType .DISPLAY:
         {
            this .lightIndex           = 0;
            this .numOpaqueShapes      = 0;
            this .numTransparentShapes = 0;

            this .setGlobalFog (this .getFog ());

            callback .call (group, type, this);
            this .draw ();
            break;
         }
      }
   },
   setHitRay (projectionMatrix, viewport, pointer)
   {
      Geometry_ViewVolume .unProjectRay (pointer .x, pointer .y, Numbers_Matrix4 .Identity, projectionMatrix, viewport, this .hitRay);
   },
   addPointingShape: (() =>
   {
      const
         bboxSize   = new Numbers_Vector3 (0, 0, 0),
         bboxCenter = new Numbers_Vector3 (0, 0, 0);

      return function (shapeNode)
      {
         const modelViewMatrix = this .getModelViewMatrix () .get ();

         modelViewMatrix .multDirMatrix (bboxSize   .assign (shapeNode .getBBoxSize ()));
         modelViewMatrix .multVecMatrix (bboxCenter .assign (shapeNode .getBBoxCenter ()));

         const
            radius     = bboxSize .magnitude () / 2,
            viewVolume = this .viewVolumes .at (-1);

         if (viewVolume .intersectsSphere (radius, bboxCenter))
         {
            const num = this .numPointingShapes ++;

            if (num === this .pointingShapes .length)
            {
               this .pointingShapes .push ({ renderObject: this, modelViewMatrix: new Float32Array (16), clipPlanes: [ ], sensors: [ ] });
            }

            const pointingContext = this .pointingShapes [num];

            pointingContext .modelViewMatrix .set (modelViewMatrix);
            pointingContext .shapeNode    = shapeNode;
            pointingContext .scissor      = viewVolume .getScissor ();
            pointingContext .humanoidNode = this .humanoids .at (-1);

            // Clip planes & sensors

            X3DRenderObject_assign (pointingContext .clipPlanes, this .localObjects);
            X3DRenderObject_assign (pointingContext .sensors,    this .sensors .at (-1));

            return true;
         }

         return false;
      };
   })(),
   addCollisionShape: (() =>
   {
      const
         bboxSize   = new Numbers_Vector3 (0, 0, 0),
         bboxCenter = new Numbers_Vector3 (0, 0, 0);

      return function (shapeNode)
      {
         const modelViewMatrix = this .getModelViewMatrix () .get ();

         modelViewMatrix .multDirMatrix (bboxSize   .assign (shapeNode .getBBoxSize ()));
         modelViewMatrix .multVecMatrix (bboxCenter .assign (shapeNode .getBBoxCenter ()));

         const
            radius     = bboxSize .magnitude () / 2,
            viewVolume = this .viewVolumes .at (-1);

         if (viewVolume .intersectsSphere (radius, bboxCenter))
         {
            const num = this .numCollisionShapes ++;

            if (num === this .collisionShapes .length)
            {
               this .collisionShapes .push ({ renderObject: this, modelViewMatrix: new Float32Array (16), collisions: [ ], clipPlanes: [ ] });
            }

            const collisionContext = this .collisionShapes [num];

            collisionContext .modelViewMatrix .set (modelViewMatrix);
            collisionContext .shapeNode = shapeNode;
            collisionContext .scissor   = viewVolume .getScissor ();

            // Collisions

            X3DRenderObject_assign (collisionContext .collisions, this .collisions);

            // Clip planes

            X3DRenderObject_assign (collisionContext .clipPlanes, this .localObjects);

            return true;
         }

         return false;
      };
   })(),
   addShadowShape: (() =>
   {
      const
         bboxSize   = new Numbers_Vector3 (0, 0, 0),
         bboxCenter = new Numbers_Vector3 (0, 0, 0);

      return function (shapeNode)
      {
         const modelViewMatrix = this .getModelViewMatrix () .get ();

         modelViewMatrix .multDirMatrix (bboxSize   .assign (shapeNode .getBBoxSize ()));
         modelViewMatrix .multVecMatrix (bboxCenter .assign (shapeNode .getBBoxCenter ()));

         const
            radius     = bboxSize .magnitude () / 2,
            viewVolume = this .viewVolumes .at (-1);

         if (viewVolume .intersectsSphere (radius, bboxCenter))
         {
            const num = this .numShadowShapes ++;

            if (num === this .shadowShapes .length)
            {
               this .shadowShapes .push ({ renderObject: this, modelViewMatrix: new Float32Array (16), clipPlanes: [ ] });
            }

            const depthContext = this .shadowShapes [num];

            depthContext .modelViewMatrix .set (modelViewMatrix);
            depthContext .shapeNode    = shapeNode;
            depthContext .scissor      = viewVolume .getScissor ();
            depthContext .humanoidNode = this .humanoids .at (-1);

            // Clip planes

            X3DRenderObject_assign (depthContext .clipPlanes, this .localObjects);

            return true;
         }

         return false;
      };
   })(),
   addDisplayShape: (() =>
   {
      const
         bboxSize   = new Numbers_Vector3 (0, 0, 0),
         bboxCenter = new Numbers_Vector3 (0, 0, 0);

      return function (shapeNode)
      {
         const modelViewMatrix = this .getModelViewMatrix () .get ();

         modelViewMatrix .multDirMatrix (bboxSize   .assign (shapeNode .getBBoxSize ()));
         modelViewMatrix .multVecMatrix (bboxCenter .assign (shapeNode .getBBoxCenter ()));

         const
            radius     = bboxSize .magnitude () / 2,
            viewVolume = this .viewVolumes .at (-1);

         if (viewVolume .intersectsSphere (radius, bboxCenter))
         {
            if (shapeNode .isTransparent ())
            {
               const num = this .numTransparentShapes ++;

               if (num === this .transparentShapes .length)
                  this .transparentShapes .push (this .createRenderContext (true));

               var renderContext = this .transparentShapes [num];

               renderContext .distance = bboxCenter .z;
            }
            else
            {
               const num = this .numOpaqueShapes ++;

               if (num === this .opaqueShapes .length)
                  this .opaqueShapes .push (this .createRenderContext (false));

               var renderContext = this .opaqueShapes [num];
            }

            renderContext .modelViewMatrix .set (modelViewMatrix);
            renderContext .scissor .assign (viewVolume .getScissor ());
            renderContext .shadows         = this .localShadows .at (-1);
            renderContext .fogNode         = this .localFogs .at (-1);
            renderContext .shapeNode       = shapeNode;
            renderContext .appearanceNode  = shapeNode .getAppearance ();
            renderContext .humanoidNode    = this .humanoids .at (-1);

            // Clip planes and local lights

            X3DRenderObject_assign (renderContext .localObjects, this .localObjects);
            X3DRenderObject_assign (renderContext .objectsCount, this .localObjectsCount);

            return true;
         }

         return false;
      };
   })(),
   createRenderContext (transparent)
   {
      return {
         renderObject: this,
         transparent: transparent,
         modelViewMatrix: new Float32Array (16),
         scissor: new Numbers_Vector4 (0, 0, 0, 0),
         localObjects: [ ],
         objectsCount: [0, 0, 0], // [clip planes, lights, texture projectors]
      };
   },
   pointing: (() =>
   {
      const projectionMatrixArray = new Float32Array (16);

      return function (shapes, numShapes)
      {
         const
            browser  = this .getBrowser (),
            gl       = browser .getContext (),
            viewport = this .getViewVolume () .getViewport (),
            [x, y]   = browser .getPointer ();

         // Configure depth shaders.

         projectionMatrixArray .set (this .getProjectionMatrix () .get ());

         // Configure viewport and background

         gl .viewport (viewport [0] - x,
                       viewport [1] - y,
                       viewport [2],
                       viewport [3]);

         gl .scissor (0, 0, 1, 1);
         gl .clear (gl .DEPTH_BUFFER_BIT);

         // Render all objects

         gl .disable (gl .CULL_FACE);

         for (let s = 0; s < numShapes; ++ s)
         {
            const
               renderContext       = shapes [s],
               { scissor, clipPlanes, modelViewMatrix, shapeNode, humanoidNode } = renderContext,
               appearanceNode      = shapeNode .getAppearance (),
               geometryContext     = shapeNode .getGeometryContext (),
               stylePropertiesNode = appearanceNode .getStyleProperties (geometryContext .geometryType),
               shaderNode          = browser .getPointingShader (clipPlanes .length, shapeNode, humanoidNode),
               id                  = browser .addPointingShape (renderContext);

            gl .scissor (scissor .x - x,
                         scissor .y - y,
                         scissor .z,
                         scissor .w);

            // Draw

            shaderNode .enable (gl);
            shaderNode .setClipPlanes (gl, clipPlanes);

            gl .uniformMatrix4fv (shaderNode .x3d_ProjectionMatrix, false, projectionMatrixArray);
            gl .uniformMatrix4fv (shaderNode .x3d_ModelViewMatrix,  false, modelViewMatrix);
            gl .uniform1f (shaderNode .x3d_Id, id);

            stylePropertiesNode ?.setShaderUniforms (gl, shaderNode);
            humanoidNode        ?.setShaderUniforms (gl, shaderNode);

            shapeNode .displaySimple (gl, renderContext, shaderNode);
            browser .resetTextureUnits ();
         }
      };
   })(),
   collide: (() =>
   {
      const
         invModelViewMatrix = new Numbers_Matrix4 (),
         modelViewMatrix    = new Numbers_Matrix4 (),
         collisionBox       = new Geometry_Box3 (Numbers_Vector3 .Zero, Numbers_Vector3 .Zero),
         collisionSize      = new Numbers_Vector3 (0, 0, 0);

      return function ()
      {
         // Collision nodes are handled here.

         const
            activeCollisions = [ ], // current active Collision nodes
            collisionRadius2 = 2.2 * this .getNavigationInfo () .getCollisionRadius (); // Make the radius a little bit larger.

         collisionSize .set (collisionRadius2, collisionRadius2, collisionRadius2);

         for (let i = 0, length = this .numCollisionShapes; i < length; ++ i)
         {
            const
               collisionContext = this .collisionShapes [i],
               collisions       = collisionContext .collisions;

            if (collisions .length)
            {
               collisionBox .set (collisionSize, Numbers_Vector3 .Zero);
               collisionBox .multRight (invModelViewMatrix .assign (collisionContext .modelViewMatrix) .inverse ());

               if (collisionContext .shapeNode .intersectsBox (collisionBox, collisionContext .clipPlanes, modelViewMatrix .assign (collisionContext .modelViewMatrix)))
               {
                  for (const collision of collisions)
                     activeCollisions .push (collision);
               }
            }
         }

         // Set isActive to FALSE for affected nodes.

         if (this .activeCollisions .length)
         {
            const inActiveCollisions = activeCollisions .length
                                       ? this .activeCollisions .filter (a => !activeCollisions .includes (a))
                                       : this .activeCollisions;

            for (const collision of inActiveCollisions)
               collision .set_active (false);
         }

         // Set isActive to TRUE for affected nodes.

         this .activeCollisions = activeCollisions;

         for (const collision of activeCollisions)
            collision .set_active (true);
      };
   })(),
   gravite: (() =>
   {
      const
         projectionMatrix            = new Numbers_Matrix4 (),
         cameraSpaceProjectionMatrix = new Numbers_Matrix4 (),
         translation                 = new Numbers_Vector3 (0, 0, 0),
         rotation                    = new Numbers_Rotation4 ();

      return function ()
      {
         const browser = this .getBrowser ();

         // Terrain following and gravitation.

         if (browser .getActiveLayer () === this)
         {
            if (browser .getCurrentViewer () !== "WALK")
               return;
         }
         else if (this .getNavigationInfo () .getViewer () !== "WALK")
         {
            return;
         }

         // Get NavigationInfo values.

         const
            navigationInfo  = this .getNavigationInfo (),
            viewpoint       = this .getViewpoint (),
            collisionRadius = navigationInfo .getCollisionRadius (),
            nearValue       = navigationInfo .getNearValue (),
            avatarHeight    = navigationInfo .getAvatarHeight (),
            stepHeight      = navigationInfo .getStepHeight ();

         // Reshape viewpoint for gravite.

         Geometry_Camera .ortho (-collisionRadius,
                        collisionRadius,
                        -collisionRadius,
                        collisionRadius,
                        nearValue,
                        Math .max (collisionRadius * 2, avatarHeight * 2),
                        projectionMatrix);

         // Transform viewpoint to look down the up vector.

         const
            upVector = viewpoint .getUpVector (),
            down     = rotation .setFromToVec (Numbers_Vector3 .zAxis, upVector);

         cameraSpaceProjectionMatrix .assign (viewpoint .getModelMatrix ());
         cameraSpaceProjectionMatrix .translate (viewpoint .getUserPosition ());
         cameraSpaceProjectionMatrix .rotate (down);
         cameraSpaceProjectionMatrix .inverse ();

         cameraSpaceProjectionMatrix .multRight (projectionMatrix);
         cameraSpaceProjectionMatrix .multLeft (viewpoint .getCameraSpaceMatrix ());

         this .getProjectionMatrix () .pushMatrix (cameraSpaceProjectionMatrix);

         let distance = -this .getDepth (projectionMatrix);

         this .getProjectionMatrix () .pop ();

         // Gravite or step up.

         distance -= avatarHeight;

         const up = rotation .setFromToVec (Numbers_Vector3 .yAxis, upVector);

         if (distance > 0)
         {
            // Gravite and fall down the to the floor.

            const currentFrameRate = this .speed ? browser .getCurrentFrameRate () : 1000000;

            this .speed -= browser .getBrowserOptions () ._Gravity .getValue () / currentFrameRate;

            let y = this .speed / currentFrameRate;

            if (y < -distance)
            {
               // The ground is reached.
               y = -distance;
               this .speed = 0;
            }

            viewpoint ._positionOffset = viewpoint ._positionOffset .getValue () .add (up .multVecRot (translation .set (0, y, 0)));
         }
         else
         {
            this .speed = 0;

            distance = -distance;

            if (distance > 0.01 && distance < stepHeight)
            {
               // Step up.

               this .constrainTranslation (up .multVecRot (translation .set (0, distance, 0)), false);

               //if (getBrowser () -> getBrowserOptions () -> animateStairWalks ())
               //{
               //	float step = getBrowser () -> getCurrentSpeed () / getBrowser () -> getCurrentFrameRate ();
               //	step = abs (getViewMatrix () .mult_matrix_dir (Vector3f (0, step, 0) * up));
               //
               //	Vector3f offset = Vector3f (0, step, 0) * up;
               //
               //	if (math::abs (offset) > math::abs (translation) or getBrowser () -> getCurrentSpeed () == 0)
               //		offset = translation;
               //
               //	getViewpoint () -> positionOffset () += offset;
               //}
               //else
                  viewpoint ._positionOffset = translation .add (viewpoint ._positionOffset .getValue ());
            }
         }
      };
   })(),
   depth: (() =>
   {
      const projectionMatrixArray = new Float32Array (16);

      return function (shapes, numShapes)
      {
         const
            browser  = this .getBrowser (),
            gl       = browser .getContext (),
            viewport = this .getViewVolume () .getViewport ();

         // Configure depth shaders.

         projectionMatrixArray .set (this .getProjectionMatrix () .get ());

         // Configure viewport and background

         gl .viewport (... viewport);
         gl .scissor (... viewport);

         gl .clearColor (1, 0, 0, 0); // '1' for infinity, '0 0 0' for normal (TODO).
         gl .clear (gl .COLOR_BUFFER_BIT | gl .DEPTH_BUFFER_BIT);

         // Render all objects

         gl .disable (gl .CULL_FACE);

         for (let s = 0; s < numShapes; ++ s)
         {
            const
               renderContext       = shapes [s],
               { scissor, clipPlanes, modelViewMatrix, shapeNode, humanoidNode } = renderContext,
               appearanceNode      = shapeNode .getAppearance (),
               geometryContext     = shapeNode .getGeometryContext (),
               stylePropertiesNode = appearanceNode .getStyleProperties (geometryContext .geometryType),
               shaderNode          = browser .getDepthShader (clipPlanes .length, shapeNode, humanoidNode);

            gl .scissor (... scissor);

            // Draw

            shaderNode .enable (gl);
            shaderNode .setClipPlanes (gl, clipPlanes);

            gl .uniformMatrix4fv (shaderNode .x3d_ProjectionMatrix, false, projectionMatrixArray);
            gl .uniformMatrix4fv (shaderNode .x3d_ModelViewMatrix,  false, modelViewMatrix);

            stylePropertiesNode ?.setShaderUniforms (gl, shaderNode);
            humanoidNode        ?.setShaderUniforms (gl, shaderNode);

            shapeNode .displaySimple (gl, renderContext, shaderNode);
            browser .resetTextureUnits ();
         }
      };
   })(),
   draw ()
   {
      const
         browser                    = this .getBrowser (),
         gl                         = browser .getContext (),
         viewport                   = this .getViewVolume () .getViewport (),
         globalObjects              = this .globalObjects,
         lights                     = this .lights,
         textureProjectors          = this .textureProjectors,
         generatedCubeMapTextures   = this .generatedCubeMapTextures,
         globalShadows              = this .globalShadows,
         shadows                    = globalShadows .at (-1),
         headlight                  = this .getNavigationInfo () ._headlight .getValue (),
         numGlobalLights            = globalObjects .reduce ((n, c) => n + !!c .lightNode, 0),
         numGlobalTextureProjectors = globalObjects .reduce ((n, c) => n + !!c .textureProjectorNode, 0),
         oit                        = browser .getFrameBuffer () .getOrderIndependentTransparency ();


      this .renderCount = ++ renderCount;

      this .logarithmicDepthBuffer = browser .getBrowserOption ("LogarithmicDepthBuffer")
         || this .getViewpoint () .getLogarithmicDepthBuffer ();


      // PREPARATIONS


      if (this .isIndependent ())
      {
         // Render shadow maps.

         for (const light of lights)
            light .renderShadowMap (this);

         // Render GeneratedCubeMapTextures.

         for (const generatedCubeMapTexture of generatedCubeMapTextures)
            generatedCubeMapTexture .renderTexture (this);
      }

      // Set up shadow matrix for all lights, and matrix for all projective textures.

      if (headlight)
         browser .getHeadlight () .setGlobalVariables (this);

      for (const light of lights)
         light .setGlobalVariables (this);

      for (const textureProjector of textureProjectors)
         textureProjector .setGlobalVariables (this);

      // Set global uniforms.

      this .viewportArray          .set (viewport);
      this .cameraSpaceMatrixArray .set (this .getCameraSpaceMatrix () .get ());
      this .projectionMatrixArray  .set (this .getProjectionMatrix () .get ());


      // DRAW


      // Configure viewport and background

      gl .viewport (... viewport);
      gl .scissor (... viewport);

      // Draw background.

      gl .clear (gl .DEPTH_BUFFER_BIT);
      gl .blendFuncSeparate (gl .SRC_ALPHA, gl .ONE_MINUS_SRC_ALPHA, gl .ONE, gl .ONE_MINUS_SRC_ALPHA);

      this .getBackground () .display (gl, this, viewport);

      // Sorted blend or order independent transparency

      // Render opaque objects first

      const opaqueShapes = this .opaqueShapes;

      for (let i = 0, length = this .numOpaqueShapes; i < length; ++ i)
      {
         const renderContext = opaqueShapes [i];

         gl .scissor (... renderContext .scissor);

         renderContext .shadows           = renderContext .shadows || shadows;
         renderContext .objectsCount [1] += numGlobalLights;
         renderContext .objectsCount [2] += numGlobalTextureProjectors;

         renderContext .shapeNode .display (gl, renderContext);
         browser .resetTextureUnits ();
      }

      // Render transparent objects

      const transparentShapes = this .transparentShapes;

      if (oit)
         browser .getFrameBuffer () .bindForOrderIndependentTransparency ();
      else
         this .transparencySorter .sort (0, this .numTransparentShapes);

      gl .depthMask (false);
      gl .enable (gl .BLEND);

      for (let i = 0, length = this .numTransparentShapes; i < length; ++ i)
      {
         const renderContext = transparentShapes [i];

         gl .scissor (... renderContext .scissor);

         renderContext .shadows           = renderContext .shadows || shadows;
         renderContext .objectsCount [1] += numGlobalLights;
         renderContext .objectsCount [2] += numGlobalTextureProjectors;

         renderContext .shapeNode .display (gl, renderContext);
         browser .resetTextureUnits ();
      }

      gl .depthMask (true);
      gl .disable (gl .BLEND);

      if (oit)
      {
         browser .getFrameBuffer () .compose ();
         browser .getFrameBuffer () .unbind ();
      }

      // POST DRAW

      if (this .isIndependent ())
      {
         // Recycle clip planes, local fogs, local lights, and local projective textures.

         const localObjects = browser .getLocalObjects ();

         for (const localObject of localObjects)
            localObject .dispose ();

         localObjects .length = 0;

         // Recycle global lights and global projective textures.

         for (const globalObject of globalObjects)
            globalObject .dispose ();
      }

      // Reset containers.

      globalObjects            .length = 0;
      lights                   .length = 0;
      globalShadows            .length = 1;
      textureProjectors        .length = 0;
      generatedCubeMapTextures .length = 0;
   },
});

function X3DRenderObject_assign (lhs, rhs)
{
   for (var i = 0, length = rhs .length; i < length; ++ i)
      lhs [i] = rhs [i];

   lhs .length = length;
}

const X3DRenderObject_default_ = X3DRenderObject;
;

x_ite_Namespace .add ("X3DRenderObject", "x_ite/Rendering/X3DRenderObject", X3DRenderObject_default_);
/* harmony default export */ const Rendering_X3DRenderObject = (X3DRenderObject_default_);
;// CONCATENATED MODULE: ./src/x_ite/Execution/BindableStack.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function BindableStack (executionContext, defaultNode)
{
   Base_X3DBaseNode .call (this, executionContext);

   this .nodes = [ defaultNode ];
}

Object .assign (Object .setPrototypeOf (BindableStack .prototype, Base_X3DBaseNode .prototype),
{
   get ()
   {
      return this .nodes;
   },
   top ()
   {
      return this .nodes .at (-1);
   },
   pushOnTop (node)
   {
      if (node !== this .nodes [0])
      {
         this .nodes .at (-1) ._isBound = false;
         this .nodes .push (node);
      }

      // Don't do set_bind.
      node ._isBound  = true;
      node ._bindTime = this .getBrowser () .getCurrentTime ();

      this .addNodeEvent ();
   },
   update (layerNode, removedNodes, changedNodes)
   {
      if (!removedNodes .length && !changedNodes .length)
         return;

      // Save top node for later use.

      const
         fromNode  = this .top (),
         boundNode = this .nodes .at (-1);

      // Remove invisible nodes and unbind them if needed.

      for (const removedNode of removedNodes)
      {
         const index = this .nodes .indexOf (removedNode);

         if (index > 0)
            this .nodes .splice (index, 1);
      }

      // Unbind nodes with set_bind false and pop top node.

      if (boundNode !== this .nodes [0])
      {
         if (changedNodes .some (node => !node ._set_bind .getValue () && node === boundNode))
         {
            this .nodes .pop ();
         }
      }

      // Push nodes with set_bind true to top of stack.

      for (const bindNode of changedNodes)
      {
         if (bindNode ._set_bind .getValue ())
         {
            const index = this .nodes .indexOf (bindNode);

            if (index > -1)
               this .nodes .splice (index, 1);

            this .nodes .push (bindNode);
         }
      }

      // Bind top node if not bound.

      const top = this .nodes .at (-1);

      if (top !== boundNode)
      {
         // First unbind last bound node.

         boundNode ._isBound = false;

         // Now bind new top node.

         top ._isBound  = true;
         top ._bindTime = this .getBrowser () .getCurrentTime ();
      }

      // Do transition.

      top .transitionStart (layerNode, fromNode);

      this .addNodeEvent ();
   },
});

for (const key of Object .keys (BindableStack .prototype))
   Object .defineProperty (BindableStack .prototype, key, { enumerable: false });

Object .defineProperties (BindableStack,
{
   typeName:
   {
      value: "BindableStack",
      enumerable: true,
   },
});

const BindableStack_default_ = BindableStack;
;

x_ite_Namespace .add ("BindableStack", "x_ite/Execution/BindableStack", BindableStack_default_);
/* harmony default export */ const Execution_BindableStack = (BindableStack_default_);
;// CONCATENATED MODULE: ./src/x_ite/Execution/BindableList.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function BindableList (executionContext, defaultNode)
{
   Base_X3DBaseNode .call (this, executionContext);

   this .modificationCount = 0;
   this .nodes             = [ defaultNode ];
   this .collectedNodes    = [ defaultNode ];
   this .changedNodes      = [ ];
   this .removedNodes      = [ ];
}

Object .assign (Object .setPrototypeOf (BindableList .prototype, Base_X3DBaseNode .prototype),
{
   get ()
   {
      return this .nodes;
   },
   getBound (name)
   {
      const length = this .nodes .length;

      if (length === 1)
         return this .nodes [0]; // Return default viewpoint.

      const enableInlineBindables = false;

      if (name)
      {
         // Return first viewpoint with @name.

         for (let i = 1; i < length; ++ i)
         {
            const
               node  = this .nodes [i],
               scene = node .getExecutionContext () .getOuterNode () ?.getScene () ?? node .getScene ();

            if (!enableInlineBindables && !scene .isMainScene ())
               continue;

            if (node .getName () == name)
               return node;
         }
      }

      // Return first bound viewpoint in scene.

      for (let i = 1; i < length; ++ i)
      {
         const
            node  = this .nodes [i],
            scene = node .getExecutionContext () .getOuterNode () ?.getScene () ?? node .getScene ();

         if (!enableInlineBindables && !scene .isMainScene ())
            continue;

         if (node ._isBound .getValue ())
            return node;
      }

      // Return first viewpoint in scene.

      for (let i = 1; i < length; ++ i)
      {
         const
            node  = this .nodes [i],
            scene = node .getExecutionContext () .getOuterNode () ?.getScene () ?? node .getScene ();

         if (!enableInlineBindables && !scene .isMainScene ())
            continue;

         return node;
      }

      return this .nodes [0]; // Return default viewpoint.
   },
   push (node)
   {
      return this .collectedNodes .push (node);
   },
   update (layerNode, stack)
   {
      const { collectedNodes, changedNodes, removedNodes } = this;

      for (const node of collectedNodes)
      {
         if (node .getModificationCount () > this .modificationCount)
            changedNodes .push (node);
      }

      if (!equals (collectedNodes, this .nodes))
      {
         // Unbind nodes not in current list (collectedNodes);

         for (const node of this .nodes)
         {
            if (!collectedNodes .includes (node))
               removedNodes .push (node);
         }

         // Swap nodes.

         const tmp = this .nodes;

         this .nodes          = collectedNodes;
         this .collectedNodes = tmp;
      }

      // Clear collected nodes.

      this .collectedNodes .length = 1;

      // Update stack.

      stack .update (layerNode, removedNodes, changedNodes)

      changedNodes .length = 0;
      removedNodes .length = 0;

      // Advance modificationCount time.

      this .modificationCount = Core_X3DBindableNode .getModificationCount ();
   },
});

for (const key of Object .keys (BindableList .prototype))
   Object .defineProperty (BindableList .prototype, key, { enumerable: false });

// Compares two nodes.

function equals (lhs, rhs)
{
   if (lhs .length !== rhs .length)
      return false;

   for (let i = 0; i < lhs .length; ++ i)
   {
      if (lhs [i] !== rhs [i])
         return false;
   }

   return true;
}

Object .defineProperties (BindableList,
{
   typeName:
   {
      value: "BindableList",
      enumerable: true,
   },
});

const BindableList_default_ = BindableList;
;

x_ite_Namespace .add ("BindableList", "x_ite/Execution/BindableList", BindableList_default_);
/* harmony default export */ const Execution_BindableList = (BindableList_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Navigation/NavigationInfo.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








const TransitionType =
{
   TELEPORT: true,
   LINEAR:   true,
   ANIMATE:  true,
};

function NavigationInfo (executionContext)
{
   Core_X3DBindableNode .call (this, executionContext);

   this .addType (Base_X3DConstants .NavigationInfo);

   this .addChildObjects (Base_X3DConstants .outputOnly, "transitionStart",  new x_ite_Fields .SFBool (),
                          Base_X3DConstants .outputOnly, "transitionActive", new x_ite_Fields .SFBool (),
                          Base_X3DConstants .outputOnly, "availableViewers", new x_ite_Fields .MFString (),
                          Base_X3DConstants .outputOnly, "viewer",           new x_ite_Fields .SFString ("EXAMINE"));

   this ._avatarSize      .setUnit ("length");
   this ._speed           .setUnit ("speed");
   this ._visibilityLimit .setUnit ("speed");
}

Object .assign (Object .setPrototypeOf (NavigationInfo .prototype, Core_X3DBindableNode .prototype),
{
   initialize ()
   {
      Core_X3DBindableNode .prototype .initialize .call (this);

      this ._type               .addInterest ("set_type__",               this);
      this ._headlight          .addInterest ("set_headlight__",          this);
      this ._transitionStart    .addInterest ("set_transitionStart__",    this);
      this ._transitionComplete .addInterest ("set_transitionComplete__", this);
      this ._isBound            .addInterest ("set_isBound__",            this);

      this .set_type__ ();
      this .set_headlight__ ();
   },
   getViewer ()
   {
      return this ._viewer .getValue ();
   },
   getCollisionRadius ()
   {
      if (this ._avatarSize .length > 0)
      {
         if (this ._avatarSize [0] > 0)
            return this ._avatarSize [0];
      }

      return 0.25;
   },
   getAvatarHeight ()
   {
      if (this ._avatarSize .length > 1)
         return this ._avatarSize [1];

      return 1.6;
   },
   getStepHeight ()
   {
      if (this ._avatarSize .length > 2)
         return this ._avatarSize [2];

      return 0.75;
   },
   getNearValue ()
   {
      const nearValue = this .getCollisionRadius ();

      if (nearValue === 0)
         return 1e-5;

      else
         return nearValue / 2;
   },
   getFarValue (viewpoint)
   {
      return this ._visibilityLimit .getValue ()
             ? this ._visibilityLimit .getValue ()
             : viewpoint .getMaxFarValue ();
   },
   getTransitionType ()
   {
      for (const value of this ._transitionType)
      {
         const transitionType = TransitionType [value];

         if (transitionType)
            return value;
      }

      return "LINEAR";
   },
   set_type__ ()
   {
      // Determine active viewer.

      this ._viewer = "EXAMINE";

      for (const string of this ._type)
      {
         switch (string)
         {
            case "EXAMINE":
            case "WALK":
            case "FLY":
            case "LOOKAT":
            case "PLANE":
            case "NONE":
               this ._viewer = string;
               break;
            case "PLANE_create3000.github.io":
            case "PLANE_create3000.de":
               this ._viewer = "PLANE";
               break;
            default:
               continue;
         }

         // Leave for loop.
         break;
      }

      // Determine available viewers.

      let
         examineViewer = false,
         walkViewer    = false,
         flyViewer     = false,
         planeViewer   = false,
         noneViewer    = false,
         lookAt        = false;

      if (! this ._type .length)
      {
         examineViewer = true;
         walkViewer    = true;
         flyViewer     = true;
         planeViewer   = true;
         noneViewer    = true;
         lookAt        = true;
      }
      else
      {
         for (const string of this ._type)
         {
            switch (string)
            {
               case "EXAMINE":
                  examineViewer = true;
                  continue;
               case "WALK":
                  walkViewer = true;
                  continue;
               case "FLY":
                  flyViewer = true;
                  continue;
               case "LOOKAT":
                  lookAt = true;
                  continue;
               case "PLANE":
                  planeViewer = true;
                  continue;
               case "NONE":
                  noneViewer = true;
                  continue;
               case "ANY":
                  examineViewer = true;
                  walkViewer    = true;
                  flyViewer     = true;
                  planeViewer   = true;
                  noneViewer    = true;
                  lookAt        = true;
                  break;
               default:
                  // Some string defaults to EXAMINE.
                  examineViewer = true;
                  continue;
            }

            break;
         }
      }

      this ._availableViewers .length = 0;

      if (examineViewer)
         this ._availableViewers .push ("EXAMINE");

      if (walkViewer)
         this ._availableViewers .push ("WALK");

      if (flyViewer)
         this ._availableViewers .push ("FLY");

      if (planeViewer)
         this ._availableViewers .push ("PLANE");

      if (lookAt)
         this ._availableViewers .push ("LOOKAT");

      if (noneViewer)
         this ._availableViewers .push ("NONE");
   },
   set_headlight__ ()
   {
      if (this ._headlight .getValue ())
         delete this .enable;
      else
         this .enable = Function .prototype;
   },
   set_transitionStart__ ()
   {
      if (! this ._transitionActive .getValue ())
         this ._transitionActive = true;
   },
   set_transitionComplete__ ()
   {
      if (this ._transitionActive .getValue ())
         this ._transitionActive = false;
   },
   set_isBound__ ()
   {
      if (this ._isBound .getValue ())
         return;

      if (this ._transitionActive .getValue ())
         this ._transitionActive = false;
   },
   enable (type, renderObject)
   {
      if (type !== Rendering_TraverseType .DISPLAY)
         return;

      if (this ._headlight .getValue ())
         renderObject .getGlobalObjects () .push (this .getBrowser () .getHeadlight ());
   },
   traverse (type, renderObject)
   {
      if (type !== Rendering_TraverseType .CAMERA)
         return;

      renderObject .getLayer () .getNavigationInfos () .push (this);
   }
});

Object .defineProperties (NavigationInfo,
{
   typeName:
   {
      value: "NavigationInfo",
      enumerable: true,
   },
   componentName:
   {
      value: "Navigation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_bind",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "type",               new x_ite_Fields .MFString ("EXAMINE", "ANY")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "avatarSize",         new x_ite_Fields .MFFloat (0.25, 1.6, 0.75)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "speed",              new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "headlight",          new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "visibilityLimit",    new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "transitionType",     new x_ite_Fields .MFString ("LINEAR")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "transitionTime",     new x_ite_Fields .SFTime (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "transitionComplete", new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isBound",            new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "bindTime",           new x_ite_Fields .SFTime ()),
      ]),
      enumerable: true,
   },
});

const NavigationInfo_default_ = NavigationInfo;
;

x_ite_Namespace .add ("NavigationInfo", "x_ite/Components/Navigation/NavigationInfo", NavigationInfo_default_);
/* harmony default export */ const Navigation_NavigationInfo = (NavigationInfo_default_);
;// CONCATENATED MODULE: ./src/standard/Utility/ObjectCache.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

function ObjectCache (Type)
{
   return Object .assign ([ ],
   {
      top: 0,
      pop ()
      {
         if (this .top !== 0)
            return this [-- this .top];

         return new Type ();
      },
      push (object)
      {
         this [this .top ++] = object;
      },
      clear ()
      {
         this .length = 0;
         this .top    = 0;
      },
   });
}

const ObjectCache_default_ = ObjectCache;
;

x_ite_Namespace .add ("ObjectCache", "standard/Utility/ObjectCache", ObjectCache_default_);
/* harmony default export */ const Utility_ObjectCache = (ObjectCache_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/EnvironmentalEffects/X3DFogObject.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





const Fogs = Utility_ObjectCache (FogContainer);

function FogContainer ()
{
   this .fogMatrix = new Float32Array (9);
}

Object .assign (FogContainer .prototype,
{
   set (fogNode, modelViewMatrix)
   {
      this .fogNode = fogNode;

      this .fogMatrix .set (modelViewMatrix .submatrix .inverse ());
   },
   getFogType ()
   {
      return this .fogNode .getFogType ();
   },
   setShaderUniforms (gl, shaderObject)
   {
      if (shaderObject .hasFog (this))
         return;

      const fogNode = this .fogNode;

      gl .uniform3fv       (shaderObject .x3d_FogColor,           fogNode .colorArray);
      gl .uniform1f        (shaderObject .x3d_FogVisibilityRange, fogNode .visibilityRange);
      gl .uniformMatrix3fv (shaderObject .x3d_FogMatrix, false,   this .fogMatrix);
   },
   dispose ()
   {
      Fogs .push (this);
   },
});

function X3DFogObject (executionContext)
{
   this .addType (Base_X3DConstants .X3DFogObject);

   this .addChildObjects (Base_X3DConstants .inputOutput, "hidden", new x_ite_Fields .SFBool ());

   this ._visibilityRange .setUnit ("length");

   this .colorArray = new Float32Array (3);
}

Object .assign (X3DFogObject .prototype,
{
   initialize ()
   {
      this ._hidden          .addInterest ("set_fogType__",         this);
      this ._fogType         .addInterest ("set_fogType__",         this);
      this ._color           .addInterest ("set_color__",           this);
      this ._visibilityRange .addInterest ("set_visibilityRange__", this);

      this .set_color__ ();
      this .set_visibilityRange__ ();
   },
   isHidden ()
   {
      return this ._hidden .getValue ();
   },
   setHidden (value)
   {
      if (value === this ._hidden .getValue ())
         return;

      this ._hidden = value;
   },
   getFogType ()
   {
      return this .fogType;
   },
   getFogs ()
   {
      return Fogs;
   },
   set_fogType__: (() =>
   {
      const fogTypes = new Map ([
         ["LINEAR",      1],
         ["EXPONENTIAL", 2],
      ]);

      return function ()
      {
         if (this ._hidden .getValue () || this .visibilityRange === 0)
            this .fogType = 0;
         else
            this .fogType = fogTypes .get (this ._fogType .getValue ()) || 1;
      };
   })(),
   set_color__ ()
   {
      const
         color      = this ._color .getValue (),
         colorArray = this .colorArray;

      colorArray [0] = color .r;
      colorArray [1] = color .g;
      colorArray [2] = color .b;
   },
   set_visibilityRange__ ()
   {
      this .visibilityRange = Math .max (0, this ._visibilityRange .getValue ());

      this .set_fogType__ ();
   },
   dispose () { },
});

Object .defineProperties (X3DFogObject,
{
   typeName:
   {
      value: "X3DFogObject",
      enumerable: true,
   },
   componentName:
   {
      value: "EnvironmentalEffects",
      enumerable: true,
   },
});

const X3DFogObject_default_ = X3DFogObject;
;

x_ite_Namespace .add ("X3DFogObject", "x_ite/Components/EnvironmentalEffects/X3DFogObject", X3DFogObject_default_);
/* harmony default export */ const EnvironmentalEffects_X3DFogObject = (X3DFogObject_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/EnvironmentalEffects/Fog.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










function Fog (executionContext)
{
   Core_X3DBindableNode .call (this, executionContext);
   EnvironmentalEffects_X3DFogObject    .call (this, executionContext);

   this .addType (Base_X3DConstants .Fog);

   this .modelMatrix = new Numbers_Matrix4 ();
}

Object .assign (Object .setPrototypeOf (Fog .prototype, Core_X3DBindableNode .prototype),
   EnvironmentalEffects_X3DFogObject .prototype,
{
   initialize ()
   {
      Core_X3DBindableNode .prototype .initialize .call (this);
      EnvironmentalEffects_X3DFogObject    .prototype .initialize .call (this);
   },
   getModelMatrix ()
   {
      return this .modelMatrix;
   },
   traverse (type, renderObject)
   {
      if (type !== Rendering_TraverseType .CAMERA)
         return;

      renderObject .getLayer () .getFogs () .push (this);

      this .modelMatrix .assign (renderObject .getModelViewMatrix () .get ());
   },
   dispose ()
   {
      EnvironmentalEffects_X3DFogObject    .prototype .dispose .call (this);
      Core_X3DBindableNode .prototype .dispose .call (this);
   },
});

Object .defineProperties (Fog,
{
   typeName:
   {
      value: "Fog",
      enumerable: true,
   },
   componentName:
   {
      value: "EnvironmentalEffects",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_bind",        new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "fogType",         new x_ite_Fields .SFString ("LINEAR")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "color",           new x_ite_Fields .SFColor (1, 1, 1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "visibilityRange", new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isBound",         new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "bindTime",        new x_ite_Fields .SFTime ()),
      ]),
      enumerable: true,
   },
});

const Fog_default_ = Fog;
;

x_ite_Namespace .add ("Fog", "x_ite/Components/EnvironmentalEffects/Fog", Fog_default_);
/* harmony default export */ const EnvironmentalEffects_Fog = (Fog_default_);
;// CONCATENATED MODULE: ./src/x_ite/Rendering/VertexArray.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

function VertexArray (gl)
{
   this .gl           = gl;
   this .vertexArrays = new Map ();
}

Object .assign (VertexArray .prototype,
{
   update (value = true)
   {
      if (value)
         this .delete ();

      return this;
   },
   enable (shaderNode)
   {
      const vertexArray = this .vertexArrays .get (shaderNode);

      if (vertexArray)
      {
         this .gl .bindVertexArray (vertexArray);

         return false;
      }
      else
      {
         const vertexArray = this .gl .createVertexArray ();

         this .vertexArrays .set (shaderNode, vertexArray)

         this .gl .bindVertexArray (vertexArray);

         // console .log ("rebuild vao");

         return true; // Rebuild
      }
   },
   delete ()
   {
      for (const vertexArray of this .vertexArrays .values ())
         this .gl .deleteVertexArray (vertexArray);

      this .vertexArrays .clear ();
   },
});

const VertexArray_default_ = VertexArray;
;

x_ite_Namespace .add ("VertexArray", "x_ite/Rendering/VertexArray", VertexArray_default_);
/* harmony default export */ const Rendering_VertexArray = (VertexArray_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Core/Shading.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

let Shading_i = 0;

const Shading =
{
   POINT:     Shading_i ++,
   WIREFRAME: Shading_i ++,
   FLAT:      Shading_i ++,
   GOURAUD:   Shading_i ++,
   PHONG:     Shading_i ++,
};

const Shading_default_ = Shading;
;

x_ite_Namespace .add ("Shading", "x_ite/Browser/Core/Shading", Shading_default_);
/* harmony default export */ const Core_Shading = (Shading_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/X3DGeometryNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/














// Box normals for bbox / line intersection.
const boxNormals = [
   new Numbers_Vector3 (0,  0,  1), // front
   new Numbers_Vector3 (0,  0, -1), // back
   new Numbers_Vector3 (0,  1,  0), // top
   new Numbers_Vector3 (0, -1,  0), // bottom
   new Numbers_Vector3 (1,  0,  0)  // right
   // left: We do not have to test for left.
];

function X3DGeometryNode (executionContext)
{
   Core_X3DNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DGeometryNode);

   this .addChildObjects (Base_X3DConstants .outputOnly, "transparent",  new x_ite_Fields .SFBool (),
                          Base_X3DConstants .outputOnly, "bbox_changed", new x_ite_Fields .SFTime (),
                          Base_X3DConstants .outputOnly, "rebuild",      new x_ite_Fields .SFTime ());

   // Members

   const browser = this .getBrowser ();

   this .min                      = new Numbers_Vector3 (0, 0, 0);
   this .max                      = new Numbers_Vector3 (0, 0, 0);
   this .bbox                     = Geometry_Box3 .Extents (this .min, this .max);
   this .solid                    = true;
   this .primitiveMode            = browser .getContext () .TRIANGLES;
   this .geometryType             = 3;
   this .flatShading              = undefined;
   this .colorMaterial            = false;
   this .attribNodes              = [ ];
   this .attribArrays             = [ ];
   this .textureCoordinateMapping = new Map ();
   this .multiTexCoords           = [ ];
   this .coordIndices             = new x_ite_Fields .MFFloat ();
   this .texCoords                = new x_ite_Fields .MFFloat ();
   this .fogDepths                = new x_ite_Fields .MFFloat ();
   this .colors                   = new x_ite_Fields .MFFloat ();
   this .normals                  = new x_ite_Fields .MFFloat ();
   this .flatNormals              = new x_ite_Fields .MFFloat ();
   this .vertices                 = new x_ite_Fields .MFFloat ();
   this .hasFogCoords             = false;
   this .hasNormals               = false;
   this .geometryKey              = "";
   this .vertexCount              = 0;
   this .planes                   = [ ];

   for (let i = 0; i < 5; ++ i)
      this .planes [i] = new Geometry_Plane3 (Numbers_Vector3 .Zero, Numbers_Vector3 .zAxis);
}

Object .assign (Object .setPrototypeOf (X3DGeometryNode .prototype, Core_X3DNode .prototype),
{
   setup ()
   {
      Core_X3DNode .prototype .setup .call (this);

      this .rebuild ();
   },
   initialize ()
   {
      Core_X3DNode .prototype .initialize .call (this);

      const
         browser = this .getBrowser (),
         gl      = browser .getContext ();

      this .getLive () .addInterest ("set_live__", this);

      this .addInterest ("requestRebuild", this);
      this ._rebuild .addInterest ("rebuild", this);

      this .frontFace             = gl .CCW;
      this .backFace              = new Map ([[gl .CCW, gl .CW], [gl .CW, gl .CCW]]);
      this .coordIndexBuffer      = gl .createBuffer ();
      this .attribBuffers         = [ ];
      this .textureCoordinateNode = browser .getDefaultTextureCoordinate ();
      this .texCoordBuffers       = Array .from ({length: browser .getMaxTexCoords ()}, () => gl .createBuffer ());
      this .fogDepthBuffer        = gl .createBuffer ();
      this .colorBuffer           = gl .createBuffer ();
      this .normalBuffer          = gl .createBuffer ();
      this .vertexBuffer          = gl .createBuffer ();
      this .vertexArrayObject     = new Rendering_VertexArray (gl);

      this .set_live__ ();
   },
   setGeometryType (value)
   {
      this .geometryType = value;
   },
   getGeometryType ()
   {
      return this .geometryType;
   },
   setTransparent (value)
   {
      if (value !== this ._transparent .getValue ())
         this ._transparent = value;
   },
   isTransparent ()
   {
      return this ._transparent .getValue ();
   },
   getBBox ()
   {
      // With screen matrix applied.
      return this .bbox;
   },
   setBBox (bbox)
   {
      if (bbox .equals (this .bbox))
         return;

      bbox .getExtents (this .min, this .max);

      this .bbox .assign (bbox);

      for (let i = 0; i < 5; ++ i)
         this .planes [i] .set (i % 2 ? this .min : this .max, boxNormals [i]);

      this ._bbox_changed .addEvent ();
   },
   getMin ()
   {
      // With screen matrix applied.
      return this .min;
   },
   getMax ()
   {
      // With screen matrix applied.
      return this .max;
   },
   getMatrix ()
   {
      return Numbers_Matrix4 .Identity;
   },
   setPrimitiveMode (value)
   {
      this .primitiveMode = value;
   },
   getPrimitiveMode ()
   {
      return this .primitiveMode;
   },
   setSolid (value)
   {
      this .solid = value;
   },
   setCCW (value)
   {
      const gl = this .getBrowser () .getContext ();

      this .frontFace = value ? gl .CCW : gl .CW;
   },
   getCoordIndices ()
   {
      return this .coordIndices;
   },
   getAttrib ()
   {
      return this .attribNodes;
   },
   getAttribs ()
   {
      return this .attribArrays;
   },
   getAttribBuffers ()
   {
      return this .attribBuffers;
   },
   setFogDepths (value)
   {
      this .fogDepths .assign (value);
   },
   getFogDepths ()
   {
      return this .fogDepths;
   },
   setColors (value)
   {
      this .colors .assign (value);
   },
   getColors ()
   {
      return this .colors;
   },
   setMultiTexCoords (value)
   {
      const
         multiTexCoords = this .multiTexCoords,
         length         = value .length;

      for (let i = 0; i < length; ++ i)
         multiTexCoords [i] = value [i];

      multiTexCoords .length = length;
   },
   getMultiTexCoords ()
   {
      return this .multiTexCoords;
   },
   getTexCoords ()
   {
      return this .texCoords;
   },
   getTextureCoordinate ()
   {
      return this .textureCoordinateNode;
   },
   setTextureCoordinate (value)
   {
      this .textureCoordinateNode .removeInterest ("updateTextureCoordinateMapping", this);

      this .textureCoordinateNode = value ?? this .getBrowser () .getDefaultTextureCoordinate ();

      this .textureCoordinateNode .addInterest ("updateTextureCoordinateMapping", this);

      this .updateTextureCoordinateMapping ();
   },
   getTextureCoordinateMapping ()
   {
      return this .textureCoordinateMapping;
   },
   updateTextureCoordinateMapping ()
   {
      this .textureCoordinateMapping .clear ();

      this .textureCoordinateNode .getTextureCoordinateMapping (this .textureCoordinateMapping);
   },
   setNormals (value)
   {
      this .normals .assign (value);
   },
   getNormals ()
   {
      return this .normals;
   },
   setVertices (value)
   {
      this .vertices .assign (value);
   },
   getVertices ()
   {
      return this .vertices;
   },
   updateVertexArrays ()
   {
      this .vertexArrayObject .update ();

      this .updateParticles = true;
   },
   buildTexCoords ()
   {
      const texCoords = this .texCoords;

      if (texCoords .length === 0)
      {
         const
            p         = this .getTexCoordParams (),
            min       = p .min,
            Sindex    = p .Sindex,
            Tindex    = p .Tindex,
            Ssize     = p .Ssize,
            S         = min [Sindex],
            T         = min [Tindex],
            vertices  = this .vertices .getValue ();

         for (let i = 0, length = vertices .length; i < length; i += 4)
         {
            texCoords .push ((vertices [i + Sindex] - S) / Ssize,
                             (vertices [i + Tindex] - T) / Ssize,
                             0,
                             1);
         }

         texCoords .shrinkToFit ();
      }

      this .getMultiTexCoords () .push (texCoords);
   },
   getTexCoordParams: (() =>
   {
      const texCoordParams = { min: new Numbers_Vector3 (0, 0, 0), Ssize: 0, Sindex: 0, Tindex: 0 };

      return function ()
      {
         const
            bbox  = this .getBBox (),
            size  = bbox .size,
            Xsize = size .x,
            Ysize = size .y,
            Zsize = size .z;

         texCoordParams .min .assign (bbox .center) .subtract (size .divide (2));

         if ((Xsize >= Ysize) && (Xsize >= Zsize))
         {
            // X size largest
            texCoordParams .Ssize  = Xsize;
            texCoordParams .Sindex = 0;

            if (Ysize >= Zsize)
               texCoordParams .Tindex = 1;
            else
               texCoordParams .Tindex = 2;
         }
         else if ((Ysize >= Xsize) && (Ysize >= Zsize))
         {
            // Y size largest
            texCoordParams .Ssize  = Ysize;
            texCoordParams .Sindex = 1;

            if (Xsize >= Zsize)
               texCoordParams .Tindex = 0;
            else
               texCoordParams .Tindex = 2;
         }
         else
         {
            // Z is the largest
            texCoordParams .Ssize  = Zsize;
            texCoordParams .Sindex = 2;

            if (Xsize >= Ysize)
               texCoordParams .Tindex = 0;
            else
               texCoordParams .Tindex = 1;
         }

         return texCoordParams;
      };
   })(),
   refineNormals (normalIndex, normals, creaseAngle)
   {
      if (creaseAngle === 0)
         return normals;

      const
         cosCreaseAngle = Math .cos (Math_Algorithm .clamp (creaseAngle, 0, Math .PI)),
         refinedNormals = [ ];

      for (const vertex of normalIndex .values ())
      {
         for (const p of vertex)
         {
            const
               P = normals [p],
               N = new Numbers_Vector3 (0, 0, 0);

            for (const q of vertex)
            {
               const Q = normals [q];

               if (Q .dot (P) >= cosCreaseAngle)
                  N .add (Q);
            }

            refinedNormals [p] = N .normalize ();
         }
      }

      return refinedNormals;
   },
   transformLine (hitRay)
   {
      // Apply sceen nodes transformation in place here.
   },
   transformMatrix (hitRay)
   {
      // Apply sceen nodes transformation in place here.
   },
   isClipped (point, clipPlanes)
   {
      return clipPlanes .some (clipPlane => clipPlane .isClipped (point));
   },
   intersectsLine: (() =>
   {
      const
         modelViewMatrix = new Numbers_Matrix4 (),
         uvt             = { u: 0, v: 0, t: 0 },
         v0              = new Numbers_Vector3 (0, 0, 0),
         v1              = new Numbers_Vector3 (0, 0, 0),
         v2              = new Numbers_Vector3 (0, 0, 0),
         clipPoint       = new Numbers_Vector3 (0, 0, 0);

      return function (hitRay, matrix, clipPlanes, intersections)
      {
         if (this .intersectsBBox (hitRay))
         {
            this .transformLine (hitRay); // Apply screen transformations from screen nodes.
            this .transformMatrix (modelViewMatrix .assign (matrix)); // Apply screen transformations from screen nodes.

            const
               texCoords   = this .multiTexCoords [0] .getValue (),
               normals     = this .normals .getValue (),
               vertices    = this .vertices .getValue (),
               vertexCount = this .vertexCount;

            for (let i = 0; i < vertexCount; i += 3)
            {
               const i4 = i * 4;

               v0 .x = vertices [i4];     v0 .y = vertices [i4 + 1]; v0 .z = vertices [i4 +  2];
               v1 .x = vertices [i4 + 4]; v1 .y = vertices [i4 + 5]; v1 .z = vertices [i4 +  6];
               v2 .x = vertices [i4 + 8]; v2 .y = vertices [i4 + 9]; v2 .z = vertices [i4 + 10];

               if (hitRay .intersectsTriangle (v0, v1, v2, uvt))
               {
                  // Get barycentric coordinates.

                  const
                     u = uvt .u,
                     v = uvt .v,
                     t = uvt .t;

                  // Determine vectors for X3DPointingDeviceSensors.

                  const point = new Numbers_Vector3 (t * vertices [i4]     + u * vertices [i4 + 4] + v * vertices [i4 +  8],
                                             t * vertices [i4 + 1] + u * vertices [i4 + 5] + v * vertices [i4 +  9],
                                             t * vertices [i4 + 2] + u * vertices [i4 + 6] + v * vertices [i4 + 10]);

                  if (clipPlanes .length)
                  {
                     if (this .isClipped (modelViewMatrix .multVecMatrix (clipPoint .assign (point)), clipPlanes))
                        continue;
                  }

                  const texCoord = new Numbers_Vector2 (t * texCoords [i4]     + u * texCoords [i4 + 4] + v * texCoords [i4 + 8],
                                                t * texCoords [i4 + 1] + u * texCoords [i4 + 5] + v * texCoords [i4 + 9]);

                  const i3 = i * 3;

                  const normal = new Numbers_Vector3 (t * normals [i3]     + u * normals [i3 + 3] + v * normals [i3 + 6],
                                              t * normals [i3 + 1] + u * normals [i3 + 4] + v * normals [i3 + 7],
                                              t * normals [i3 + 2] + u * normals [i3 + 5] + v * normals [i3 + 8]);

                  intersections .push ({ texCoord: texCoord, normal: normal, point: this .getMatrix () .multVecMatrix (point) });
               }
            }
         }

         return intersections .length;
      };
   })(),
   getPlanesWithOffset: (() =>
   {
      const
         min    = new Numbers_Vector3 (0, 0, 0),
         max    = new Numbers_Vector3 (0, 0, 0),
         planes = [ ];

      for (let i = 0; i < 5; ++ i)
         planes [i] = new Geometry_Plane3 (Numbers_Vector3 .Zero, Numbers_Vector3 .zAxis);

      return function (minX, minY, minZ, maxX, maxY, maxZ)
      {
         min .set (minX, minY, minZ);
         max .set (maxX, maxY, maxZ);

         for (let i = 0; i < 5; ++ i)
            planes [i] .set (i % 2 ? min : max, boxNormals [i]);

         return planes;
      };
   })(),
   intersectsBBox: (() =>
   {
      const intersection = new Numbers_Vector3 (0, 0, 0);

      return function (hitRay, offsets)
      {
         if (offsets)
         {
            var
               min    = this .min,
               max    = this .max,
               minX   = min .x - offsets .x,
               maxX   = max .x + offsets .x,
               minY   = min .y - offsets .y,
               maxY   = max .y + offsets .y,
               minZ   = min .z - offsets .z,
               maxZ   = max .z + offsets .z,
               planes = this .getPlanesWithOffset (minX, minY, minZ, maxX, maxY, maxZ);
         }
         else
         {
            var
               min    = this .min,
               max    = this .max,
               minX   = min .x,
               maxX   = max .x,
               minY   = min .y,
               maxY   = max .y,
               minZ   = min .z,
               maxZ   = max .z,
               planes = this .planes;
         }

         // front
         if (planes [0] .intersectsLine (hitRay, intersection))
         {
            if (intersection .x >= minX && intersection .x <= maxX &&
                intersection .y >= minY && intersection .y <= maxY)
               return true;
         }

         // back
         if (planes [1] .intersectsLine (hitRay, intersection))
         {
            if (intersection .x >= minX && intersection .x <= maxX &&
                intersection .y >= minY && intersection .y <= maxY)
               return true;
         }

         // top
         if (planes [2] .intersectsLine (hitRay, intersection))
         {
            if (intersection .x >= minX && intersection .x <= maxX &&
                intersection .z >= minZ && intersection .z <= maxZ)
               return true;
         }

         // bottom
         if (planes [3] .intersectsLine (hitRay, intersection))
         {
            if (intersection .x >= minX && intersection .x <= maxX &&
                intersection .z >= minZ && intersection .z <= maxZ)
               return true;
         }

         // right
         if (planes [4] .intersectsLine (hitRay, intersection))
         {
            if (intersection .y >= minY && intersection .y <= maxY &&
                intersection .z >= minZ && intersection .z <= maxZ)
               return true;
         }

         return false;
      };
   })(),
   intersectsBox: (() =>
   {
      const
         v0        = new Numbers_Vector3 (0, 0, 0),
         v1        = new Numbers_Vector3 (0, 0, 0),
         v2        = new Numbers_Vector3 (0, 0, 0),
         invMatrix = new Numbers_Matrix4 (),
         clipPoint = new Numbers_Vector3 (0, 0, 0);

      return function (box, clipPlanes, modelViewMatrix)
      {
         if (box .intersectsBox (this .bbox))
         {
            box .multRight (invMatrix .assign (this .getMatrix ()) .inverse ());

            this .transformMatrix (modelViewMatrix); // Apply screen transformations from screen nodes.

            const vertices = this .vertices .getValue ();

            for (let i = 0, length = this .vertexCount; i < length; i += 3)
            {
               const i4 = i * 4;

               v0 .x = vertices [i4];     v0 .y = vertices [i4 + 1]; v0 .z = vertices [i4 +  2];
               v1 .x = vertices [i4 + 4]; v1 .y = vertices [i4 + 5]; v1 .z = vertices [i4 +  6];
               v2 .x = vertices [i4 + 8]; v2 .y = vertices [i4 + 9]; v2 .z = vertices [i4 + 10];

               if (box .intersectsTriangle (v0, v1, v2))
               {
                  if (clipPlanes .length)
                  {
                     if (this .isClipped (modelViewMatrix .multVecMatrix (clipPoint .assign (v0)), clipPlanes))
                        continue;

                     if (this .isClipped (modelViewMatrix .multVecMatrix (clipPoint .assign (v1)), clipPlanes))
                        continue;

                     if (this .isClipped (modelViewMatrix .multVecMatrix (clipPoint .assign (v2)), clipPlanes))
                        continue;
                  }

                  return true;
               }
            }
         }

         return false;
      };
   })(),
   set_live__ ()
   {
      if (this .getLive () .getValue ())
         this .getBrowser () .getBrowserOptions () ._Shading .addInterest ("set_shading__", this);
      else
         this .getBrowser () .getBrowserOptions () ._Shading .removeInterest ("set_shading__", this);
   },
   set_shading__: (() =>
   {
      const
         v0     = new Numbers_Vector3 (0, 0, 0),
         v1     = new Numbers_Vector3 (0, 0, 0),
         v2     = new Numbers_Vector3 (0, 0, 0),
         normal = new Numbers_Vector3 (0, 0, 0);

      return function (shading)
      {
         const
            browser = this .getBrowser (),
            gl      = browser .getContext ();

         if (this .geometryType < 2)
         {
            gl .bindBuffer (gl .ARRAY_BUFFER, this .normalBuffer);
            gl .bufferData (gl .ARRAY_BUFFER, this .normals .getValue (), gl .DYNAMIC_DRAW);
         }
         else
         {
            const flatShading = browser .getBrowserOptions () .getShading () === Core_Shading .FLAT;

            if (flatShading === this .flatShading)
               return;

            this .flatShading = flatShading;

            // Generate flat normals if needed.

            if (flatShading)
            {
               if (!this .flatNormals .length)
               {
                  const
                     cw          = this .frontFace === gl .CW,
                     flatNormals = this .flatNormals,
                     vertices    = this .vertices .getValue ();

                  for (let i = 0, length = vertices .length; i < length; i += 12)
                  {
                     Geometry_Triangle3 .normal (v0 .set (vertices [i],     vertices [i + 1], vertices [i + 2]),
                                        v1 .set (vertices [i + 4], vertices [i + 5], vertices [i + 6]),
                                        v2 .set (vertices [i + 8], vertices [i + 9], vertices [i + 10]),
                                        normal);

                     if (cw)
                        normal .negate ();

                     flatNormals .push (normal .x, normal .y, normal .z,
                                        normal .x, normal .y, normal .z,
                                        normal .x, normal .y, normal .z);
                  }

                  flatNormals .shrinkToFit ();
               }
            }

            // Transfer normals.

            gl .bindBuffer (gl .ARRAY_BUFFER, this .normalBuffer);
            gl .bufferData (gl .ARRAY_BUFFER, flatShading ? this .flatNormals .getValue () : this .normals .getValue (), gl .DYNAMIC_DRAW);
         }
      };
   })(),
   requestRebuild ()
   {
      this ._rebuild .addEvent ();
   },
   rebuild: (() =>
   {
      const point = new Numbers_Vector3 (0, 0, 0);

      return function ()
      {
         this .clear ();
         this .build ();

         // Shrink arrays before transferring them to graphics card.

         for (const attribArray of this .attribArrays)
            attribArray .shrinkToFit ();

         for (const multiTexCoord of this .multiTexCoords)
            multiTexCoord .shrinkToFit ();

         this .coordIndices .shrinkToFit ();
         this .fogDepths    .shrinkToFit ();
         this .colors       .shrinkToFit ();
         this .normals      .shrinkToFit ();
         this .vertices     .shrinkToFit ();

         // Determine bbox.

         const
            vertices = this .vertices .getValue (),
            min      = this .min,
            max      = this .max;

         if (vertices .length)
         {
            if (min .x === Number .POSITIVE_INFINITY)
            {
               for (let i = 0, length = vertices .length; i < length; i += 4)
               {
                  point .set (vertices [i], vertices [i + 1], vertices [i + 2]);

                  min .min (point);
                  max .max (point);
               }
            }

            this .bbox .setExtents (min, max);
         }
         else
         {
            this .bbox .setExtents (min .set (0, 0, 0), max .set (0, 0, 0));
         }

         this ._bbox_changed .addEvent ();

         for (let i = 0; i < 5; ++ i)
            this .planes [i] .set (i % 2 ? min : max, boxNormals [i]);

         // Generate texCoord if needed.

         if (this .multiTexCoords .length === 0)
            this .buildTexCoords ();

         // Transfer arrays and update.

         this .transfer ();
         this .updateGeometryKey ();
         this .updateRenderFunctions ();
      };
   })(),
   clear ()
   {
      // BBox

      this .min .set (Number .POSITIVE_INFINITY, Number .POSITIVE_INFINITY, Number .POSITIVE_INFINITY);
      this .max .set (Number .NEGATIVE_INFINITY, Number .NEGATIVE_INFINITY, Number .NEGATIVE_INFINITY);

      // Create attribArray arrays.
      {
         const attribArrays = this .attribArrays;

         for (const attribArray of attribArrays)
            attribArray .length = 0;

         const length = this .attribNodes .length;

         for (let a = attribArrays .length; a < length; ++ a)
            attribArrays [a] = new x_ite_Fields .MFFloat ();

         attribArrays .length = length;
      }

      // Buffer

      this .flatShading = undefined;

      this .coordIndices   .length = 0;
      this .fogDepths      .length = 0;
      this .colors         .length = 0;
      this .multiTexCoords .length = 0;
      this .texCoords      .length = 0;
      this .normals        .length = 0;
      this .flatNormals    .length = 0;
      this .vertices       .length = 0;
   },
   transfer ()
   {
      const gl = this .getBrowser () .getContext ();

      // Transfer coord indices.

      gl .bindBuffer (gl .ARRAY_BUFFER, this .coordIndexBuffer);
      gl .bufferData (gl .ARRAY_BUFFER, this .coordIndices .getValue (), gl .DYNAMIC_DRAW);

      // Transfer attribArrays.

      for (let i = this .attribBuffers .length, length = this .attribArrays .length; i < length; ++ i)
         this .attribBuffers .push (gl .createBuffer ());

      for (let i = 0, length = this .attribArrays .length; i < length; ++ i)
      {
         gl .bindBuffer (gl .ARRAY_BUFFER, this .attribBuffers [i]);
         gl .bufferData (gl .ARRAY_BUFFER, this .attribArrays [i] .getValue (), gl .DYNAMIC_DRAW);
      }

      // Transfer fog depths.

      const lastHasFogCoords = this .hasFogCoords;

      gl .bindBuffer (gl .ARRAY_BUFFER, this .fogDepthBuffer);
      gl .bufferData (gl .ARRAY_BUFFER, this .fogDepths .getValue (), gl .DYNAMIC_DRAW);

      this .hasFogCoords = !! this .fogDepths .length;

      if (this .hasFogCoords !== lastHasFogCoords)
         this .updateVertexArrays ();

      // Transfer colors.

      const lastColorMaterial = this .colorMaterial;

      gl .bindBuffer (gl .ARRAY_BUFFER, this .colorBuffer);
      gl .bufferData (gl .ARRAY_BUFFER, this .colors .getValue (), gl .DYNAMIC_DRAW);

      this .colorMaterial = !! this .colors .length;

      if (this .colorMaterial !== lastColorMaterial)
         this .updateVertexArrays ();

      // Transfer multiTexCoords.

      for (let i = 0, length = this .multiTexCoords .length; i < length; ++ i)
      {
         gl .bindBuffer (gl .ARRAY_BUFFER, this .texCoordBuffers [i]);
         gl .bufferData (gl .ARRAY_BUFFER, this .multiTexCoords [i] .getValue (), gl .DYNAMIC_DRAW);
      }

      // Transfer normals or flat normals.

      const lastHasNormals = this .hasNormals;

      this .set_shading__ (this .getBrowser () .getBrowserOptions () ._Shading);

      this .hasNormals = !! this .normals .length;

      if (this .hasNormals !== lastHasNormals)
         this .updateVertexArrays ();

      // Transfer vertices.

      gl .bindBuffer (gl .ARRAY_BUFFER, this .vertexBuffer);
      gl .bufferData (gl .ARRAY_BUFFER, this .vertices .getValue (), gl .DYNAMIC_DRAW);

      this .vertexCount = this .vertices .length / 4;
   },
   updateGeometryKey ()
   {
      this .geometryKey  = "";
      this .geometryKey += this .geometryType;
      this .geometryKey += this .hasFogCoords  ? "1" : "0";
      this .geometryKey += this .colorMaterial ? "1" : "0";
      this .geometryKey += this .hasNormals    ? "1" : "0";
   },
   updateRenderFunctions ()
   {
      if (this .vertexCount)
      {
         // Use default render functions.

         delete this .displaySimple;
         delete this .display;
         delete this .displaySimpleParticles;
         delete this .displayParticles;
      }
      else
      {
         // Use no render function.

         this .displaySimple          = Function .prototype;
         this .display                = Function .prototype;
         this .displaySimpleParticles = Function .prototype;
         this .displayParticles       = Function .prototype;
      }
   },
   traverse (type, renderObject)
   { },
   displaySimple (gl, renderContext, shaderNode)
   {
      if (this .vertexArrayObject .enable (shaderNode))
      {
         if (this .coordIndices .length)
            shaderNode .enableCoordIndexAttribute (gl, this .coordIndexBuffer, 0, 0);

         if (this .multiTexCoords .length)
            shaderNode .enableTexCoordAttribute (gl, this .texCoordBuffers, 0, 0);

         if (this .hasNormals)
            shaderNode .enableNormalAttribute (gl, this .normalBuffer, 0, 0);

         shaderNode .enableVertexAttribute (gl, this .vertexBuffer, 0, 0);
      }

      gl .drawArrays (this .primitiveMode, 0, this .vertexCount);
   },
   display (gl, renderContext)
   {
      const
         browser        = this .getBrowser (),
         appearanceNode = renderContext .appearanceNode,
         shaderNode     = appearanceNode .getShader (this, renderContext);

      if (this .solid || !appearanceNode .getBackMaterial () || browser .getWireframe ())
      {
         this .displayGeometry (gl, renderContext, appearanceNode, shaderNode, true, true);
      }
      else
      {
         const backShaderNode = appearanceNode .getBackShader (this, renderContext);

         this .displayGeometry (gl, renderContext, appearanceNode, backShaderNode, true,  false);
         this .displayGeometry (gl, renderContext, appearanceNode, shaderNode,     false, true);
      }
   },
   displayGeometry (gl, renderContext, appearanceNode, shaderNode, back, front)
   {
      const
         browser       = this .getBrowser (),
         blendModeNode = appearanceNode .getBlendMode (),
         attribNodes   = this .attribNodes,
         attribBuffers = this .attribBuffers,
         primitiveMode = browser .getPrimitiveMode (this .primitiveMode);

      blendModeNode ?.enable (gl);

      shaderNode .enable (gl);
      shaderNode .setUniforms (gl, this, renderContext, front);

      // Setup vertex attributes.

      if (this .vertexArrayObject .enable (shaderNode))
      {
         if (this .coordIndices .length)
            shaderNode .enableCoordIndexAttribute (gl, this .coordIndexBuffer, 0, 0);

         for (let i = 0, length = attribNodes .length; i < length; ++ i)
            attribNodes [i] .enable (gl, shaderNode, attribBuffers [i]);

         if (this .hasFogCoords)
            shaderNode .enableFogDepthAttribute (gl, this .fogDepthBuffer, 0, 0);

         if (this .colorMaterial)
            shaderNode .enableColorAttribute (gl, this .colorBuffer, 0, 0);

         shaderNode .enableTexCoordAttribute (gl, this .texCoordBuffers, 0, 0);
         shaderNode .enableNormalAttribute   (gl, this .normalBuffer,    0, 0);
         shaderNode .enableVertexAttribute   (gl, this .vertexBuffer,    0, 0);
      }

      // Draw depending on wireframe, solid and transparent.

      if (browser .getWireframe ())
      {
         for (let i = 0, length = this .vertexCount; i < length; i += 3)
            gl .drawArrays (primitiveMode, i, 3);
      }
      else
      {
         const positiveScale = Numbers_Matrix4 .prototype .determinant3 .call (renderContext .modelViewMatrix) > 0;

         gl .frontFace (positiveScale ? this .frontFace : this .backFace .get (this .frontFace));

         if (renderContext .transparent || back !== front)
         {
            // Render transparent or back or front.

            gl .enable (gl .CULL_FACE);

            // Render back.

            if (back && !this .solid)
            {
               gl .cullFace (gl .FRONT);
               gl .drawArrays (primitiveMode, 0, this .vertexCount);
            }

            // Render front.

            if (front)
            {
               gl .cullFace (gl .BACK);
               gl .drawArrays (primitiveMode, 0, this .vertexCount);
            }
         }
         else
         {
            // Render solid or both sides.

            if (this .solid)
               gl .enable (gl .CULL_FACE);
            else
               gl .disable (gl .CULL_FACE);

            gl .drawArrays (primitiveMode, 0, this .vertexCount);
         }
      }

      blendModeNode ?.disable (gl);
   },
   displaySimpleParticles (gl, shaderNode, particleSystem)
   {
      const outputParticles = particleSystem .outputParticles;

      if (outputParticles .vertexArrayObject .update (this .updateParticles) .enable (shaderNode))
      {
         const { particleStride, particleOffset, matrixOffset } = particleSystem;

         shaderNode .enableParticleAttribute       (gl, outputParticles, particleStride, particleOffset, 1);
         shaderNode .enableParticleMatrixAttribute (gl, outputParticles, particleStride, matrixOffset,   1);
         shaderNode .enableTexCoordAttribute       (gl, this .texCoordBuffers, 0, 0);
         shaderNode .enableNormalAttribute         (gl, this .normalBuffer,    0, 0);
         shaderNode .enableVertexAttribute         (gl, this .vertexBuffer,    0, 0);

         this .updateParticles = false;
      }

      gl .drawArraysInstanced (this .primitiveMode, 0, this .vertexCount, particleSystem .numParticles);
   },
   displayParticles (gl, renderContext, particleSystem)
   {
      const
         browser        = this .getBrowser (),
         appearanceNode = renderContext .appearanceNode,
         shaderNode     = appearanceNode .getShader (this, renderContext);

      if (this .solid || !appearanceNode .getBackMaterial () || browser .getWireframe ())
      {
         this .displayParticlesGeometry (gl, renderContext, appearanceNode, shaderNode, true, true, particleSystem);
      }
      else
      {
         const backShaderNode = appearanceNode .getBackShader (this, renderContext);

         this .displayParticlesGeometry (gl, renderContext, appearanceNode, backShaderNode, true,  false, particleSystem);
         this .displayParticlesGeometry (gl, renderContext, appearanceNode, shaderNode,     false, true,  particleSystem);
      }
   },
   displayParticlesGeometry (gl, renderContext, appearanceNode, shaderNode, back, front, particleSystem)
   {
      const
         browser       = this .getBrowser (),
         blendModeNode = appearanceNode .getBlendMode (),
         attribNodes   = this .attribNodes,
         attribBuffers = this .attribBuffers,
         primitiveMode = browser .getPrimitiveMode (this .primitiveMode);

      blendModeNode ?.enable (gl);

      // Setup shader.

      shaderNode .enable (gl);
      shaderNode .setUniforms (gl, this, renderContext, front);

      // Setup vertex attributes.

      const outputParticles = particleSystem .outputParticles;

      if (outputParticles .vertexArrayObject .update (this .updateParticles) .enable (shaderNode))
      {
         const { particleStride, particleOffset, matrixOffset } = particleSystem;

         shaderNode .enableParticleAttribute       (gl, outputParticles, particleStride, particleOffset, 1);
         shaderNode .enableParticleMatrixAttribute (gl, outputParticles, particleStride, matrixOffset,   1);

         for (let i = 0, length = attribNodes .length; i < length; ++ i)
            attribNodes [i] .enable (gl, shaderNode, attribBuffers [i]);

         if (this .hasFogCoords)
            shaderNode .enableFogDepthAttribute (gl, this .fogDepthBuffer, 0, 0);

         if (this .colorMaterial)
            shaderNode .enableColorAttribute (gl, this .colorBuffer, 0, 0);

         shaderNode .enableTexCoordAttribute (gl, this .texCoordBuffers, 0, 0);
         shaderNode .enableNormalAttribute   (gl, this .normalBuffer,    0, 0);
         shaderNode .enableVertexAttribute   (gl, this .vertexBuffer,    0, 0);

         this .updateParticles = false;
      }

      // Draw depending on wireframe, solid and transparent.

      const positiveScale = Numbers_Matrix4 .prototype .determinant3 .call (renderContext .modelViewMatrix) > 0;

      gl .frontFace (positiveScale ? this .frontFace : this .backFace .get (this .frontFace));

      if (renderContext .transparent || back !== front)
      {
         // Render transparent or back or front.

         gl .enable (gl .CULL_FACE);

         if (back && !this .solid)
         {
            gl .cullFace (gl .FRONT);
            gl .drawArraysInstanced (primitiveMode, 0, this .vertexCount, particleSystem .numParticles);
         }

         if (front)
         {
            gl .cullFace (gl .BACK);
            gl .drawArraysInstanced (primitiveMode, 0, this .vertexCount, particleSystem .numParticles);
         }
      }
      else
      {
         // Render solid or both sides.

         if (this .solid)
            gl .enable (gl .CULL_FACE);
         else
            gl .disable (gl .CULL_FACE);

         gl .drawArraysInstanced (primitiveMode, 0, this .vertexCount, particleSystem .numParticles);
      }

      blendModeNode ?.disable (gl);
   },
});

Object .defineProperties (X3DGeometryNode,
{
   typeName:
   {
      value: "X3DGeometryNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
});

const X3DGeometryNode_default_ = X3DGeometryNode;
;

x_ite_Namespace .add ("X3DGeometryNode", "x_ite/Components/Rendering/X3DGeometryNode", X3DGeometryNode_default_);
/* harmony default export */ const Rendering_X3DGeometryNode = (X3DGeometryNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Shape/AlphaMode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

let AlphaMode_i = 0;

const AlphaMode =
{
   AUTO:   AlphaMode_i ++, // Must be zero!
   OPAQUE: AlphaMode_i ++,
   MASK:   AlphaMode_i ++,
   BLEND:  AlphaMode_i ++,
};

const AlphaMode_default_ = AlphaMode;
;

x_ite_Namespace .add ("AlphaMode", "x_ite/Browser/Shape/AlphaMode", AlphaMode_default_);
/* harmony default export */ const Shape_AlphaMode = (AlphaMode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Rendering/GeometryContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function GeometryContext (options = { })
{
   Object .assign (this,
   {
      alphaMode: Shape_AlphaMode .OPAQUE,
      geometryType: 3,
      hasFogCoords: false,
      colorMaterial: false,
      hasNormals: false,
      textureNode: false,
      objectsCount: [0, 0, 0],
      textureCoordinateMapping: new Map (),
      textureCoordinateNode: null,
   },
   options)

   this .updateGeometryKey ();
}

Object .assign (GeometryContext .prototype,
{
   updateGeometryKey: Rendering_X3DGeometryNode .prototype .updateGeometryKey,
   getTextureCoordinateMapping ()
   {
      return this .textureCoordinateMapping;
   },
   getTextureCoordinate ()
   {
      return this .textureCoordinateNode;
   },
});

const GeometryContext_default_ = GeometryContext;
;

x_ite_Namespace .add ("GeometryContext", "x_ite/Browser/Rendering/GeometryContext", GeometryContext_default_);
/* harmony default export */ const Rendering_GeometryContext = (GeometryContext_default_);
;// CONCATENATED MODULE: ./src/standard/Utility/BitSet.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function BitSet (value = 0)
{
   this .value = value;
}

Object .assign (BitSet .prototype,
{
   *[Symbol .iterator] ()
   {
      let
         value = this .value,
         index = 0;

      while (value)
      {
         if (value & 1)
            yield index;

         value >>>= 1;
         index   += 1;
      }
   },
   get (index)
   {
      const mask = 1 << index;

      return !! (this .value & mask);
   },
   set (index, value)
   {
      const mask = 1 << index;

      if (value)
         this .value |= mask;
      else
         this .value &= ~mask;
   },
   clear ()
   {
      this .value = 0;
   },
   *entries ()
   {
      for (const i of this)
         yield [i, i];
   },
   valueOf ()
   {
      return this .value;
   },
   toString (radix)
   {
      return this .value .toString (radix);
   },
});

BitSet .prototype .keys   = BitSet .prototype [Symbol .iterator];
BitSet .prototype .values = BitSet .prototype [Symbol .iterator];

Object .defineProperty (BitSet .prototype, "size",
{
   get ()
   {
      return Math_Algorithm .bitCount (this .value);
   },
});

const BitSet_default_ = BitSet;
;

x_ite_Namespace .add ("BitSet", "standard/Utility/BitSet", BitSet_default_);
/* harmony default export */ const Utility_BitSet = (BitSet_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/EnvironmentalEffects/X3DBackgroundNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/















const
   RADIUS = 1,
   SIZE   = Math .SQRT2 / 2;

function X3DBackgroundNode (executionContext)
{
   Core_X3DBindableNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DBackgroundNode);

   this .addChildObjects (Base_X3DConstants .inputOutput, "hidden", new x_ite_Fields .SFBool ());

   this ._skyAngle    .setUnit ("angle");
   this ._groundAngle .setUnit ("angle");

   this .projectionMatrixArray = new Float32Array (16);
   this .modelMatrix           = new Numbers_Matrix4 ();
   this .modelViewMatrixArray  = new Float32Array (16);
   this .clipPlanes            = [ ];
   this .colors                = [ ];
   this .sphere                = [ ];
   this .textureNodes          = new Array (6);
   this .textureBits           = new Utility_BitSet ();
   this .sphereContext         = new Rendering_GeometryContext ({ colorMaterial: true });
   this .sphereAlphaContext    = new Rendering_GeometryContext ({ colorMaterial: true, alphaMode: Shape_AlphaMode .BLEND });
   this .texturesContext       = new Rendering_GeometryContext ({ textureNode: true });
   this .texturesAlphaContext  = new Rendering_GeometryContext ({ textureNode: true, alphaMode: Shape_AlphaMode .BLEND });
}

Object .assign (Object .setPrototypeOf (X3DBackgroundNode .prototype, Core_X3DBindableNode .prototype),
{
   initialize ()
   {
      Core_X3DBindableNode .prototype .initialize .call (this);

      const
         browser = this .getBrowser (),
         gl      = browser .getContext ();

      this .colorBuffer         = gl .createBuffer ();
      this .sphereBuffer        = gl .createBuffer ();
      this .texCoordBuffers     = [gl .createBuffer ()];
      this .textureBuffers      = Array .from ({length: 6}, () => gl .createBuffer ());
      this .sphereArrayObject   = new Rendering_VertexArray (gl);
      this .textureArrayObjects = Array .from ({length: 6}, () => new Rendering_VertexArray (gl));

      this ._groundAngle .addInterest ("build", this);
      this ._groundColor .addInterest ("build", this);
      this ._skyAngle    .addInterest ("build", this);
      this ._skyColor    .addInterest ("build", this);

      this .build ();
      this .transferRectangle ();
   },
   isHidden ()
   {
      return this ._hidden .getValue ();
   },
   setHidden (value)
   {
      if (value === this ._hidden .getValue ())
         return;

      this ._hidden = value;
   },
   isTransparent ()
   {
      if (this ._hidden .getValue ())
         return true;

      if (this ._transparency .getValue () <= 0)
         return false;

      if (this .textureBits .size !== 6)
         return true;

      for (const i of this .textureBits)
      {
         if (this .textureNodes [i] ._transparent .getValue ())
            return true;
      }

      return false;
   },
   set_texture__ (textureNode, index)
   {
      this .textureNodes [index] ?._loadState .removeInterest ("set_loadState__", this);

      this .textureNodes [index] = textureNode;

      textureNode ?._loadState .addInterest ("set_loadState__", this, textureNode, index);

      this .set_loadState__ (textureNode, index);
   },
   set_loadState__ (textureNode, index)
   {
      this .setTextureBit (index, textureNode, textureNode ?.checkLoadState () ?? Base_X3DConstants .NOT_STARTED);
   },
   setTextureBit (bit, textureNode, loadState)
   {
      this .textureBits .set (bit, loadState === Base_X3DConstants .COMPLETE_STATE || textureNode ?.getWidth ());
   },
   getColor (theta, color, angle)
   {
      const index = Math_Algorithm .upperBound (angle, 0, angle .length, theta);

      return color [index];
   },
   build ()
   {
      const s = SIZE;

      this .colors .length = 0;
      this .sphere .length = 0;

      if (this ._groundColor .length === 0 && this ._skyColor .length == 1)
      {
         // Build cube

         this .sphere .vertices = 36;

         this .sphere .push ( s,  s, -s, 1, -s,  s, -s, 1, -s, -s, -s, 1, // Back
                              s,  s, -s, 1, -s, -s, -s, 1,  s, -s, -s, 1,
                             -s,  s,  s, 1,  s,  s,  s, 1, -s, -s,  s, 1, // Front
                             -s, -s,  s, 1,  s,  s,  s, 1,  s, -s,  s, 1,
                             -s,  s, -s, 1, -s,  s,  s, 1, -s, -s,  s, 1, // Left
                             -s,  s, -s, 1, -s, -s,  s, 1, -s, -s, -s, 1,
                              s,  s,  s, 1,  s,  s, -s, 1,  s, -s,  s, 1, // Right
                              s, -s,  s, 1,  s,  s, -s, 1,  s, -s, -s, 1,
                              s,  s,  s, 1, -s,  s,  s, 1, -s,  s, -s, 1, // Top
                              s,  s,  s, 1, -s,  s, -s, 1,  s,  s, -s, 1,
                             -s, -s,  s, 1,  s, -s,  s, 1, -s, -s, -s, 1, // Bottom
                             -s, -s, -s, 1,  s, -s,  s, 1,  s, -s, -s, 1);

         const color = this ._skyColor [0];

         for (let i = 0, vertices = this .sphere .vertices; i < vertices; ++ i)
            this .colors .push (... color, 1);
      }
      else
      {
         // Build sphere

         if (this ._skyColor .length > this ._skyAngle .length)
         {
            const vAngle = this ._skyAngle .slice ();

            if (vAngle .length === 0 || vAngle [0] > 0)
               vAngle .unshift (0);

            if (vAngle .at (-1) < Math .PI)
               vAngle .push (Math .PI);

            if (vAngle .length === 2)
						vAngle .splice (1, 0, (vAngle [0] + vAngle [1]) / 2)

            this .buildSphere (RADIUS, vAngle, this ._skyAngle, this ._skyColor, false);
         }

         if (this ._groundColor .length > this ._groundAngle .length)
         {
            const vAngle = this ._groundAngle .slice () .reverse ();

            if (vAngle .length === 0 || vAngle [0] < Math .PI / 2)
               vAngle .unshift (Math .PI / 2);

            if (vAngle .at (-1) > 0)
               vAngle .push (0);

            this .buildSphere (RADIUS, vAngle, this ._groundAngle, this ._groundColor, true);
         }
      }

      this .transferSphere ();
   },
   buildSphere: (() =>
   {
      const U_DIMENSION = 20;

      const
         z1 = new Numbers_Complex (0, 0),
         z2 = new Numbers_Complex (0, 0),
         y1 = new Numbers_Complex (0, 0),
         y2 = new Numbers_Complex (0, 0),
         y3 = new Numbers_Complex (0, 0),
         y4 = new Numbers_Complex (0, 0);

      return function (radius, vAngle, angle, color, bottom)
      {
         const
            vAngleMax   = bottom ? Math .PI / 2 : Math .PI,
            V_DIMENSION = vAngle .length - 1;

         for (let v = 0; v < V_DIMENSION; ++ v)
         {
            let
               theta1 = Math_Algorithm .clamp (vAngle [v],     0, vAngleMax),
               theta2 = Math_Algorithm .clamp (vAngle [v + 1], 0, vAngleMax);

            if (bottom)
            {
               theta1 = Math .PI - theta1;
               theta2 = Math .PI - theta2;
            }

            z1 .setPolar (radius, theta1);
            z2 .setPolar (radius, theta2);

            const
               c1 = this .getColor (vAngle [v],     color, angle),
               c2 = this .getColor (vAngle [v + 1], color, angle);

            for (let u = 0; u < U_DIMENSION; ++ u)
            {
               // p4 --- p1
               //  |   / |
               //  | /   |
               // p3 --- p2

               // The last point is the first one.
               const u1 = u < U_DIMENSION - 1 ? u + 1 : 0;

               // p1, p2
               let phi = 2 * Math .PI * (u / U_DIMENSION);
               y1 .setPolar (-z1 .imag, phi);
               y2 .setPolar (-z2 .imag, phi);

               // p3, p4
               phi = 2 * Math .PI * (u1 / U_DIMENSION);
               y3 .setPolar (-z2 .imag, phi);
               y4 .setPolar (-z1 .imag, phi);

               // Triangle 1 and 2

               this .colors .push (... c1, 1,
                                   ... c2, 1,
                                   ... c2, 1,
                                   // Triangle 2
                                   ... c1, 1,
                                   ... c1, 1,
                                   ... c2, 1);

               this .sphere .push (y1 .imag, z1 .real, y1 .real, 1,
                                   y3 .imag, z2 .real, y3 .real, 1,
                                   y2 .imag, z2 .real, y2 .real, 1,
                                   // Triangle 2
                                   y1 .imag, z1 .real, y1 .real, 1,
                                   y4 .imag, z1 .real, y4 .real, 1,
                                   y3 .imag, z2 .real, y3 .real, 1);
            }
         }
      };
   })(),
   transferSphere ()
   {
      const gl = this .getBrowser () .getContext ();

      // Transfer colors.

      gl .bindBuffer (gl .ARRAY_BUFFER, this .colorBuffer);
      gl .bufferData (gl .ARRAY_BUFFER, new Float32Array (this .colors), gl .DYNAMIC_DRAW);

      // Transfer sphere.

      gl .bindBuffer (gl .ARRAY_BUFFER, this .sphereBuffer);
      gl .bufferData (gl .ARRAY_BUFFER, new Float32Array (this .sphere), gl .DYNAMIC_DRAW);

      this .sphereCount = this .sphere .length / 4;
   },
   transferRectangle: (() =>
   {
      const s = SIZE;

      const texCoords = new Float32Array ([
         1, 1, 0, 1,
         0, 1, 0, 1,
         0, 0, 0, 1,
         1, 1, 0, 1,
         0, 0, 0, 1,
         1, 0, 0, 1,
      ]);

      const frontVertices = new Float32Array ([
         s,  s, -s, 1,
        -s,  s, -s, 1,
        -s, -s, -s, 1,
         s,  s, -s, 1,
        -s, -s, -s, 1,
         s, -s, -s, 1,
      ]);

      const backVertices = new Float32Array ([
         -s,  s,  s, 1,
          s,  s,  s, 1,
          s, -s,  s, 1,
         -s,  s,  s, 1,
          s, -s,  s, 1,
         -s, -s,  s, 1,
      ]);

      const leftVertices = new Float32Array ([
         -s,  s, -s, 1,
         -s,  s,  s, 1,
         -s, -s,  s, 1,
         -s,  s, -s, 1,
         -s, -s,  s, 1,
         -s, -s, -s, 1,
      ]);

      const rightVertices = new Float32Array ([
         s,  s,  s, 1,
         s,  s, -s, 1,
         s, -s, -s, 1,
         s,  s,  s, 1,
         s, -s, -s, 1,
         s, -s,  s, 1,
      ]);

      const topVertices = new Float32Array ([
          s, s,  s, 1,
         -s, s,  s, 1,
         -s, s, -s, 1,
          s, s,  s, 1,
         -s, s, -s, 1,
          s, s, -s, 1,
      ]);

      const bottomVertices = new Float32Array ([
          s, -s, -s, 1,
         -s, -s, -s, 1,
         -s, -s,  s, 1,
          s, -s, -s, 1,
         -s, -s,  s, 1,
          s, -s,  s, 1,
      ]);

      const vertices = [
         frontVertices,
         backVertices,
         leftVertices,
         rightVertices,
         topVertices,
         bottomVertices,
      ];

      return function ()
      {
         const gl = this .getBrowser () .getContext ();

         // Transfer texCoords.

         gl .bindBuffer (gl .ARRAY_BUFFER, this .texCoordBuffers [0]);
         gl .bufferData (gl .ARRAY_BUFFER, texCoords, gl .DYNAMIC_DRAW);

         // Transfer rectangle.

         for (let i = 0; i < 6; ++ i)
         {
            gl .bindBuffer (gl .ARRAY_BUFFER, this .textureBuffers [i]);
            gl .bufferData (gl .ARRAY_BUFFER, vertices [i], gl .DYNAMIC_DRAW);
         }
      };
   })(),
   traverse (type, renderObject)
   {
      switch (type)
      {
         case Rendering_TraverseType .CAMERA:
         {
            renderObject .getLayer () .getBackgrounds () .push (this);

            this .modelMatrix .assign (renderObject .getModelViewMatrix () .get ());
            return;
         }
         case Rendering_TraverseType .DISPLAY:
         {
            const
               localObjects = renderObject .getLocalObjects (),
               clipPlanes   = this .clipPlanes;

            let c = 0;

            for (let l = 0, length = localObjects .length; l < length; ++ l)
            {
               if (localObjects [l] .isClipped)
                  clipPlanes [c ++] = localObjects [l];
            }

            clipPlanes .length = c;

            this .sphereContext   .objectsCount [0] = clipPlanes .length;
            this .texturesContext .objectsCount [0] = clipPlanes .length;
            return;
         }
      }
   },
   display: (() =>
   {
      const
         modelViewMatrix = new Numbers_Matrix4 (),
         rotation        = new Numbers_Rotation4 (),
         scale           = new Numbers_Vector3 (0, 0, 0);

      return function (gl, renderObject, viewport)
      {
         if (this ._hidden .getValue ())
            return;

         // Setup context.

         gl .disable (gl .DEPTH_TEST);
         gl .depthMask (false);
         gl .enable (gl .CULL_FACE);
         gl .frontFace (gl .CCW);

         // Get projection matrix.

         this .projectionMatrixArray .set (renderObject .getViewpoint () .getProjectionMatrixWithLimits (0.125, 200_000, viewport));

         // Rotate and scale background.

         modelViewMatrix .assign (this .modelMatrix);
         modelViewMatrix .multRight (renderObject .getViewMatrix () .get ());
         modelViewMatrix .get (null, rotation);
         modelViewMatrix .identity ();
         modelViewMatrix .rotate (rotation);
         modelViewMatrix .scale (scale .set (100_000, 100_000, 100_000));

         this .modelViewMatrixArray .set (modelViewMatrix);

         // Draw background sphere and texture cube.

         this .drawSphere (renderObject);

         if (+this .textureBits)
            this .drawCube (renderObject);

         gl .depthMask (true);
         gl .enable (gl .DEPTH_TEST);
         gl .disable (gl .BLEND);
      };
   })(),
   drawSphere (renderObject)
   {
      const transparency = Math_Algorithm .clamp (this ._transparency .getValue (), 0, 1);

      if (transparency === 1)
         return;

      const
         browser    = this .getBrowser (),
         gl         = browser .getContext (),
         shaderNode = browser .getDefaultMaterial () .getShader (transparency ? this .sphereAlphaContext : this .sphereContext);

      shaderNode .enable (gl);
      shaderNode .setClipPlanes (gl, this .clipPlanes);

      // Uniforms

      gl .uniformMatrix4fv (shaderNode .x3d_ProjectionMatrix, false, this .projectionMatrixArray);
      gl .uniformMatrix4fv (shaderNode .x3d_ModelViewMatrix,  false, this .modelViewMatrixArray);

      gl .uniform3f (shaderNode .x3d_EmissiveColor,                      1, 1, 1)
      gl .uniform1f (shaderNode .x3d_Transparency,                       transparency)
      gl .uniform1i (shaderNode .x3d_TextureCoordinateGeneratorMode [0], 0);

      // Enable vertex attribute arrays.

      if (this .sphereArrayObject .enable (shaderNode))
      {
         shaderNode .enableColorAttribute  (gl, this .colorBuffer,  0, 0);
         shaderNode .enableVertexAttribute (gl, this .sphereBuffer, 0, 0);
      }

      // Draw.

      if (transparency)
         gl .enable (gl .BLEND);
      else
         gl .disable (gl .BLEND);

      gl .drawArrays (gl .TRIANGLES, 0, this .sphereCount);
   },
   drawCube: (() =>
   {
      const textureMatrixArray = new Float32Array (Numbers_Matrix4 .Identity);

      return function (renderObject)
      {
         const
            browser         = this .getBrowser (),
            gl              = browser .getContext (),
            shaderNode      = browser .getDefaultMaterial () .getShader (this .texturesContext),
            alphaShaderNode = browser .getDefaultMaterial () .getShader (this .texturesAlphaContext);

         shaderNode .enable (gl);
         shaderNode .setClipPlanes (gl, this .clipPlanes);

         // Set uniforms.

         gl .uniformMatrix4fv (shaderNode .x3d_ProjectionMatrix,  false, this .projectionMatrixArray);
         gl .uniformMatrix4fv (shaderNode .x3d_ModelViewMatrix,   false, this .modelViewMatrixArray);
         gl .uniformMatrix4fv (shaderNode .x3d_TextureMatrix [0], false, textureMatrixArray);

         gl .uniform3f (shaderNode .x3d_EmissiveColor,                      1, 1, 1);
         gl .uniform1f (shaderNode .x3d_Transparency,                       0);
         gl .uniform1i (shaderNode .x3d_TextureCoordinateGeneratorMode [0], 0);

         // Draw all textures.

         for (const i of this .textureBits)
         {
            const textureNode = this .textureNodes [i];

            this .drawRectangle (gl, browser, textureNode ._transparent .getValue () ? alphaShaderNode : shaderNode, renderObject, textureNode, this .textureBuffers [i], this .textureArrayObjects [i]);
         }
      };
   })(),
   drawRectangle (gl, browser, shaderNode, renderObject, textureNode, buffer, vertexArray)
   {
      textureNode .setShaderUniforms (gl, shaderNode, renderObject);

      if (vertexArray .enable (gl, shaderNode))
      {
         shaderNode .enableTexCoordAttribute (gl, this .texCoordBuffers, 0, 0);
         shaderNode .enableVertexAttribute (gl, buffer, 0, 0);
      }

      // Draw.

      if (textureNode ._transparent .getValue ())
         gl .enable (gl .BLEND);
      else
         gl .disable (gl .BLEND);

      gl .drawArrays (gl .TRIANGLES, 0, 6);

      browser .resetTextureUnits ();
   },
});

Object .defineProperties (X3DBackgroundNode,
{
   typeName:
   {
      value: "X3DBackgroundNode",
      enumerable: true,
   },
   componentName:
   {
      value: "EnvironmentalEffects",
      enumerable: true,
   },
});

const X3DBackgroundNode_default_ = X3DBackgroundNode;
;

x_ite_Namespace .add ("X3DBackgroundNode", "x_ite/Components/EnvironmentalEffects/X3DBackgroundNode", X3DBackgroundNode_default_);
/* harmony default export */ const EnvironmentalEffects_X3DBackgroundNode = (X3DBackgroundNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shape/X3DAppearanceChildNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function X3DAppearanceChildNode (executionContext)
{
   Core_X3DNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DAppearanceChildNode);
}

Object .setPrototypeOf (X3DAppearanceChildNode .prototype, Core_X3DNode .prototype);

Object .defineProperties (X3DAppearanceChildNode,
{
   typeName:
   {
      value: "X3DAppearanceChildNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Shape",
      enumerable: true,
   },
});

const X3DAppearanceChildNode_default_ = X3DAppearanceChildNode;
;

x_ite_Namespace .add ("X3DAppearanceChildNode", "x_ite/Components/Shape/X3DAppearanceChildNode", X3DAppearanceChildNode_default_);
/* harmony default export */ const Shape_X3DAppearanceChildNode = (X3DAppearanceChildNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing/X3DTextureNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function X3DTextureNode (executionContext)
{
   Shape_X3DAppearanceChildNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DTextureNode);

   this .addChildObjects (Base_X3DConstants .outputOnly, "transparent", new x_ite_Fields .SFBool ());
}

Object .assign (Object .setPrototypeOf (X3DTextureNode .prototype, Shape_X3DAppearanceChildNode .prototype),
{
   setTransparent (value)
   {
      if (value !== this ._transparent .getValue ())
         this ._transparent = value;
   },
   isTransparent ()
   {
      return this ._transparent .getValue ();
   },
});

Object .defineProperties (X3DTextureNode,
{
   typeName:
   {
      value: "X3DTextureNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Texturing",
      enumerable: true,
   },
});

const X3DTextureNode_default_ = X3DTextureNode;
;

x_ite_Namespace .add ("X3DTextureNode", "x_ite/Components/Texturing/X3DTextureNode", X3DTextureNode_default_);
/* harmony default export */ const Texturing_X3DTextureNode = (X3DTextureNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Base/X3DCast.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function X3DCast (type, node, innerNode = true)
{
   try
   {
      if (node)
      {
         if (node instanceof x_ite_Fields .SFNode)
            node = node .getValue ();

         if (node)
         {
            if (innerNode)
               node = node .getInnerNode ();

            if (node .getType () .includes (type))
               return node;
         }
      }
   }
   catch
   { }

   return null;
}

const X3DCast_default_ = X3DCast;
;

x_ite_Namespace .add ("X3DCast", "x_ite/Base/X3DCast", X3DCast_default_);
/* harmony default export */ const Base_X3DCast = (X3DCast_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing/X3DSingleTextureNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function X3DSingleTextureNode (executionContext)
{
   Texturing_X3DTextureNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DSingleTextureNode);
}

Object .assign (Object .setPrototypeOf (X3DSingleTextureNode .prototype, Texturing_X3DTextureNode .prototype),
{
   initialize ()
   {
      Texturing_X3DTextureNode .prototype .initialize .call (this);

      this ._textureProperties .addInterest ("set_textureProperties__", this, true);

      const gl = this .getBrowser () .getContext ();

      this .texture = gl .createTexture ();

      this .set_textureProperties__ (false);
   },
   set_textureProperties__ (update)
   {
      if (this .texturePropertiesNode)
         this .texturePropertiesNode .removeInterest ("updateTextureParameters", this);

      this .texturePropertiesNode = Base_X3DCast (Base_X3DConstants .TextureProperties, this ._textureProperties);

      if (! this .texturePropertiesNode)
         this .texturePropertiesNode = this .getBrowser () .getDefaultTextureProperties ();

      this .texturePropertiesNode .addInterest ("updateTextureParameters", this);

      if (update)
         this .updateTextureParameters ();
   },
   getCount ()
   {
      return 1;
   },
   getTexture ()
   {
      return this .texture;
   },
   updateTextureParameters: (() =>
   {
      // Anisotropic Filtering in WebGL is handled by an extension, use one of getExtension depending on browser:

      const ANISOTROPIC_EXT = [
         "EXT_texture_filter_anisotropic",
         "MOZ_EXT_texture_filter_anisotropic",
         "WEBKIT_EXT_texture_filter_anisotropic",
      ];

      return function (target, haveTextureProperties, textureProperties, width, height, repeatS, repeatT, repeatR)
      {
         const gl = this .getBrowser () .getContext ();

         gl .bindTexture (target, this .getTexture ());

         if (Math .max (width, height) < this .getBrowser () .getMinTextureSize () && ! haveTextureProperties)
         {
            // Don't generate MipMaps.
            gl .texParameteri (target, gl .TEXTURE_MIN_FILTER, gl .NEAREST);
            gl .texParameteri (target, gl .TEXTURE_MAG_FILTER, gl .NEAREST);
         }
         else
         {
            if (textureProperties ._generateMipMaps .getValue ())
               gl .generateMipmap (target);

            gl .texParameteri (target, gl .TEXTURE_MIN_FILTER, gl [textureProperties .getMinificationFilter ()]);
            gl .texParameteri (target, gl .TEXTURE_MAG_FILTER, gl [textureProperties .getMagnificationFilter ()]);
         }

         if (haveTextureProperties)
         {
            gl .texParameteri (target, gl .TEXTURE_WRAP_S, gl [textureProperties .getBoundaryModeS ()]);
            gl .texParameteri (target, gl .TEXTURE_WRAP_T, gl [textureProperties .getBoundaryModeT ()]);

            if (gl .getVersion () >= 2)
               gl .texParameteri (target, gl .TEXTURE_WRAP_R, gl [textureProperties .getBoundaryModeR ()]);
         }
         else
         {
            gl .texParameteri (target, gl .TEXTURE_WRAP_S, repeatS ? gl .REPEAT : gl .CLAMP_TO_EDGE);
            gl .texParameteri (target, gl .TEXTURE_WRAP_T, repeatT ? gl .REPEAT : gl .CLAMP_TO_EDGE);

            if (gl .getVersion () >= 2)
               gl .texParameteri (target, gl .TEXTURE_WRAP_R, repeatR ? gl .REPEAT : gl .CLAMP_TO_EDGE);
         }

         //gl .texParameterfv (target, gl .TEXTURE_BORDER_COLOR, textureProperties ._borderColor .getValue ());
         //gl .texParameterf  (target, gl .TEXTURE_PRIORITY,     textureProperties ._texturePriority .getValue ());

         for (const extension of ANISOTROPIC_EXT)
         {
            const ext = gl .getExtension (extension);

            if (ext)
            {
               gl .texParameterf (target, ext .TEXTURE_MAX_ANISOTROPY_EXT, textureProperties ._anisotropicDegree .getValue ());
               break;
            }
         }
      };
   })(),
   updateTextureBits (textureBits, channel = 0)
   {
      const textureType = this .getTextureType () - 1;

      textureBits .set (channel * 2 + 0, textureType & 0b01);
      textureBits .set (channel * 2 + 1, textureType & 0b10);
   },
   getShaderOptions: (() =>
   {
      const textureTypes = {
         2: "2D",
         3: "3D",
         4: "CUBE"
      };

      return function (options, channel = 0)
      {
         options .push (`X3D_TEXTURE${channel}_${textureTypes [this .getTextureType ()]}`);
      };
   })(),
});

Object .defineProperties (X3DSingleTextureNode,
{
   typeName:
   {
      value: "X3DSingleTextureNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Texturing",
      enumerable: true,
   },
});

const X3DSingleTextureNode_default_ = X3DSingleTextureNode;
;

x_ite_Namespace .add ("X3DSingleTextureNode", "x_ite/Components/Texturing/X3DSingleTextureNode", X3DSingleTextureNode_default_);
/* harmony default export */ const Texturing_X3DSingleTextureNode = (X3DSingleTextureNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing/X3DTexture2DNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




const defaultData = new Uint8Array ([ 255, 255, 255, 255 ]);

function X3DTexture2DNode (executionContext)
{
   Texturing_X3DSingleTextureNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DTexture2DNode);

   const gl = this .getBrowser () .getContext ();

   this .target = gl .TEXTURE_2D;
   this .width  = 0;
   this .height = 0;
}

Object .assign (Object .setPrototypeOf (X3DTexture2DNode .prototype, Texturing_X3DSingleTextureNode .prototype),
{
   initialize ()
   {
      Texturing_X3DSingleTextureNode .prototype .initialize .call (this);

      this ._repeatS .addInterest ("updateTextureParameters", this);
      this ._repeatT .addInterest ("updateTextureParameters", this);

      const gl = this .getBrowser () .getContext ();

      gl .bindTexture (gl .TEXTURE_2D, this .getTexture ());
      gl .texImage2D  (gl .TEXTURE_2D, 0, gl .RGBA, 1, 1, 0, gl .RGBA, gl .UNSIGNED_BYTE, defaultData);
   },
   getTarget ()
   {
      return this .target;
   },
   getTextureType ()
   {
      return 2;
   },
   getTextureTypeString ()
   {
      return "2D";
   },
   getWidth ()
   {
      return this .width;
   },
   getHeight ()
   {
      return this .height;
   },
   clearTexture ()
   {
      this .setTexture (1, 1, false, defaultData, false);
   },
   setTexture (width, height, transparent, data, flipY)
   {
      this .width  = width;
      this .height = height;

      const gl = this .getBrowser () .getContext ();

      gl .bindTexture (gl .TEXTURE_2D, this .getTexture ());
      gl .pixelStorei (gl .UNPACK_FLIP_Y_WEBGL, flipY);
      //gl .pixelStorei (gl .UNPACK_COLORSPACE_CONVERSION_WEBGL, colorspace ? gl .BROWSER_DEFAULT_WEBGL : gl .NONE);
      gl .texImage2D  (gl .TEXTURE_2D, 0, gl .RGBA, width, height, 0, gl .RGBA, gl .UNSIGNED_BYTE, data);
      gl .pixelStorei (gl .UNPACK_FLIP_Y_WEBGL, false);
      //gl .pixelStorei (gl .UNPACK_COLORSPACE_CONVERSION_WEBGL, gl .BROWSER_DEFAULT_WEBGL);

      this .setTransparent (transparent);
      this .updateTextureParameters ();
      this .addNodeEvent ();
   },
   updateTexture (data, flipY)
   {
      const gl = this .getBrowser () .getContext ();

      gl .bindTexture (gl .TEXTURE_2D, this .getTexture ());
      gl .pixelStorei (gl .UNPACK_FLIP_Y_WEBGL, flipY);
      gl .texSubImage2D (gl .TEXTURE_2D, 0, 0, 0, gl .RGBA, gl .UNSIGNED_BYTE, data);
      gl .pixelStorei (gl .UNPACK_FLIP_Y_WEBGL, false);

      if (this .texturePropertiesNode ._generateMipMaps .getValue ())
         gl .generateMipmap (gl .TEXTURE_2D);

      this .addNodeEvent ();
   },
   updateTextureParameters ()
   {
      Texturing_X3DSingleTextureNode .prototype .updateTextureParameters .call (this,
                                                                      this .target,
                                                                      this ._textureProperties .getValue (),
                                                                      this .texturePropertiesNode,
                                                                      this .width,
                                                                      this .height,
                                                                      this ._repeatS .getValue (),
                                                                      this ._repeatT .getValue (),
                                                                      false);
   },
   setShaderUniforms (gl, shaderObject, renderObject, channel = shaderObject .x3d_Texture [0])
   {
      const textureUnit = this .getBrowser () .getTexture2DUnit ();

      gl .activeTexture (gl .TEXTURE0 + textureUnit);
      gl .bindTexture (gl .TEXTURE_2D, this .getTexture ());
      gl .uniform1i (channel .texture2D, textureUnit);
   },
});

Object .defineProperties (X3DTexture2DNode,
{
   typeName:
   {
      value: "X3DTexture2DNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Texturing",
      enumerable: true,
   },
});

const X3DTexture2DNode_default_ = X3DTexture2DNode;
;

x_ite_Namespace .add ("X3DTexture2DNode", "x_ite/Components/Texturing/X3DTexture2DNode", X3DTexture2DNode_default_);
/* harmony default export */ const Texturing_X3DTexture2DNode = (X3DTexture2DNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing/ImageTexture.js
/* provided dependency */ var ImageTexture_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










function ImageTexture (executionContext)
{
   Texturing_X3DTexture2DNode .call (this, executionContext);
   Networking_X3DUrlObject     .call (this, executionContext);

   this .addType (Base_X3DConstants .ImageTexture);

   this .image    = ImageTexture_$("<img></img>");
   this .urlStack = new x_ite_Fields .MFString ();
}

Object .assign (Object .setPrototypeOf (ImageTexture .prototype, Texturing_X3DTexture2DNode .prototype),
   Networking_X3DUrlObject .prototype,
{
   initialize ()
   {
      Texturing_X3DTexture2DNode .prototype .initialize .call (this);
      Networking_X3DUrlObject     .prototype .initialize .call (this);

      this ._colorSpaceConversion .addInterest ("loadNow", this);

      this .image .on ("load",        this .setImage .bind (this));
      this .image .on ("abort error", this .setError .bind (this));
      this .image .prop ("crossOrigin", "Anonymous");

      this .requestImmediateLoad () .catch (Function .prototype);
   },
   getElement ()
   {
      return this .image [0];
   },
   unloadData ()
   {
      this .clearTexture ();
   },
   loadData ()
   {
      this .urlStack .setValue (this ._url);
      this .loadNext ();
   },
   loadNext ()
   {
      if (this .urlStack .length === 0)
      {
         this .clearTexture ();
         this .setLoadState (Base_X3DConstants .FAILED_STATE);
         return;
      }

      // Get URL.

      this .URL = new URL (this .urlStack .shift (), this .getExecutionContext () .getBaseURL ());

      if (this .URL .protocol !== "data:")
      {
         if (!this .getCache ())
            this .URL .searchParams .set ("_", Date .now ());
      }

      this .image .attr ("src", this .URL .href);
   },
   setError (event)
   {
      if (this .URL .protocol !== "data:")
         console .warn (`Error loading image '${decodeURI (this .URL .href)}'`, event .type);

      this .loadNext ();
   },
   setImage: async function ()
   {
      if (DEVELOPMENT)
      {
         if (this .URL .protocol !== "data:")
            console .info (`Done loading image '${decodeURI (this .URL .href)}'`);
      }

      try
      {
         const
            gl    = this .getBrowser () .getContext (),
            image = this .image [0];

         // https://developer.mozilla.org/en-US/docs/Web/API/createImageBitmap
         // createImageBitmap

         if (gl .getVersion () === 1 && !(Math_Algorithm .isPowerOfTwo (image .width) && Math_Algorithm .isPowerOfTwo (image .height)))
         {
            const
               canvas = document .createElement ("canvas"),
               cx     = canvas .getContext ("2d", { willReadFrequently: true }),
               width  = Math_Algorithm .nextPowerOfTwo (image .width),
               height = Math_Algorithm .nextPowerOfTwo (image .height);

            // Flip Y and scale image to next power of two if needed.

            canvas .width  = width;
            canvas .height = height;

            cx .clearRect (0, 0, width, height);
            cx .save ();

            // Flip vertically.
            cx .translate (0, height);
            cx .scale (1, -1);

            cx .drawImage (image, 0, 0, image .width, image .height, 0, 0, width, height);
            cx .restore ();

            // Determine image alpha.

            const
               data        = cx .getImageData (0, 0, width, height) .data,
               transparent = this .isImageTransparent (data);

            // Upload image to GPU.

            this .setTexture (width, height, transparent, data, false);
            this .setLoadState (Base_X3DConstants .COMPLETE_STATE);
         }
         else
         {
            const
               data        = await this .getImageData (image, this ._colorSpaceConversion .getValue ()),
               transparent = this .isImageTransparent (data),
               width       = image .width,
               height      = image .height;

            // Flip vertically.

            this .flipImage (data, width, height, 4);

            // Upload image to GPU.

            this .setTexture (width, height, transparent, data, false);
            this .setLoadState (Base_X3DConstants .COMPLETE_STATE);
         }
      }
      catch (error)
      {
         // Catch security error from cross origin requests.
         this .setError ({ type: error .message });
      }
   },
   getImageData: async function (image, colorSpaceConversion = true)
   {
      const
         gl          = this .getBrowser () .getContext (),
         framebuffer = gl .createFramebuffer (),
         texture     = gl .createTexture (),
         data        = new Uint8Array (image .width * image .height * 4);

      gl .bindFramebuffer (gl .FRAMEBUFFER, framebuffer);
      gl .bindTexture (gl .TEXTURE_2D, texture);
      gl .pixelStorei (gl .UNPACK_COLORSPACE_CONVERSION_WEBGL, colorSpaceConversion ? gl .BROWSER_DEFAULT_WEBGL : gl .NONE);
      gl .texImage2D (gl .TEXTURE_2D, 0, gl .RGBA, gl .RGBA, gl .UNSIGNED_BYTE, image);
      gl .pixelStorei (gl .UNPACK_COLORSPACE_CONVERSION_WEBGL, gl .BROWSER_DEFAULT_WEBGL);
      gl .framebufferTexture2D (gl .FRAMEBUFFER, gl .COLOR_ATTACHMENT0, gl .TEXTURE_2D, texture, 0);
      await gl .readPixelsAsync (0, 0, image .width, image .height, gl .RGBA, gl .UNSIGNED_BYTE, data);
      gl .deleteFramebuffer (framebuffer);
      gl .deleteTexture (texture);

      return data;
   },
   isImageTransparent (data)
   {
      for (let i = 3, length = data .length; i < length; i += 4)
      {
         if (data [i] !== 255)
            return true;
      }

      return false;
   },
   flipImage (data, width, height, components)
   {
      const
         height1_2   = height >>> 1,
         bytesPerRow = width * components,
         tmp         = new Uint8Array (bytesPerRow);

      for (let y = 0; y < height1_2; ++ y)
      {
         const
            top    = y * bytesPerRow,
            bottom = (height - y - 1) * bytesPerRow;

         tmp .set (data .subarray (top, top + bytesPerRow));
         data .copyWithin (top, bottom, bottom + bytesPerRow);
         data .set (tmp, bottom);
      }

      return data;
   },
   dispose ()
   {
      Networking_X3DUrlObject     .prototype .dispose .call (this);
      Texturing_X3DTexture2DNode .prototype .dispose .call (this);
   },
});

Object .defineProperties (ImageTexture,
{
   typeName:
   {
      value: "ImageTexture",
      enumerable: true,
   },
   componentName:
   {
      value: "Texturing",
      enumerable: true,
   },
   containerField:
   {
      value: "texture",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "description",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "load",                 new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "url",                  new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "autoRefresh",          new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "autoRefreshTimeLimit", new x_ite_Fields .SFTime (3600)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "colorSpaceConversion", new x_ite_Fields .SFBool (true)), // experimental
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "repeatS",              new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "repeatT",              new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "textureProperties",    new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const ImageTexture_default_ = ImageTexture;
;

x_ite_Namespace .add ("ImageTexture", "x_ite/Components/Texturing/ImageTexture", ImageTexture_default_);
/* harmony default export */ const Texturing_ImageTexture = (ImageTexture_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/EnvironmentalEffects/Background.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function Background (executionContext)
{
   EnvironmentalEffects_X3DBackgroundNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Background);
}

Object .assign (Object .setPrototypeOf (Background .prototype, EnvironmentalEffects_X3DBackgroundNode .prototype),
{
   initialize ()
   {
      EnvironmentalEffects_X3DBackgroundNode .prototype .initialize .call (this);

      const
         frontTexture      = new Texturing_ImageTexture (this .getExecutionContext ()),
         backTexture       = new Texturing_ImageTexture (this .getExecutionContext ()),
         leftTexture       = new Texturing_ImageTexture (this .getExecutionContext ()),
         rightTexture      = new Texturing_ImageTexture (this .getExecutionContext ()),
         topTexture        = new Texturing_ImageTexture (this .getExecutionContext ()),
         bottomTexture     = new Texturing_ImageTexture (this .getExecutionContext ()),
         textureProperties = this .getBrowser () .getBackgroundTextureProperties ();

      this ._frontUrl  .addFieldInterest (frontTexture  ._url);
      this ._backUrl   .addFieldInterest (backTexture   ._url);
      this ._leftUrl   .addFieldInterest (leftTexture   ._url);
      this ._rightUrl  .addFieldInterest (rightTexture  ._url);
      this ._topUrl    .addFieldInterest (topTexture    ._url);
      this ._bottomUrl .addFieldInterest (bottomTexture ._url);

      frontTexture  ._url = this ._frontUrl;
      backTexture   ._url = this ._backUrl;
      leftTexture   ._url = this ._leftUrl;
      rightTexture  ._url = this ._rightUrl;
      topTexture    ._url = this ._topUrl;
      bottomTexture ._url = this ._bottomUrl;

      frontTexture  ._textureProperties = textureProperties;
      backTexture   ._textureProperties = textureProperties;
      leftTexture   ._textureProperties = textureProperties;
      rightTexture  ._textureProperties = textureProperties;
      topTexture    ._textureProperties = textureProperties;
      bottomTexture ._textureProperties = textureProperties;

      frontTexture  .setup ();
      backTexture   .setup ();
      leftTexture   .setup ();
      rightTexture  .setup ();
      topTexture    .setup ();
      bottomTexture .setup ();

      this .set_texture__ (frontTexture,  0);
      this .set_texture__ (backTexture,   1);
      this .set_texture__ (leftTexture,   2);
      this .set_texture__ (rightTexture,  3);
      this .set_texture__ (topTexture,    4);
      this .set_texture__ (bottomTexture, 5);
   }
});

Object .defineProperties (Background,
{
   typeName:
   {
      value: "Background",
      enumerable: true,
   },
   componentName:
   {
      value: "EnvironmentalEffects",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",     new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_bind",     new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "frontUrl",     new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "backUrl",      new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "leftUrl",      new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "rightUrl",     new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "topUrl",       new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "bottomUrl",    new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "skyAngle",     new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "skyColor",     new x_ite_Fields .MFColor (new x_ite_Fields .SFColor ())),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "groundAngle",  new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "groundColor",  new x_ite_Fields .MFColor ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "transparency", new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isBound",      new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "bindTime",     new x_ite_Fields .SFTime ()),
      ]),
      enumerable: true,
   },
});

const Background_default_ = Background;
;

x_ite_Namespace .add ("Background", "x_ite/Components/EnvironmentalEffects/Background", Background_default_);
/* harmony default export */ const EnvironmentalEffects_Background = (Background_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Layering/X3DLayerNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/
















function X3DLayerNode (executionContext, defaultViewpoint, groupNode)
{
   Core_X3DNode         .call (this, executionContext);
   Rendering_X3DRenderObject .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DLayerNode);

   this .addChildObjects (Base_X3DConstants .inputOutput, "hidden",  new x_ite_Fields .SFBool (),
                          Base_X3DConstants .outputOnly,  "display", new x_ite_Fields .SFBool (true));

   if (executionContext .getSpecificationVersion () <= 3.3)
      this .addAlias ("isPickable", this ._pickable);

   this .groupNode    = groupNode;
   this .viewportNode = null;

   this .defaultNavigationInfo = new Navigation_NavigationInfo (executionContext);
   this .defaultViewpoint      = defaultViewpoint;
   this .defaultBackground     = new EnvironmentalEffects_Background (executionContext);
   this .defaultFog            = new EnvironmentalEffects_Fog (executionContext);

   this .navigationInfoStack = new Execution_BindableStack (executionContext, this .defaultNavigationInfo);
   this .viewpointStack      = new Execution_BindableStack (executionContext, this .defaultViewpoint);
   this .backgroundStack     = new Execution_BindableStack (executionContext, this .defaultBackground);
   this .fogStack            = new Execution_BindableStack (executionContext, this .defaultFog);

   this .navigationInfos = new Execution_BindableList (executionContext, this .defaultNavigationInfo);
   this .viewpoints      = new Execution_BindableList (executionContext, this .defaultViewpoint);
   this .backgrounds     = new Execution_BindableList (executionContext, this .defaultBackground);
   this .fogs            = new Execution_BindableList (executionContext, this .defaultFog);

   this .defaultBackground .setHidden (true);
   this .defaultFog        .setHidden (true);
}

Object .assign (Object .setPrototypeOf (X3DLayerNode .prototype, Core_X3DNode .prototype),
   Rendering_X3DRenderObject .prototype,
{
   layer0: false,
   initialize ()
   {
      Core_X3DNode         .prototype .initialize .call (this);
      Rendering_X3DRenderObject .prototype .initialize .call (this);

      this .defaultNavigationInfo .setup ();
      this .defaultViewpoint      .setup ();
      this .defaultBackground     .setup ();
      this .defaultFog            .setup ();

      this .navigationInfoStack .setup ();
      this .viewpointStack      .setup ();
      this .backgroundStack     .setup ();
      this .fogStack            .setup ();

      this .navigationInfos .setup ();
      this .viewpoints      .setup ();
      this .backgrounds     .setup ();
      this .fogs            .setup ();

      this ._hidden   .addInterest ("set_visible_and_hidden__", this);
      this ._visible  .addInterest ("set_visible_and_hidden__", this);
      this ._viewport .addInterest ("set_viewport__",           this);

      this .set_visible_and_hidden__ ();
      this .set_viewport__ ();
   },
   isHidden ()
   {
      return this ._hidden .getValue ();
   },
   setHidden (value)
   {
      if (value === this ._hidden .getValue ())
         return;

      this ._hidden = value;
   },
   getBBox (bbox, shadows)
   {
      return this .groupNode .getBBox (bbox, shadows);
   },
   setLayer0 (value)
   {
      this .layer0 = value;
      this .defaultBackground .setHidden (!value);
   },
   getLayer ()
   {
      return this;
   },
   getGroup ()
   {
      return this .groupNode;
   },
   getViewport ()
   {
      return this .viewportNode;
   },
   getBackground ()
   {
      return this .backgroundStack .top ();
   },
   getFog ()
   {
      return this .fogStack .top ();
   },
   getNavigationInfo ()
   {
      return this .navigationInfoStack .top ();
   },
   getViewpoint ()
   {
      return this .viewpointStack .top ();
   },
   getBackgrounds ()
   {
      return this .backgrounds;
   },
   getFogs ()
   {
      return this .fogs;
   },
   getNavigationInfos ()
   {
      return this .navigationInfos;
   },
   getViewpoints ()
   {
      return this .viewpoints;
   },
   getUserViewpoints ()
   {
      const userViewpoints = [ ];

      for (const viewpointNode of this .viewpoints .get ())
      {
         if (viewpointNode ._description .length)
            userViewpoints .push (viewpointNode);
      }

      return userViewpoints;
   },
   getBackgroundStack ()
   {
      return this .backgroundStack;
   },
   getFogStack ()
   {
      return this .fogStack;
   },
   getNavigationInfoStack ()
   {
      return this .navigationInfoStack;
   },
   getViewpointStack ()
   {
      return this .viewpointStack;
   },
   getCollisionTime ()
   {
      return this .collisionTime;
   },
   viewAll (transitionTime = 1, factor = 1, straighten = false)
   {
      const
         viewpointNode = this .getViewpoint (),
         bbox          = this .getBBox (new Geometry_Box3 ()) .multRight (viewpointNode .getModelMatrix () .copy () .inverse ());

      viewpointNode .lookAt (this, bbox .center, viewpointNode .getLookAtDistance (bbox), transitionTime, factor, straighten);
   },
   straightenView ()
   {
      this .getViewpoint () .straightenView (this);
   },
   set_visible_and_hidden__ ()
   {
      const value = this ._visible .getValue () && !this ._hidden .getValue ();

      if (value === this ._display .getValue ())
         return;

      this ._display = value;
   },
   set_viewport__ ()
   {
      this .viewportNode = Base_X3DCast (Base_X3DConstants .X3DViewportNode, this ._viewport);

      if (!this .viewportNode)
         this .viewportNode = this .getBrowser () .getDefaultViewport ();
   },
   bindBindables (viewpointName)
   {
      this .traverse (Rendering_TraverseType .CAMERA, this);

      // Bind first viewpoint in viewpoint list.

      const
         navigationInfoNode = this .navigationInfos .getBound (),
         backgroundNode     = this .backgrounds     .getBound (),
         fogNode            = this .fogs            .getBound (),
         viewpointNode      = this .viewpoints      .getBound (viewpointName);

      this .navigationInfoStack .pushOnTop (navigationInfoNode);
      this .viewpointStack      .pushOnTop (viewpointNode);
      this .backgroundStack     .pushOnTop (backgroundNode);
      this .fogStack            .pushOnTop (fogNode);

      viewpointNode .resetUserOffsets ();

      if (viewpointNode ._viewAll .getValue ())
         viewpointNode .viewAll (this .getBBox (new Geometry_Box3 ()));
   },
   traverse (type, renderObject = this)
   {
      const viewpointNode = this .getViewpoint ();

      this .getProjectionMatrix ()  .pushMatrix (viewpointNode .getProjectionMatrix (this));
      this .getCameraSpaceMatrix () .pushMatrix (viewpointNode .getCameraSpaceMatrix ());
      this .getViewMatrix ()        .pushMatrix (viewpointNode .getViewMatrix ());

      switch (type)
      {
         case Rendering_TraverseType .POINTER:
            this .pointer (type, renderObject);
            break;
         case Rendering_TraverseType .CAMERA:
            this .camera (type, renderObject);
            break;
         case Rendering_TraverseType .PICKING:
            this .picking (type, renderObject);
            break;
         case Rendering_TraverseType .COLLISION:
            this .collision (type, renderObject);
            break;
         case Rendering_TraverseType .SHADOW:
         case Rendering_TraverseType .DISPLAY:
            this .display (type, renderObject);
            break;
      }

      this .getViewMatrix ()        .pop ();
      this .getCameraSpaceMatrix () .pop ();
      this .getProjectionMatrix ()  .pop ();
   },
   pointer (type, renderObject)
   {
      const
         browser  = this .getBrowser (),
         viewport = this .viewportNode .getRectangle ();

      if (browser .getPointingLayer ())
      {
         if (browser .getPointingLayer () !== this)
            return;
      }
      else
      {
         if (!browser .isPointerInRectangle (viewport))
            return;
      }

      this .setHitRay (this .getProjectionMatrix () .get (), viewport, browser .getPointer ());
      this .getNavigationInfo () .enable (type, renderObject);
      this .getModelViewMatrix () .pushMatrix (this .getViewMatrix () .get ());

      this .viewportNode .push (this);
      renderObject .render (type, this .groupNode .traverse, this .groupNode);
      this .viewportNode .pop (this);

      this .getModelViewMatrix () .pop ();
   },
   camera (type, renderObject)
   {
      if (this ._display .getValue ())
      {
         this .getModelViewMatrix () .pushMatrix (Numbers_Matrix4 .Identity);

         this .viewportNode .push (this);
         this .groupNode .traverse (type, renderObject);
         this .viewportNode .pop (this);

         this .getModelViewMatrix () .pop ();

         this .navigationInfos .update (this, this .navigationInfoStack);
         this .viewpoints      .update (this, this .viewpointStack);
         this .backgrounds     .update (this, this .backgroundStack);
         this .fogs            .update (this, this .fogStack);

         this .getViewpoint () .update ();
      }
   },
   picking (type, renderObject)
   {
      if (this ._pickable .getValue ())
      {
         this .getModelViewMatrix () .pushMatrix (Numbers_Matrix4 .Identity);

         this .viewportNode .push (this);
         this .groupNode .traverse (type, renderObject);
         this .viewportNode .pop (this);

         this .getModelViewMatrix () .pop ();
      }
   },
   collision: (() =>
   {
      const projectionMatrix = new Numbers_Matrix4 ();

      return function (type, renderObject)
      {
         if (this ._display .getValue ())
         {
            const navigationInfo = this .getNavigationInfo ();

            if (navigationInfo ._transitionActive .getValue ())
               return;

            const
               collisionRadius = navigationInfo .getCollisionRadius (),
               avatarHeight    = navigationInfo .getAvatarHeight (),
               size            = Math .max (collisionRadius * 2, avatarHeight * 2);

            Geometry_Camera .ortho (-size, size, -size, size, -size, size, projectionMatrix);

            this .getProjectionMatrix () .pushMatrix (projectionMatrix);
            this .getModelViewMatrix  () .pushMatrix (this .getViewMatrix () .get ());

            // Render
            this .viewportNode .push (this);
            renderObject .render (type, this .groupNode .traverse, this .groupNode);
            this .viewportNode .pop (this);

            this .getModelViewMatrix  () .pop ();
            this .getProjectionMatrix () .pop ();
         }
      };
   })(),
   display (type, renderObject)
   {
      if (this ._display .getValue ())
      {
         this .getNavigationInfo () .enable (type, renderObject);
         this .getModelViewMatrix () .pushMatrix (this .getViewMatrix () .get ());

         this .viewportNode .push (this);
         renderObject .render (type, this .groupNode .traverse, this .groupNode);
         this .viewportNode .pop (this);

         this .getModelViewMatrix () .pop ();
      }
   },
});

Object .defineProperties (X3DLayerNode,
{
   typeName:
   {
      value: "X3DLayerNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Layering",
      enumerable: true,
   },
});

const X3DLayerNode_default_ = X3DLayerNode;
;

x_ite_Namespace .add ("X3DLayerNode", "x_ite/Components/Layering/X3DLayerNode", X3DLayerNode_default_);
/* harmony default export */ const Layering_X3DLayerNode = (X3DLayerNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Core/X3DSensorNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function X3DSensorNode (executionContext)
{
   Core_X3DChildNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DSensorNode);
}

Object .setPrototypeOf (X3DSensorNode .prototype, Core_X3DChildNode .prototype);

Object .defineProperties (X3DSensorNode,
{
   typeName:
   {
      value: "X3DSensorNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Core",
      enumerable: true,
   },
});

const X3DSensorNode_default_ = X3DSensorNode;
;

x_ite_Namespace .add ("X3DSensorNode", "x_ite/Components/Core/X3DSensorNode", X3DSensorNode_default_);
/* harmony default export */ const Core_X3DSensorNode = (X3DSensorNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Time/X3DTimeDependentNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function X3DTimeDependentNode (executionContext)
{
   this .addType (Base_X3DConstants .X3DTimeDependentNode);

   this .addChildObjects (Base_X3DConstants .outputOnly,  "initialized", new x_ite_Fields .SFTime (),
                          Base_X3DConstants .inputOutput, "isEvenLive",  new x_ite_Fields .SFBool ());

   this .startTimeValue  = 0;
   this .pauseTimeValue  = 0;
   this .resumeTimeValue = 0;
   this .stopTimeValue   = 0;
   this .start           = 0;
   this .pause           = 0;
   this .pauseInterval   = 0;
   this .timeouts        = new Map ();
   this .disabled        = false;
}

Object .assign (Object .setPrototypeOf (X3DTimeDependentNode .prototype, Core_X3DChildNode .prototype),
{
   initialize ()
   {
      this .getLive ()  .addInterest ("set_live__", this);
      this ._isEvenLive .addInterest ("set_live__", this);

      this ._initialized .addInterest ("set_loop__",       this);
      this ._enabled     .addInterest ("set_enabled__",    this);
      this ._loop        .addInterest ("set_loop__",       this);
      this ._startTime   .addInterest ("set_startTime__",  this);
      this ._pauseTime   .addInterest ("set_pauseTime__",  this);
      this ._resumeTime  .addInterest ("set_resumeTime__", this);
      this ._stopTime    .addInterest ("set_stopTime__",   this);

      this .startTimeValue  = this ._startTime  .getValue ();
      this .pauseTimeValue  = this ._pauseTime  .getValue ();
      this .resumeTimeValue = this ._resumeTime .getValue ();
      this .stopTimeValue   = this ._stopTime   .getValue ();

      this ._initialized = this .getBrowser () .getCurrentTime ();
   },
   getLiveState ()
   {
      ///  Determines the live state of this node.

      return this .isLive () && (this .getExecutionContext () .getLive () .getValue () || this ._isEvenLive .getValue ());
   },
   getElapsedTime ()
   {
      return this .getBrowser () .getCurrentTime () - this .start - this .pauseInterval;
   },
   resetElapsedTime ()
   {
      this .start         = this .getBrowser () .getCurrentTime ();
      this .pause         = this .getBrowser () .getCurrentTime ();
      this .pauseInterval = 0;
   },
   set_live__ ()
   {
      if (this .getLive () .getValue () || this ._isEvenLive .getValue ())
      {
         if (this .disabled)
         {
            this .disabled = false;

            if (this ._isActive .getValue () && !this ._isPaused .getValue ())
               this .real_resume ();
         }
      }
      else
      {
         if (!this .disabled && this ._isActive .getValue () && !this ._isPaused .getValue ())
         {
            // Only disable if needed, ie. if running!
            this .disabled = true;
            this .real_pause ();
         }
      }
   },
   set_enabled__ ()
   {
      if (this ._enabled .getValue ())
         this .set_loop__ ();

      else
         this .stop ();
   },
   set_loop__ ()
   {
      if (this ._enabled .getValue ())
      {
         if (this ._loop .getValue ())
         {
            if (this .stopTimeValue <= this .startTimeValue)
            {
               if (this .startTimeValue <= this .getBrowser () .getCurrentTime ())
                  this .do_start ();
            }
         }
      }

      this .set_loop ();
   },
   set_startTime__ ()
   {
      this .startTimeValue = this ._startTime .getValue ();

      if (this ._enabled .getValue ())
      {
         this .removeTimeout ("start");

         if (this .startTimeValue <= this .getBrowser () .getCurrentTime ())
            this .do_start ();

         else
            this .addTimeout ("start", "do_start", this .startTimeValue);
      }
   },
   set_pauseTime__ ()
   {
      this .pauseTimeValue = this ._pauseTime .getValue ();

      if (this ._enabled .getValue ())
      {
         this .removeTimeout ("pause");

         if (this .pauseTimeValue <= this .resumeTimeValue)
            return;

         if (this .pauseTimeValue <= this .getBrowser () .getCurrentTime ())
            this .do_pause ();

         else
            this .addTimeout ("pause", "do_pause", this .pauseTimeValue);
      }
   },
   set_resumeTime__ ()
   {
      this .resumeTimeValue = this ._resumeTime .getValue ();

      if (this ._enabled .getValue ())
      {
         this .removeTimeout ("resume");

         if (this .resumeTimeValue <= this .pauseTimeValue)
            return;

         if (this .resumeTimeValue <= this .getBrowser () .getCurrentTime ())
            this .do_resume ();

         else
            this .addTimeout ("resume", "do_resume", this .resumeTimeValue);
      }
   },
   set_stopTime__ ()
   {
      this .stopTimeValue = this ._stopTime .getValue ();

      if (this ._enabled .getValue ())
      {
         this .removeTimeout ("stop");

         if (this .stopTimeValue <= this .startTimeValue)
            return;

         if (this .stopTimeValue <= this .getBrowser () .getCurrentTime ())
            this .do_stop ();

         else
            this .addTimeout ("stop", "do_stop", this .stopTimeValue);
      }
   },
   do_start ()
   {
      if (!this ._isActive .getValue ())
      {
         this .resetElapsedTime ();

         // The event order below is very important.

         this ._isActive    = true;
         this ._elapsedTime = 0;

         this .set_start ();

         if (this .getLive () .getValue ())
         {
            this .getBrowser () .timeEvents () .addInterest ("set_time" ,this);
         }
         else
         {
            this .disabled = true;
            this .real_pause ();
         }
      }
   },
   do_pause ()
   {
      if (this ._isActive .getValue () && !this ._isPaused .getValue ())
      {
         this ._isPaused = true;

         if (this .pauseTimeValue !== this .getBrowser () .getCurrentTime ())
            this .pauseTimeValue = this .getBrowser () .getCurrentTime ();

         if (this .getLive () .getValue ())
            this .real_pause ();
      }
   },
   real_pause ()
   {
      this .pause = Date .now ();

      this .set_pause ();

      this .getBrowser () .timeEvents () .removeInterest ("set_time" ,this);
   },
   do_resume ()
   {
      if (this ._isActive .getValue () && this ._isPaused .getValue ())
      {
         this ._isPaused = false;

         if (this .resumeTimeValue !== this .getBrowser () .getCurrentTime ())
            this .resumeTimeValue = this .getBrowser () .getCurrentTime ();

         if (this .getLive () .getValue ())
            this .real_resume ();
      }
   },
   real_resume ()
   {
      const interval = (Date .now () - this .pause) / 1000;

      this .pauseInterval += interval;

      this .set_resume (interval);

      this .getBrowser () .timeEvents () .addInterest ("set_time", this);
      this .getBrowser () .addBrowserEvent ();
   },
   do_stop ()
   {
      this .stop ();
   },
   stop ()
   {
      if (this ._isActive .getValue ())
      {
         // The event order below is very important.

         this .set_stop ();

         this ._elapsedTime = this .getElapsedTime ();

         if (this ._isPaused .getValue ())
            this ._isPaused = false;

         this ._isActive = false;

         this .getBrowser () .timeEvents () .removeInterest ("set_time" ,this);
      }
   },
   addTimeout (name, callback, time)
   {
      this .removeTimeout (name);

      this .timeouts .set (name, setTimeout (this .processTimeout .bind (this, callback), (time - this .getBrowser () .getCurrentTime ()) * 1000));
   },
   removeTimeout (name)
   {
      clearTimeout (this .timeouts .get (name));

      this .timeouts .delete (name);
   },
   processTimeout (callback)
   {
      if (!this ._enabled .getValue ())
         return;

      if (!(this .getLive () .getValue () || this ._isEvenLive .getValue ()))
         return;

      this .getBrowser () .advanceTime ();

      this [callback] ();
   },
   set_loop: Function .prototype,
   set_start: Function .prototype,
   set_pause: Function .prototype,
   set_resume: Function .prototype,
   set_stop: Function .prototype,
   set_time: Function .prototype,
   dispose ()
   {
      for (const name of [... this .timeouts .keys ()])
         this .removeTimeout (name);
   },
});

Object .defineProperties (X3DTimeDependentNode,
{
   typeName:
   {
      value: "X3DTimeDependentNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Time",
      enumerable: true,
   },
});

const X3DTimeDependentNode_default_ = X3DTimeDependentNode;
;

x_ite_Namespace .add ("X3DTimeDependentNode", "x_ite/Components/Time/X3DTimeDependentNode", X3DTimeDependentNode_default_);
/* harmony default export */ const Time_X3DTimeDependentNode = (X3DTimeDependentNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Time/TimeSensor.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









function TimeSensor (executionContext)
{
   Core_X3DSensorNode        .call (this, executionContext);
   Time_X3DTimeDependentNode .call (this, executionContext);

   this .addType (Base_X3DConstants .TimeSensor);

   this .addChildObjects (Base_X3DConstants .inputOutput, "range", new x_ite_Fields .MFFloat (0, 0, 1)); // current, first, last (in fractions) - play range starting at current

   this .cycle    = 0;
   this .interval = 0;
   this .fraction = 0;
   this .first    = 0;
   this .last     = 1;
   this .scale    = 1;
}

Object .assign (Object .setPrototypeOf (TimeSensor .prototype, Core_X3DSensorNode .prototype),
   Time_X3DTimeDependentNode .prototype,
{
   initialize ()
   {
      Core_X3DSensorNode        .prototype .initialize .call (this);
      Time_X3DTimeDependentNode .prototype .initialize .call (this);

      this ._cycleInterval .addInterest ("set_cycleInterval__", this);
      this ._range         .addInterest ("set_range__",         this);
   },
   setRange (fraction, firstFraction, lastFraction, offset)
   {
      const
         currentTime   = this .getBrowser () .getCurrentTime (),
         startTime     = this ._startTime .getValue (),
         cycleInterval = this ._cycleInterval .getValue ();

      this .first    = Math_Algorithm .clamp (firstFraction, 0, 1);
      this .last     = Math_Algorithm .clamp (lastFraction, 0, 1);
      this .scale    = this .last - this .first;
      this .interval = cycleInterval * this .scale;
      this .offset   = offset && this .interval ? (currentTime - startTime) / this .interval : 0;
      this .fraction = Math_Algorithm .fract (fraction + this .offset);
      this .cycle    = currentTime - (this .fraction - this .first) * cycleInterval;
   },
   set_cycleInterval__ ()
   {
      if (!this ._isActive .getValue ())
         return;

      this .setRange (this .fraction, this ._range [1], this ._range [2], false);
   },
   set_range__ ()
   {
      if (!this ._isActive .getValue ())
         return;

      this .setRange (this ._range [0], this ._range [1], this ._range [2], false);

      if (this ._isPaused .getValue ())
         return;

      this .set_fraction (this .getBrowser () .getCurrentTime ());
   },
   set_start ()
   {
      this .setRange (this ._range [0], this ._range [1], this ._range [2], true);

      const time = this .getBrowser () .getCurrentTime ();

      this ._cycleTime        = time;
      this ._fraction_changed = this .fraction;
      this ._time             = time;
   },
   set_resume (pauseInterval)
   {
      this .setRange (this .fraction, this ._range [1], this ._range [2], false);
   },
   set_fraction (time)
   {
      this ._fraction_changed = this .fraction = this .first + (this .interval ? Math_Algorithm .fract ((time - this .cycle) / this .interval) : 0) * this .scale;
   },
   set_time ()
   {
      // The event order below is very important.

      const time = this .getBrowser () .getCurrentTime ();

      if (time - this .cycle >= this .interval)
      {
         if (this ._loop .getValue ())
         {
            if (this .interval)
            {
               this .cycle += this .interval * Math .floor ((time - this .cycle) / this .interval);

               this ._elapsedTime = this .getElapsedTime ();
               this ._cycleTime   = time;

               this .set_fraction (time);
            }
         }
         else
         {
            this ._fraction_changed = this .fraction = this .last;
            this .stop ();
         }
      }
      else
      {
         this ._elapsedTime = this .getElapsedTime ();

         this .set_fraction (time);
      }

      this ._time = time;
   },
   dispose ()
   {
      Time_X3DTimeDependentNode .prototype .dispose .call (this);
      Core_X3DSensorNode        .prototype .dispose .call (this);
   },
});

Object .defineProperties (TimeSensor,
{
   typeName:
   {
      value: "TimeSensor",
      enumerable: true,
   },
   componentName:
   {
      value: "Time",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",         new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",      new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",          new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "cycleInterval",    new x_ite_Fields .SFTime (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "loop",             new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "startTime",        new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "resumeTime",       new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pauseTime",        new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "stopTime",         new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isPaused",         new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",         new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "cycleTime",        new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "elapsedTime",      new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "fraction_changed", new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "time",             new x_ite_Fields .SFTime ()),
      ]),
      enumerable: true,
   },
});

const TimeSensor_default_ = TimeSensor;
;

x_ite_Namespace .add ("TimeSensor", "x_ite/Components/Time/TimeSensor", TimeSensor_default_);
/* harmony default export */ const Time_TimeSensor = (TimeSensor_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Interpolation/X3DInterpolatorNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function X3DInterpolatorNode (executionContext)
{
   Core_X3DChildNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DInterpolatorNode);
}

Object .assign (Object .setPrototypeOf (X3DInterpolatorNode .prototype, Core_X3DChildNode .prototype),
{
   setup ()
   {
      // If an X3DInterpolatorNode value_changed outputOnly field is read before it receives any inputs,
      // keyValue[0] is returned if keyValue is not empty. If keyValue is empty (i.e., [ ]), the initial
      // value for the respective field type is returned (EXAMPLE  (0, 0, 0) for Fields .SFVec3f);

      this .set_key__ ();

      if (this ._key .length)
         this .interpolate (0, 0, 0);

      Core_X3DChildNode .prototype .setup .call (this);
   },
   initialize ()
   {
      Core_X3DChildNode .prototype .initialize .call (this);

      this ._set_fraction .addInterest ("set_fraction__", this);
      this ._key          .addInterest ("set_key__", this);
   },
   set_fraction__ ()
   {
      const
         key      = this ._key,
         length   = key .length,
         fraction = this ._set_fraction .getValue ();

      switch (length)
      {
         case 0:
            // Interpolator nodes containing no keys in the key field shall not produce any events.
            return;
         case 1:
            return this .interpolate (0, 0, 0);
         default:
         {
            if (fraction <= key [0])
               return this .interpolate (0, 1, 0);

            const index1 = Math_Algorithm .upperBound (key, 0, length, fraction);

            if (index1 !== length)
            {
               const
                  index0 = index1 - 1,
                  weight = (fraction - key [index0]) / (key [index1] - key [index0]);

               this .interpolate (index0, index1, Math_Algorithm .clamp (weight, 0, 1));
            }
            else
               this .interpolate (length - 2, length - 1, 1);
         }
      }
   },
   set_key__ ()
   {
      this .set_keyValue__ ();
   },
   set_keyValue__ () { },
   interpolate () { },
});

Object .defineProperties (X3DInterpolatorNode,
{
   typeName:
   {
      value: "X3DInterpolatorNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Interpolation",
      enumerable: true,
   },
});

const X3DInterpolatorNode_default_ = X3DInterpolatorNode;
;

x_ite_Namespace .add ("X3DInterpolatorNode", "x_ite/Components/Interpolation/X3DInterpolatorNode", X3DInterpolatorNode_default_);
/* harmony default export */ const Interpolation_X3DInterpolatorNode = (X3DInterpolatorNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Interpolation/EaseInEaseOut.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function EaseInEaseOut (executionContext)
{
   Interpolation_X3DInterpolatorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .EaseInEaseOut);
}

Object .assign (Object .setPrototypeOf (EaseInEaseOut .prototype, Interpolation_X3DInterpolatorNode .prototype),
{
   initialize ()
   {
      Interpolation_X3DInterpolatorNode .prototype .initialize .call (this);

      this ._easeInEaseOut .addInterest ("set_keyValue__", this);
   },
   set_keyValue__ ()
   {
      if (this ._easeInEaseOut .length < this ._key .length)
         this ._easeInEaseOut .resize (this ._key .length, this ._easeInEaseOut .length ? this ._easeInEaseOut [this ._easeInEaseOut .length - 1] : new x_ite_Fields .SFVec2f ());
   },
   interpolate (index0, index1, weight)
   {
      let
         easeOut = this ._easeInEaseOut [index0] .y,
         easeIn  = this ._easeInEaseOut [index1] .x;

      const sum = easeOut + easeIn;

      if (sum < 0)
      {
         this ._modifiedFraction_changed = weight;
      }
      else
      {
         if (sum > 1)
         {
            easeIn  /= sum;
            easeOut /= sum;
         }

         const t = 1 / (2 - easeOut - easeIn);

         if (weight < easeOut)
         {
            this ._modifiedFraction_changed = (t / easeOut) * weight * weight;
         }
         else if (weight <= 1 - easeIn) // Spec says (weight < 1 - easeIn), but then we get a NaN below if easeIn == 0.
         {
            this ._modifiedFraction_changed = t * (2 * weight - easeOut);
         }
         else
         {
            const w = 1 - weight;

            this ._modifiedFraction_changed = 1 - ((t * w * w) / easeIn);
         }
      }
   },
});

Object .defineProperties (EaseInEaseOut,
{
   typeName:
   {
      value: "EaseInEaseOut",
      enumerable: true,
   },
   componentName:
   {
      value: "Interpolation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",                 new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_fraction",             new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "key",                      new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "easeInEaseOut",            new x_ite_Fields .MFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "modifiedFraction_changed", new x_ite_Fields .SFFloat ()),
      ]),
      enumerable: true,
   },
});

const EaseInEaseOut_default_ = EaseInEaseOut;
;

x_ite_Namespace .add ("EaseInEaseOut", "x_ite/Components/Interpolation/EaseInEaseOut", EaseInEaseOut_default_);
/* harmony default export */ const Interpolation_EaseInEaseOut = (EaseInEaseOut_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Interpolation/PositionInterpolator.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function PositionInterpolator (executionContext)
{
   Interpolation_X3DInterpolatorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .PositionInterpolator);
}

Object .assign (Object .setPrototypeOf (PositionInterpolator .prototype, Interpolation_X3DInterpolatorNode .prototype),
{
   initialize ()
   {
      Interpolation_X3DInterpolatorNode .prototype .initialize .call (this);

      this ._keyValue .addInterest ("set_keyValue__", this);
   },
   set_keyValue__ ()
   {
      const
         key      = this ._key,
         keyValue = this ._keyValue;

      if (keyValue .length < key .length)
         keyValue .resize (key .length, keyValue .length ? keyValue [keyValue .length - 1] : new x_ite_Fields .SFVec3f ());
   },
   interpolate: (() =>
   {
      const keyValue = new Numbers_Vector3 (0, 0, 0);

      return function (index0, index1, weight)
      {
         this ._value_changed = keyValue .assign (this ._keyValue [index0] .getValue ()) .lerp (this ._keyValue [index1] .getValue (), weight);
      };
   })(),
});

Object .defineProperties (PositionInterpolator,
{
   typeName:
   {
      value: "PositionInterpolator",
      enumerable: true,
   },
   componentName:
   {
      value: "Interpolation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",      new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_fraction",  new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "key",           new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "keyValue",      new x_ite_Fields .MFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "value_changed", new x_ite_Fields .SFVec3f ()),
      ]),
      enumerable: true,
   },
});

const PositionInterpolator_default_ = PositionInterpolator;
;

x_ite_Namespace .add ("PositionInterpolator", "x_ite/Components/Interpolation/PositionInterpolator", PositionInterpolator_default_);
/* harmony default export */ const Interpolation_PositionInterpolator = (PositionInterpolator_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Interpolation/OrientationInterpolator.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function OrientationInterpolator (executionContext)
{
   Interpolation_X3DInterpolatorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .OrientationInterpolator);

   this ._keyValue      .setUnit ("angle");
   this ._value_changed .setUnit ("angle");
}

Object .assign (Object .setPrototypeOf (OrientationInterpolator .prototype, Interpolation_X3DInterpolatorNode .prototype),
{
   initialize ()
   {
      Interpolation_X3DInterpolatorNode .prototype .initialize .call (this);

      this ._keyValue .addInterest ("set_keyValue__", this);
   },
   set_keyValue__ ()
   {
      const
         key      = this ._key,
         keyValue = this ._keyValue;

      if (keyValue .length < key .length)
         keyValue .resize (key .length, keyValue .length ? keyValue [keyValue .length - 1] : new x_ite_Fields .SFRotation ());
   },
   interpolate: (() =>
   {
      const
         keyValue0 = new Numbers_Rotation4 (),
         keyValue1 = new Numbers_Rotation4 ();

      return function (index0, index1, weight)
      {
         // Both values can change in slerp.
         keyValue0 .assign (this ._keyValue [index0] .getValue ());
         keyValue1 .assign (this ._keyValue [index1] .getValue ());

         this ._value_changed = keyValue0 .slerp (keyValue1, weight);
      };
   }) (),
});

Object .defineProperties (OrientationInterpolator,
{
   typeName:
   {
      value: "OrientationInterpolator",
      enumerable: true,
   },
   componentName:
   {
      value: "Interpolation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",      new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_fraction",  new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "key",           new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "keyValue",      new x_ite_Fields .MFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "value_changed", new x_ite_Fields .SFRotation ()),
      ]),
      enumerable: true,
   },
});

const OrientationInterpolator_default_ = OrientationInterpolator;
;

x_ite_Namespace .add ("OrientationInterpolator", "x_ite/Components/Interpolation/OrientationInterpolator", OrientationInterpolator_default_);
/* harmony default export */ const Interpolation_OrientationInterpolator = (OrientationInterpolator_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Interpolation/ScalarInterpolator.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function ScalarInterpolator (executionContext)
{
   Interpolation_X3DInterpolatorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .ScalarInterpolator);
}

Object .assign (Object .setPrototypeOf (ScalarInterpolator .prototype, Interpolation_X3DInterpolatorNode .prototype),
{
   initialize ()
   {
      Interpolation_X3DInterpolatorNode .prototype .initialize .call (this);

      this ._keyValue .addInterest ("set_keyValue__", this);
   },
   set_keyValue__ ()
   {
      const
         key      = this ._key,
         keyValue = this ._keyValue;

      if (keyValue .length < key .length)
         keyValue .resize (key .length, keyValue .length ? keyValue [keyValue .length - 1] : 0);
   },
   interpolate (index0, index1, weight)
   {
      this ._value_changed = Math_Algorithm .lerp (this ._keyValue [index0], this ._keyValue [index1], weight);
   },
});

Object .defineProperties (ScalarInterpolator,
{
   typeName:
   {
      value: "ScalarInterpolator",
      enumerable: true,
   },
   componentName:
   {
      value: "Interpolation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",      new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_fraction",  new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "key",           new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "keyValue",      new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "value_changed", new x_ite_Fields .SFFloat ()),
      ]),
      enumerable: true,
   },
});

const ScalarInterpolator_default_ = ScalarInterpolator;
;

x_ite_Namespace .add ("ScalarInterpolator", "x_ite/Components/Interpolation/ScalarInterpolator", ScalarInterpolator_default_);
/* harmony default export */ const Interpolation_ScalarInterpolator = (ScalarInterpolator_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Navigation/X3DViewpointNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

















function X3DViewpointNode (executionContext)
{
   Core_X3DBindableNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DViewpointNode);

   this .addChildObjects (Base_X3DConstants .inputOutput, "positionOffset",         new x_ite_Fields .SFVec3f (),
                          Base_X3DConstants .inputOutput, "orientationOffset",      new x_ite_Fields .SFRotation (),
                          Base_X3DConstants .inputOutput, "scaleOffset",            new x_ite_Fields .SFVec3f (1, 1, 1),
                          Base_X3DConstants .inputOutput, "scaleOrientationOffset", new x_ite_Fields .SFRotation (),
                          Base_X3DConstants .inputOutput, "centerOfRotationOffset", new x_ite_Fields .SFVec3f (),
                          Base_X3DConstants .inputOutput, "fieldOfViewScale",       new x_ite_Fields .SFFloat (1));

   this .descriptions         = [ ];
   this .userPosition         = new Numbers_Vector3 (0, 1, 0);
   this .userOrientation      = new Numbers_Rotation4 ();
   this .userCenterOfRotation = new Numbers_Vector3 (0, 0, 0);
   this .modelMatrix          = new Numbers_Matrix4 ();
   this .cameraSpaceMatrix    = new Numbers_Matrix4 (1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0,  10, 1);
   this .viewMatrix           = new Numbers_Matrix4 (1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, -10, 1);

   const browser = this .getBrowser ();

   this .timeSensor                   = new Time_TimeSensor              (browser .getPrivateScene ());
   this .easeInEaseOut                = new Interpolation_EaseInEaseOut           (browser .getPrivateScene ());
   this .positionInterpolator         = new Interpolation_PositionInterpolator    (browser .getPrivateScene ());
   this .orientationInterpolator      = new Interpolation_OrientationInterpolator (browser .getPrivateScene ());
   this .scaleInterpolator            = new Interpolation_PositionInterpolator    (browser .getPrivateScene ());
   this .scaleOrientationInterpolator = new Interpolation_OrientationInterpolator (browser .getPrivateScene ());
   this .fieldOfViewScaleInterpolator = new Interpolation_ScalarInterpolator      (browser .getPrivateScene ());
}

Object .assign (Object .setPrototypeOf (X3DViewpointNode .prototype, Core_X3DBindableNode .prototype),
{
   initialize ()
   {
      Core_X3DBindableNode .prototype .initialize .call (this);

      this .timeSensor ._stopTime = 1;
      this .timeSensor .setup ();

      this .easeInEaseOut ._key           = new x_ite_Fields .MFFloat (0, 1);
      this .easeInEaseOut ._easeInEaseOut = new x_ite_Fields .MFVec2f (new x_ite_Fields .SFVec2f (0, 0), new x_ite_Fields .SFVec2f (0, 0));
      this .easeInEaseOut .setup ();

      this .positionInterpolator         ._key = new x_ite_Fields .MFFloat (0, 1);
      this .orientationInterpolator      ._key = new x_ite_Fields .MFFloat (0, 1);
      this .scaleInterpolator            ._key = new x_ite_Fields .MFFloat (0, 1);
      this .scaleOrientationInterpolator ._key = new x_ite_Fields .MFFloat (0, 1);
      this .fieldOfViewScaleInterpolator ._key = new x_ite_Fields .MFFloat (0, 1);

      this .positionInterpolator         .setup ();
      this .orientationInterpolator      .setup ();
      this .scaleInterpolator            .setup ();
      this .scaleOrientationInterpolator .setup ();
      this .fieldOfViewScaleInterpolator .setup ();

      this .timeSensor ._fraction_changed .addFieldInterest (this .easeInEaseOut ._set_fraction);

      this .easeInEaseOut ._modifiedFraction_changed .addFieldInterest (this .positionInterpolator         ._set_fraction);
      this .easeInEaseOut ._modifiedFraction_changed .addFieldInterest (this .orientationInterpolator      ._set_fraction);
      this .easeInEaseOut ._modifiedFraction_changed .addFieldInterest (this .scaleInterpolator            ._set_fraction);
      this .easeInEaseOut ._modifiedFraction_changed .addFieldInterest (this .scaleOrientationInterpolator ._set_fraction);
      this .easeInEaseOut ._modifiedFraction_changed .addFieldInterest (this .fieldOfViewScaleInterpolator ._set_fraction);

      this .positionInterpolator         ._value_changed .addFieldInterest (this ._positionOffset);
      this .orientationInterpolator      ._value_changed .addFieldInterest (this ._orientationOffset);
      this .scaleInterpolator            ._value_changed .addFieldInterest (this ._scaleOffset);
      this .scaleOrientationInterpolator ._value_changed .addFieldInterest (this ._scaleOrientationOffset);
      this .fieldOfViewScaleInterpolator ._value_changed .addFieldInterest (this ._fieldOfViewScale);

      this ._nearDistance   .addInterest ("set_nearDistance__",   this);
      this ._farDistance    .addInterest ("set_farDistance__",    this);
      this ._viewAll        .addInterest ("set_viewAll__",        this);
      this ._navigationInfo .addInterest ("set_navigationInfo__", this);
      this ._isBound        .addInterest ("set_bound__",          this);

      this .set_nearDistance__ ();
      this .set_farDistance__ ();
      this .set_navigationInfo__ ();
   },
   set_nearDistance__ ()
   {
      const nearDistance = this ._nearDistance .getValue ();

      this .nearDistance = nearDistance >= 0 ? nearDistance : undefined;
   },
   set_farDistance__ ()
   {
      const farDistance = this ._farDistance .getValue ();

      this .farDistance = farDistance >= 0 ? farDistance : undefined;
   },
   set_viewAll__ ()
   {
      if (! this ._viewAll .getValue ())
         return;

      if (! this ._isBound .getValue ())
         return;

      this ._set_bind = true;
   },
   set_navigationInfo__ ()
   {
      if (this .navigationInfoNode)
         this ._isBound .removeFieldInterest (this .navigationInfoNode ._set_bind);

      this .navigationInfoNode = Base_X3DCast (Base_X3DConstants .NavigationInfo, this ._navigationInfo);

      if (this .navigationInfoNode)
         this ._isBound .addFieldInterest (this .navigationInfoNode ._set_bind);
   },
   set_bound__ ()
   {
      const browser = this .getBrowser ();

      if (this ._isBound .getValue ())
         browser .getNotification () ._string = this ._description;
      else
         this .timeSensor ._stopTime = browser .getCurrentTime ();
   },
   set_active__ (navigationInfoNode, active)
   {
      if (active .getValue ())
         return;

      this .timeSensor ._isActive .removeInterest ("set_active__", this);

      if (!this ._isBound .getValue ())
         return;

      if (this .timeSensor ._fraction_changed .getValue () !== 1)
         return;

      navigationInfoNode ._transitionComplete = true;
   },
   getDescriptions ()
   {
      return this .descriptions;
   },
   setInterpolators () { },
   getPosition ()
   {
      return this ._position .getValue ();
   },
   getUserPosition ()
   {
      return this .userPosition .assign (this .getPosition ()) .add (this ._positionOffset .getValue ());
   },
   getOrientation ()
   {
      return this ._orientation .getValue ();
   },
   getUserOrientation ()
   {
      return this .userOrientation .assign (this .getOrientation ()) .multRight (this ._orientationOffset .getValue ());
   },
   getCenterOfRotation ()
   {
      return this ._centerOfRotation .getValue ();
   },
   getUserCenterOfRotation ()
   {
      return this .userCenterOfRotation .assign (this .getCenterOfRotation ()) .add (this ._centerOfRotationOffset .getValue ());
   },
   getProjectionMatrix (renderObject)
   {
      const navigationInfo = renderObject .getNavigationInfo ();

      return this .getProjectionMatrixWithLimits (this .nearDistance ?? navigationInfo .getNearValue (),
                                                  this .farDistance ?? navigationInfo .getFarValue (this),
                                                  renderObject .getLayer () .getViewport () .getRectangle ());
   },
   getCameraSpaceMatrix ()
   {
      return this .cameraSpaceMatrix;
   },
   getViewMatrix ()
   {
      return this .viewMatrix;
   },
   getModelMatrix ()
   {
      return this .modelMatrix;
   },
   getMaxFarValue ()
   {
      return this .getBrowser () .getRenderingProperty ("LogarithmicDepthBuffer") ? 1e10 : 1e5;
   },
   getUpVector ()
   {
      // Local y-axis,
      // see https://www.web3d.org/documents/specifications/19775-1/V3.3/index.html#NavigationInfo.
      return Numbers_Vector3 .yAxis;
   },
   getSpeedFactor ()
   {
      return 1;
   },
   setVRMLTransition (value)
   {
      // VRML behavior support.
      this .VRMLTransition = value;
   },
   getVRMLTransition ()
   {
      // VRML behavior support.
      return this .VRMLTransition;
   },
   transitionStart (layerNode, fromViewpointNode)
   {
      if (this ._jump .getValue ())
      {
         const relative = this .getRelativeTransformation (fromViewpointNode);

         if (! this ._retainUserOffsets .getValue ())
            this .resetUserOffsets ();

         if (this ._viewAll .getValue ())
            this .viewAll (layerNode .getBBox (new Geometry_Box3 ()));

         // Handle NavigationInfo.

         const
            navigationInfoNode = layerNode .getNavigationInfo (),
            transitionTime     = navigationInfoNode ._transitionTime .getValue ();

         let transitionType = navigationInfoNode .getTransitionType ();

         // VRML behavior

         if (this .getExecutionContext () .getSpecificationVersion () == 2.0)
         {
            if (this .getVRMLTransition ())
               transitionType = "LINEAR";
            else
               transitionType = "TELEPORT";
         }

         this .setVRMLTransition (false);

         // End VRML behavior

         if (transitionTime <= 0)
            transitionType = "TELEPORT";

         if (this .constructor !== fromViewpointNode .constructor)
            transitionType = "TELEPORT";

         switch (transitionType)
         {
            case "TELEPORT":
            {
               navigationInfoNode ._transitionComplete = true;
               return;
            }
            case "ANIMATE":
            {
               this .easeInEaseOut ._easeInEaseOut = new x_ite_Fields .MFVec2f (new x_ite_Fields .SFVec2f (0, 1), new x_ite_Fields .SFVec2f (1, 0));
               break;
            }
            default:
            {
               // LINEAR
               this .easeInEaseOut ._easeInEaseOut = new x_ite_Fields .MFVec2f (new x_ite_Fields .SFVec2f (0, 0), new x_ite_Fields .SFVec2f (0, 0));
               break;
            }
         }

         navigationInfoNode ._transitionStart = true;

         this .timeSensor ._cycleInterval = transitionTime;
         this .timeSensor ._stopTime      = this .getBrowser () .getCurrentTime ();
         this .timeSensor ._startTime     = this .getBrowser () .getCurrentTime ();

         this .timeSensor ._isActive .addInterest ("set_active__", this, navigationInfoNode);

         this .positionInterpolator         ._keyValue = new x_ite_Fields .MFVec3f    (relative .position,         this ._positionOffset);
         this .orientationInterpolator      ._keyValue = new x_ite_Fields .MFRotation (relative .orientation,      this ._orientationOffset);
         this .scaleInterpolator            ._keyValue = new x_ite_Fields .MFVec3f    (relative .scale,            this ._scaleOffset);
         this .scaleOrientationInterpolator ._keyValue = new x_ite_Fields .MFRotation (relative .scaleOrientation, this ._scaleOrientationOffset);

         this ._positionOffset         = relative .position;
         this ._orientationOffset      = relative .orientation;
         this ._scaleOffset            = relative .scale;
         this ._scaleOrientationOffset = relative .scaleOrientation;

         this .setInterpolators (fromViewpointNode, relative);
      }
      else
      {
         const navigationInfoNode = layerNode .getNavigationInfo ();

         navigationInfoNode ._transitionComplete = true;

         const relative = this .getRelativeTransformation (fromViewpointNode);

         this ._positionOffset         = relative .position;
         this ._orientationOffset      = relative .orientation;
         this ._scaleOffset            = relative .scale;
         this ._scaleOrientationOffset = relative .scaleOrientation;

         this .setInterpolators (fromViewpointNode, relative);
      }
   },
   transitionStop ()
   {
      this .timeSensor ._stopTime = this .getBrowser () .getCurrentTime ();
      this .timeSensor ._isActive .removeInterest ("set_active__", this);
   },
   resetUserOffsets ()
   {
      this ._positionOffset         = Numbers_Vector3   .Zero;
      this ._orientationOffset      = Numbers_Rotation4 .Identity;
      this ._scaleOffset            = Numbers_Vector3   .One;
      this ._scaleOrientationOffset = Numbers_Rotation4 .Identity;
      this ._centerOfRotationOffset = Numbers_Vector3   .Zero;
      this ._fieldOfViewScale       = 1;

      this .set_nearDistance__ ();
      this .set_farDistance__ ();
   },
   getRelativeTransformation: (() =>
   {
      const
         position         = new Numbers_Vector3 (0, 0, 0),
         orientation      = new Numbers_Rotation4 (),
         scale            = new Numbers_Vector3 (0, 0, 0),
         scaleOrientation = new Numbers_Rotation4 ();

      return function (fromViewpointNode)
      {
         const differenceMatrix = this .modelMatrix .copy () .multRight (fromViewpointNode .getViewMatrix ()) .inverse ();

         differenceMatrix .get (position, orientation, scale, scaleOrientation);

         position .subtract (this .getPosition ());
         orientation .multLeft (this .getOrientation () .copy () .inverse ());

         return {
            position: position,
            orientation: orientation,
            scale: scale,
            scaleOrientation: scaleOrientation,
         };
      };
   })(),
   getLookAtRotation: (() =>
   {
      const
         x = new Numbers_Vector3 (0, 0, 0),
         y = new Numbers_Vector3 (0, 0, 0),
         z = new Numbers_Vector3 (0, 0, 0),
         m = new Numbers_Matrix3 (),
         r = new Numbers_Rotation4 ();

      return function (fromPoint, toPoint)
      {
         const up = this .getUpVector (true);

         z .assign (fromPoint) .subtract (toPoint) .normalize ();
         x .assign (up) .cross (z) .normalize ();
         y .assign (z) .cross (x) .normalize ();

         m .set (... x, ... y, ... z);
         r .setMatrix (m);

         return r;
      };
   })(),
   lookAtPoint (layerNode, point, transitionTime = 1, factor = 1, straighten = false)
   {
      this .getCameraSpaceMatrix () .multVecMatrix (point);
      this .getModelMatrix () .copy () .inverse () .multVecMatrix (point);

      const minDistance = layerNode .getNavigationInfo () .getNearValue () * 2;

      this .lookAt (layerNode, point, minDistance, transitionTime = 1, factor = 1, straighten = false);
   },
   lookAtBBox (layerNode, bbox, transitionTime = 1, factor, straighten)
   {
      bbox = bbox .copy () .multRight (this .getModelMatrix () .copy () .inverse ());

      const minDistance = Math .max (layerNode .getNavigationInfo () .getNearValue () * 2, this .getLookAtDistance (bbox));

      this .lookAt (layerNode, bbox .center, minDistance, transitionTime, factor, straighten);
   },
   lookAt (layerNode, point, distance, transitionTime = 1, factor = 1, straighten = false)
   {
      const
         offset = point .copy () .add (this .getUserOrientation () .multVecRot (new Numbers_Vector3 (0, 0, distance))) .subtract (this .getPosition ());

      layerNode .getNavigationInfo () ._transitionStart = true;

      this .timeSensor ._cycleInterval = transitionTime;
      this .timeSensor ._stopTime      = this .getBrowser () .getCurrentTime ();
      this .timeSensor ._startTime     = this .getBrowser () .getCurrentTime ();

      this .timeSensor ._isActive .addInterest ("set_active__", this, layerNode .getNavigationInfo ());

      this .easeInEaseOut ._easeInEaseOut = new x_ite_Fields .MFVec2f (new x_ite_Fields .SFVec2f (0, 1), new x_ite_Fields .SFVec2f (1, 0));

      const
         translation = this ._positionOffset .getValue () .copy () .lerp (offset, factor),
         direction   = this .getPosition () .copy () .add (translation) .subtract (point);

      let rotation = this ._orientationOffset .getValue () .copy () .multRight (new Numbers_Rotation4 (this .getUserOrientation () .multVecRot (new Numbers_Vector3 (0, 0, 1)), direction));

      if (straighten)
      {
         rotation = this .getOrientation () .copy () .inverse () .multRight (this .straightenHorizon (this .getOrientation () .copy () .multRight (rotation)));
      }

      this .positionInterpolator         ._keyValue = new x_ite_Fields .MFVec3f (this ._positionOffset, translation);
      this .orientationInterpolator      ._keyValue = new x_ite_Fields .MFRotation (this ._orientationOffset, rotation);
      this .scaleInterpolator            ._keyValue = new x_ite_Fields .MFVec3f (this ._scaleOffset, Numbers_Vector3 .One);
      this .scaleOrientationInterpolator ._keyValue = new x_ite_Fields .MFRotation (this ._scaleOrientationOffset, this ._scaleOrientationOffset);

      const relative = this .getRelativeTransformation (this);

      this ._fieldOfViewScale       = 1;
      this ._centerOfRotationOffset = point .copy () .subtract (this .getCenterOfRotation ());
      this .nearDistance            = Math .min (distance / 2, 0.125);
      this .farDistance             = this .nearDistance * this .getMaxFarValue () / 0.125;

      this .setInterpolators (this, relative);
   },
   straightenView (layerNode)
   {
      layerNode .getNavigationInfo () ._transitionStart = true;

      this .timeSensor ._cycleInterval = 1;
      this .timeSensor ._stopTime      = this .getBrowser () .getCurrentTime ();
      this .timeSensor ._startTime     = this .getBrowser () .getCurrentTime ();

      this .timeSensor ._isActive .addInterest ("set_active__", this, layerNode .getNavigationInfo ());

      this .easeInEaseOut ._easeInEaseOut = new x_ite_Fields .MFVec2f (new x_ite_Fields .SFVec2f (0, 1), new x_ite_Fields .SFVec2f (1, 0));

      const rotation = this .getOrientation () .copy () .inverse () .multRight (this .straightenHorizon (this .getUserOrientation ()));

      this .positionInterpolator         ._keyValue = new x_ite_Fields .MFVec3f (this ._positionOffset, this ._positionOffset);
      this .orientationInterpolator      ._keyValue = new x_ite_Fields .MFRotation (this ._orientationOffset, rotation);
      this .scaleInterpolator            ._keyValue = new x_ite_Fields .MFVec3f (this ._scaleOffset, this ._scaleOffset);
      this .scaleOrientationInterpolator ._keyValue = new x_ite_Fields .MFRotation (this ._scaleOrientationOffset, this ._scaleOrientationOffset);

      const relative = this .getRelativeTransformation (this);

      this ._fieldOfViewScale = 1;

      this .setInterpolators (this, relative);
   },
   straightenHorizon: (() =>
   {
      const
         localXAxis  = new Numbers_Vector3 (0, 0, 0),
         localZAxis  = new Numbers_Vector3 (0, 0, 0),
         rotation    = new Numbers_Rotation4 ();

      return function (orientation, upVector = this .getUpVector (true))
      {
         orientation .multVecRot (localXAxis .assign (Numbers_Vector3 .xAxis) .negate ());
         orientation .multVecRot (localZAxis .assign (Numbers_Vector3 .zAxis));

         const vector = localZAxis .cross (upVector);

         // If viewer looks along the up vector.
         if (Math .abs (localZAxis .dot (upVector)) >= 1)
            return orientation;

         if (Math .abs (vector .dot (localXAxis)) >= 1)
            return orientation;

         rotation .setFromToVec (localXAxis, vector);

         return orientation .multRight (rotation);
      };
   })(),
   viewAll (bbox)
   {
      bbox .multRight (this .modelMatrix .copy () .inverse ());

      const
         direction       = this .getUserPosition () .copy () .subtract (bbox .center) .normalize (),
         distance        = this .getLookAtDistance (bbox),
         userPosition    = bbox .center .copy () .add (direction .multiply (distance)),
         userOrientation = this .getLookAtRotation (userPosition, bbox .center);

      this ._positionOffset         = userPosition .subtract (this .getPosition ());
      this ._orientationOffset      = this .getOrientation () .copy () .inverse () .multRight (userOrientation);
      this ._centerOfRotationOffset = bbox .center .copy () .subtract (this .getCenterOfRotation ());
      this ._fieldOfViewScale       = 1;
      this .nearDistance            = Math .min ((distance - bbox .size .magnitude ()) / 2, 0.125);
      this .farDistance             = this .nearDistance * this .getMaxFarValue () / 0.125;
   },
   traverse (type, renderObject)
   {
      if (type !== Rendering_TraverseType .CAMERA)
         return;

      if (this .navigationInfoNode)
         this .navigationInfoNode .traverse (type, renderObject);

      this .descriptions .length = 0;

      if (this ._description .getValue ())
      {
         if (renderObject .getViewpointGroups () .every (viewpointGroupNode => viewpointGroupNode ._displayed .getValue ()))
         {
            for (const viewpointGroupNode of renderObject .getViewpointGroups ())
            {
               if (viewpointGroupNode ._description .getValue ())
                  this .descriptions .push (viewpointGroupNode ._description .getValue ());
            }

            this .descriptions .push (this ._description .getValue ());
         }
      }

      renderObject .getLayer () .getViewpoints () .push (this);

      this .modelMatrix .assign (renderObject .getModelViewMatrix () .get ());
   },
   update ()
   {
      this .cameraSpaceMatrix .set (this .getUserPosition (),
                                    this .getUserOrientation (),
                                    this ._scaleOffset .getValue (),
                                    this ._scaleOrientationOffset .getValue ());

      this .cameraSpaceMatrix .multRight (this .modelMatrix);

      this .viewMatrix .assign (this .cameraSpaceMatrix) .inverse ();
   }
});

Object .defineProperties (X3DViewpointNode,
{
   typeName:
   {
      value: "X3DViewpointNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Navigation",
      enumerable: true,
   },
});

const X3DViewpointNode_default_ = X3DViewpointNode;
;

x_ite_Namespace .add ("X3DViewpointNode", "x_ite/Components/Navigation/X3DViewpointNode", X3DViewpointNode_default_);
/* harmony default export */ const Navigation_X3DViewpointNode = (X3DViewpointNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Navigation/Viewpoint.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










function Viewpoint (executionContext)
{
   Navigation_X3DViewpointNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Viewpoint);

   this ._position         .setUnit ("length");
   this ._centerOfRotation .setUnit ("length");
   this ._fieldOfView      .setUnit ("angle");

   this .projectionMatrix = new Numbers_Matrix4 ();
}

Object .assign (Object .setPrototypeOf (Viewpoint .prototype, Navigation_X3DViewpointNode .prototype),
{
   getRelativeTransformation (fromViewpointNode)
   {
      const relative = Navigation_X3DViewpointNode .prototype .getRelativeTransformation .call (this, fromViewpointNode);

      if (fromViewpointNode .constructor === this .constructor)
         relative .fieldOfView = fromViewpointNode .getFieldOfView ();

      return relative;
   },
   setInterpolators (fromViewpointNode, relative)
   {
      if (fromViewpointNode .constructor === this .constructor)
      {
         const scale = relative .fieldOfView / this .getFieldOfView ();

         this .fieldOfViewScaleInterpolator ._keyValue = new x_ite_Fields .MFFloat (scale, this ._fieldOfViewScale .getValue ());

         this ._fieldOfViewScale = scale;
      }
      else
      {
         this .fieldOfViewScaleInterpolator ._keyValue = new x_ite_Fields .MFFloat (this ._fieldOfViewScale .getValue (), this ._fieldOfViewScale .getValue ());

         this ._fieldOfViewScale = this ._fieldOfViewScale .getValue ();
      }
   },
   getLogarithmicDepthBuffer ()
   {
      return false;
   },
   getFieldOfView ()
   {
      const fov = this ._fieldOfView .getValue () * this ._fieldOfViewScale .getValue ();

      return fov > 0 && fov < Math .PI ? fov : Math .PI / 4;
   },
   getScreenScale (point, viewport, screenScale)
   {
      // Returns the screen scale in meter/pixel for on pixel.

      const
         width  = viewport [2],
         height = viewport [3];

      let size = Math .abs (point .z) * Math .tan (this .getFieldOfView () / 2) * 2;

      if (width > height)
         size /= height;
      else
         size /= width;

      return screenScale .set (size, size, size);
   },
   getViewportSize: (() =>
   {
      const viewportSize = new Numbers_Vector2 (0, 0);

      return function (viewport, nearValue)
      {
         // Returns viewport size in meters.

         const
            width  = viewport [2],
            height = viewport [3],
            size   = nearValue * Math .tan (this .getFieldOfView () / 2) * 2,
            aspect = width / height;

         if (aspect > 1)
            return viewportSize .set (size * aspect, size);

         return viewportSize .set (size, size / aspect);
      };
   })(),
   getLookAtDistance (bbox)
   {
      return (bbox .size .magnitude () / 2) / Math .tan (this .getFieldOfView () / 2);
   },
   getProjectionMatrixWithLimits (nearValue, farValue, viewport)
   {
      return Geometry_Camera .perspective (this .getFieldOfView (), nearValue, farValue, viewport [2], viewport [3], this .projectionMatrix);
   },
});

Object .defineProperties (Viewpoint,
{
   typeName:
   {
      value: "Viewpoint",
      enumerable: true,
   },
   componentName:
   {
      value: "Navigation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_bind",          new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",       new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "position",          new x_ite_Fields .SFVec3f (0, 0, 10)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "orientation",       new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "centerOfRotation",  new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "fieldOfView",       new x_ite_Fields .SFFloat (0.785398)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "nearDistance",      new x_ite_Fields .SFFloat (-1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "farDistance",       new x_ite_Fields .SFFloat (-1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "viewAll",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "jump",              new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "retainUserOffsets", new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isBound",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "bindTime",          new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "navigationInfo",    new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const Viewpoint_default_ = Viewpoint;
;

x_ite_Namespace .add ("Viewpoint", "x_ite/Components/Navigation/Viewpoint", Viewpoint_default_);
/* harmony default export */ const Navigation_Viewpoint = (Viewpoint_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Grouping/X3DBoundedObject.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function X3DBoundedObject (executionContext)
{
   this .addType (Base_X3DConstants .X3DBoundedObject);

   this .addChildObjects (Base_X3DConstants .inputOutput, "hidden",                   new x_ite_Fields .SFBool (),
                          Base_X3DConstants .outputOnly,  "display",                  new x_ite_Fields .SFBool (true),
                          Base_X3DConstants .outputOnly,  "transformSensors_changed", new x_ite_Fields .SFTime ());

   this ._bboxSize   .setUnit ("length");
   this ._bboxCenter .setUnit ("length");

   this .childBBox            = new Geometry_Box3 (); // Must be unique for each X3DBoundedObject.
   this .transformSensorNodes = new Set ();
}

Object .assign (X3DBoundedObject .prototype,
{
   initialize ()
   {
      this ._hidden  .addInterest ("set_visible_and_hidden__", this);
      this ._visible .addInterest ("set_visible_and_hidden__", this);

      this .set_visible_and_hidden__ ();
   },
   isHidden ()
   {
      return this ._hidden .getValue ();
   },
   setHidden (value)
   {
      if (value === this ._hidden .getValue ())
         return;

      this ._hidden = value;
   },
   getDefaultBBoxSize: (() =>
   {
      const defaultBBoxSize = new Numbers_Vector3 (-1, -1, -1);

      return function ()
      {
         return defaultBBoxSize;
      };
   })(),
   getBBox (nodes, bbox, shadows)
   {
      // Must be unique for each X3DBoundedObject.
      const childBBox = this .childBBox;

      // Add bounding boxes.

      bbox .set ();

      for (const node of nodes)
      {
         if (node .getBBox)
            bbox .add (node .getBBox (childBBox, shadows));
      }

      return bbox;
   },
   displayBBox: (() =>
   {
      const
         bbox   = new Geometry_Box3 (),
         matrix = new Numbers_Matrix4 ();

      return function (type, renderObject)
      {
         const modelViewMatrix = renderObject .getModelViewMatrix ();

         this .getBBox (bbox);
         matrix .set (bbox .center, null, bbox .size);

         modelViewMatrix .push ();
         modelViewMatrix .multLeft (matrix);

         this .getBrowser () .getBBoxNode () .traverse (type, renderObject);

         modelViewMatrix .pop ();
      };
   })(),
   addTransformSensor (transformSensorNode)
   {
      this .transformSensorNodes .add (transformSensorNode);

      this ._transformSensors_changed = this .getBrowser () .getCurrentTime ();
   },
   removeTransformSensor (transformSensorNode)
   {
      this .transformSensorNodes .delete (transformSensorNode);

      this ._transformSensors_changed = this .getBrowser () .getCurrentTime ();
   },
   getTransformSensors ()
   {
      return this .transformSensorNodes;
   },
   set_visible_and_hidden__ ()
   {
      const value = this ._visible .getValue () && !this ._hidden .getValue ();

      if (value === this ._display .getValue ())
         return;

      this ._display = value;
   },
   dispose () { },
});

Object .defineProperties (X3DBoundedObject,
{
   typeName:
   {
      value: "X3DBoundedObject",
      enumerable: true,
   },
   componentName:
   {
      value: "Grouping",
      enumerable: true,
   },
});

const X3DBoundedObject_default_ = X3DBoundedObject;
;

x_ite_Namespace .add ("X3DBoundedObject", "x_ite/Components/Grouping/X3DBoundedObject", X3DBoundedObject_default_);
/* harmony default export */ const Grouping_X3DBoundedObject = (X3DBoundedObject_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Grouping/X3DGroupingNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function X3DGroupingNode (executionContext)
{
   Core_X3DChildNode     .call (this, executionContext);
   Grouping_X3DBoundedObject .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DGroupingNode);

   this .allowedTypes              = new Set ();
   this .clipPlaneNodes            = [ ];
   this .localFogNodes             = [ ];
   this .lightNodes                = [ ];
   this .textureProjectorNodes     = [ ];
   this .pointingDeviceSensorNodes = [ ];
   this .maybeCameraObjects        = [ ];
   this .cameraObjects             = [ ];
   this .maybePickableSensorNodes  = [ ];
   this .pickableSensorNodes       = [ ];
   this .pickableObjects           = [ ];
   this .childNodes                = [ ];
   this .displayNodes              = [ ];
   this .visibleNodes              = [ ];
   this .boundedObjects            = [ ];
   this .sensors                   = [ ];
}

Object .assign (Object .setPrototypeOf (X3DGroupingNode .prototype, Core_X3DChildNode .prototype),
   Grouping_X3DBoundedObject .prototype,
{
   initialize ()
   {
      Core_X3DChildNode     .prototype .initialize .call (this);
      Grouping_X3DBoundedObject .prototype .initialize .call (this);

      this ._transformSensors_changed .addInterest ("set_transformSensors__", this);

      this ._addChildren    .addInterest ("set_addChildren__",    this);
      this ._removeChildren .addInterest ("set_removeChildren__", this);
      this ._children       .addInterest ("set_children__",       this);

      this .set_children__ ();
   },
   getBBox (bbox, shadows)
   {
      return this .getSubBBox (bbox, shadows);
   },
   getSubBBox (bbox, shadows)
   {
      if (this ._bboxSize .getValue () .equals (this .getDefaultBBoxSize ()))
         return Grouping_X3DBoundedObject .prototype .getBBox .call (this, this .visibleNodes, bbox, shadows);

      return bbox .set (this ._bboxSize .getValue (), this ._bboxCenter .getValue ());
   },
   setAllowedTypes (/* type, ... */)
   {
      const allowedTypes = this .allowedTypes;

      allowedTypes .clear ();

      for (const type of arguments)
         allowedTypes .add (type);
   },
   set_addChildren__ ()
   {
      if (this ._addChildren .length === 0)
         return;

      this ._addChildren .setTainted (true);
      this ._addChildren .assign (filter (this ._addChildren, this ._children));

      if (!this ._children .isTainted ())
      {
         this ._children .removeInterest ("set_children__", this);
         this ._children .addInterest ("connectChildren", this);
      }

      this ._children .splice (this ._children .length, 0, ... this ._addChildren);
      this .add (this ._addChildren);

      this ._addChildren .length = 0;
      this ._addChildren .setTainted (false);
   },
   set_removeChildren__ ()
   {
      if (this ._removeChildren .length === 0)
         return;

      this ._removeChildren .setTainted (true);

      if (this ._children .length > 0)
      {
         if (!this ._children .isTainted ())
         {
            this ._children .removeInterest ("set_children__", this);
            this ._children .addInterest ("connectChildren", this);
         }

         this ._children .assign (filter (this ._children, this ._removeChildren));
         this .remove (this ._removeChildren);
      }

      this ._removeChildren .length = 0;
      this ._removeChildren .setTainted (false);
   },
   set_children__ ()
   {
      this .clear ();
      this .add (this ._children);
   },
   connectChildren ()
   {
      this ._children .removeInterest ("connectChildren", this);
      this ._children .addInterest ("set_children__", this);
   },
   clear ()
   {
      for (const maybePickableSensorNode of this .maybePickableSensorNodes)
         maybePickableSensorNode ._isPickableObject .removeInterest ("set_pickableObjects__", this);

      for (const childNode of this .childNodes)
      {
         childNode ._isCameraObject   .removeInterest ("set_cameraObjects__",   this);
         childNode ._isPickableObject .removeInterest ("set_pickableObjects__", this);

         if (Base_X3DCast (Base_X3DConstants .X3DBoundedObject, childNode))
         {
            childNode ._display     .removeInterest ("set_displays_",     this);
            childNode ._bboxDisplay .removeInterest ("set_bboxDisplays__", this);
         }
      }

      this .clipPlaneNodes            .length = 0;
      this .localFogNodes             .length = 0;
      this .lightNodes                .length = 0;
      this .textureProjectorNodes     .length = 0;
      this .pointingDeviceSensorNodes .length = 0;
      this .maybeCameraObjects        .length = 0;
      this .maybePickableSensorNodes  .length = 0;
      this .childNodes                .length = 0;
   },
   add (children)
   {
      for (const child of children)
      {
         const childNode = Base_X3DCast (Base_X3DConstants .X3DChildNode, child);

         if (!childNode)
            continue;

         const type = childNode .getType ();

         for (let t = type .length - 1; t >= 0; -- t)
         {
            // if (this .allowedTypes .size)
            // {
            //    if (!childNode .getType () .some (Set .prototype .has, this .allowedTypes))
            //       continue;
            // }

            switch (type [t])
            {
               case Base_X3DConstants .X3DPointingDeviceSensorNode:
               {
                  this .pointingDeviceSensorNodes .push (childNode);
                  break;
               }
               case Base_X3DConstants .ClipPlane:
               {
                  this .clipPlaneNodes .push (childNode);
                  break;
               }
               case Base_X3DConstants .LocalFog:
               {
                  this .localFogNodes .push (childNode);
                  break;
               }
               case Base_X3DConstants .X3DTextureProjectorNode:
               {
                  this .textureProjectorNodes .push (childNode);
                  break;
               }
               case Base_X3DConstants .X3DLightNode:
               {
                  this .lightNodes .push (childNode);
                  break;
               }
               case Base_X3DConstants .X3DBindableNode:
               {
                  this .maybeCameraObjects .push (childNode);
                  break;
               }
               case Base_X3DConstants .TransformSensor:
               case Base_X3DConstants .X3DPickSensorNode:
               {
                  childNode ._isPickableObject .addInterest ("set_pickableObjects__", this);

                  this .maybePickableSensorNodes .push (childNode);
                  break;
               }
               case Base_X3DConstants .Sound:
               case Base_X3DConstants .SpatialSound:
               case Base_X3DConstants .X3DBackgroundNode:
               case Base_X3DConstants .X3DChildNode:
               {
                  childNode ._isCameraObject   .addInterest ("set_cameraObjects__",   this);
                  childNode ._isPickableObject .addInterest ("set_pickableObjects__", this);

                  if (Base_X3DCast (Base_X3DConstants .X3DBoundedObject, childNode))
                  {
                     childNode ._display     .addInterest ("set_displays_",     this);
                     childNode ._bboxDisplay .addInterest ("set_bboxDisplays__", this);
                  }

                  this .maybeCameraObjects .push (childNode);
                  this .childNodes .push (childNode);
                  break;
               }
               case Base_X3DConstants .BooleanFilter:
               case Base_X3DConstants .BooleanToggle:
               case Base_X3DConstants .HAnimMotion:
               case Base_X3DConstants .NurbsOrientationInterpolator:
               case Base_X3DConstants .NurbsPositionInterpolator:
               case Base_X3DConstants .NurbsSurfaceInterpolator:
               case Base_X3DConstants .TimeSensor:
               case Base_X3DConstants .X3DFollowerNode:
               case Base_X3DConstants .X3DInfoNode:
               case Base_X3DConstants .X3DInterpolatorNode:
               case Base_X3DConstants .X3DKeyDeviceSensorNode:
               case Base_X3DConstants .X3DLayoutNode:
               case Base_X3DConstants .X3DScriptNode:
               case Base_X3DConstants .X3DSequencerNode:
               case Base_X3DConstants .X3DSoundNode:
               case Base_X3DConstants .X3DTriggerNode:
                  break;
               default:
                  continue;
            }

            break;
         }

         if (childNode .getMustDisplay ())
         {
            if (!this .childNodes .includes (childNode))
               this .childNodes .push (childNode);
         }
      }

      this .set_pickableObjects__ ()
      this .set_displayNodes__ ()
      this .set_displays_ ()
      this .set_bboxDisplays__ ();
   },
   remove (children)
   {
      for (const child of children)
      {
         const childNode = Base_X3DCast (Base_X3DConstants .X3DChildNode, child);

         if (!childNode)
            continue;

         if (childNode .getMustDisplay ())
         {
            const index = this .childNodes .indexOf (childNode);

            if (index >= 0)
               this .childNodes .splice (index, 1);
         }

         const type = childNode .getType ();

         for (let t = type .length - 1; t >= 0; -- t)
         {
            switch (type [t])
            {
               case Base_X3DConstants .X3DPointingDeviceSensorNode:
               {
                  const index = this .pointingDeviceSensorNodes .indexOf (childNode);

                  if (index >= 0)
                     this .pointingDeviceSensorNodes .splice (index, 1);

                  break;
               }
               case Base_X3DConstants .ClipPlane:
               {
                  const index = this .clipPlaneNodes .indexOf (childNode);

                  if (index >= 0)
                     this .clipPlaneNodes .splice (index, 1);

                  break;
               }
               case Base_X3DConstants .LocalFog:
               {
                  const index = this .localFogNodes .indexOf (childNode);

                  if (index >= 0)
                     this .localFogNodes .splice (index, 1);

                  break;
               }
               case Base_X3DConstants .X3DTextureProjectorNode:
               {
                  const index = this .textureProjectorNodes .indexOf (childNode);

                  if (index >= 0)
                     this .textureProjectorNodes .splice (index, 1);

                  break;
               }
               case Base_X3DConstants .X3DLightNode:
               {
                  const index = this .lightNodes .indexOf (childNode);

                  if (index >= 0)
                     this .lightNodes .splice (index, 1);

                  break;
               }
               case Base_X3DConstants .X3DBindableNode:
               {
                  const index = this .maybeCameraObjects .indexOf (childNode);

                  if (index >= 0)
                     this .maybeCameraObjects .splice (index, 1);

                  break;
               }
               case Base_X3DConstants .TransformSensor:
               case Base_X3DConstants .X3DPickSensorNode:
               {
                  childNode ._isPickableObject .removeInterest ("set_pickableObjects__", this);

                  const index = this .maybePickableSensorNodes .indexOf (childNode);

                  if (index >= 0)
                     this .maybePickableSensorNodes .splice (index, 1);

                  break;
               }
               case Base_X3DConstants .Sound:
               case Base_X3DConstants .SpatialSound:
               case Base_X3DConstants .X3DBackgroundNode:
               case Base_X3DConstants .X3DChildNode:
               {
                  childNode ._isCameraObject   .removeInterest ("set_cameraObjects__",   this);
                  childNode ._isPickableObject .removeInterest ("set_pickableObjects__", this);

                  if (Base_X3DCast (Base_X3DConstants .X3DBoundedObject, childNode))
                  {
                     childNode ._display     .removeInterest ("set_displays_",     this);
                     childNode ._bboxDisplay .removeInterest ("set_bboxDisplays__", this);
                  }

                  var index = this .maybeCameraObjects .indexOf (childNode);

                  if (index >= 0)
                     this .maybeCameraObjects .splice (index, 1);

                  var index = this .childNodes .indexOf (childNode);

                  if (index >= 0)
                     this .childNodes .splice (index, 1);

                  break;
               }
               case Base_X3DConstants .BooleanFilter:
               case Base_X3DConstants .BooleanToggle:
               case Base_X3DConstants .HAnimMotion:
               case Base_X3DConstants .NurbsOrientationInterpolator:
               case Base_X3DConstants .NurbsPositionInterpolator:
               case Base_X3DConstants .NurbsSurfaceInterpolator:
               case Base_X3DConstants .TimeSensor:
               case Base_X3DConstants .X3DFollowerNode:
               case Base_X3DConstants .X3DInfoNode:
               case Base_X3DConstants .X3DInterpolatorNode:
               case Base_X3DConstants .X3DKeyDeviceSensorNode:
               case Base_X3DConstants .X3DLayoutNode:
               case Base_X3DConstants .X3DScriptNode:
               case Base_X3DConstants .X3DSequencerNode:
               case Base_X3DConstants .X3DSoundNode:
               case Base_X3DConstants .X3DTriggerNode:
                  break;
               default:
                  continue;
            }

            break;
         }
      }

      this .set_displayNodes__ ();
      this .set_displays_ ();
      this .set_bboxDisplays__ ();
   },
   set_cameraObjects__ ()
   {
      const cameraObjects = this .cameraObjects;

      cameraObjects .length = 0;

      for (const childNode of this .maybeCameraObjects)
      {
         if (!childNode .isCameraObject ())
            continue;

         if (Base_X3DCast (Base_X3DConstants .X3DBoundedObject, childNode))
         {
            if (childNode ._display .getValue ())
               cameraObjects .push (childNode);
         }
         else
         {
            cameraObjects .push (childNode);
         }
      }

      this .setCameraObject (!!(cameraObjects .length));
   },
   set_pickableObjects__ ()
   {
      const
         pickableSensorNodes = this .pickableSensorNodes,
         pickableObjects     = this .pickableObjects;

      pickableSensorNodes .length = 0;
      pickableObjects     .length = 0;

      for (const sensorNode of this .maybePickableSensorNodes)
      {
         if (sensorNode .isPickableObject ())
            pickableSensorNodes .push (sensorNode);
      }

      for (const childNode of this .visibleNodes)
      {
         if (childNode .isPickableObject ())
            pickableObjects .push (childNode);
      }

      this .set_transformSensors__ ()
   },
   set_transformSensors__ ()
   {
      this .setPickableObject (!!(this .getTransformSensors () .size || this .pickableSensorNodes .length || this .pickableObjects .length));
   },
   set_displayNodes__ ()
   {
      const displayNodes = this .displayNodes;

      displayNodes .length = 0;

      for (const node of this .clipPlaneNodes)
         displayNodes .push (node);

      for (const node of this .localFogNodes)
         displayNodes .push (node);

      for (const node of this .lightNodes)
         displayNodes .push (node);

      for (const node of this .textureProjectorNodes)
         displayNodes .push (node);
   },
   set_displays_ ()
   {
      const visibleNodes = this .visibleNodes;

      visibleNodes .length = 0;

      for (const childNode of this .childNodes)
      {
         if (Base_X3DCast (Base_X3DConstants .X3DBoundedObject, childNode))
         {
            if (childNode ._display .getValue ())
               visibleNodes .push (childNode);
         }
         else
         {
            visibleNodes .push (childNode);
         }
      }

      this .set_cameraObjects__ ();
      this .set_pickableObjects__ ();
   },
   set_bboxDisplays__ ()
   {
      const boundedObjects = this .boundedObjects;

      boundedObjects .length = 0;

      for (const childNode of this .childNodes)
      {
         if (Base_X3DCast (Base_X3DConstants .X3DBoundedObject, childNode))
         {
            if (childNode ._bboxDisplay .getValue ())
            {
               boundedObjects .push (childNode);
            }
         }
      }
   },
   traverse (type, renderObject)
   {
      switch (type)
      {
         case Rendering_TraverseType .POINTER:
         {
            const
               pointingDeviceSensorNodes = this .pointingDeviceSensorNodes,
               clipPlaneNodes            = this .clipPlaneNodes,
               sensors                   = this .sensors;

            sensors .length = 0;

            if (pointingDeviceSensorNodes .length)
            {
               for (const pointingDeviceSensorNode of pointingDeviceSensorNodes)
                  pointingDeviceSensorNode .push (renderObject, sensors);

               if (sensors .length)
                  renderObject .getSensors () .push (sensors);
            }

            for (const clipPlaneNode of clipPlaneNodes)
               clipPlaneNode .push (renderObject);

            for (const visibleNode of this .visibleNodes)
               visibleNode .traverse (type, renderObject);

            for (const clipPlaneNode of clipPlaneNodes)
               clipPlaneNode .pop (renderObject);

            if (sensors .length)
               renderObject .getSensors () .pop ();

            return;
         }
         case Rendering_TraverseType .CAMERA:
         {
            for (const cameraObject of this .cameraObjects)
               cameraObject .traverse (type, renderObject);

            return;
         }
         case Rendering_TraverseType .PICKING:
         {
            if (this .getTransformSensors () .size)
            {
               const modelMatrix = renderObject .getModelViewMatrix () .get ();

               for (const transformSensorNode of this .getTransformSensors ())
                  transformSensorNode .collect (modelMatrix);
            }

            for (const pickableSensorNode of this .pickableSensorNodes)
               pickableSensorNode .traverse (type, renderObject);

            const
               browser          = this .getBrowser (),
               pickingHierarchy = browser .getPickingHierarchy ();

            pickingHierarchy .push (this);

            if (browser .getPickable () .at (-1))
            {
               for (const visibleNode of this .visibleNodes)
                  visibleNode .traverse (type, renderObject);
            }
            else
            {
               for (const pickableObject of this .pickableObjects)
                  pickableObject .traverse (type, renderObject);
            }

            pickingHierarchy .pop ();
            return;
         }
         case Rendering_TraverseType .COLLISION:
         {
            const clipPlaneNodes = this .clipPlaneNodes;

            for (const clipPlaneNode of clipPlaneNodes)
               clipPlaneNode .push (renderObject);

            for (const visibleNode of this .visibleNodes)
               visibleNode .traverse (type, renderObject);

            for (const clipPlaneNode of clipPlaneNodes)
               clipPlaneNode .pop (renderObject);

            return;
         }
         case Rendering_TraverseType .SHADOW:
         {
            // Nodes that are not visible do not cast shadows.

            const clipPlaneNodes = this .clipPlaneNodes;

            for (const clipPlaneNode of clipPlaneNodes)
               clipPlaneNode .push (renderObject);

            for (const visibleNode of this .visibleNodes)
               visibleNode .traverse (type, renderObject);

            for (const clipPlaneNode of clipPlaneNodes)
               clipPlaneNode .push (renderObject);

            return;
         }
         case Rendering_TraverseType .DISPLAY:
         {
            const displayNodes = this .displayNodes;

            for (const displayNode of displayNodes)
               displayNode .push (renderObject, this);

            for (const visibleNode of this .visibleNodes)
               visibleNode .traverse (type, renderObject);

            for (const boundedObject of this .boundedObjects)
               boundedObject .displayBBox (type, renderObject);

            for (const displayNode of displayNodes)
               displayNode .pop (renderObject);

            return;
         }
      }
   },
   dispose ()
   {
      Grouping_X3DBoundedObject .prototype .dispose .call (this);
      Core_X3DChildNode     .prototype .dispose .call (this);
   },
});

function filter (array, remove)
{
   const set = new Set (remove);

   return array .filter (value => !set .has (value));
}

Object .defineProperties (X3DGroupingNode,
{
   typeName:
   {
      value: "X3DGroupingNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Grouping",
      enumerable: true,
   },
});

const X3DGroupingNode_default_ = X3DGroupingNode;
;

x_ite_Namespace .add ("X3DGroupingNode", "x_ite/Components/Grouping/X3DGroupingNode", X3DGroupingNode_default_);
/* harmony default export */ const Grouping_X3DGroupingNode = (X3DGroupingNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Grouping/Group.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function Group (executionContext)
{
   Grouping_X3DGroupingNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Group);
}

Object .setPrototypeOf (Group .prototype, Grouping_X3DGroupingNode .prototype);

Object .defineProperties (Group,
{
   typeName:
   {
      value: "Group",
      enumerable: true,
   },
   componentName:
   {
      value: "Grouping",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",       new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "visible",        new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "bboxDisplay",    new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxSize",       new x_ite_Fields .SFVec3f (-1, -1, -1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxCenter",     new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "addChildren",    new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "removeChildren", new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "children",       new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const Group_default_ = Group;
;

x_ite_Namespace .add ("Group", "x_ite/Components/Grouping/Group", Group_default_);
/* harmony default export */ const Grouping_Group = (Group_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Layering/Layer.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









function Layer (executionContext)
{
   Layering_X3DLayerNode .call (this,
                       executionContext,
                       new Navigation_Viewpoint (executionContext),
                       new Grouping_Group (executionContext));

   this .addType (Base_X3DConstants .Layer);
}

Object .assign (Object .setPrototypeOf (Layer .prototype, Layering_X3DLayerNode .prototype),
{
   initialize ()
   {
      Layering_X3DLayerNode .prototype .initialize .call (this);

      this ._addChildren    .addFieldInterest (this .getGroup () ._addChildren);
      this ._removeChildren .addFieldInterest (this .getGroup () ._removeChildren);
      this ._children       .addFieldInterest (this .getGroup () ._children);

      this .getGroup () ._children = this ._children;
      this .getGroup () .setPrivate (true);
      this .getGroup () .setup ();
   },
});

Object .defineProperties (Layer,
{
   typeName:
   {
      value: "Layer",
      enumerable: true,
   },
   componentName:
   {
      value: "Layering",
      enumerable: true,
   },
   containerField:
   {
      value: "layers",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",       new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pickable",       new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "objectType",     new x_ite_Fields .MFString ("ALL")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "visible",        new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "viewport",       new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "addChildren",    new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "removeChildren", new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "children",       new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const Layer_default_ = Layer;
;

x_ite_Namespace .add ("Layer", "x_ite/Components/Layering/Layer", Layer_default_);
/* harmony default export */ const Layering_Layer = (Layer_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Layering/LayerSet.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










function LayerSet (executionContext)
{
   Core_X3DNode .call (this, executionContext);

   this .addType (Base_X3DConstants .LayerSet);

   this .layerNodes      = [ new Layering_Layer (executionContext) ];
   this .layerNode0      = this .layerNodes [0];
   this .activeLayerNode = null;
}

Object .assign (Object .setPrototypeOf (LayerSet .prototype, Core_X3DNode .prototype),
{
   initialize ()
   {
      Core_X3DNode .prototype .initialize .call (this);

      this .layerNode0 .setPrivate (true);
      this .layerNode0 .setup ();
      this .layerNode0 .setLayer0 (true);

      this ._activeLayer .addInterest ("set_activeLayer__", this);
      this ._order       .addInterest ("set_layers__", this);
      this ._layers      .addInterest ("set_layers__", this);

      this .set_layers__ ();
   },
   getActiveLayer ()
   {
      return this .activeLayerNode;
   },
   setLayer0 (value)
   {
      this .layerNode0 = value;

      this .set_layers__ ();
   },
   getLayer0 ()
   {
      return this .layerNode0;
   },
   getLayers ()
   {
      return this .layerNodes;
   },
   set_activeLayer__ ()
   {
      if (this ._activeLayer .getValue () === 0)
      {
         if (this .activeLayerNode !== this .layerNode0)
            this .activeLayerNode = this .layerNode0;
      }
      else
      {
         const index = this ._activeLayer - 1;

         if (index >= 0 && index < this ._layers .length)
         {
            if (this .activeLayerNode !== this ._layers [index] .getValue ())
               this .activeLayerNode = Base_X3DCast (Base_X3DConstants .X3DLayerNode, this ._layers [index]);
         }
         else
         {
            if (this .activeLayerNode !== null)
               this .activeLayerNode = null;
         }
      }
   },
   set_layers__ ()
   {
      const layers = this ._layers .getValue ();

      this .layerNodes .length = 0;

      for (let index of this ._order)
      {
         if (index === 0)
         {
            this .layerNodes .push (this .layerNode0);
         }
         else
         {
            -- index;

            if (index >= 0 && index < layers .length)
            {
               const layerNode = Base_X3DCast (Base_X3DConstants .X3DLayerNode, layers [index]);

               if (layerNode)
                  this .layerNodes .push (layerNode);
            }
         }
      }

      this .set_activeLayer__ ();
   },
   bindBindables (viewpointName)
   {
      const layers = this ._layers .getValue ();

      this .layerNode0 .bindBindables (viewpointName);

      for (let i = 0, length = layers .length; i < length; ++ i)
      {
         const layerNode = Base_X3DCast (Base_X3DConstants .X3DLayerNode, layers [i]);

         if (layerNode)
            layerNode .bindBindables (viewpointName);
      }
   },
   traverse (type, renderObject)
   {
      for (const layerNode of this .layerNodes)
         layerNode .traverse (type, renderObject);
   },
});

Object .defineProperties (LayerSet,
{
   typeName:
   {
      value: "LayerSet",
      enumerable: true,
   },
   componentName:
   {
      value: "Layering",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",    new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "activeLayer", new x_ite_Fields .SFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "order",       new x_ite_Fields .MFInt32 (0)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "layers",      new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const LayerSet_default_ = LayerSet;
;

x_ite_Namespace .add ("LayerSet", "x_ite/Components/Layering/LayerSet", LayerSet_default_);
/* harmony default export */ const Layering_LayerSet = (LayerSet_default_);
;// CONCATENATED MODULE: ./src/x_ite/Execution/X3DWorld.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function X3DWorld (executionContext)
{
   Base_X3DBaseNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DWorld)

   this .addChildObjects (Base_X3DConstants .outputOnly, "activeLayer", new Fields_SFNode (this .layer0));

   this .defaultLayerSet = new Layering_LayerSet (executionContext);
   this .layerSet        = this .defaultLayerSet;
   this .layer0          = new Layering_Layer (executionContext);
}

Object .assign (Object .setPrototypeOf (X3DWorld .prototype, Base_X3DBaseNode .prototype),
{
   initialize ()
   {
      Base_X3DBaseNode .prototype .initialize .call (this);

      this .layerSet .setPrivate (true);
      this .layerSet .setup ();
      this .layerSet .setLayer0 (this .layer0);
      this .layerSet ._activeLayer .addInterest ("set_rootNodes__", this);

      this .getExecutionContext () .getRootNodes () .addInterest ("set_rootNodes__", this);

      this .set_rootNodes__ ();

      this .layer0 .setPrivate (true);
      this .layer0 .setLayer0 (true);
      this .layer0 .setup ();

      this .set_activeLayer__ ();
   },
   getCache ()
   {
      return this .getBrowser () .getBrowserOption ("Cache");
   },
   getLayerSet ()
   {
      return this .layerSet;
   },
   getActiveLayer ()
   {
      return this ._activeLayer .getValue ();
   },
   set_rootNodes__ ()
   {
      const
         oldLayerSet = this .layerSet,
         rootNodes   = this .getExecutionContext () .getRootNodes ();

      this .layerSet          = this .defaultLayerSet;
      this .layer0 ._children = rootNodes;

      for (const rootNode of rootNodes)
      {
         const layerSet = Base_X3DCast (Base_X3DConstants .LayerSet, rootNode);

         if (layerSet)
            this .layerSet = layerSet;
      }

      if (this .layerSet === oldLayerSet)
         return;

      this .layerSet .setLayer0 (this .layer0);

      oldLayerSet    ._activeLayer .removeInterest ("set_activeLayer__", this);
      this .layerSet ._activeLayer .addInterest ("set_activeLayer__", this);

      this .set_activeLayer__ ();
   },
   set_activeLayer__ ()
   {
      this ._activeLayer = this .layerSet .getActiveLayer ();
   },
   bindBindables ()
   {
      // Bind first X3DBindableNodes found in each layer.

      const worldURL = this .getExecutionContext () .getWorldURL ();

      this .layerSet .bindBindables (decodeURIComponent (new URL (worldURL) .hash .substring (1)));
   },
   traverse (type, renderObject)
   {
      this .layerSet .traverse (type, renderObject);
   },
});

for (const key of Object .keys (X3DWorld .prototype))
   Object .defineProperty (X3DWorld .prototype, key, { enumerable: false });

Object .defineProperties (X3DWorld,
{
   typeName:
   {
      value: "X3DWorld",
      enumerable: true,
   },
});

Base_X3DConstants .addNode (X3DWorld);

const X3DWorld_default_ = X3DWorld;
;

x_ite_Namespace .add ("X3DWorld", "x_ite/Execution/X3DWorld", X3DWorld_default_);
/* harmony default export */ const Execution_X3DWorld = (X3DWorld_default_);
;// CONCATENATED MODULE: ./src/x_ite/InputOutput/FileLoader.js
/* provided dependency */ var FileLoader_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







const foreignContentTypes = new Set ([
   "text/html",
   "application/xhtml+xml",
])

function FileLoader (node)
{
   Base_X3DObject .call (this);

   this .node             = node;
   this .browser          = node .getBrowser ();
   this .external         = this .browser .isExternal ();
   this .executionContext = this .external ? node .getExecutionContext () : this .browser .currentScene;
   this .target           = "";
   this .url              = [ ];
   this .URL              = new URL (this .getBaseURL ());
   this .controller       = new AbortController ();
}

Object .assign (Object .setPrototypeOf (FileLoader .prototype, Base_X3DObject .prototype),
{
   abort ()
   {
      this .url .length = 0;

      this .controller .abort ();
   },
   getURL ()
   {
      return this .URL;
   },
   getBaseURL ()
   {
      if (this .node instanceof Execution_X3DWorld)
      {
         if (this .external)
            return this .browser .getBaseURL ();
      }

      return this .executionContext .getBaseURL ();
   },
   getTarget (parameters)
   {
      for (const parameter of parameters)
      {
         const pair = parameter .split ("=");

         if (pair .length !== 2)
            continue;

         if (pair [0] === "target")
            return pair [1];
      }

      return "";
   },
   createX3DFromString (worldURL, string = "", resolve, reject)
   {
      try
      {
         const scene = this .browser .createScene ();

         if (this .node instanceof Execution_X3DWorld)
            scene .loader = this;
         else
            scene .setExecutionContext (this .executionContext);

         scene .setWorldURL (new URL (worldURL, this .getBaseURL ()) .href);

         if (resolve)
            resolve = this .setScene .bind (this, scene, resolve, reject);

         new Parser_GoldenGate (scene) .parseIntoScene (string, resolve, reject);

         return scene;
      }
      catch (error)
      {
         if (reject)
            reject (error);
         else
            throw error;
      }
   },
   setScene (scene, resolve, reject)
   {
      scene ._initLoadCount .addInterest ("set_initLoadCount__", this, scene, resolve, reject);
      scene ._initLoadCount .addEvent ();
   },
   set_initLoadCount__ (scene, resolve, reject, field)
   {
      // Wait for extern protos to be loaded.

      if (field .getValue ())
         return;

      scene ._initLoadCount .removeInterest ("set_initLoadCount__", this);

      delete scene .loader;

      // Wait for instances to be created.

      setTimeout (() =>
      {
         try
         {
            resolve (scene);
         }
         catch (error)
         {
            if (reject)
               reject (error);
            else
               throw error;
         }
      });

      if (DEVELOPMENT)
      {
         if (this .URL .protocol !== "data:")
            console .info (`Done loading scene '${decodeURI (this .URL .href)}'`);
      }
   },
   createX3DFromURL (url, parameter, callback, bindViewpoint, foreign)
   {
      this .bindViewpoint = bindViewpoint;
      this .foreign       = foreign;
      this .target        = this .getTarget (parameter || new x_ite_Fields .MFString ());

      return this .loadDocument (url, this .createX3DFromURLAsync .bind (this, callback));
   },
   createX3DFromURLAsync (callback, data)
   {
      if (data === null)
         callback (null);
      else
         this .createX3DFromString (this .URL, data, callback, this .loadDocumentError .bind (this));
   },
   loadDocument (url, callback)
   {
      this .url      = url .copy ();
      this .callback = callback;

      if (url .length === 0)
         return this .loadDocumentError (new Error ("No URL given."));

      this .loadDocumentAsync (this .url .shift ())
         .catch (this .loadDocumentError .bind (this));
   },
   loadDocumentAsync: async function (url)
   {
      if (url .length === 0)
      {
         this .loadDocumentError (new Error ("URL is empty."));
         return;
      }

      // Script
      {
         const result = url .match (/^\s*(?:vrmlscript|javascript|ecmascript)\:(.*)$/s);

         if (result)
         {
            this .callback (result [1]);
            return;
         }
      }

      this .URL = new URL (url, this .getBaseURL ());

      // Data URL
      {
         const result = url .match (/^data:(.*?)(?:;charset=(.*?))?(?:;(base64))?,/s);

         if (result && result [3] !== "base64")
         {
            // const mimeType = result [1];

            let data = url .substring (result [0] .length);

            data = unescape (data);            // Unescape data, don't use decodeURIComponent!
            data = data .replace (/^ï»¿/, ""); // Remove BOM.

            this .callback (data);
            return;
         }
      }

      if (this .URL .protocol !== "data:" && this .bindViewpoint)
      {
         const referer = new URL (this .getBaseURL ());

         if (this .URL .protocol === referer .protocol &&
             this .URL .hostname === referer .hostname &&
             this .URL .port     === referer .port &&
             this .URL .pathname === referer .pathname &&
             this .URL .hash)
         {
            this .bindViewpoint (decodeURIComponent (this .URL .hash .substr (1)));
            return;
         }
      }

      if (this .foreign)
      {
         // Handle target

         if (this .target .length && this .target !== "_self")
            return this .foreign (this .URL .href, this .target);

         // Handle well known foreign content depending on extension or if path looks like directory.

         if (this .URL .protocol !== "data:" && this .URL .href .match (/\.(?:html|htm|xhtml)$/))
            return this .foreign (this .URL .href, this .target);
      }

      // Load URL async

      const
         options     = { cache: this .node .getCache () ? "default" : "reload", signal: this .controller .signal },
         response    = this .checkResponse (await fetch (this .URL, options)),
         contentType = response .headers .get ("content-type") ?.replace (/;.*$/, "");

      if (this .foreign)
      {
         // console .log (contentType);

         if (foreignContentTypes .has (contentType))
            return this .foreign (this .URL .href, this .target);
      }

      this .callback (FileLoader_$.ungzip (await response .arrayBuffer ()), this .URL);
   },
   checkResponse (response)
   {
      if (response .ok)
         return response;

      throw Error (response .statusText || response .status);
   },
   loadDocumentError (error)
   {
      // Output error.

      this .printError (error);

      // Try to load next URL.

      if (this .url .length)
      {
         this .loadDocumentAsync (this .url .shift ())
            .catch (this .loadDocumentError .bind (this));
      }
      else
      {
         this .callback (null);
      }
   },
   printError (error)
   {
      if (this .URL .protocol === "data:")
         console .error (`Couldn't load data URL.`, error);
      else
         console .error (`Couldn't load URL '${decodeURI (this .URL .href)}'.`, error);
   },
});

for (const key of Object .keys (FileLoader .prototype))
   Object .defineProperty (FileLoader .prototype, key, { enumerable: false });

const FileLoader_default_ = FileLoader;
;

x_ite_Namespace .add ("FileLoader", "x_ite/InputOutput/FileLoader", FileLoader_default_);
/* harmony default export */ const InputOutput_FileLoader = (FileLoader_default_);
;// CONCATENATED MODULE: ./src/x_ite/Prototype/X3DExternProtoDeclaration.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









const
   _proto = Symbol (),
   _scene = Symbol ();

function X3DExternProtoDeclaration (executionContext, url)
{
   Prototype_X3DProtoDeclarationNode .call (this, executionContext);
   Networking_X3DUrlObject            .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DExternProtoDeclaration)

   this .addChildObjects (Base_X3DConstants .inputOutput, "load",                 new x_ite_Fields .SFBool (true),
                          Base_X3DConstants .inputOutput, "url",                  url .copy (), // Must be of type MFString.
                          Base_X3DConstants .inputOutput, "autoRefresh",          new x_ite_Fields .SFTime (),
                          Base_X3DConstants .inputOutput, "autoRefreshTimeLimit", new x_ite_Fields .SFTime (3600));
}

Object .assign (Object .setPrototypeOf (X3DExternProtoDeclaration .prototype, Prototype_X3DProtoDeclarationNode .prototype),
   Networking_X3DUrlObject .prototype,
{
   initialize ()
   {
      Prototype_X3DProtoDeclarationNode .prototype .initialize .call (this);
      Networking_X3DUrlObject            .prototype .initialize .call (this);
   },
   set_live__ ()
   {
      Networking_X3DUrlObject .prototype .set_live__ .call (this);

      if (this .checkLoadState () !== Base_X3DConstants .COMPLETE_STATE)
         return;

      this [_scene] .setLive (this .getLive () .getValue ());
   },
   canUserDefinedFields ()
   {
      return true;
   },
   setProtoDeclaration (proto)
   {
      this [_proto] = proto;

      if (proto)
      {
         for (const field of [... this .getUserDefinedFields ()])
            this .removeUserDefinedField (field .getName ())

         for (const field of proto .getUserDefinedFields ())
            this .addUserDefinedField (field .getAccessType (), field .getName (), field);
      }

      this .updateInstances ();
   },
   getProtoDeclaration ()
   {
      return this [_proto];
   },
   loadData ()
   {
      // 7.73 — ExternProtoDeclaration function

      this .getScene () .addInitLoadCount (this);

      new InputOutput_FileLoader (this) .createX3DFromURL (this ._url, null, this .setInternalSceneAsync .bind (this));
   },
   setInternalSceneAsync (value)
   {
      if (value)
         this .setInternalScene (value);

      else
         this .setError (new Error ("File could not be loaded."));

      this .getScene () .removeInitLoadCount (this);
   },
   setInternalScene (value)
   {
      this [_scene] = value;

      const
         protoName = decodeURIComponent (new URL (this [_scene] .getWorldURL ()) .hash .substring (1)),
         proto     = protoName ? this [_scene] .protos .get (protoName) : this [_scene] .protos [0];

      if (!proto)
         throw new Error ("PROTO not found");

      this [_scene] .setLive (this .getLive () .getValue ());
      this [_scene] .setExecutionContext (this .getExecutionContext ());

      this .setLoadState (Base_X3DConstants .COMPLETE_STATE);
      this .setProtoDeclaration (proto);
   },
   getInternalScene ()
   {
      ///  Returns the internal X3DScene of this extern proto, that is loaded from the url given.

      return this [_scene];
   },
   setError (error)
   {
      console .error (`Error loading extern prototype '${this .getName ()}':`, error);

      this [_scene] = this .getBrowser () .getPrivateScene ();

      this .setLoadState (Base_X3DConstants .FAILED_STATE);
      this .setProtoDeclaration (null);
   },
   toVRMLStream (generator)
   {
      generator .string += generator .Indent ();
      generator .string += "EXTERNPROTO";
      generator .string += generator .Space ();
      generator .string += this .getName ();
      generator .string += generator .TidySpace ();
      generator .string += "[";

      const userDefinedFields = this .getUserDefinedFields ();

      if (userDefinedFields .length === 0)
      {
         generator .string += generator .TidySpace ();
      }
      else
      {
         let
            fieldTypeLength   = 0,
            accessTypeLength  = 0;

         for (const field of userDefinedFields)
         {
            fieldTypeLength  = Math .max (fieldTypeLength, field .getTypeName () .length);
            accessTypeLength = Math .max (accessTypeLength, generator .AccessType (field .getAccessType ()) .length);
         }

         generator .string += generator .TidyBreak ();

         generator .IncIndent ();

         for (const field of userDefinedFields)
         {
            this .toVRMLStreamUserDefinedField (generator, field, fieldTypeLength, accessTypeLength);

            generator .string += generator .Break ();
         }

         generator .DecIndent ();

         generator .string += generator .Indent ();
      }

      generator .string += "]";
      generator .string += generator .TidyBreak ();
      generator .string += generator .Indent ();

      this ._url .toVRMLStream (generator);
   },
   toVRMLStreamUserDefinedField (generator, field, fieldTypeLength, accessTypeLength)
   {
      generator .string += generator .Indent ();
      generator .string += generator .AccessType (field .getAccessType ()) .padEnd (accessTypeLength, " ");
      generator .string += generator .Space ();
      generator .string += field .getTypeName () .padEnd (fieldTypeLength, " ");
      generator .string += generator .Space ();
      generator .string += field .getName ();
   },
   toXMLStream (generator)
   {
      generator .string += generator .Indent ();
      generator .string += "<ExternProtoDeclare";
      generator .string += generator .Space ();
      generator .string += "name='";
      generator .string += generator .XMLEncode (this .getName ());
      generator .string += "'";
      generator .string += generator .Space ();
      generator .string += "url='";

      this ._url .toXMLStream (generator);

      generator .string += "'";
      generator .string += ">";
      generator .string += generator .TidyBreak ();

      generator .IncIndent ();

      const userDefinedFields = this .getUserDefinedFields ();

      for (const field of userDefinedFields)
      {
         generator .string += generator .Indent ();
         generator .string += "<field";
         generator .string += generator .Space ();
         generator .string += "accessType='";
         generator .string += generator .AccessType (field .getAccessType ());
         generator .string += "'";
         generator .string += generator .Space ();
         generator .string += "type='";
         generator .string += field .getTypeName ();
         generator .string += "'";
         generator .string += generator .Space ();
         generator .string += "name='";
         generator .string += generator .XMLEncode (field .getName ());
         generator .string += "'";
         generator .string += generator .closingTags ? "></field>" : "/>";
         generator .string += generator .TidyBreak ();
      }

      generator .DecIndent ();

      generator .string += generator .Indent ();
      generator .string += "</ExternProtoDeclare>";
   },
   toJSONStream (generator)
   {
      generator .string += generator .Indent ();
      generator .string += '{';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += "ExternProtoDeclare";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();
      generator .string += generator .Indent ();
      generator .string += '{';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();
      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "@name";
      generator .string += '"';
      generator .string += ':';
      generator .string += '"';
      generator .string += generator .JSONEncode (this .getName ());
      generator .string += '"';
      generator .string += ',';
      generator .string += generator .TidyBreak ();


      // Fields

      const userDefinedFields = this .getUserDefinedFields ();

      if (userDefinedFields .length)
      {
         generator .string += generator .Indent ();
         generator .string += '"';
         generator .string += "field";
         generator .string += '"';
         generator .string += ':';
         generator .string += generator .TidySpace ();
         generator .string += '[';
         generator .string += generator .TidyBreak ();
         generator .string += generator .IncIndent ();

         for (const field of userDefinedFields)
         {
            generator .string += generator .Indent ();
            generator .string += '{';
            generator .string += generator .TidyBreak ();
            generator .string += generator .IncIndent ();

            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "@accessType";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '"';
            generator .string += generator .AccessType (field .getAccessType ());
            generator .string += '"';
            generator .string += ',';
            generator .string += generator .TidyBreak ();

            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "@type";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '"';
            generator .string += field .getTypeName ();
            generator .string += '"';
            generator .string += ',';
            generator .string += generator .TidyBreak ();

            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "@name";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '"';
            generator .string += generator .JSONEncode (field .getName ());
            generator .string += '"';
            generator .string += generator .TidyBreak ();

            generator .string += generator .DecIndent ();
            generator .string += generator .Indent ();
            generator .string += '}';

            if (field !== userDefinedFields .at (-1))
               generator .string += ',';

            generator .string += generator .TidyBreak ();
         }

         generator .string += generator .DecIndent ();
         generator .string += generator .Indent ();
         generator .string += ']';
         generator .string += ',';
         generator .string += generator .TidyBreak ();
      }


      // URL

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "@url";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();

      this ._url .toJSONStream (generator);

      generator .string += generator .TidyBreak ();


      // End

      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';
      generator .string += generator .TidyBreak ();
      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';
   },
});

for (const key of Object .keys (X3DExternProtoDeclaration .prototype))
   Object .defineProperty (X3DExternProtoDeclaration .prototype, key, { enumerable: false });

Object .defineProperties (X3DExternProtoDeclaration .prototype,
{
   name:
   {
      get: X3DExternProtoDeclaration .prototype .getName,
      enumerable: true,
   },
   fields:
   {
      get: X3DExternProtoDeclaration .prototype .getFieldDefinitions,
      enumerable: true,
   },
   isExternProto:
   {
      value: true,
      enumerable: true,
   },
   urls:
   {
      get () { return this ._url; },
      enumerable: true,
   },
   loadState:
   {
      get: X3DExternProtoDeclaration .prototype .checkLoadState,
      enumerable: true,
   },
});

Object .defineProperties (X3DExternProtoDeclaration,
{
   typeName:
   {
      value: "X3DExternProtoDeclaration",
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata", new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

Base_X3DConstants .addNode (X3DExternProtoDeclaration);

const X3DExternProtoDeclaration_default_ = X3DExternProtoDeclaration;
;

x_ite_Namespace .add ("X3DExternProtoDeclaration", "x_ite/Prototype/X3DExternProtoDeclaration", X3DExternProtoDeclaration_default_);
/* harmony default export */ const Prototype_X3DExternProtoDeclaration = (X3DExternProtoDeclaration_default_);
;// CONCATENATED MODULE: ./src/x_ite/Prototype/ExternProtoDeclarationArray.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function ExternProtoDeclarationArray (values = [ ])
{
   return Base_X3DInfoArray .call (this, Array .from (values, value => [value .name, value]), Prototype_X3DExternProtoDeclaration);
}

Object .setPrototypeOf (ExternProtoDeclarationArray .prototype, Base_X3DInfoArray .prototype);

for (const key of Object .keys (ExternProtoDeclarationArray .prototype))
   Object .defineProperty (ExternProtoDeclarationArray .prototype, key, { enumerable: false });

Object .defineProperties (ExternProtoDeclarationArray,
{
   typeName:
   {
      value: "ExternProtoDeclarationArray",
      enumerable: true,
   },
});

const ExternProtoDeclarationArray_default_ = ExternProtoDeclarationArray;
;

x_ite_Namespace .add ("ExternProtoDeclarationArray", "x_ite/Prototype/ExternProtoDeclarationArray", ExternProtoDeclarationArray_default_);
/* harmony default export */ const Prototype_ExternProtoDeclarationArray = (ExternProtoDeclarationArray_default_);
;// CONCATENATED MODULE: ./src/x_ite/Prototype/ProtoDeclarationArray.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function ProtoDeclarationArray (values = [ ])
{
   return Base_X3DInfoArray .call (this, Array .from (values, value => [value .name, value]), Prototype_X3DProtoDeclaration);
}

Object .setPrototypeOf (ProtoDeclarationArray .prototype, Base_X3DInfoArray .prototype);

for (const key of Object .keys (ProtoDeclarationArray .prototype))
   Object .defineProperty (ProtoDeclarationArray .prototype, key, { enumerable: false });

Object .defineProperties (ProtoDeclarationArray,
{
   typeName:
   {
      value: "ProtoDeclarationArray",
      enumerable: true,
   },
});

const ProtoDeclarationArray_default_ = ProtoDeclarationArray;
;

x_ite_Namespace .add ("ProtoDeclarationArray", "x_ite/Prototype/ProtoDeclarationArray", ProtoDeclarationArray_default_);
/* harmony default export */ const Prototype_ProtoDeclarationArray = (ProtoDeclarationArray_default_);
;// CONCATENATED MODULE: ./src/x_ite/Routing/X3DRoute.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





const
   X3DRoute_executionContext = Symbol (),
   _sourceNode       = Symbol (),
   _sourceField      = Symbol (),
   _destinationNode  = Symbol (),
   _destinationField = Symbol ();

function X3DRoute (executionContext, sourceNode, sourceField, destinationNode, destinationField)
{
   Base_X3DObject .call (this, executionContext);

   this [X3DRoute_executionContext] = executionContext;
   this [_sourceNode]       = sourceNode;
   this [_sourceField]      = sourceField;
   this [_destinationNode]  = destinationNode;
   this [_destinationField] = destinationField;

   // Must connect in every context, to make X3DBaseNode.hasRoutes work.

   sourceField .addFieldInterest (destinationField);

   sourceField      .addOutputRoute (this);
   destinationField .addInputRoute (this);
}

Object .assign (Object .setPrototypeOf (X3DRoute .prototype, Base_X3DObject .prototype),
{
   getExecutionContext ()
   {
      return this [X3DRoute_executionContext];
   },
   getRouteId ()
   {
      return X3DRoute .getRouteId (this [_sourceField], this [_destinationField]);
   },
   getSourceNode ()
   {
      ///  SAI
      return this [_sourceNode];
   },
   getSourceField ()
   {
      ///  SAI
      return this [_sourceField];
   },
   getDestinationNode ()
   {
      ///  SAI
      return this [_destinationNode];
   },
   getDestinationField ()
   {
      ///  SAI
      return this [_destinationField];
   },
   disconnect ()
   {
      this [_sourceField] .removeFieldInterest (this [_destinationField]);

      this [_sourceField]      .removeOutputRoute (this);
      this [_destinationField] .removeInputRoute (this);
   },
   toVRMLStream (generator)
   {
      const
         sourceNodeName      = generator .LocalName (this [_sourceNode]),
         destinationNodeName = generator .LocalName (this [_destinationNode]);

      generator .string += generator .Indent ();
      generator .string += "ROUTE";
      generator .string += generator .Space ();
      generator .string += sourceNodeName;
      generator .string += ".";
      generator .string += this [_sourceField] .getName ();

      if (this [_sourceField] .getAccessType () === Base_X3DConstants .inputOutput)
         generator .string += "_changed";

      generator .string += generator .Space ();
      generator .string += "TO";
      generator .string += generator .Space ();
      generator .string += destinationNodeName;
      generator .string += ".";

      if (this [_destinationField] .getAccessType () === Base_X3DConstants .inputOutput)
         generator .string += "set_";

      generator .string += this [_destinationField] .getName ();
   },
   toXMLStream (generator)
   {
      const
         sourceNodeName      = generator .LocalName (this [_sourceNode]),
         destinationNodeName = generator .LocalName (this [_destinationNode]);

      generator .string += generator .Indent ();
      generator .string += "<ROUTE";
      generator .string += generator .Space ();
      generator .string += "fromNode='";
      generator .string += generator .XMLEncode (sourceNodeName);
      generator .string += "'";
      generator .string += generator .Space ();
      generator .string += "fromField='";
      generator .string += generator .XMLEncode (this [_sourceField] .getName ());

      if (this [_sourceField] .getAccessType () === Base_X3DConstants .inputOutput)
         generator .string += "_changed";

      generator .string += "'";
      generator .string += generator .Space ();
      generator .string += "toNode='";
      generator .string += generator .XMLEncode (destinationNodeName);
      generator .string += "'";
      generator .string += generator .Space ();
      generator .string += "toField='";

      if (this [_destinationField] .getAccessType () === Base_X3DConstants .inputOutput)
         generator .string += "set_";

      generator .string += generator .XMLEncode (this [_destinationField] .getName ());
      generator .string += "'";
      generator .string += generator .closingTags ? "></ROUTE>" : "/>";
   },
   toJSONStream (generator)
   {
      const
         sourceNodeName      = generator .LocalName (this [_sourceNode]),
         destinationNodeName = generator .LocalName (this [_destinationNode]);

      generator .string += generator .Indent ();
      generator .string += '{';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += "ROUTE";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();
      generator .string += generator .Indent ();
      generator .string += '{';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "@fromNode";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += generator .JSONEncode (sourceNodeName);
      generator .string += '"';
      generator .string += ',';
      generator .string += generator .TidyBreak ();

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "@fromField";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += generator .JSONEncode (this [_sourceField] .getName ());
      generator .string += '"';
      generator .string += ',';
      generator .string += generator .TidyBreak ();

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "@toNode";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += generator .JSONEncode (destinationNodeName);
      generator .string += '"';
      generator .string += ',';
      generator .string += generator .TidyBreak ();

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "@toField";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += generator .JSONEncode (this [_destinationField] .getName ());
      generator .string += '"';
      generator .string += generator .TidyBreak ();

      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';
      generator .string += generator .TidyBreak ();
      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';
   },
   dispose ()
   {
      this .disconnect ();

      this [X3DRoute_executionContext] .deleteRoute (this);

      Base_X3DObject .prototype .dispose .call (this);
   }
});

for (const key of Object .keys (X3DRoute .prototype))
   Object .defineProperty (X3DRoute .prototype, key, { enumerable: false });

Object .defineProperties (X3DRoute .prototype,
{
   sourceNode:
   {
      get ()
      {
         return Fields_SFNodeCache .get (this [_sourceNode]);
      },
      enumerable: true,
   },
   sourceField:
   {
      get ()
      {
         return this [_sourceField] .getName ();
      },
      enumerable: true,
   },
   destinationNode:
   {
      get ()
      {
         return Fields_SFNodeCache .get (this [_destinationNode]);
      },
      enumerable: true,
   },
   destinationField:
   {
      get ()
      {
         return this [_destinationField] .getName ();
      },
      enumerable: true,
   },
});

Object .defineProperties (X3DRoute,
{
   typeName:
   {
      value: "X3DRoute",
      enumerable: true,
   },
});

Object .assign (X3DRoute,
{
   getRouteId (sourceField, destinationField)
   {
      return `${sourceField .getId ()}.${destinationField .getId ()}`;
   },
});

const X3DRoute_default_ = X3DRoute;
;

x_ite_Namespace .add ("X3DRoute", "x_ite/Routing/X3DRoute", X3DRoute_default_);
/* harmony default export */ const Routing_X3DRoute = (X3DRoute_default_);
;// CONCATENATED MODULE: ./src/x_ite/Routing/RouteArray.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function RouteArray (values = [ ])
{
   return Base_X3DInfoArray .call (this, Array .from (values, value => [value .getId (), value]), Routing_X3DRoute);
}

Object .setPrototypeOf (RouteArray .prototype, Base_X3DInfoArray .prototype);

for (const key of Object .keys (RouteArray .prototype))
   Object .defineProperty (RouteArray .prototype, key, { enumerable: false });

Object .defineProperties (RouteArray,
{
   typeName:
   {
      value: "RouteArray",
      enumerable: true,
   },
});

const RouteArray_default_ = RouteArray;
;

x_ite_Namespace .add ("RouteArray", "x_ite/Routing/RouteArray", RouteArray_default_);
/* harmony default export */ const Routing_RouteArray = (RouteArray_default_);
;// CONCATENATED MODULE: ./src/x_ite/Execution/X3DExecutionContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

















const
   _namedNodes     = Symbol (),
   _importedNodes  = Symbol (),
   _protos         = Symbol (),
   _externprotos   = Symbol (),
   X3DExecutionContext_routes         = Symbol (),
   _outerNode      = Symbol ();

function X3DExecutionContext (executionContext, outerNode = null, browser = executionContext .getBrowser ())
{
   Base_X3DBaseNode .call (this, executionContext, browser);

   this .addType (Base_X3DConstants .X3DExecutionContext)

   this .addChildObjects (Base_X3DConstants .initializeOnly, "rootNodes",          new x_ite_Fields .MFNode (),
                          Base_X3DConstants .outputOnly,     "worldInfos",         new x_ite_Fields .MFNode (),
                          Base_X3DConstants .outputOnly,     "sceneGraph_changed", new x_ite_Fields .SFTime ())

   this ._rootNodes .collectCloneCount = () => 1;

   this [_outerNode]     = outerNode;
   this [_namedNodes]    = new Execution_NamedNodesArray ();
   this [_importedNodes] = new Execution_ImportedNodesArray ();
   this [_protos]        = new Prototype_ProtoDeclarationArray ();
   this [_externprotos]  = new Prototype_ExternProtoDeclarationArray ();
   this [X3DExecutionContext_routes]        = new Routing_RouteArray ();

   this [_namedNodes]     .addParent (this);
   this [_importedNodes]  .addParent (this);
   this [_protos]         .addParent (this);
   this [_externprotos]   .addParent (this);
   this [X3DExecutionContext_routes]         .addParent (this);
}

Object .assign (Object .setPrototypeOf (X3DExecutionContext .prototype, Base_X3DBaseNode .prototype),
{
   initialize ()
   {
      Base_X3DBaseNode .prototype .initialize .call (this);

      if (!this .isScene ())
         this ._sceneGraph_changed .addInterest ("set_sceneGraph", this)
   },
   set_sceneGraph ()
   {
      this .getExecutionContext () ._sceneGraph_changed = this .getBrowser () .getCurrentTime ();
   },
   isScene ()
   {
      return false;
   },
   getOuterNode ()
   {
      // Can be either of type X3DProtoDeclaration or X3DPrototypeInstance, or null.
      return this [_outerNode];
   },
   getSpecificationVersion ()
   {
      return this .getExecutionContext () .getSpecificationVersion ();
   },
   getEncoding ()
   {
      return this .getExecutionContext () .getEncoding ();
   },
   getWorldURL ()
   {
      return this .getExecutionContext () .getWorldURL ();
   },
   getBaseURL ()
   {
      return this .getExecutionContext () .getBaseURL ();
   },
   getProfile ()
   {
      return this .getExecutionContext () .getProfile ();
   },
   hasComponent (name, level)
   {
      return this .getExecutionContext () .hasComponent (name, level);
   },
   getComponents ()
   {
      return this .getExecutionContext () .getComponents ();
   },
   fromUnit (category, value)
   {
      return this .getExecutionContext () .fromUnit (category, value);
   },
   toUnit (category, value)
   {
      return this .getExecutionContext () .toUnit (category, value);
   },
   getUnits ()
   {
      return this .getExecutionContext () .getUnits ();
   },
   createNode (typeName, setup = true /* non-public argument */)
   {
      typeName = String (typeName);

      if (setup === false)
      {
         const ConcreteNode = this .getBrowser () .getConcreteNodes () .get (typeName);

         if (!ConcreteNode)
            return null;

         const specificationRange = ConcreteNode .specificationRange;

         if (this .getSpecificationVersion () < specificationRange [0])
            return null;

         if (this .getSpecificationVersion () > specificationRange [1])
            return null;

         if (!this .hasComponent (ConcreteNode .componentName))
            console .warn (`Node type '${typeName}' does not match component/profile statements in '${this .getWorldURL ()}'.`);

         return new ConcreteNode (this);
      }
      else
      {
         const ConcreteNode = this .getBrowser () .getConcreteNodes () .get (typeName);

         if (!ConcreteNode)
            throw new Error (`Unknown node type '${typeName}'.`);

         const specificationRange = ConcreteNode .specificationRange;

         if (this .getSpecificationVersion () < specificationRange [0])
            throw new Error (`Node type '${typeName}' does not match specification version in '${this .getWorldURL ()}.`);

         if (this .getSpecificationVersion () > specificationRange [1])
            throw new Error (`Node type '${typeName}' does not match specification version in '${this .getWorldURL ()}.`);

         if (!this .hasComponent (ConcreteNode .componentName))
            console .warn (`Node type '${typeName}' does not match component/profile statements in '${this .getWorldURL ()}'.`);

         const baseNode = new ConcreteNode (this);

         baseNode .setup ();

         return Fields_SFNodeCache .get (baseNode);
      }
   },
   createProto (name, setup = true /* non-public argument */)
   {
      name = String (name);

      for (let executionContext = this;;)
      {
         const protoNode = executionContext .protos .get (name)
            ?? executionContext .externprotos .get (name);

         if (protoNode)
            return protoNode .createInstance (this, setup);

         if (executionContext .isScene ())
            break;

         executionContext = executionContext .getExecutionContext ();
      }

      if (setup === false)
         return null;

      throw new Error (`Unknown proto or externproto type '${name}'.`);
   },
   addNamedNode (name, node)
   {
      name = String (name);
      node = Base_X3DCast (Base_X3DConstants .X3DNode, node, false);

      if (!node)
         throw new Error ("Couldn't add named node: node must be of type X3DNode.");

      if (node .getExecutionContext () !== this)
         throw new Error ("Couldn't add named node: node does not belong to this execution context.");

      if (name .length === 0)
         throw new Error ("Couldn't add named node: node name is empty.");

      if (this [_namedNodes] .has (name))
         throw new Error (`Couldn't add named node: node named '${name}' is already in use.`);

      if (this [_namedNodes] .get (node .getName ()) ?.getValue () === node)
         throw new Error (`Couldn't add named node: node named '${node .getName ()}' is already added.`);

      // Add named node.

      node .setName (name);

      this [_namedNodes] .add (name, Fields_SFNodeCache .get (node));
   },
   updateNamedNode (name, node)
   {
      name = String (name);
      node = Base_X3DCast (Base_X3DConstants .X3DNode, node, false);

      if (!node)
         throw new Error ("Couldn't update named node: node must be of type X3DNode.");

      if (node .getExecutionContext () !== this)
         throw new Error ("Couldn't update named node: node does not belong to this execution context.");

      if (name .length === 0)
         throw new Error ("Couldn't update named node: node name is empty.");

      // Remove named node.

      this .removeNamedNode (node .getName ());
      this .removeNamedNode (name);

      // Update named node.

      node .setName (name);

      this [_namedNodes] .add (name, Fields_SFNodeCache .get (node));

      this ._namedNodes_changed = this .getBrowser () .getCurrentTime ();
   },
   removeNamedNode (name)
   {
      name = String (name);

      const node = this [_namedNodes] .get (name);

      if (!node || !node .getValue ())
         return;

      node .getValue () .setName ("");

      this [_namedNodes] .remove (name);

      this ._namedNodes_changed = this .getBrowser () .getCurrentTime ();
   },
   getNamedNode (name)
   {
      name = String (name);

      const node = this [_namedNodes] .get (name);

      if (node)
         return node;

      throw new Error (`Named node '${name}' not found.`);
   },
   getNamedNodes ()
   {
      return this [_namedNodes];
   },
   getUniqueName (name)
   {
      return getUniqueName (this [_namedNodes], name);
   },
   addImportedNode (inlineNode, exportedName, importedName = exportedName)
   {
      exportedName = String (exportedName);
      importedName = String (importedName);

      if (this [_importedNodes] .has (importedName))
         throw new Error (`Couldn't add imported node: imported name '${importedName}' already in use.`);

      this .updateImportedNode (inlineNode, exportedName, importedName);
   },
   updateImportedNode (inlineNode, exportedName, importedName)
   {
      inlineNode   = Base_X3DCast (Base_X3DConstants .Inline, inlineNode, false);
      exportedName = String (exportedName);
      importedName = importedName === undefined ? exportedName : String (importedName);

      if (!inlineNode)
         throw new Error ("Node must be of type Inline node.");

      if (inlineNode .getExecutionContext () !== this)
         throw new Error ("Couldn't update imported node: Inline node does not belong to this execution context.");

      if (exportedName .length === 0)
         throw new Error ("Couldn't update imported node: exported name is empty.");

      if (importedName .length === 0)
         throw new Error ("Couldn't update imported node: imported name is empty.");

      // Update imported node.

      this .removeImportedNode (importedName);

      const importedNode = new Execution_X3DImportedNode (this, inlineNode, exportedName, importedName);

      this [_importedNodes] .add (importedName, importedNode);

      this ._importedNodes_changed = this .getBrowser () .getCurrentTime ();
   },
   removeImportedNode (importedName)
   {
      importedName = String (importedName);

      const importedNode = this [_importedNodes] .get (importedName);

      if (!importedNode)
         return;

      importedNode .dispose ();

      this [_importedNodes] .remove (importedName);

      this ._importedNodes_changed = this .getBrowser () .getCurrentTime ();
   },
   getImportedNode (importedName)
   {
      importedName = String (importedName);

      const importedNode = this [_importedNodes] .get (importedName);

      if (importedNode)
         return Fields_SFNodeCache .get (importedNode .getExportedNode ());

      throw new Error (`Imported node '${importedName}' not found.`);
   },
   getImportedNodes ()
   {
      return this [_importedNodes];
   },
   getLocalNode (name)
   {
      name = String (name);

      try
      {
         return this .getNamedNode (name);
      }
      catch
      {
         const importedNode = this [_importedNodes] .get (name);

         if (importedNode)
            return Fields_SFNodeCache .get (importedNode);

         throw new Error (`Unknown named or imported node '${name}'.`);
      }
   },
   getLocalName (node)
   {
      node = Base_X3DCast (Base_X3DConstants .X3DNode, node, false);

      if (!node)
         throw new Error ("Couldn't get local name: node must be of type X3DNode.");

      if (node .getExecutionContext () === this)
         return node .getName ();

      for (const importedNode of this [_importedNodes])
      {
         try
         {
            if (importedNode .getExportedNode () === node)
               return importedNode .getImportedName ();
         }
         catch
         { }
      }

      throw new Error ("Couldn't get local name: node is shared.");
   },
   setRootNodes () { },
   getRootNodes ()
   {
      return this ._rootNodes;
   },
   getProtoDeclaration (name)
   {
      name = String (name);

      const proto = this [_protos] .get (name);

      if (proto)
         return proto;

      throw new Error (`Proto declaration '${name}' not found.`);
   },
   addProtoDeclaration (name, proto)
   {
      name = String (name);

      if (!(proto instanceof Prototype_X3DProtoDeclaration))
         throw new Error ("Couldn't add proto declaration: proto must be of type X3DProtoDeclaration.");

      if (proto .getExecutionContext () !== this)
         throw new Error ("Couldn't add proto declaration: proto does not belong to this execution context.");

      if (this [_protos] .get (name))
         throw new Error (`Couldn't add proto declaration: proto '${name}' already in use.`);

      if (this [_protos] .get (proto .getName ()) === proto)
         throw new Error (`Couldn't add proto declaration: proto '${proto .getName ()}' already added.`);

      name = String (name);

      if (name .length === 0)
         throw new Error ("Couldn't add proto declaration: proto name is empty.");

      this [_protos] .add (name, proto);
      proto .setName (name);

      this ._protos_changed = this .getBrowser () .getCurrentTime ();
   },
   updateProtoDeclaration (name, proto)
   {
      name = String (name);

      if (!(proto instanceof Prototype_X3DProtoDeclaration))
         throw new Error ("Couldn't update proto declaration: proto must be of type X3DProtoDeclaration.");

      if (proto .getExecutionContext () !== this)
         throw new Error ("Couldn't update proto declaration: proto does not belong to this execution context.");

      name = String (name);

      if (name .length === 0)
         throw new Error ("Couldn't update proto declaration: proto name is empty.");

      this [_protos] .update (proto .getName (), name, proto);
      proto .setName (name);

      this ._protos_changed = this .getBrowser () .getCurrentTime ();
   },
   removeProtoDeclaration (name)
   {
      name = String (name);

      this [_protos] .remove (name);

      this ._protos_changed = this .getBrowser () .getCurrentTime ();
   },
   getProtoDeclarations ()
   {
      return this [_protos];
   },
   getUniqueProtoName (name)
   {
      return getUniqueName (this [_protos], name);
   },
   getExternProtoDeclaration (name)
   {
      name = String (name);

      const externproto = this [_externprotos] .get (name);

      if (externproto)
         return externproto;

      throw new Error (`Extern proto declaration '${name}' not found.`);
   },
   addExternProtoDeclaration (name, externproto)
   {
      name = String (name);

      if (!(externproto instanceof Prototype_X3DExternProtoDeclaration))
         throw new Error ("Couldn't add extern proto declaration: extern proto must be of type X3DExternProtoDeclaration.");

      if (externproto .getExecutionContext () !== this)
         throw new Error ("Couldn't add extern proto declaration: extern proto does not belong to this execution context.");

      if (this [_externprotos] .get (name))
         throw new Error (`Couldn't add extern proto declaration: extern proto '${name}' already in use.`);

      if (this [_externprotos] .get (externproto .getName ()) === externproto)
         throw new Error (`Couldn't add extern proto declaration: extern proto '${externproto .getName ()}' already added.`);

      name = String (name);

      if (name .length === 0)
         throw new Error ("Couldn't add extern proto declaration: extern proto name is empty.");

      this [_externprotos] .add (name, externproto);
      externproto .setName (name);

      this ._externprotos_changed = this .getBrowser () .getCurrentTime ();
   },
   updateExternProtoDeclaration (name, externproto)
   {
      name = String (name);

      if (!(externproto instanceof Prototype_X3DExternProtoDeclaration))
         throw new Error ("Couldn't update extern proto declaration: extern proto must be of type X3DExternProtoDeclaration.");

      if (externproto .getExecutionContext () !== this)
         throw new Error ("Couldn't update extern proto declaration: extern proto does not belong to this execution context.");

      name = String (name);

      if (name .length === 0)
         throw new Error ("Couldn't update extern proto declaration: extern proto name is empty.");

      this [_externprotos] .update (externproto .getName (), name, externproto);
      externproto .setName (name);

      this ._externprotos_changed = this .getBrowser () .getCurrentTime ();
   },
   removeExternProtoDeclaration (name)
   {
      name = String (name);

      this [_externprotos] .remove (name);

      this ._externprotos_changed = this .getBrowser () .getCurrentTime ();
   },
   getExternProtoDeclarations ()
   {
      return this [_externprotos];
   },
   getUniqueExternProtoName (name)
   {
      return getUniqueName (this [_externprotos], name);
   },
   addRoute (sourceNode, sourceField, destinationNode, destinationField)
   {
      sourceNode       = Base_X3DCast (Base_X3DConstants .X3DNode, sourceNode, false);
      sourceField      = String (sourceField);
      destinationNode  = Base_X3DCast (Base_X3DConstants .X3DNode, destinationNode, false);
      destinationField = String (destinationField);

      if (!sourceNode)
         throw new Error ("Bad ROUTE specification: source node must be of type X3DNode.");

      if (!destinationNode)
         throw new Error ("Bad ROUTE specification: destination node must be of type X3DNode.");

      // Imported nodes handling.

      let
         importedSourceNode      = sourceNode      instanceof Execution_X3DImportedNode ? sourceNode      : null,
         importedDestinationNode = destinationNode instanceof Execution_X3DImportedNode ? destinationNode : null;

      try
      {
         // If sourceNode is shared node try to find the corresponding X3DImportedNode.
         if (sourceNode .getExecutionContext () !== this)
            importedSourceNode = this .getLocalNode (this .getLocalName (sourceNode)) .getValue ();
      }
      catch
      {
         // Source node is shared but not imported.
      }

      try
      {
         // If destinationNode is shared node try to find the corresponding X3DImportedNode.
         if (destinationNode .getExecutionContext () !== this)
            importedDestinationNode = this .getLocalNode (this .getLocalName (destinationNode)) .getValue ();
      }
      catch
      {
         // Destination node is shared but not imported.
      }

      if (importedSourceNode instanceof Execution_X3DImportedNode && importedDestinationNode instanceof Execution_X3DImportedNode)
      {
         importedSourceNode      .addRoute (importedSourceNode, sourceField, importedDestinationNode, destinationField);
         importedDestinationNode .addRoute (importedSourceNode, sourceField, importedDestinationNode, destinationField);
      }
      else if (importedSourceNode instanceof Execution_X3DImportedNode)
      {
         importedSourceNode .addRoute (importedSourceNode, sourceField, destinationNode, destinationField);
      }
      else if (importedDestinationNode instanceof Execution_X3DImportedNode)
      {
         importedDestinationNode .addRoute (sourceNode, sourceField, importedDestinationNode, destinationField);
      }

      // If either sourceNode or destinationNode is an X3DImportedNode return here without value.
      if (importedSourceNode === sourceNode || importedDestinationNode === destinationNode)
         return;

      // Create route and return.

      return this .addSimpleRoute (sourceNode, sourceField, destinationNode, destinationField);
   },
   addSimpleRoute (sourceNode, sourceField, destinationNode, destinationField)
   {
      // Source and dest node are here X3DBaseNode.

      try
      {
         // Private function.
         // Create route and return.

         sourceField      = sourceNode      .getField (sourceField),
         destinationField = destinationNode .getField (destinationField);

         if (!sourceField .isOutput ())
            throw new Error (`Field named '${sourceField .getName ()}' in node named '${sourceNode .getName ()}' of type ${sourceNode .getTypeName ()} is not an output field.`);

         if (!destinationField .isInput ())
            throw new Error (`Field named '${destinationField .getName ()}' in node named '${destinationNode .getName ()}' of type ${destinationNode .getTypeName ()} is not an input field.`);

         if (sourceField .getType () !== destinationField .getType ())
            throw new Error (`ROUTE types ${sourceField .getTypeName ()} and ${destinationField .getTypeName ()} do not match.`);

         const id = Routing_X3DRoute .getRouteId (sourceField, destinationField);

         let route = this [X3DExecutionContext_routes] .get (id);

         if (route)
            return route;

         route = new Routing_X3DRoute (this, sourceNode, sourceField, destinationNode, destinationField);

         this [X3DExecutionContext_routes] .add (id, route);

         this ._routes_changed = this .getBrowser () .getCurrentTime ();

         return route;
      }
      catch (error)
      {
         throw new Error (`Bad ROUTE specification: ${error .message}`);
      }
   },
   deleteRoute (route)
   {
      // sourceNode, sourceField, destinationNode, destinationField
      if (arguments .length === 4)
         route = this .getRoute (... arguments);

      if (!(route instanceof Routing_X3DRoute))
         return;

      if (route .getExecutionContext () !== this)
         return;

      this .deleteSimpleRoute (route);
      this .deleteImportedRoute (route .sourceNode, route .destinationNode, route);
   },
   deleteSimpleRoute (route)
   {
      this [X3DExecutionContext_routes] .remove (route .getRouteId ());

      route .disconnect ();

      this ._routes_changed = this .getBrowser () .getCurrentTime ();
   },
   deleteImportedRoute (sourceNode, destinationNode, route)
   {
      // Imported nodes handling.

      let
         importedSourceNode      = null,
         importedDestinationNode = null;

      try
      {
         // If sourceNode is shared node try to find the corresponding X3DImportedNode.
         if (sourceNode .getValue () .getExecutionContext () !== this)
            importedSourceNode = this .getLocalNode (this .getLocalName (sourceNode)) .getValue ();
      }
      catch
      {
         // Source node is shared but not imported.
      }

      try
      {
         // If destinationNode is shared node try to find the corresponding X3DImportedNode.
         if (destinationNode .getValue () .getExecutionContext () !== this)
            importedDestinationNode = this .getLocalNode (this .getLocalName (destinationNode)) .getValue ();
      }
      catch
      {
         // Destination node is shared but not imported.
      }

      if (importedSourceNode instanceof Execution_X3DImportedNode && importedDestinationNode instanceof Execution_X3DImportedNode)
      {
         importedSourceNode      .deleteRoute (route);
         importedDestinationNode .deleteRoute (route);
      }
      else if (importedSourceNode instanceof Execution_X3DImportedNode)
      {
         importedSourceNode .deleteRoute (route);
      }
      else if (importedDestinationNode instanceof Execution_X3DImportedNode)
      {
         importedDestinationNode .deleteRoute (route);
      }
   },
   getRoute (sourceNode, sourceField, destinationNode, destinationField)
   {
      sourceNode       = Base_X3DCast (Base_X3DConstants .X3DNode, sourceNode, false);
      sourceField      = String (sourceField)
      destinationNode  = Base_X3DCast (Base_X3DConstants .X3DNode, destinationNode, false);
      destinationField = String (destinationField)

      if (!sourceNode)
         throw new Error ("Bad ROUTE specification: sourceNode must be of type X3DNode.");

      if (!destinationNode)
         throw new Error ("Bad ROUTE specification: destinationNode must be of type X3DNode.");

      sourceField      = sourceNode      .getField (sourceField);
      destinationField = destinationNode .getField (destinationField);

      return this [X3DExecutionContext_routes] .get (Routing_X3DRoute .getRouteId (sourceField, destinationField));
   },
   getRoutes ()
   {
      return this [X3DExecutionContext_routes];
   },
   getWorldInfos ()
   {
      return this ._worldInfos;
   },
   addWorldInfo (worldInfoNode)
   {
      this ._worldInfos .push (worldInfoNode);
   },
   removeWorldInfo (worldInfoNode)
   {
      for (let i = this ._worldInfos .length - 1; i >= 0; -- i)
      {
         if (this ._worldInfos [i] .getValue () === worldInfoNode)
            this ._worldInfos .splice (i, 1);
      }
   },
   toVRMLStream (generator)
   {
      generator .PushExecutionContext (this);
      generator .EnterScope ();
      generator .NamedNodes (this .getNamedNodes ());
      generator .ImportedNodes (this .getImportedNodes ());

      // Output extern protos

      this .getExternProtoDeclarations () .toVRMLStream (generator);

      // Output protos

      this .getProtoDeclarations () .toVRMLStream (generator);

      // Output root nodes

      const rootNodes = this .getRootNodes ();

      for (let i = 0, length = rootNodes .length; i < length; ++ i)
      {
         const rootNode = rootNodes [i];

         generator .string += generator .Indent ();

         if (rootNode)
            rootNode .toVRMLStream (generator);
         else
            generator .string += "NULL";

         generator .string += generator .TidyBreak ();

         if (i !== length - 1)
            generator .string += generator .TidyBreak ();
      }

      // Output imported nodes

      const importedNodes = this .getImportedNodes ();

      if (importedNodes .length)
      {
         generator .string += generator .TidyBreak ();

         importedNodes .toVRMLStream (generator);
      }

      // Output routes

      const routes = this .getRoutes ();

      if (routes .length)
      {
         generator .string += generator .TidyBreak ();

         routes .toVRMLStream (generator);
      }

      generator .LeaveScope ();
      generator .PopExecutionContext ();
   },
   toXMLStream (generator)
   {
      generator .PushExecutionContext (this);
      generator .EnterScope ();
      generator .NamedNodes (this .getNamedNodes ());
      generator .ImportedNodes (this .getImportedNodes ());

      // Output extern protos

      this .getExternProtoDeclarations () .toXMLStream (generator);

      // Output protos

      this .getProtoDeclarations () .toXMLStream (generator);

      // Output root nodes

      const rootNodes = this .getRootNodes ();

      if (rootNodes .length)
      {
         rootNodes .toXMLStream (generator);

         generator .string += generator .TidyBreak ();
      }

      // Output imported nodes

      this .getImportedNodes () .toXMLStream (generator);

      // Output routes

      this .getRoutes () .toXMLStream (generator);

      generator .LeaveScope ();
      generator .PopExecutionContext ();
   },
   toJSONStream (generator)
   {
      generator .PushExecutionContext (this);
      generator .EnterScope ();
      generator .NamedNodes (this .getNamedNodes ());
      generator .ImportedNodes (this .getImportedNodes ());


      // Extern proto declarations

      this .getExternProtoDeclarations () .toJSONStream (generator, true);


      // Proto declarations

      this .getProtoDeclarations () .toJSONStream (generator, true);


      // Root nodes

      if (this .getRootNodes () .length)
      {
         for (const rootNode of this .getRootNodes ())
         {
            generator .string += generator .Indent ();

            if (rootNode)
            {
               rootNode .toJSONStream (generator);
            }
            else
            {
               generator .string += generator .Indent ();
               generator .string += "null";
            }

            generator .string += ',';
            generator .string += generator .TidyBreak ();
         }
      }


      // Imported nodes

      this .getImportedNodes () .toJSONStream (generator, true);


      // Routes

      this .getRoutes () .toJSONStream (generator, true);


      generator .LeaveScope ();
      generator .PopExecutionContext ();
   },
   dispose ()
   {
      for (const route of [... this [X3DExecutionContext_routes]])
         this .deleteRoute (route);

      Base_X3DBaseNode .prototype .dispose .call (this);
   },
});

for (const key of Object .keys (X3DExecutionContext .prototype))
   Object .defineProperty (X3DExecutionContext .prototype, key, { enumerable: false });

Object .defineProperties (X3DExecutionContext .prototype,
{
   specificationVersion:
   {
      get: X3DExecutionContext .prototype .getSpecificationVersion,
      enumerable: true,
   },
   encoding:
   {
      get: X3DExecutionContext .prototype .getEncoding,
      enumerable: true,
   },
   profile:
   {
      get: X3DExecutionContext .prototype .getProfile,
      enumerable: true,
   },
   components:
   {
      get: X3DExecutionContext .prototype .getComponents,
      enumerable: true,
   },
   worldURL:
   {
      get: X3DExecutionContext .prototype .getWorldURL,
      enumerable: true,
   },
   baseURL:
   {
      get: X3DExecutionContext .prototype .getBaseURL,
      enumerable: true,
   },
   units:
   {
      get: X3DExecutionContext .prototype .getUnits,
      enumerable: true,
   },
   namedNodes:
   {
      get: X3DExecutionContext .prototype .getNamedNodes,
      enumerable: true,
   },
   importedNodes:
   {
      get: X3DExecutionContext .prototype .getImportedNodes,
      enumerable: true,
   },
   rootNodes:
   {
      get: X3DExecutionContext .prototype .getRootNodes,
      set: X3DExecutionContext .prototype .setRootNodes,
      enumerable: true,
   },
   protos:
   {
      get: X3DExecutionContext .prototype .getProtoDeclarations,
      enumerable: true,
   },
   externprotos:
   {
      get: X3DExecutionContext .prototype .getExternProtoDeclarations,
      enumerable: true,
   },
   routes:
   {
      get: X3DExecutionContext .prototype .getRoutes,
      enumerable: true,
   },
});

Object .defineProperties (X3DExecutionContext,
{
   typeName:
   {
      value: "X3DExecutionContext",
      enumerable: true,
   },
});

Base_X3DConstants .addNode (X3DExecutionContext);

const X3DExecutionContext_default_ = X3DExecutionContext;
;

x_ite_Namespace .add ("X3DExecutionContext", "x_ite/Execution/X3DExecutionContext", X3DExecutionContext_default_);
/* harmony default export */ const Execution_X3DExecutionContext = (X3DExecutionContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Core/X3DPrototypeInstance.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







const
   X3DPrototypeInstance_fieldDefinitions = Symbol .for ("X_ITE.X3DBaseNode.fieldDefinitions"),
   _protoNode        = Symbol (),
   _protoFields      = Symbol (),
   X3DPrototypeInstance_body             = Symbol ();

function X3DPrototypeInstance (executionContext, protoNode)
{
   this [_protoNode]        = protoNode;
   this [X3DPrototypeInstance_fieldDefinitions] = new Base_FieldDefinitionArray (protoNode .getFieldDefinitions ());
   this [X3DPrototypeInstance_body]             = null;

   Core_X3DNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DPrototypeInstance);
}

Object .assign (Object .setPrototypeOf (X3DPrototypeInstance .prototype, Core_X3DNode .prototype),
{
   create (executionContext)
   {
      return new X3DPrototypeInstance (executionContext, this [_protoNode]);
   },
   getTypeName ()
   {
      return this [_protoNode] .getName ();
   },
   initialize ()
   {
      Core_X3DNode .prototype .initialize .call (this);

      this .setProtoNode (this [_protoNode]);
   },
   construct ()
   {
      this [X3DPrototypeInstance_body] ?.dispose ();

      const
         protoNode = this [_protoNode],
         proto     = protoNode .getProtoDeclaration ();

      // Assign field definitions.

      this [X3DPrototypeInstance_fieldDefinitions] .assign (protoNode .getFieldDefinitions ());

      // If there is a proto, the externproto is completely loaded.

      if (protoNode .isExternProto)
      {
         if (protoNode .checkLoadState () !== Base_X3DConstants .COMPLETE_STATE)
         {
            this [X3DPrototypeInstance_body] = null;

            if (this .isInitialized ())
               Base_X3DChildObject .prototype .addEvent .call (this);

            protoNode ._updateInstances .addInterest ("construct", this);
            protoNode .requestImmediateLoad () .catch (Function .prototype);

            return;
         }

         for (const protoField of proto .getUserDefinedFields ())
         {
            try
            {
               const field = this .getField (protoField .getName ());

               // Continue if something is wrong.
               if (field .getAccessType () !== protoField .getAccessType ())
                  continue;

               // Continue if something is wrong.
               if (field .getType () !== protoField .getType ())
                  continue;

               // Continue if field is eventIn or eventOut.
               if (!field .isInitializable ())
                  continue;

               // Is set during parse.
               if (field .getModificationTime ())
                  continue;

               // Has IS references.
               if (field .hasReferences ())
                  continue;

               if (field .equals (protoField))
                  continue;

               // If default value of protoField is different from field, thus update default value for field.
               field .assign (protoField);
            }
            catch
            {
               // Definition exists in proto but does not exist in extern proto.
               this .addPredefinedField (proto .getFieldDefinitions () .get (protoField .getName ()));
            }
         }
      }

      // Create execution context.

      this [X3DPrototypeInstance_body] = new Execution_X3DExecutionContext (proto .getExecutionContext (), this);

      // Copy proto.

      this .importExternProtos (proto .getBody () .externprotos);
      this .importProtos       (proto .getBody () .protos);
      this .copyRootNodes      (proto .getBody () .rootNodes);
      this .copyImportedNodes  (proto .getBody (), proto .getBody () .getImportedNodes ());
      this .copyRoutes         (proto .getBody (), proto .getBody () .routes);

      this [X3DPrototypeInstance_body] .setup ();

      if (this .isInitialized ())
         Base_X3DChildObject .prototype .addEvent .call (this);

      protoNode ._updateInstances .removeInterest ("construct", this);
      protoNode ._updateInstances .addInterest ("update", this);
   },
   update ()
   {
      // Remove old fields.

      const
         oldProtoFields = this [_protoFields],
         oldFields      = new Map (Array .from (this .getPredefinedFields (), f => [f .getName (), f]));

      for (const field of oldFields .values ())
         this .removePredefinedField (field .getName ());

      // Add new fields.

      this [_protoFields] = new Map (Array .from (this [_protoNode] .getUserDefinedFields (), f => [f, f .getName ()]));

      for (const fieldDefinition of this [_protoNode] .getFieldDefinitions ())
         this .addPredefinedField (fieldDefinition);

      // Reuse old fields, and therefor routes.

      for (const protoField of this [_protoFields] .keys ())
      {
         const oldFieldName = oldProtoFields .get (protoField);

         if (!oldFieldName)
            continue;

         const
            newField = this .getPredefinedFields () .get (protoField .getName ()),
            oldField = oldFields .get (oldFieldName);

         if (!oldField)
            continue;

         oldField .addParent (this);
         oldField .setAccessType (newField .getAccessType ());
         oldField .setName (newField .getName ());

         this .getPredefinedFields () .update (newField .getName (), newField .getName (), oldField);

         oldFields .delete (oldFieldName);
         newField .dispose ();
      }

      for (const oldField of oldFields .values ())
         oldField .dispose ();

      // Construct now.

      this .construct ();
   },
   getExtendedEventHandling ()
   {
      return false;
   },
   getProtoNode ()
   {
      return this [_protoNode];
   },
   setProtoNode (protoNode)
   {
      // Disconnect old proto node.

      const oldProtoNode = this [_protoNode];

      oldProtoNode ._name_changed .removeFieldInterest (this ._typeName_changed);
      oldProtoNode ._updateInstances .removeInterest ("construct", this);
      oldProtoNode ._updateInstances .removeInterest ("update",    this);

      // Get fields from new proto node.

      this [_protoNode]   = protoNode;
      this [_protoFields] = new Map (Array .from (protoNode .getUserDefinedFields (), f => [f, f .getName ()]));

      protoNode ._name_changed .addFieldInterest (this ._typeName_changed);

      protoNode === oldProtoNode ? this .construct () : this .update ();
   },
   getBody ()
   {
      return this [X3DPrototypeInstance_body];
   },
   getInnerNode ()
   {
      if (this [X3DPrototypeInstance_body])
      {
         const rootNodes = this [X3DPrototypeInstance_body] .getRootNodes ();

         if (rootNodes .length)
         {
            const rootNode = rootNodes [0];

            if (rootNode)
               return rootNode .getValue () .getInnerNode ();
         }
      }

      throw new Error ("Root node not available.");
   },
   importExternProtos (externprotos1)
   {
      const externprotos2 = this [X3DPrototypeInstance_body] .externprotos;

      for (const externproto of externprotos1)
         externprotos2 .add (externproto .getName (), externproto);
   },
   importProtos (protos1)
   {
      const protos2 = this [X3DPrototypeInstance_body] .protos;

      for (const proto of protos1)
         protos2 .add (proto .getName (), proto);
   },
   copyRootNodes (rootNodes1)
   {
      const rootNodes2 = this [X3DPrototypeInstance_body] .getRootNodes ();

      for (const node of rootNodes1)
         rootNodes2 .push (node .copy (this));
   },
   copyImportedNodes (executionContext, importedNodes)
   {
      for (const importedNode of importedNodes)
      {
         try
         {
            const
               inlineNode   = this [X3DPrototypeInstance_body] .getNamedNode (importedNode .getInlineNode () .getName ()),
               importedName = importedNode .getImportedName (),
               exportedName = importedNode .getExportedName ();

            this [X3DPrototypeInstance_body] .addImportedNode (inlineNode, exportedName, importedName);
         }
         catch (error)
         {
            console .error ("Bad IMPORT specification in copy: ", error);
         }
      }
   },
   copyRoutes (executionContext, routes)
   {
      for (const route of routes)
      {
         try
         {
            const
               sourceNode      = this [X3DPrototypeInstance_body] .getLocalNode (executionContext .getLocalName (route .sourceNode)),
               destinationNode = this [X3DPrototypeInstance_body] .getLocalNode (executionContext .getLocalName (route .destinationNode));

            this [X3DPrototypeInstance_body] .addRoute (sourceNode, route .sourceField, destinationNode, route .destinationField);
         }
         catch (error)
         {
            console .error (error);
         }
      }
   },
   toXMLStream (generator)
   {
      const sharedNode = generator .IsSharedNode (this);

      generator .EnterScope ();

      const name = generator .Name (this);

      if (name .length)
      {
         if (generator .ExistsNode (this))
         {
            generator .string += generator .Indent ();
            generator .string += "<ProtoInstance";
            generator .string += generator .Space ();
            generator .string += "name='";
            generator .string += generator .XMLEncode (this .getTypeName ());
            generator .string += "'";
            generator .string += generator .Space ();
            generator .string += "USE='";
            generator .string += generator .XMLEncode (name);
            generator .string += "'";

            const containerField = generator .ContainerField ();

            if (containerField)
            {
               if (containerField .getName () !== this .getContainerField ())
               {
                  generator .string += generator .Space ();
                  generator .string += "containerField='";
                  generator .string += generator .XMLEncode (containerField .getName ());
                  generator .string += "'";
               }
            }

            generator .string += generator .closingTags ? "></ProtoInstance>" : "/>";

            generator .LeaveScope ();
            return;
         }
      }

      generator .string += generator .Indent ();
      generator .string += "<ProtoInstance";
      generator .string += generator .Space ();
      generator .string += "name='";
      generator .string += generator .XMLEncode (this .getTypeName ());
      generator .string += "'";

      if (name .length)
      {
         generator .AddNode (this);

         generator .string += generator .Space ();
         generator .string += "DEF='";
         generator .string += generator .XMLEncode (name);
         generator .string += "'";
      }

      const containerField = generator .ContainerField ();

      if (containerField)
      {
         if (containerField .getName () !== this .getContainerField ())
         {
            generator .string += generator .Space ();
            generator .string += "containerField='";
            generator .string += generator .XMLEncode (containerField .getName ());
            generator .string += "'";
         }
      }

      const fields = this .getChangedFields ();

      if (fields .length === 0)
      {
         generator .string += generator .closingTags ? "></ProtoInstance>" : "/>";
      }
      else
      {
         generator .string += ">";
         generator .string += generator .TidyBreak ();

         generator .IncIndent ();

         const references = [ ];

         for (const field of fields)
         {
            // If the field is a inputOutput and we have as reference only inputOnly or outputOnly we must output the value
            // for this field.

            let mustOutputValue = false;

            if (generator .ExecutionContext ())
            {
               if (field .getAccessType () === Base_X3DConstants .inputOutput && field .getReferences () .size !== 0)
               {
                  if (![... field .getReferences ()] .some (reference => reference .isInitializable ()))
                     mustOutputValue = !this .isDefaultValue (field);
               }
            }

            // If we have no execution context we are not in a proto and must not generate IS references the same is true
            // if the node is a shared node as the node does not belong to the execution context.

            if (field .getReferences () .size === 0 || !generator .ExecutionContext () || sharedNode || mustOutputValue)
            {
               if (mustOutputValue)
                  references .push (field);

               switch (field .getType ())
               {
                  case Base_X3DConstants .MFNode:
                  {
                     generator .string += generator .Indent ();
                     generator .string += "<fieldValue";
                     generator .string += generator .Space ();
                     generator .string += "name='";
                     generator .string += generator .XMLEncode (field .getName ());
                     generator .string += "'";

                     if (field .length === 0)
                     {
                        generator .string += generator .closingTags ? "></fieldValue>" : "/>";
                        generator .string += generator .TidyBreak ();
                     }
                     else
                     {
                        generator .PushContainerField (field);

                        generator .string += ">";
                        generator .string += generator .TidyBreak ();

                        generator .IncIndent ();

                        field .toXMLStream (generator);

                        generator .string += generator .TidyBreak ();

                        generator .DecIndent ();

                        generator .string += generator .Indent ();
                        generator .string += "</fieldValue>";
                        generator .string += generator .TidyBreak ();

                        generator .PopContainerField ();
                     }

                     break;
                  }
                  case Base_X3DConstants .SFNode:
                  {
                     if (field .getValue () !== null)
                     {
                        generator .PushContainerField (null);

                        generator .string += generator .Indent ();
                        generator .string += "<fieldValue";
                        generator .string += generator .Space ();
                        generator .string += "name='";
                        generator .string += generator .XMLEncode (field .getName ());
                        generator .string += "'";
                        generator .string += ">";
                        generator .string += generator .TidyBreak ();

                        generator .IncIndent ();

                        field .toXMLStream (generator);

                        generator .string += generator .TidyBreak ();

                        generator .DecIndent ();

                        generator .string += generator .Indent ();
                        generator .string += "</fieldValue>";
                        generator .string += generator .TidyBreak ();

                        generator .PopContainerField ();
                        break;
                     }

                     // Proceed with next case.
                  }
                  default:
                  {
                     generator .string += generator .Indent ();
                     generator .string += "<fieldValue";
                     generator .string += generator .Space ();
                     generator .string += "name='";
                     generator .string += generator .XMLEncode (field .getName ());
                     generator .string += "'";
                     generator .string += generator .Space ();
                     generator .string += "value='";

                     field .toXMLStream (generator);

                     generator .string += "'";
                     generator .string += generator .closingTags ? "></fieldValue>" : "/>";
                     generator .string += generator .TidyBreak ();
                     break;
                  }
               }
            }
            else
            {
               references .push (field);
            }
         }

         if (references .length && !sharedNode)
         {
            generator .string += generator .Indent ();
            generator .string += "<IS>";
            generator .string += generator .TidyBreak ();

            generator .IncIndent ();

            for (const field of references)
            {
               const protoFields = field .getReferences ();

               for (const protoField of protoFields)
               {
                  generator .string += generator .Indent ();
                  generator .string += "<connect";
                  generator .string += generator .Space ();
                  generator .string += "nodeField='";
                  generator .string += generator .XMLEncode (field .getName ());
                  generator .string += "'";
                  generator .string += generator .Space ();
                  generator .string += "protoField='";
                  generator .string += generator .XMLEncode (protoField .getName ());
                  generator .string += "'";
                  generator .string += generator .closingTags ? "></connect>" : "/>";
                  generator .string += generator .TidyBreak ();
               }
            }

            generator .DecIndent ();

            generator .string += generator .Indent ();
            generator .string += "</IS>";
            generator .string += generator .TidyBreak ();
         }

         generator .DecIndent ();

         generator .string += generator .Indent ();
         generator .string += "</ProtoInstance>";
      }

      generator .LeaveScope ();
   },
   toJSONStream (generator)
   {
      const sharedNode = generator .IsSharedNode (this);

      generator .EnterScope ();

      const name = generator .Name (this);

      if (name .length)
      {
         if (generator .ExistsNode (this))
         {
            generator .string += '{';
            generator .string += generator .TidySpace ();
            generator .string += '"';
            generator .string += "ProtoInstance";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidyBreak ();
            generator .string += generator .IncIndent ();
            generator .string += generator .Indent ();
            generator .string += '{';
            generator .string += generator .TidyBreak ();
            generator .string += generator .IncIndent ();

            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "@name";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '"';
            generator .string += generator .JSONEncode (this .getTypeName ());
            generator .string += '"';
            generator .string += ',';
            generator .string += generator .TidyBreak ();

            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "@USE";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '"';
            generator .string += generator .JSONEncode (name);
            generator .string += '"';
            generator .string += generator .TidyBreak ();

            generator .string += generator .DecIndent ();
            generator .string += generator .Indent ();
            generator .string += '}';
            generator .string += generator .TidyBreak ();
            generator .string += generator .DecIndent ();
            generator .string += generator .Indent ();
            generator .string += '}';

            generator .LeaveScope ();
            return;
         }
      }

      // Type name

      generator .string += '{';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += "ProtoInstance";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();
      generator .string += generator .Indent ();
      generator .string += '{';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();


      // DEF name

      if (name .length)
      {
         generator .AddNode (this);

         generator .string += generator .Indent ();
         generator .string += '"';
         generator .string += "@DEF";
         generator .string += '"';
         generator .string += ':';
         generator .string += generator .TidySpace ();
         generator .string += '"';
         generator .string += generator .JSONEncode (name);
         generator .string += '"';
         generator .string += ',';
         generator .string += generator .TidyBreak ();
      }


      // Type name

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "@name";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += generator .JSONEncode (this .getTypeName ());
      generator .string += '"';
      generator .string += ',';
      generator .string += generator .TidyBreak ();


      // Fields

      const
         fields     = this .getChangedFields (),
         references = [ ];

      if (fields .length)
      {
         generator .string += generator .Indent ();
         generator .string += '"';
         generator .string += "fieldValue";
         generator .string += '"';
         generator .string += ':';
         generator .string += generator .TidySpace ();
         generator .string += '[';
         generator .string += generator .TidyBreak ();
         generator .string += generator .IncIndent ();

         const outputFields = [ ];

         for (const field of fields)
         {
            // If the field is a inputOutput and we have as reference only inputOnly or outputOnly we must output the value
            // for this field.

            let mustOutputValue = false;

            if (generator .ExecutionContext ())
            {
               if (field .getAccessType () === Base_X3DConstants .inputOutput && field .getReferences () .size !== 0)
               {
                  if (![... field .getReferences ()] .some (reference => reference .isInitializable ()))
                     mustOutputValue = !this .isDefaultValue (field);
               }
            }

            // If we have no execution context we are not in a proto and must not generate IS references the same is true
            // if the node is a shared node as the node does not belong to the execution context.

            if (field .getReferences () .size === 0 || !generator .ExecutionContext () || sharedNode || mustOutputValue)
            {
               if (mustOutputValue)
                  references .push (field);

               outputFields .push (field);
            }
            else
            {
               references .push (field);
            }
         }

         for (const field of outputFields)
         {
            switch (field .getType ())
            {
               case Base_X3DConstants .SFNode:
               {
                  generator .string += generator .Indent ();
                  generator .string += '{';
                  generator .string += generator .TidyBreak ();
                  generator .string += generator .IncIndent ();
                  generator .string += generator .Indent ();
                  generator .string += '"';
                  generator .string += "@name";
                  generator .string += '"';
                  generator .string += ':';
                  generator .string += generator .TidySpace ();
                  generator .string += '"';
                  generator .string += generator .JSONEncode (field .getName ());
                  generator .string += '"';
                  generator .string += ',';
                  generator .string += generator .TidyBreak ();
                  generator .string += generator .Indent ();
                  generator .string += '"';
                  generator .string += "-children";
                  generator .string += '"';
                  generator .string += ':';
                  generator .string += generator .TidySpace ();
                  generator .string += '[';
                  generator .string += generator .TidyBreak ();
                  generator .string += generator .IncIndent ();
                  generator .string += generator .Indent ();

                  field .toJSONStream (generator);

                  generator .string += generator .TidyBreak ();
                  generator .string += generator .DecIndent ();
                  generator .string += generator .Indent ();
                  generator .string += ']';
                  generator .string += generator .TidyBreak ();
                  generator .string += generator .DecIndent ();
                  generator .string += generator .Indent ();
                  generator .string += '}';
                  break;
               }
               case Base_X3DConstants .MFNode:
               {
                  generator .string += generator .Indent ();
                  generator .string += '{';
                  generator .string += generator .TidyBreak ();
                  generator .string += generator .IncIndent ();
                  generator .string += generator .Indent ();
                  generator .string += '"';
                  generator .string += "@name";
                  generator .string += '"';
                  generator .string += ':';
                  generator .string += generator .TidySpace ();
                  generator .string += '"';
                  generator .string += generator .JSONEncode (field .getName ());
                  generator .string += '"';
                  generator .string += ',';
                  generator .string += generator .TidyBreak ();
                  generator .string += generator .Indent ();
                  generator .string += '"';
                  generator .string += "-children";
                  generator .string += '"';
                  generator .string += ':';
                  generator .string += generator .TidySpace ();

                  field .toJSONStream (generator);

                  generator .string += generator .TidyBreak ();
                  generator .string += generator .DecIndent ();
                  generator .string += generator .Indent ();
                  generator .string += '}';
                  break;
               }
               default:
               {
                  generator .string += generator .Indent ();
                  generator .string += '{';
                  generator .string += generator .TidyBreak ();
                  generator .string += generator .IncIndent ();
                  generator .string += generator .Indent ();
                  generator .string += '"';
                  generator .string += "@name";
                  generator .string += '"';
                  generator .string += ':';
                  generator .string += generator .TidySpace ();
                  generator .string += '"';
                  generator .string += generator .JSONEncode (field .getName ());
                  generator .string += '"';
                  generator .string += ',';
                  generator .string += generator .TidyBreak ();
                  generator .string += generator .Indent ();
                  generator .string += '"';
                  generator .string += "@value";
                  generator .string += '"';
                  generator .string += ':';
                  generator .string += generator .TidySpace ();

                  field .toJSONStream (generator);

                  generator .string += generator .TidyBreak ();
                  generator .string += generator .DecIndent ();
                  generator .string += generator .Indent ();
                  generator .string += '}';
                  break;
               }
            }

            if (field !== outputFields .at (-1))
               generator .string += ',';

            generator .string += generator .TidyBreak ();
         }

         generator .string += generator .DecIndent ();
         generator .string += generator .Indent ();
         generator .string += ']';
         generator .string += ',';
         generator .string += generator .TidyBreak ();


         // IS references

         if (references .length && !sharedNode)
         {
            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "IS";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '{';
            generator .string += generator .TidyBreak ();
            generator .string += generator .IncIndent ();
            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "connect";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '[';
            generator .string += generator .TidyBreak ();
            generator .string += generator .IncIndent ();

            for (const field of references)
            {
               const protoFields = [... field .getReferences ()];

               for (const protoField of protoFields)
               {
                  generator .string += generator .Indent ();
                  generator .string += '{';
                  generator .string += generator .TidyBreak ();
                  generator .string += generator .IncIndent ();

                  generator .string += generator .Indent ();
                  generator .string += '"';
                  generator .string += "@nodeField";
                  generator .string += '"';
                  generator .string += ':';
                  generator .string += generator .TidySpace ();
                  generator .string += '"';
                  generator .string += generator .JSONEncode (field .getName ());
                  generator .string += '"';
                  generator .string += ',';
                  generator .string += generator .TidyBreak ();

                  generator .string += generator .Indent ();
                  generator .string += '"';
                  generator .string += "@protoField";
                  generator .string += '"';
                  generator .string += ':';
                  generator .string += generator .TidySpace ();
                  generator .string += '"';
                  generator .string += generator .JSONEncode (protoField .getName ());
                  generator .string += '"';
                  generator .string += generator .TidyBreak ();

                  generator .string += generator .DecIndent ();
                  generator .string += generator .Indent ();
                  generator .string += '}';

                  if (field === references .at (-1) && protoField === protoFields .at (-1))
                     ;
                  else
                  {
                     generator .string += ',';
                  }

                  generator .string += generator .TidyBreak ();
               }
            }

            generator .string += generator .DecIndent ();
            generator .string += generator .Indent ();
            generator .string += ']';
            generator .string += generator .TidyBreak ();
            generator .string += generator .DecIndent ();
            generator .string += generator .Indent ();
            generator .string += '}';
            generator .string += ',';
            generator .string += generator .TidyBreak ();
         }
      }

      generator .JSONRemoveComma ();


      // End

      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';
      generator .string += generator .TidyBreak ();
      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';

      generator .LeaveScope ();
   },
   dispose ()
   {
      const protoNode = this [_protoNode];

      protoNode ._name_changed .removeFieldInterest (this ._typeName_changed);
      protoNode ._updateInstances .removeInterest ("construct", this);
      protoNode ._updateInstances .removeInterest ("update",    this);

      this [X3DPrototypeInstance_body] ?.dispose ();

      Core_X3DNode .prototype .dispose .call (this);
   },
});

Object .defineProperties (X3DPrototypeInstance,
{
   typeName:
   {
      value: "X3DPrototypeInstance",
      enumerable: true,
   },
   componentName:
   {
      value: "Core",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
});

const X3DPrototypeInstance_default_ = X3DPrototypeInstance;
;

x_ite_Namespace .add ("X3DPrototypeInstance", "x_ite/Components/Core/X3DPrototypeInstance", X3DPrototypeInstance_default_);
/* harmony default export */ const Core_X3DPrototypeInstance = (X3DPrototypeInstance_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Core.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/
















const Core_default_ = {
   name: "Core",
   concreteNodes:
   [
      Core_MetadataBoolean,
      Core_MetadataDouble,
      Core_MetadataFloat,
      Core_MetadataInteger,
      Core_MetadataSet,
      Core_MetadataString,
      Core_WorldInfo,
   ],
   abstractNodes:
   [
      Core_X3DBindableNode,
      Core_X3DChildNode,
      Core_X3DInfoNode,
      Core_X3DMetadataObject,
      Core_X3DNode,
      Core_X3DPrototypeInstance,
      Core_X3DSensorNode,
   ],
};
;

x_ite_Namespace .add ("Core", "x_ite/Components/Core", Core_default_);
/* harmony default export */ const Core = (Core_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/X3DGeometricPropertyNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function X3DGeometricPropertyNode (executionContext)
{
   Core_X3DNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DGeometricPropertyNode);
}

Object .setPrototypeOf (X3DGeometricPropertyNode .prototype, Core_X3DNode .prototype);

Object .defineProperties (X3DGeometricPropertyNode,
{
   typeName:
   {
      value: "X3DGeometricPropertyNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
});

const X3DGeometricPropertyNode_default_ = X3DGeometricPropertyNode;
;

x_ite_Namespace .add ("X3DGeometricPropertyNode", "x_ite/Components/Rendering/X3DGeometricPropertyNode", X3DGeometricPropertyNode_default_);
/* harmony default export */ const Rendering_X3DGeometricPropertyNode = (X3DGeometricPropertyNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/EnvironmentalEffects/FogCoordinate.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function FogCoordinate (executionContext)
{
   Rendering_X3DGeometricPropertyNode .call (this, executionContext);

   this .addType (Base_X3DConstants .FogCoordinate);

   this ._depth .setUnit ("length");
}

Object .assign (Object .setPrototypeOf (FogCoordinate .prototype, Rendering_X3DGeometricPropertyNode .prototype),
{
   initialize ()
   {
      Rendering_X3DGeometricPropertyNode .prototype .initialize .call (this);

      this ._depth .addInterest ("set_depth__", this);

      this .set_depth__ ();
   },
   set_depth__ ()
   {
      this .depth  = this ._depth .getValue ();
      this .length = this ._depth .length;
   },
   isEmpty ()
   {
      return this .length === 0;
   },
   getSize ()
   {
      return this .length;
   },
   addDepth (index, array)
   {
      if (index >= 0 && this .length)
      {
         return array .push (this .depth [index % this .length]);
      }
      else
      {
         array .push (0);
      }
   },
   addDepths (array, min = this .length)
   {
      const length = this .length;

      if (length)
      {
         const depth = this .depth;

         for (let index = 0; index < min; ++ index)
            array .push (depth [index % length]);
      }
      else
      {
         for (let index = 0; index < min; ++ index)
            array .push (0);
      }

      return array;
   },
});

Object .defineProperties (FogCoordinate,
{
   typeName:
   {
      value: "FogCoordinate",
      enumerable: true,
   },
   componentName:
   {
      value: "EnvironmentalEffects",
      enumerable: true,
   },
   containerField:
   {
      value: "fogCoord",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "depth",    new x_ite_Fields .MFFloat ()),
      ]),
      enumerable: true,
   },
});

const FogCoordinate_default_ = FogCoordinate;
;

x_ite_Namespace .add ("FogCoordinate", "x_ite/Components/EnvironmentalEffects/FogCoordinate", FogCoordinate_default_);
/* harmony default export */ const EnvironmentalEffects_FogCoordinate = (FogCoordinate_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/EnvironmentalEffects/LocalFog.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function LocalFog (executionContext)
{
   Core_X3DChildNode .call (this, executionContext);
   EnvironmentalEffects_X3DFogObject .call (this, executionContext);

   this .addType (Base_X3DConstants .LocalFog);
}

Object .assign (Object .setPrototypeOf (LocalFog .prototype, Core_X3DChildNode .prototype),
   EnvironmentalEffects_X3DFogObject .prototype,
{
   initialize ()
   {
      Core_X3DChildNode .prototype .initialize .call (this);
      EnvironmentalEffects_X3DFogObject .prototype .initialize .call (this);
   },
   push (renderObject)
   {
      if (this ._enabled .getValue () && this .getFogType ())
      {
         const fogContainer = this .getFogs () .pop ();

         fogContainer .set (this, renderObject .getModelViewMatrix () .get ());

         renderObject .getLocalFogs () .push (fogContainer);
      }
   },
   pop (renderObject)
   {
      if (this ._enabled .getValue () && this .getFogType ())
         this .getBrowser () .getLocalObjects () .push (renderObject .getLocalFogs () .pop ());
   },
   dispose ()
   {
      EnvironmentalEffects_X3DFogObject .prototype .dispose .call (this);
      Core_X3DChildNode .prototype .dispose .call (this);
   },
});

Object .defineProperties (LocalFog,
{
   typeName:
   {
      value: "LocalFog",
      enumerable: true,
   },
   componentName:
   {
      value: "EnvironmentalEffects",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",         new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "fogType",         new x_ite_Fields .SFString ("LINEAR")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "color",           new x_ite_Fields .SFColor (1, 1, 1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "visibilityRange", new x_ite_Fields .SFFloat ()),
      ]),
      enumerable: true,
   },
});

const LocalFog_default_ = LocalFog;
;

x_ite_Namespace .add ("LocalFog", "x_ite/Components/EnvironmentalEffects/LocalFog", LocalFog_default_);
/* harmony default export */ const EnvironmentalEffects_LocalFog = (LocalFog_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/EnvironmentalEffects/TextureBackground.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function TextureBackground (executionContext)
{
   EnvironmentalEffects_X3DBackgroundNode .call (this, executionContext);

   this .addType (Base_X3DConstants .TextureBackground);
}

Object .assign (Object .setPrototypeOf (TextureBackground .prototype, EnvironmentalEffects_X3DBackgroundNode .prototype),
{
   initialize ()
   {
      EnvironmentalEffects_X3DBackgroundNode .prototype .initialize .call (this);

      this ._frontTexture  .addInterest ("set_texture__", this, 0);
      this ._backTexture   .addInterest ("set_texture__", this, 1);
      this ._leftTexture   .addInterest ("set_texture__", this, 2);
      this ._rightTexture  .addInterest ("set_texture__", this, 3);
      this ._topTexture    .addInterest ("set_texture__", this, 4);
      this ._bottomTexture .addInterest ("set_texture__", this, 5);

      this .set_texture__ (0, this ._frontTexture);
      this .set_texture__ (1, this ._backTexture);
      this .set_texture__ (2, this ._leftTexture);
      this .set_texture__ (3, this ._rightTexture);
      this .set_texture__ (4, this ._topTexture);
      this .set_texture__ (5, this ._bottomTexture);
   },
   set_texture__ (index, textureNode)
   {
      EnvironmentalEffects_X3DBackgroundNode .prototype .set_texture__ .call (this, Base_X3DCast (Base_X3DConstants .X3DTextureNode, textureNode), index);
   },
});

Object .defineProperties (TextureBackground,
{
   typeName:
   {
      value: "TextureBackground",
      enumerable: true,
   },
   componentName:
   {
      value: "EnvironmentalEffects",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",      new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_bind",      new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "skyAngle",      new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "skyColor",      new x_ite_Fields .MFColor (new x_ite_Fields .SFColor ())),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "groundAngle",   new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "groundColor",   new x_ite_Fields .MFColor ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "transparency",  new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isBound",       new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "bindTime",      new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "frontTexture",  new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "backTexture",   new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "leftTexture",   new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "rightTexture",  new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "topTexture",    new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "bottomTexture", new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const TextureBackground_default_ = TextureBackground;
;

x_ite_Namespace .add ("TextureBackground", "x_ite/Components/EnvironmentalEffects/TextureBackground", TextureBackground_default_);
/* harmony default export */ const EnvironmentalEffects_TextureBackground = (TextureBackground_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/EnvironmentalEffects.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









const EnvironmentalEffects_default_ = {
   name: "EnvironmentalEffects",
   concreteNodes:
   [
      EnvironmentalEffects_Background,
      EnvironmentalEffects_Fog,
      EnvironmentalEffects_FogCoordinate,
      EnvironmentalEffects_LocalFog,
      EnvironmentalEffects_TextureBackground,
   ],
   abstractNodes:
   [
      EnvironmentalEffects_X3DBackgroundNode,
      EnvironmentalEffects_X3DFogObject,
   ],
};
;

x_ite_Namespace .add ("EnvironmentalEffects", "x_ite/Components/EnvironmentalEffects", EnvironmentalEffects_default_);
/* harmony default export */ const EnvironmentalEffects = (EnvironmentalEffects_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/EnvironmentalSensor/X3DEnvironmentalSensorNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






function X3DEnvironmentalSensorNode (executionContext)
{
   Core_X3DSensorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DEnvironmentalSensorNode);

   this .addChildObjects (Base_X3DConstants .outputOnly, "traversed", new x_ite_Fields .SFBool (true));

   this ._size   .setUnit ("length");
   this ._center .setUnit ("length");

   this .zeroTest         = false;
   this .currentTraversed = true;
}

Object .assign (Object .setPrototypeOf (X3DEnvironmentalSensorNode .prototype, Core_X3DSensorNode .prototype),
{
   initialize ()
   {
      Core_X3DSensorNode .prototype .initialize .call (this);

      this .getLive () .addInterest ("set_live__", this);

      this ._enabled   .addInterest ("set_live__", this);
      this ._size      .addInterest ("set_live__", this);
      this ._traversed .addInterest ("set_live__", this);

      this .set_live__ ();
   },
   set_live__ ()
   {
      if (this ._traversed .getValue () && this .getLive () .getValue () && this ._enabled .getValue () && !(this .zeroTest && this ._size. getValue () .equals (Numbers_Vector3 .Zero)))
      {
         this .getBrowser () .sensorEvents () .addInterest ("update", this);
      }
      else
      {
         this .getBrowser () .sensorEvents () .removeInterest ("update", this);

         if (this ._isActive .getValue ())
         {
            this ._isActive = false;
            this ._exitTime = this .getBrowser () .getCurrentTime ();
         }
      }
   },
   setZeroTest (value)
   {
      this .zeroTest = value;
   },
   getZeroTest ()
   {
      return this .zeroTest;
   },
   setTraversed (value)
   {
      if (value)
      {
         if (this ._traversed .getValue () === false)
            this ._traversed = true;
      }
      else
      {
         if (this .currentTraversed !== this ._traversed .getValue ())
            this ._traversed = this .currentTraversed;
      }

      this .currentTraversed = value;
   },
   getTraversed ()
   {
      return this .currentTraversed;
   },
   update () { },
});

Object .defineProperties (X3DEnvironmentalSensorNode,
{
   typeName:
   {
      value: "X3DEnvironmentalSensorNode",
      enumerable: true,
   },
   componentName:
   {
      value: "EnvironmentalSensor",
      enumerable: true,
   },
});

const X3DEnvironmentalSensorNode_default_ = X3DEnvironmentalSensorNode;
;

x_ite_Namespace .add ("X3DEnvironmentalSensorNode", "x_ite/Components/EnvironmentalSensor/X3DEnvironmentalSensorNode", X3DEnvironmentalSensorNode_default_);
/* harmony default export */ const EnvironmentalSensor_X3DEnvironmentalSensorNode = (X3DEnvironmentalSensorNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/EnvironmentalSensor/ProximitySensor.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/











function ProximitySensor (executionContext)
{
   EnvironmentalSensor_X3DEnvironmentalSensorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .ProximitySensor);

   this .setCameraObject (true);

   this ._centerOfRotation_changed .setUnit ("length");
   this ._position_changed         .setUnit ("length");

   this .setZeroTest (true);

   this .min           = new Numbers_Vector3 (0, 0, 0);
   this .max           = new Numbers_Vector3 (0, 0, 0);
   this .layerNode     = null;
   this .modelMatrix   = new Numbers_Matrix4 ();
   this .inside        = false;
}

Object .assign (Object .setPrototypeOf (ProximitySensor .prototype, EnvironmentalSensor_X3DEnvironmentalSensorNode .prototype),
{
   initialize ()
   {
      EnvironmentalSensor_X3DEnvironmentalSensorNode .prototype .initialize .call (this);

      this ._enabled .addInterest ("set_enabled__", this);
      this ._size    .addInterest ("set_extents__", this);
      this ._center  .addInterest ("set_extents__", this);

      this ._traversed .addFieldInterest (this ._isCameraObject);

      this .set_enabled__ ();
      this .set_extents__ ();
   },
   set_enabled__ ()
   {
      this .setCameraObject (this ._enabled .getValue ());

      if (this ._enabled .getValue ())
         delete this .traverse;
      else
         this .traverse = Function .prototype;
   },
   set_extents__ ()
   {
      const
         s  = this ._size .getValue (),
         c  = this ._center .getValue (),
         sx = s .x / 2,
         sy = s .y / 2,
         sz = s .z / 2,
         cx = c .x,
         cy = c .y,
         cz = c .z;

      this .min .set (cx - sx, cy - sy, cz - sz);
      this .max .set (cx + sx, cy + sy, cz + sz);
   },
   update: (() =>
   {
      const
         position               = new Numbers_Vector3 (0, 0, 0),
         orientation            = new Numbers_Rotation4 (),
         centerOfRotation       = new Numbers_Vector3 (0, 0, 0),
         centerOfRotationMatrix = new Numbers_Matrix4 ();

      return function ()
      {
         if (this .inside && this .getTraversed ())
         {
            if (this .layerNode)
            {
               const
                  viewpointNode  = this .layerNode .getViewpoint (),
                  invModelMatrix = this .modelMatrix .inverse ()

               centerOfRotationMatrix
                  .assign (viewpointNode .getModelMatrix ())
                  .translate (viewpointNode .getUserCenterOfRotation ())
                  .multRight (invModelMatrix)
                  .get (centerOfRotation);

               invModelMatrix
                  .multLeft (viewpointNode .getCameraSpaceMatrix ())
                  .get (position, orientation);

               if (this ._isActive .getValue ())
               {
                  if (!this ._position_changed .getValue () .equals (position))
                     this ._position_changed = position;

                  if (!this ._orientation_changed .getValue () .equals (orientation))
                     this ._orientation_changed = orientation;

                  if (!this ._centerOfRotation_changed .getValue () .equals (centerOfRotation))
                     this ._centerOfRotation_changed = centerOfRotation;
               }
               else
               {
                  this ._isActive                 = true;
                  this ._enterTime                = this .getBrowser () .getCurrentTime ();
                  this ._position_changed         = position;
                  this ._orientation_changed      = orientation;
                  this ._centerOfRotation_changed = centerOfRotation;
               }
            }
         }
         else
         {
            if (this ._isActive .getValue ())
            {
               this ._isActive = false;
               this ._exitTime = this .getBrowser () .getCurrentTime ();
            }
         }

         this .inside    = false;
         this .layerNode = null;

         this .setTraversed (false);
      };
   })(),
   traverse: (() =>
   {
      const
         invModelViewMatrix = new Numbers_Matrix4 (),
         infinity           = new Numbers_Vector3 (-1, -1, -1);

      return function (type, renderObject)
      {
         switch (type)
         {
            case Rendering_TraverseType .CAMERA:
            {
               this .layerNode = renderObject .getLayer ();
               this .modelMatrix .assign (renderObject .getModelViewMatrix () .get ());
               return;
            }
            case Rendering_TraverseType .DISPLAY:
            {
               this .setTraversed (true);

               if (this .inside)
                  return;

               if (this ._size .getValue () .equals (infinity))
               {
                  this .inside = true;
               }
               else
               {
                  invModelViewMatrix .assign (renderObject .getModelViewMatrix () .get ()) .inverse ();

                  this .inside = this .containsPoint (invModelViewMatrix .origin);
               }

               return;
            }
         }
      };
   })(),
   containsPoint (point)
   {
      const
         min = this .min,
         max = this .max;

      return min .x <= point .x &&
             max .x >= point .x &&
             min .y <= point .y &&
             max .y >= point .y &&
             min .z <= point .z &&
             max .z >= point .z;
   },
});

Object .defineProperties (ProximitySensor,
{
   typeName:
   {
      value: "ProximitySensor",
      enumerable: true,
   },
   componentName:
   {
      value: "EnvironmentalSensor",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",                 new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",                  new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "size",                     new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "center",                   new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "enterTime",                new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "exitTime",                 new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",                 new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "position_changed",         new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "orientation_changed",      new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "centerOfRotation_changed", new x_ite_Fields .SFVec3f ()),
      ]),
      enumerable: true,
   },
});

const ProximitySensor_default_ = ProximitySensor;
;

x_ite_Namespace .add ("ProximitySensor", "x_ite/Components/EnvironmentalSensor/ProximitySensor", ProximitySensor_default_);
/* harmony default export */ const EnvironmentalSensor_ProximitySensor = (ProximitySensor_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/EnvironmentalSensor/TransformSensor.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/












const
   ModelMatrixCache  = Utility_ObjectCache (Numbers_Matrix4),
   TargetMatrixCache = Utility_ObjectCache (Numbers_Matrix4);

function TransformSensor (executionContext)
{
   EnvironmentalSensor_X3DEnvironmentalSensorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .TransformSensor);

   this ._position_changed .setUnit ("length");

   this .setZeroTest (true);

   this .min              = new Numbers_Vector3 ();
   this .max              = new Numbers_Vector3 ();
   this .targetObjectNode = null;
   this .modelMatrices    = [ ];
   this .targetMatrices   = [ ];
}

Object .assign (Object .setPrototypeOf (TransformSensor .prototype, EnvironmentalSensor_X3DEnvironmentalSensorNode .prototype),
{
   initialize ()
   {
      EnvironmentalSensor_X3DEnvironmentalSensorNode .prototype .initialize .call (this);

      this .getLive () .addInterest ("set_enabled__", this);

      this ._enabled      .addInterest ("set_enabled__",      this);
      this ._size         .addInterest ("set_enabled__",      this);
      this ._size         .addInterest ("set_extents__",      this);
      this ._center       .addInterest ("set_extents__",      this);
      this ._targetObject .addInterest ("set_targetObject__", this);

      this .set_extents__ ();
      this .set_targetObject__ ();
   },
   set_live__ ()
   { },
   set_enabled__ ()
   {
      if (this .getLive () .getValue () && this .targetObjectNode && this ._enabled .getValue () && !this ._size. getValue () .equals (Numbers_Vector3 .Zero))
      {
         this .setPickableObject (true);
         this .getBrowser () .addTransformSensor (this);
         this .targetObjectNode .addTransformSensor (this);
      }
      else
      {
         this .setPickableObject (false);
         this .getBrowser () .removeTransformSensor (this);

         if (this .targetObjectNode)
            this .targetObjectNode .removeTransformSensor (this);

         if (this ._isActive .getValue ())
         {
            this ._isActive = false;
            this ._exitTime = this .getBrowser () .getCurrentTime ();
         }
      }
   },
   set_extents__ ()
   {
      const
         s  = this ._size .getValue (),
         c  = this ._center .getValue (),
         sx = s .x / 2,
         sy = s .y / 2,
         sz = s .z / 2,
         cx = c .x,
         cy = c .y,
         cz = c .z;

      this .min .set (cx - sx, cy - sy, cz - sz);
      this .max .set (cx + sx, cy + sy, cz + sz);
   },
   set_targetObject__ ()
   {
      this .targetObjectNode = null;

      try
      {
         const
            node = this ._targetObject .getValue () .getInnerNode (),
            type = node .getType ();

         for (let t = type .length - 1; t >= 0; -- t)
         {
            switch (type [t])
            {
               case Base_X3DConstants .X3DGroupingNode:
               case Base_X3DConstants .X3DShapeNode:
               {
                  this .targetObjectNode = node;
                  break;
               }
               default:
                  continue;
            }

            break;
         }
      }
      catch
      { }

      this .set_enabled__ ();
   },
   traverse (type, renderObject)
   {
      // TransformSensor nodes are sorted out and only traversed during PICKING, except if is child of a LOD or Switch node.

      if (type !== Rendering_TraverseType .PICKING)
         return;

      if (this .isPickableObject ())
         this .modelMatrices .push (ModelMatrixCache .pop () .assign (renderObject .getModelViewMatrix () .get ()));
   },
   collect (targetMatrix)
   {
      this .targetMatrices .push (TargetMatrixCache .pop () .assign (targetMatrix));
   },
   process: (() =>
   {
      const
         position    = new Numbers_Vector3 (0, 0, 0),
         orientation = new Numbers_Rotation4 ();

      return function ()
      {
         const
            modelMatrices  = this .modelMatrices,
            targetMatrices = this .targetMatrices,
            matrix         = this .intersects ();

         if (matrix)
         {
            matrix .get (position, orientation);

            if (this ._isActive .getValue ())
            {
               if (!this ._position_changed .getValue () .equals (position))
                  this ._position_changed = position;

               if (!this ._orientation_changed .getValue () .equals (orientation))
                  this ._orientation_changed = orientation;
            }
            else
            {
               this ._isActive            = true;
               this ._enterTime           = this .getBrowser () .getCurrentTime ();
               this ._position_changed    = position;
               this ._orientation_changed = orientation;
            }
         }
         else
         {
            if (this ._isActive .getValue ())
            {
               this ._isActive = false;
               this ._exitTime = this .getBrowser () .getCurrentTime ();
            }
         }

         for (const modelMatrix of modelMatrices)
            ModelMatrixCache .push (modelMatrix);

         for (const targetMatrix of targetMatrices)
            TargetMatrixCache .push (targetMatrix);

         modelMatrices  .length = 0;
         targetMatrices .length = 0;
      };
   })(),
   intersects: (() =>
   {
      const infinity = new Numbers_Vector3 (-1, -1, -1);

      return function ()
      {
         const
            modelMatrices  = this .modelMatrices,
            targetMatrices = this .targetMatrices,
            always         = this ._size .getValue () .equals (infinity);

         for (const modelMatrix of modelMatrices)
         {
            const invModelMatrix = modelMatrix .inverse ();

            for (const targetMatrix of targetMatrices)
            {
               const matrix = targetMatrix .multRight (invModelMatrix);

               if (always || this .containsPoint (matrix .origin))
               {
                  return matrix;
               }
            }
         }

         return null;
      };
   })(),
   containsPoint (point)
   {
      const
         min = this .min,
         max = this .max;

      return min .x <= point .x &&
             max .x >= point .x &&
             min .y <= point .y &&
             max .y >= point .y &&
             min .z <= point .z &&
             max .z >= point .z;
   },
});

Object .defineProperties (TransformSensor,
{
   typeName:
   {
      value: "TransformSensor",
      enumerable: true,
   },
   componentName:
   {
      value: "EnvironmentalSensor",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",            new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",             new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "size",                new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "center",              new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "enterTime",           new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "exitTime",            new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",            new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "position_changed",    new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "orientation_changed", new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "targetObject",        new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const TransformSensor_default_ = TransformSensor;
;

x_ite_Namespace .add ("TransformSensor", "x_ite/Components/EnvironmentalSensor/TransformSensor", TransformSensor_default_);
/* harmony default export */ const EnvironmentalSensor_TransformSensor = (TransformSensor_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/EnvironmentalSensor/VisibilitySensor.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










function VisibilitySensor (executionContext)
{
   EnvironmentalSensor_X3DEnvironmentalSensorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .VisibilitySensor);

   this .setZeroTest (false);

   this .visible = false;
}

Object .assign (Object .setPrototypeOf (VisibilitySensor .prototype, EnvironmentalSensor_X3DEnvironmentalSensorNode .prototype),
{
   initialize ()
   {
      EnvironmentalSensor_X3DEnvironmentalSensorNode .prototype .initialize .call (this);

      this ._enabled .addInterest ("set_enabled__", this);

      this .set_enabled__ ();
   },
   set_enabled__ ()
   {
      if (this ._enabled .getValue ())
         delete this .traverse;
      else
         this .traverse = Function .prototype;
   },
   update ()
   {
      if (this .visible && this .getTraversed ())
      {
         if (!this ._isActive .getValue ())
         {
            this ._isActive  = true;
            this ._enterTime = this .getBrowser () .getCurrentTime ();
         }

         this .visible = false;
      }
      else
      {
         if (this ._isActive .getValue ())
         {
            this ._isActive = false;
            this ._exitTime = this .getBrowser () .getCurrentTime ();
         }
      }

      this .setTraversed (false);
   },
   traverse: (() =>
   {
      const
         bbox     = new Geometry_Box3 (),
         infinity = new Numbers_Vector3 (-1, -1, -1);

      return function (type, renderObject)
      {
         if (type !== Rendering_TraverseType .DISPLAY)
            return;

         this .setTraversed (true);

         if (this .visible)
            return;

         if (this ._size .getValue () .equals (infinity))
         {
            this .visible = true;
         }
         else
         {
            bbox
               .set (this ._size .getValue (), this ._center .getValue ())
               .multRight (renderObject .getModelViewMatrix () .get ());

            this .visible = renderObject .getViewVolume () .intersectsBox (bbox);
         }
      };
   })(),
});

Object .defineProperties (VisibilitySensor,
{
   typeName:
   {
      value: "VisibilitySensor",
      enumerable: true,
   },
   componentName:
   {
      value: "EnvironmentalSensor",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",  new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",   new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "size",      new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "center",    new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "enterTime", new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "exitTime",  new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",  new x_ite_Fields .SFBool ()),
      ]),
      enumerable: true,
   },
});

const VisibilitySensor_default_ = VisibilitySensor;
;

x_ite_Namespace .add ("VisibilitySensor", "x_ite/Components/EnvironmentalSensor/VisibilitySensor", VisibilitySensor_default_);
/* harmony default export */ const EnvironmentalSensor_VisibilitySensor = (VisibilitySensor_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/EnvironmentalSensor.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






const EnvironmentalSensor_default_ = {
   name: "EnvironmentalSensor",
   concreteNodes:
   [
      EnvironmentalSensor_ProximitySensor,
      EnvironmentalSensor_TransformSensor,
      EnvironmentalSensor_VisibilitySensor,
   ],
   abstractNodes:
   [
      EnvironmentalSensor_X3DEnvironmentalSensorNode,
   ],
};
;

x_ite_Namespace .add ("EnvironmentalSensor", "x_ite/Components/EnvironmentalSensor", EnvironmentalSensor_default_);
/* harmony default export */ const EnvironmentalSensor = (EnvironmentalSensor_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers/X3DFollowerNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function X3DFollowerNode (executionContext)
{
   Core_X3DChildNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DFollowerNode);

   this .buffer = [ ];

   // Auxillary variables
   this .a      = this .getVector ();
   this .vector = this .getVector ();
}

Object .assign (Object .setPrototypeOf (X3DFollowerNode .prototype, Core_X3DChildNode .prototype),
{
   initialize ()
   {
      Core_X3DChildNode .prototype .initialize .call (this);

      this .getLive () .addInterest ("set_live__", this);
   },
   getBuffer ()
   {
      return this .buffer;
   },
   getValue ()
   {
      return this ._set_value .getValue ();
   },
   getDestination ()
   {
      return this ._set_destination .getValue ();
   },
   getInitialValue ()
   {
      return this ._initialValue .getValue ();
   },
   getInitialDestination ()
   {
      return this ._initialDestination .getValue ();
   },
   setValue (value)
   {
      this ._value_changed = value;
   },
   setDestination (value)
   {
      this .destination .assign (value);
   },
   duplicate (value)
   {
      return value .copy ();
   },
   assign (buffer, i, value)
   {
      buffer [i] .assign (value);
   },
   equals (lhs, rhs, tolerance)
   {
      return this .a .assign (lhs) .subtract (rhs) .magnitude () < tolerance;
   },
   interpolate (source, destination, weight)
   {
      return this .vector .assign (source) .lerp (destination, weight);
   },
   set_live__ ()
   {
      if (this .getLive () .getValue () && this ._isActive .getValue ())
      {
         this .getBrowser () .prepareEvents () .addInterest ("prepareEvents", this);
         this .getBrowser () .addBrowserEvent ();
      }
      else
         this .getBrowser () .prepareEvents () .removeInterest ("prepareEvents", this);
   },
   set_active (value)
   {
      if (value !== this ._isActive .getValue ())
      {
         this ._isActive = value;

         this .set_live__ ();
      }
   },
});

Object .defineProperties (X3DFollowerNode,
{
   typeName:
   {
      value: "X3DFollowerNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Followers",
      enumerable: true,
   },
});

const X3DFollowerNode_default_ = X3DFollowerNode;
;

x_ite_Namespace .add ("X3DFollowerNode", "x_ite/Components/Followers/X3DFollowerNode", X3DFollowerNode_default_);
/* harmony default export */ const Followers_X3DFollowerNode = (X3DFollowerNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers/X3DChaserNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function X3DChaserNode (executionContext)
{
   Followers_X3DFollowerNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DChaserNode);

   this .destination   = null;
   this .previousValue = null;
   this .bufferEndTime = 0;
   this .stepTime      = 0;

   // Auxillary variables
   this .deltaOut = this .getVector ();
}

Object .assign (Object .setPrototypeOf (X3DChaserNode .prototype, Followers_X3DFollowerNode .prototype),
{
   initialize ()
   {
      Followers_X3DFollowerNode .prototype .initialize .call (this);

      this ._set_value       .addInterest ("set_value__",       this);
      this ._set_destination .addInterest ("set_destination__", this);
      this ._duration        .addInterest ("set_duration__",    this);

      this .set_duration__ ();

      var
         buffer             = this .getBuffer (),
         initialValue       = this .getInitialValue (),
         initialDestination = this .getInitialDestination (),
         numBuffers         = this .getNumBuffers ();

      this .bufferEndTime = this .getBrowser () .getCurrentTime ();
      this .previousValue = this .duplicate (initialValue);

      buffer [0] = this .duplicate (initialDestination);

      for (var i = 1; i < numBuffers; ++ i)
         buffer [i] = this .duplicate (initialValue);

      this .destination = this .duplicate (initialDestination);

      if (this .equals (initialDestination, initialValue, this .getTolerance ()))
         this .setValue (initialDestination);

      else
         this .set_active (true);
   },
   getNumBuffers ()
   {
      return 60;
   },
   getTolerance ()
   {
      return 1e-8;
   },
   getArray ()
   {
      return this .getVector ();
   },
   setPreviousValue (value)
   {
      this .previousValue .assign (value);
   },
   step (value1, value2, t)
   {
      this .output .add (this .deltaOut .assign (value1) .subtract (value2) .multiply (t));
   },
   stepResponse (t)
   {
      if (t <= 0)
         return 0;

      var duration = this ._duration .getValue ();

      if (t >= duration)
         return 1;

      return 0.5 - 0.5 * Math .cos ((t / duration) * Math .PI);
   },
   set_value__ ()
   {
      if (! this ._isActive .getValue ())
         this .bufferEndTime = this .getBrowser () .getCurrentTime ();

      var
         buffer = this .getBuffer (),
         value  = this .getValue ();

      for (var i = 0, length = buffer .length; i < length; ++ i)
         this .assign (buffer, i, value);

      this .setPreviousValue (value);
      this .setValue (value);

      this .set_active (true);
   },
   set_destination__ ()
   {
      this .setDestination (this .getDestination ());

      if (! this ._isActive .getValue ())
         this .bufferEndTime = this .getBrowser () .getCurrentTime ();

      this .set_active (true);
   },
   set_duration__ ()
   {
      this .stepTime = this ._duration .getValue () / this .getNumBuffers ();
   },
   prepareEvents ()
   {
      var
         buffer     = this .getBuffer (),
         numBuffers = buffer .length,
         fraction   = this .updateBuffer ();

      this .output = this .interpolate (this .previousValue,
                                          buffer [numBuffers - 1],
                                          this .stepResponse ((numBuffers - 1 + fraction) * this .stepTime));

      for (var i = numBuffers - 2; i >= 0; -- i)
      {
         this .step (buffer [i], buffer [i + 1], this .stepResponse ((i + fraction) * this .stepTime));
      }

      this .setValue (this .output);

      if (this .equals (this .output, this .destination, this .getTolerance ()))
         this .set_active (false);
   },
   updateBuffer ()
   {
      var
         buffer     = this .getBuffer (),
         numBuffers = buffer .length,
         fraction   = (this .getBrowser () .getCurrentTime () - this .bufferEndTime) / this .stepTime;

      if (fraction >= 1)
      {
         var seconds = Math .floor (fraction);

         fraction -= seconds;

         if (seconds < numBuffers)
         {
            this .setPreviousValue (buffer [numBuffers - seconds]);

            for (var i = numBuffers - 1; i >= seconds; -- i)
            {
               this .assign (buffer, i, buffer [i - seconds])
            }

            for (var i = 0; i < seconds; ++ i)
            {
               var alpha = i / seconds;

               this .assign (buffer, i, this .interpolate (this .destination, buffer [seconds], alpha))
            }
         }
         else
         {
            this .setPreviousValue (seconds == numBuffers ? buffer [0] : this .destination);

            for (var i = 0; i < numBuffers; ++ i)
               this .assign (buffer, i, this .destination);
         }

         this .bufferEndTime += seconds * this .stepTime;
      }

      return fraction;
   },
});

Object .defineProperties (X3DChaserNode,
{
   typeName:
   {
      value: "X3DChaserNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Followers",
      enumerable: true,
   },
});

const X3DChaserNode_default_ = X3DChaserNode;
;

x_ite_Namespace .add ("X3DChaserNode", "x_ite/Components/Followers/X3DChaserNode", X3DChaserNode_default_);
/* harmony default export */ const Followers_X3DChaserNode = (X3DChaserNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers/ColorChaser.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









var
   initialValue       = new Numbers_Vector3 (0, 0, 0),
   initialDestination = new Numbers_Vector3 (0, 0, 0),
   deltaOut           = new Numbers_Vector3 (0, 0, 0),
   vector             = new Numbers_Vector3 (0, 0, 0);

function ColorChaser (executionContext)
{
   Followers_X3DChaserNode .call (this, executionContext);

   this .addType (Base_X3DConstants .ColorChaser);
}

Object .assign (Object .setPrototypeOf (ColorChaser .prototype, Followers_X3DChaserNode .prototype),
{
   getVector ()
   {
      return new Numbers_Vector3 (0, 0, 0);
   },
   getValue ()
   {
      return this ._set_value .getValue () .getHSV (vector);
   },
   getDestination ()
   {
      return this ._set_destination .getValue () .getHSV (vector);
   },
   getInitialValue ()
   {
      return this ._initialValue .getValue () .getHSV (initialValue);
   },
   getInitialDestination ()
   {
      return this ._initialDestination .getValue () .getHSV (initialDestination);
   },
   setValue (value)
   {
      this ._value_changed .setHSV (value .x, value .y, value .z);
   },
   interpolate (source, destination, weight)
   {
      return Numbers_Color3 .lerp (source, destination, weight, vector);
   },
   step (value1, value2, t)
   {
      deltaOut .assign (this .output) .add (value1) .subtract (value2);

      //step .x = Algorithm .interval (step .x, 0, 2 * Math .PI);

      Numbers_Color3 .lerp (this .output, deltaOut, t, this .output);
   },
});

Object .defineProperties (ColorChaser,
{
   typeName:
   {
      value: "ColorChaser",
      enumerable: true,
   },
   componentName:
   {
      value: "Followers",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.3", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_value",          new x_ite_Fields .SFColor ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_destination",    new x_ite_Fields .SFColor ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialValue",       new x_ite_Fields .SFColor (0.8, 0.8, 0.8)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialDestination", new x_ite_Fields .SFColor (0.8, 0.8, 0.8)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "duration",           new x_ite_Fields .SFTime (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isActive",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "value_changed",      new x_ite_Fields .SFColor ()),
      ]),
      enumerable: true,
   },
});

const ColorChaser_default_ = ColorChaser;
;

x_ite_Namespace .add ("ColorChaser", "x_ite/Components/Followers/ColorChaser", ColorChaser_default_);
/* harmony default export */ const Followers_ColorChaser = (ColorChaser_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers/X3DDamperNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function X3DDamperNode (executionContext)
{
   Followers_X3DFollowerNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DDamperNode);
}

Object .assign (Object .setPrototypeOf (X3DDamperNode .prototype, Followers_X3DFollowerNode .prototype),
{
   initialize ()
   {
      Followers_X3DFollowerNode .prototype .initialize .call (this);

      this ._order           .addInterest ("set_order__", this);
      this ._set_value       .addInterest ("set_value__", this);
      this ._set_destination .addInterest ("set_destination__", this);

      var
         buffer             = this .getBuffer (),
         initialValue       = this .getInitialValue (),
         initialDestination = this .getInitialDestination ();

      buffer [0] = this .duplicate (initialDestination);

      for (var i = 1, length = this .getOrder () + 1; i < length; ++ i)
         buffer [i] = this .duplicate (initialValue);

      if (this .equals (initialDestination, initialValue, this .getTolerance ()))
         this .setValue (initialDestination);

      else
         this .set_active (true);
   },
   getOrder ()
   {
      return Math_Algorithm .clamp (this ._order .getValue (), 0, 5);
   },
   getTolerance ()
   {
      if (this ._tolerance .getValue () < 0)
         return 1e-4;

      return this ._tolerance .getValue ();
   },
   prepareEvents ()
   {
      var
         buffer = this .getBuffer (),
         order  = buffer .length - 1;

      if (this ._tau .getValue ())
      {
         var
            delta = 1 / this .getBrowser () .currentFrameRate,
            alpha = Math .exp (-delta / this ._tau .getValue ());

         for (var i = 0; i < order; ++ i)
         {
            this .assign (buffer, i + 1, this .interpolate (buffer [i], buffer [i + 1], alpha));
         }

         this .setValue (buffer [order]);

         if (! this .equals (buffer [order], buffer [0], this .getTolerance ()))
            return;
      }
      else
      {
         this .setValue (buffer [0]);

         order = 0;
      }

      for (var i = 1, length = buffer .length; i < length; ++ i)
         this .assign (buffer, i, buffer [order]);

      this .set_active (false);
   },
   set_value__ ()
   {
      var
         buffer = this .getBuffer (),
         value  = this .getValue ();

      for (var i = 1, length = buffer .length; i < length; ++ i)
         this .assign (buffer, i, value);

      this .setValue (value);

      this .set_active (true);
   },
   set_destination__ ()
   {
      this .assign (this .getBuffer (), 0, this .getDestination ());

      this .set_active (true);
   },
   set_order__ ()
   {
      var
         buffer = this .getBuffer (),
         value  = buffer [buffer .length - 1];

      for (var i = buffer .length, length = this .getOrder () + 1; i < length; ++ i)
         buffer [i] = this .duplicate (value);

      buffer .length = length;
   },
});

Object .defineProperties (X3DDamperNode,
{
   typeName:
   {
      value: "X3DDamperNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Followers",
      enumerable: true,
   },
});

const X3DDamperNode_default_ = X3DDamperNode;
;

x_ite_Namespace .add ("X3DDamperNode", "x_ite/Components/Followers/X3DDamperNode", X3DDamperNode_default_);
/* harmony default export */ const Followers_X3DDamperNode = (X3DDamperNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers/ColorDamper.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









var
   ColorDamper_a                  = new Numbers_Vector3 (0, 0, 0),
   ColorDamper_initialValue       = new Numbers_Vector3 (0, 0, 0),
   ColorDamper_initialDestination = new Numbers_Vector3 (0, 0, 0),
   ColorDamper_vector             = new Numbers_Vector3 (0, 0, 0);

function ColorDamper (executionContext)
{
   Followers_X3DDamperNode .call (this, executionContext);

   this .addType (Base_X3DConstants .ColorDamper);
}

Object .assign (Object .setPrototypeOf (ColorDamper .prototype, Followers_X3DDamperNode .prototype),
{
   getVector ()
   {
      return new Numbers_Vector3 (0, 0, 0);
   },
   getValue ()
   {
      return this ._set_value .getValue () .getHSV (ColorDamper_vector);
   },
   getDestination ()
   {
      return this ._set_destination .getValue () .getHSV (ColorDamper_vector);
   },
   getInitialValue ()
   {
      return this ._initialValue .getValue () .getHSV (ColorDamper_initialValue);
   },
   getInitialDestination ()
   {
      return this ._initialDestination .getValue () .getHSV (ColorDamper_initialDestination);
   },
   setValue (value)
   {
      this ._value_changed .setHSV (value .x, value .y, value .z);
   },
   equals (lhs, rhs, tolerance)
   {
      return ColorDamper_a .assign (lhs) .subtract (rhs) .magnitude () < tolerance;
   },
   interpolate (source, destination, weight)
   {
      return Numbers_Color3 .lerp (source, destination, weight, ColorDamper_vector);
   },
});

Object .defineProperties (ColorDamper,
{
   typeName:
   {
      value: "ColorDamper",
      enumerable: true,
   },
   componentName:
   {
      value: "Followers",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_value",          new x_ite_Fields .SFColor ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_destination",    new x_ite_Fields .SFColor ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialValue",       new x_ite_Fields .SFColor (0.8, 0.8, 0.8)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialDestination", new x_ite_Fields .SFColor (0.8, 0.8, 0.8)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "order",              new x_ite_Fields .SFInt32 (3)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "tau",                new x_ite_Fields .SFTime (0.3)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "tolerance",          new x_ite_Fields .SFFloat (-1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isActive",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "value_changed",      new x_ite_Fields .SFColor ()),
      ]),
      enumerable: true,
   },
});

const ColorDamper_default_ = ColorDamper;
;

x_ite_Namespace .add ("ColorDamper", "x_ite/Components/Followers/ColorDamper", ColorDamper_default_);
/* harmony default export */ const Followers_ColorDamper = (ColorDamper_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Followers/X3DArrayFollowerTemplate.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

function X3DArrayFollowerTemplate (Type)
{
   function X3DArrayFollowerObject ()
   {
      this .array = this .getArray ();
      this .zero  = this .getVector ();
   }

   Object .assign (X3DArrayFollowerObject .prototype,
   {
      getArray ()
      {
         const array = [ ];

         array .assign = function (value)
         {
            if (Array .isArray (value))
            {
               for (var i = 0, length = Math .min (this .length, value .length); i < length; ++ i)
                  this [i] .assign (value [i]);

               for (var i = length, length = value .length; i < length; ++ i)
                  this [i] = value [i] .copy ();

               this .length = length;
            }
            else
            {
               for (var i = 0, length = Math .min (this .length, value .length); i < length; ++ i)
                  this [i] .assign (value [i] .getValue ());

               for (var i = length, length = value .length; i < length; ++ i)
                  this [i] = value [i] .getValue () .copy ();

               this .length = length;
            }
         };

         return array;
      },
      getValue ()
      {
         return this ._set_value;
      },
      getDestination ()
      {
         return this ._set_destination;
      },
      getInitialValue ()
      {
         return this ._initialValue;
      },
      getInitialDestination ()
      {
         return this ._initialDestination;
      },
      setValue (value)
      {
         if (Array .isArray (value))
         {
            const value_changed = this ._value_changed;

            for (var i = 0, length = value .length; i < length; ++ i)
               value_changed [i] = value [i];

            value_changed .length = length;
         }
         else
         {
            this ._value_changed = value;
         }
      },
      duplicate (value)
      {
         const array = this .getArray ();

         array .assign (value);

         return array;
      },
      equals (lhs, rhs, tolerance)
      {
         if (lhs .length !== rhs .length)
            return false;

         const a = this .a;

         let distance = 0;

         for (let i = 0, length = lhs .length; i < length; ++ i)
           distance = Math .max (a .assign (lhs [i]) .subtract (rhs [i]) .magnitude ());

         return distance < tolerance;
      },
      interpolate (source, destination, weight)
      {
         const array = this .array;

         array .assign (source);

         for (let i = 0, length = array .length; i < length; ++ i)
            array [i] .lerp (destination [i] || this .zero, weight);

         return array;
      },
      set_destination__ ()
      {
         const
            buffers = this .getBuffer (),
            l       = this ._set_destination .length;

         for (let i = 0, length = buffers .length; i < length; ++ i)
         {
            const buffer = buffers [i];

            for (let b = buffer .length; b < l; ++ b)
               buffer [b] = this .getVector ();

            buffer .length = l;
         }

         Type .prototype .set_destination__ .call (this);
      },
   });

   return X3DArrayFollowerObject;
}

const X3DArrayFollowerTemplate_default_ = X3DArrayFollowerTemplate;
;

x_ite_Namespace .add ("X3DArrayFollowerTemplate", "x_ite/Browser/Followers/X3DArrayFollowerTemplate", X3DArrayFollowerTemplate_default_);
/* harmony default export */ const Followers_X3DArrayFollowerTemplate = (X3DArrayFollowerTemplate_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Followers/X3DArrayChaserTemplate.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function X3DArrayChaserTemplate (Type)
{
   const X3DArrayFollower = Followers_X3DArrayFollowerTemplate (Type);

   function X3DArrayChaserObject ()
   {
      X3DArrayFollower .call (this);

      this .array = this .getArray ();
   }

   Object .assign (X3DArrayChaserObject .prototype,
      X3DArrayFollower .prototype,
   {
      step (value1, value2, t)
      {
         const
            output   = this .output,
            deltaOut = this .deltaOut;

         for (let i = 0, length = output .length; i < length; ++ i)
            output [i] .add (deltaOut .assign (value1 [i] || this .zero) .subtract (value2 [i] || this .zero) .multiply (t));
      },
   });

   return X3DArrayChaserObject;
}

const X3DArrayChaserTemplate_default_ = X3DArrayChaserTemplate;
;

x_ite_Namespace .add ("X3DArrayChaserTemplate", "x_ite/Browser/Followers/X3DArrayChaserTemplate", X3DArrayChaserTemplate_default_);
/* harmony default export */ const Followers_X3DArrayChaserTemplate = (X3DArrayChaserTemplate_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers/CoordinateChaser.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









var X3DArrayChaserObject = Followers_X3DArrayChaserTemplate (Followers_X3DChaserNode);

function CoordinateChaser (executionContext)
{
   Followers_X3DChaserNode        .call (this, executionContext);
   X3DArrayChaserObject .call (this, executionContext);

   this .addType (Base_X3DConstants .CoordinateChaser);
}

Object .assign (Object .setPrototypeOf (CoordinateChaser .prototype, Followers_X3DChaserNode .prototype),
   X3DArrayChaserObject .prototype,
{
   getVector ()
   {
      return new Numbers_Vector3 (0, 0, 0);
   },
});

Object .defineProperties (CoordinateChaser,
{
   typeName:
   {
      value: "CoordinateChaser",
      enumerable: true,
   },
   componentName:
   {
      value: "Followers",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.3", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_value",          new x_ite_Fields .MFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_destination",    new x_ite_Fields .MFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialValue",       new x_ite_Fields .MFVec3f (new Numbers_Vector3 (0, 0, 0))),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialDestination", new x_ite_Fields .MFVec3f (new Numbers_Vector3 (0, 0, 0))),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "duration",           new x_ite_Fields .SFTime (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isActive",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "value_changed",      new x_ite_Fields .MFVec3f ()),
      ]),
      enumerable: true,
   },
});

const CoordinateChaser_default_ = CoordinateChaser;
;

x_ite_Namespace .add ("CoordinateChaser", "x_ite/Components/Followers/CoordinateChaser", CoordinateChaser_default_);
/* harmony default export */ const Followers_CoordinateChaser = (CoordinateChaser_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers/CoordinateDamper.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









var X3DArrayFollowerObject = Followers_X3DArrayFollowerTemplate (Followers_X3DDamperNode);

function CoordinateDamper (executionContext)
{
   Followers_X3DDamperNode          .call (this, executionContext);
   X3DArrayFollowerObject .call (this, executionContext);

   this .addType (Base_X3DConstants .CoordinateDamper);
}

Object .assign (Object .setPrototypeOf (CoordinateDamper .prototype, Followers_X3DDamperNode .prototype),
   X3DArrayFollowerObject .prototype,
{
   getVector ()
   {
      return new Numbers_Vector3 (0, 0, 0);
   },
});

Object .defineProperties (CoordinateDamper,
{
   typeName:
   {
      value: "CoordinateDamper",
      enumerable: true,
   },
   componentName:
   {
      value: "Followers",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_value",          new x_ite_Fields .MFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_destination",    new x_ite_Fields .MFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialValue",       new x_ite_Fields .MFVec3f (new Numbers_Vector3 (0, 0, 0))),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialDestination", new x_ite_Fields .MFVec3f (new Numbers_Vector3 (0, 0, 0))),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "order",              new x_ite_Fields .SFInt32 (3)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "tau",                new x_ite_Fields .SFTime (0.3)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "tolerance",          new x_ite_Fields .SFFloat (-1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isActive",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "value_changed",      new x_ite_Fields .MFVec3f ()),
      ]),
      enumerable: true,
   },
});

const CoordinateDamper_default_ = CoordinateDamper;
;

x_ite_Namespace .add ("CoordinateDamper", "x_ite/Components/Followers/CoordinateDamper", CoordinateDamper_default_);
/* harmony default export */ const Followers_CoordinateDamper = (CoordinateDamper_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers/OrientationChaser.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








var
   OrientationChaser_a        = new Numbers_Rotation4 (),
   rotation = new Numbers_Rotation4 ();

function OrientationChaser (executionContext)
{
   Followers_X3DChaserNode .call (this, executionContext);

   this .addType (Base_X3DConstants .OrientationChaser);

   this ._set_value          .setUnit ("angle");
   this ._set_destination    .setUnit ("angle");
   this ._initialValue       .setUnit ("angle");
   this ._initialDestination .setUnit ("angle");
   this ._value_changed      .setUnit ("angle");
}

Object .assign (Object .setPrototypeOf (OrientationChaser .prototype, Followers_X3DChaserNode .prototype),
{
   getVector ()
   {
      return new Numbers_Rotation4 ();
   },
   equals (lhs, rhs, tolerance)
   {
      OrientationChaser_a .assign (lhs) .inverse () .multRight (rhs);

      return Math .abs (OrientationChaser_a .angle) < tolerance;
   },
   interpolate (source, destination, weight)
   {
      return rotation .assign (source) .slerp (destination, weight);
   },
   step (value1, value2, t)
   {
      this .deltaOut .assign (value2) .inverse () .multRight (value1) .multLeft (this .output);

      this .output .slerp (this .deltaOut, t);
   },
});

Object .defineProperties (OrientationChaser,
{
   typeName:
   {
      value: "OrientationChaser",
      enumerable: true,
   },
   componentName:
   {
      value: "Followers",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_value",          new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_destination",    new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialValue",       new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialDestination", new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "duration",           new x_ite_Fields .SFTime (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isActive",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "value_changed",      new x_ite_Fields .SFRotation ()),
      ]),
      enumerable: true,
   },
});

const OrientationChaser_default_ = OrientationChaser;
;

x_ite_Namespace .add ("OrientationChaser", "x_ite/Components/Followers/OrientationChaser", OrientationChaser_default_);
/* harmony default export */ const Followers_OrientationChaser = (OrientationChaser_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers/OrientationDamper.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








var
   OrientationDamper_a        = new Numbers_Rotation4 (),
   OrientationDamper_rotation = new Numbers_Rotation4 ();

function OrientationDamper (executionContext)
{
   Followers_X3DDamperNode .call (this, executionContext);

   this .addType (Base_X3DConstants .OrientationDamper);

   this ._set_value          .setUnit ("angle");
   this ._set_destination    .setUnit ("angle");
   this ._initialValue       .setUnit ("angle");
   this ._initialDestination .setUnit ("angle");
   this ._value_changed      .setUnit ("angle");
}

Object .assign (Object .setPrototypeOf (OrientationDamper .prototype, Followers_X3DDamperNode .prototype),
{
   getVector ()
   {
      return new Numbers_Rotation4 ();
   },
   equals (lhs, rhs, tolerance)
   {
      OrientationDamper_a .assign (lhs) .inverse () .multRight (rhs);

      return Math .abs (OrientationDamper_a .angle) < tolerance;
   },
   interpolate (source, destination, weight)
   {
      return OrientationDamper_rotation .assign (source) .slerp (destination, weight);
   },
});

Object .defineProperties (OrientationDamper,
{
   typeName:
   {
      value: "OrientationDamper",
      enumerable: true,
   },
   componentName:
   {
      value: "Followers",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_value",          new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_destination",    new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialValue",       new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialDestination", new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "order",              new x_ite_Fields .SFInt32 (3)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "tau",                new x_ite_Fields .SFTime (0.3)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "tolerance",          new x_ite_Fields .SFFloat (-1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isActive",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "value_changed",      new x_ite_Fields .SFRotation ()),
      ]),
      enumerable: true,
   },
});

const OrientationDamper_default_ = OrientationDamper;
;

x_ite_Namespace .add ("OrientationDamper", "x_ite/Components/Followers/OrientationDamper", OrientationDamper_default_);
/* harmony default export */ const Followers_OrientationDamper = (OrientationDamper_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers/PositionChaser.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function PositionChaser (executionContext)
{
   Followers_X3DChaserNode .call (this, executionContext);

   this .addType (Base_X3DConstants .PositionChaser);
}

Object .assign (Object .setPrototypeOf (PositionChaser .prototype, Followers_X3DChaserNode .prototype),
{
   getVector ()
   {
      return new Numbers_Vector3 (0, 0, 0);
   },
});

Object .defineProperties (PositionChaser,
{
   typeName:
   {
      value: "PositionChaser",
      enumerable: true,
   },
   componentName:
   {
      value: "Followers",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_value",          new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_destination",    new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialValue",       new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialDestination", new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "duration",           new x_ite_Fields .SFTime (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isActive",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "value_changed",      new x_ite_Fields .SFVec3f ()),
      ]),
      enumerable: true,
   },
});

const PositionChaser_default_ = PositionChaser;
;

x_ite_Namespace .add ("PositionChaser", "x_ite/Components/Followers/PositionChaser", PositionChaser_default_);
/* harmony default export */ const Followers_PositionChaser = (PositionChaser_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers/PositionChaser2D.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function PositionChaser2D (executionContext)
{
   Followers_X3DChaserNode .call (this, executionContext);

   this .addType (Base_X3DConstants .PositionChaser2D);
}

Object .assign (Object .setPrototypeOf (PositionChaser2D .prototype, Followers_X3DChaserNode .prototype),
{
   getVector ()
   {
      return new Numbers_Vector2 (0, 0);
   },
});

Object .defineProperties (PositionChaser2D,
{
   typeName:
   {
      value: "PositionChaser2D",
      enumerable: true,
   },
   componentName:
   {
      value: "Followers",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_value",          new x_ite_Fields .SFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_destination",    new x_ite_Fields .SFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialValue",       new x_ite_Fields .SFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialDestination", new x_ite_Fields .SFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "duration",           new x_ite_Fields .SFTime (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isActive",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "value_changed",      new x_ite_Fields .SFVec2f ()),
      ]),
      enumerable: true,
   },
});

const PositionChaser2D_default_ = PositionChaser2D;
;

x_ite_Namespace .add ("PositionChaser2D", "x_ite/Components/Followers/PositionChaser2D", PositionChaser2D_default_);
/* harmony default export */ const Followers_PositionChaser2D = (PositionChaser2D_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers/PositionDamper.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function PositionDamper (executionContext)
{
   Followers_X3DDamperNode .call (this, executionContext);

   this .addType (Base_X3DConstants .PositionDamper);
}

Object .assign (Object .setPrototypeOf (PositionDamper .prototype, Followers_X3DDamperNode .prototype),
{
   getVector ()
   {
      return new Numbers_Vector3 (0, 0, 0);
   },
});

Object .defineProperties (PositionDamper,
{
   typeName:
   {
      value: "PositionDamper",
      enumerable: true,
   },
   componentName:
   {
      value: "Followers",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_value",          new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_destination",    new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialValue",       new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialDestination", new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "order",              new x_ite_Fields .SFInt32 (3)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "tolerance",          new x_ite_Fields .SFFloat (-1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "tau",                new x_ite_Fields .SFTime (0.3)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "value_changed",      new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isActive",           new x_ite_Fields .SFBool ()),
      ]),
      enumerable: true,
   },
});

const PositionDamper_default_ = PositionDamper;
;

x_ite_Namespace .add ("PositionDamper", "x_ite/Components/Followers/PositionDamper", PositionDamper_default_);
/* harmony default export */ const Followers_PositionDamper = (PositionDamper_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers/PositionDamper2D.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function PositionDamper2D (executionContext)
{
   Followers_X3DDamperNode .call (this, executionContext);

   this .addType (Base_X3DConstants .PositionDamper2D);
}

Object .assign (Object .setPrototypeOf (PositionDamper2D .prototype, Followers_X3DDamperNode .prototype),
{
   getVector ()
   {
      return new Numbers_Vector2 (0, 0);
   },
});

Object .defineProperties (PositionDamper2D,
{
   typeName:
   {
      value: "PositionDamper2D",
      enumerable: true,
   },
   componentName:
   {
      value: "Followers",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_value",          new x_ite_Fields .SFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_destination",    new x_ite_Fields .SFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialValue",       new x_ite_Fields .SFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialDestination", new x_ite_Fields .SFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "order",              new x_ite_Fields .SFInt32 (3)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "tau",                new x_ite_Fields .SFTime (0.3)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "tolerance",          new x_ite_Fields .SFFloat (-1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isActive",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "value_changed",      new x_ite_Fields .SFVec2f ()),
      ]),
      enumerable: true,
   },
});

const PositionDamper2D_default_ = PositionDamper2D;
;

x_ite_Namespace .add ("PositionDamper2D", "x_ite/Components/Followers/PositionDamper2D", PositionDamper2D_default_);
/* harmony default export */ const Followers_PositionDamper2D = (PositionDamper2D_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers/ScalarChaser.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function ScalarChaser (executionContext)
{
   Followers_X3DChaserNode .call (this, executionContext);

   this .addType (Base_X3DConstants .ScalarChaser);
}

Object .assign (Object .setPrototypeOf (ScalarChaser .prototype, Followers_X3DChaserNode .prototype),
{
   getVector ()
   {
      return 0;
   },
   setPreviousValue (value)
   {
      this .previousValue = value;
   },
   setDestination (value)
   {
      this .destination = value;
   },
   duplicate (value)
   {
      return value;
   },
   assign (buffer, i, value)
   {
      buffer [i] = value;
   },
   equals (lhs, rhs, tolerance)
   {
      return Math .abs (lhs - rhs) < tolerance;
   },
   interpolate (source, destination, weight)
   {
      return Math_Algorithm .lerp (source, destination, weight);
   },
   step (value1, value2, t)
   {
      this .output += (value1 - value2) * t;
   },
});

Object .defineProperties (ScalarChaser,
{
   typeName:
   {
      value: "ScalarChaser",
      enumerable: true,
   },
   componentName:
   {
      value: "Followers",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_value",          new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_destination",    new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialValue",       new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialDestination", new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "duration",           new x_ite_Fields .SFTime (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isActive",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "value_changed",      new x_ite_Fields .SFFloat ()),
      ]),
      enumerable: true,
   },
});

const ScalarChaser_default_ = ScalarChaser;
;

x_ite_Namespace .add ("ScalarChaser", "x_ite/Components/Followers/ScalarChaser", ScalarChaser_default_);
/* harmony default export */ const Followers_ScalarChaser = (ScalarChaser_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers/ScalarDamper.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function ScalarDamper (executionContext)
{
   Followers_X3DDamperNode .call (this, executionContext);

   this .addType (Base_X3DConstants .ScalarDamper);
}

Object .assign (Object .setPrototypeOf (ScalarDamper .prototype, Followers_X3DDamperNode .prototype),
{
   getVector ()
   {
      return 0;
   },
   duplicate (value)
   {
      return value;
   },
   assign (buffer, i, value)
   {
      buffer [i] = value;
   },
   equals (lhs, rhs, tolerance)
   {
      return Math .abs (lhs - rhs) < tolerance;
   },
   interpolate (source, destination, weight)
   {
      return Math_Algorithm .lerp (source, destination, weight);
   },
});

Object .defineProperties (ScalarDamper,
{
   typeName:
   {
      value: "ScalarDamper",
      enumerable: true,
   },
   componentName:
   {
      value: "Followers",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.3", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_value",          new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_destination",    new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialValue",       new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialDestination", new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "order",              new x_ite_Fields .SFInt32 (3)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "tau",                new x_ite_Fields .SFTime (0.3)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "tolerance",          new x_ite_Fields .SFFloat (-1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isActive",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "value_changed",      new x_ite_Fields .SFFloat ()),
      ]),
      enumerable: true,
   },
});

const ScalarDamper_default_ = ScalarDamper;
;

x_ite_Namespace .add ("ScalarDamper", "x_ite/Components/Followers/ScalarDamper", ScalarDamper_default_);
/* harmony default export */ const Followers_ScalarDamper = (ScalarDamper_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers/TexCoordChaser2D.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









var TexCoordChaser2D_X3DArrayChaserObject = Followers_X3DArrayChaserTemplate (Followers_X3DChaserNode);

function TexCoordChaser2D (executionContext)
{
   Followers_X3DChaserNode        .call (this, executionContext);
   TexCoordChaser2D_X3DArrayChaserObject .call (this, executionContext);

   this .addType (Base_X3DConstants .TexCoordChaser2D);
}

Object .assign (Object .setPrototypeOf (TexCoordChaser2D .prototype, Followers_X3DChaserNode .prototype),
   TexCoordChaser2D_X3DArrayChaserObject .prototype,
{
   getVector ()
   {
      return new Numbers_Vector2 (0, 0);
   },
});

Object .defineProperties (TexCoordChaser2D,
{
   typeName:
   {
      value: "TexCoordChaser2D",
      enumerable: true,
   },
   componentName:
   {
      value: "Followers",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.3", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_value",          new x_ite_Fields .MFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_destination",    new x_ite_Fields .MFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialValue",       new x_ite_Fields .MFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialDestination", new x_ite_Fields .MFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "duration",           new x_ite_Fields .SFTime (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isActive",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "value_changed",      new x_ite_Fields .MFVec2f ()),
      ]),
      enumerable: true,
   },
});

const TexCoordChaser2D_default_ = TexCoordChaser2D;
;

x_ite_Namespace .add ("TexCoordChaser2D", "x_ite/Components/Followers/TexCoordChaser2D", TexCoordChaser2D_default_);
/* harmony default export */ const Followers_TexCoordChaser2D = (TexCoordChaser2D_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers/TexCoordDamper2D.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









var TexCoordDamper2D_X3DArrayFollowerObject = Followers_X3DArrayFollowerTemplate (Followers_X3DDamperNode);

function TexCoordDamper2D (executionContext)
{
   Followers_X3DDamperNode          .call (this, executionContext);
   TexCoordDamper2D_X3DArrayFollowerObject .call (this, executionContext);

   this .addType (Base_X3DConstants .TexCoordDamper2D);
}

Object .assign (Object .setPrototypeOf (TexCoordDamper2D .prototype, Followers_X3DDamperNode .prototype),
   TexCoordDamper2D_X3DArrayFollowerObject .prototype,
{
   getVector ()
   {
      return new Numbers_Vector2 (0, 0, 0);
   },
});

Object .defineProperties (TexCoordDamper2D,
{
   typeName:
   {
      value: "TexCoordDamper2D",
      enumerable: true,
   },
   componentName:
   {
      value: "Followers",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_value",          new x_ite_Fields .MFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_destination",    new x_ite_Fields .MFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialValue",       new x_ite_Fields .MFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "initialDestination", new x_ite_Fields .MFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "order",              new x_ite_Fields .SFInt32 (3)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "tau",                new x_ite_Fields .SFTime (0.3)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "tolerance",          new x_ite_Fields .SFFloat (-1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isActive",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "value_changed",      new x_ite_Fields .MFVec2f ()),
      ]),
      enumerable: true,
   },
});

const TexCoordDamper2D_default_ = TexCoordDamper2D;
;

x_ite_Namespace .add ("TexCoordDamper2D", "x_ite/Components/Followers/TexCoordDamper2D", TexCoordDamper2D_default_);
/* harmony default export */ const Followers_TexCoordDamper2D = (TexCoordDamper2D_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Followers.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



















const Followers_default_ = {
   name: "Followers",
   concreteNodes:
   [
      Followers_ColorChaser,
      Followers_ColorDamper,
      Followers_CoordinateChaser,
      Followers_CoordinateDamper,
      Followers_OrientationChaser,
      Followers_OrientationDamper,
      Followers_PositionChaser,
      Followers_PositionChaser2D,
      Followers_PositionDamper,
      Followers_PositionDamper2D,
      Followers_ScalarChaser,
      Followers_ScalarDamper,
      Followers_TexCoordChaser2D,
      Followers_TexCoordDamper2D,
   ],
   abstractNodes:
   [
      Followers_X3DChaserNode,
      Followers_X3DDamperNode,
      Followers_X3DFollowerNode,
   ],
};
;

x_ite_Namespace .add ("Followers", "x_ite/Components/Followers", Followers_default_);
/* harmony default export */ const Followers = (Followers_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Geometry3D/Box.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function Box (executionContext)
{
   Rendering_X3DGeometryNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Box);

   this ._size .setUnit ("length");
}

Object .assign (Object .setPrototypeOf (Box .prototype, Rendering_X3DGeometryNode .prototype),
{
   build: (() =>
   {
      const defaultSize = new Numbers_Vector3 (2, 2, 2);

      return function ()
      {
         const
            options  = this .getBrowser () .getBoxOptions (),
            geometry = options .getGeometry (),
            size     = this ._size .getValue ();

         this .setMultiTexCoords (geometry .getMultiTexCoords ());
         this .setNormals        (geometry .getNormals ());

         if (size .equals (defaultSize))
         {
            this .setVertices (geometry .getVertices ());

            this .getMin () .assign (geometry .getMin ());
            this .getMax () .assign (geometry .getMax ());
         }
         else
         {
            const
               x               = Math .abs (size .x / 2),
               y               = Math .abs (size .y / 2),
               z               = Math .abs (size .z / 2),
               defaultVertices = geometry .getVertices () .getValue (),
               vertexArray     = this .getVertices ();

            for (let i = 0, length = defaultVertices .length; i < length; i += 4)
            {
               vertexArray .push (x * defaultVertices [i],
                                  y * defaultVertices [i + 1],
                                  z * defaultVertices [i + 2],
                                  1);
            }

            this .getMin () .set (-x, -y, -z);
            this .getMax () .set ( x,  y,  z);
         }

         this .setSolid (this ._solid .getValue ());
      };
   })(),
});

Object .defineProperties (Box,
{
   typeName:
   {
      value: "Box",
      enumerable: true,
   },
   componentName:
   {
      value: "Geometry3D",
      enumerable: true,
   },
   containerField:
   {
      value: "geometry",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "size",     new x_ite_Fields .SFVec3f (2, 2, 2)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "solid",    new x_ite_Fields .SFBool (true)),
      ]),
      enumerable: true,
   },
});

const Box_default_ = Box;
;

x_ite_Namespace .add ("Box", "x_ite/Components/Geometry3D/Box", Box_default_);
/* harmony default export */ const Geometry3D_Box = (Box_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Geometry3D/Cone.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










function Cone (executionContext)
{
   Rendering_X3DGeometryNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Cone);

   this ._height       .setUnit ("length");
   this ._bottomRadius .setUnit ("length");
}

Object .assign (Object .setPrototypeOf (Cone .prototype, Rendering_X3DGeometryNode .prototype),
{
   set_live__ ()
   {
      Rendering_X3DGeometryNode .prototype .set_live__ .call (this);

      if (this .getLive () .getValue ())
         this .getBrowser () .getConeOptions () .addInterest ("requestRebuild", this);
      else
         this .getBrowser () .getConeOptions () .removeInterest ("requestRebuild", this);
   },
   build ()
   {
      const
         options       = this .getBrowser () .getConeOptions (),
         xDimension    = options ._xDimension .getValue (),
         height        = this ._height .getValue (),
         bottomRadius  = this ._bottomRadius .getValue (),
         texCoordArray = this .getTexCoords (),
         normalArray   = this .getNormals (),
         vertexArray   = this .getVertices ();

      this .getMultiTexCoords () .push (texCoordArray);

      const
         y1 = height / 2,
         y2 = -y1,
         nz = Numbers_Complex .Polar (1, -Math .PI / 2 + Math .atan (bottomRadius / height));

      if (this ._side .getValue ())
      {
         for (let i = 0; i < xDimension; ++ i)
         {
            const
               u1     = (i + 0.5) / xDimension,
               theta1 = 2 * Math .PI * u1,
               n1     = Numbers_Complex .Polar (nz .imag, theta1);

            const
               u2     = i / xDimension,
               theta2 = 2 * Math .PI * u2,
               p2     = Numbers_Complex .Polar (-bottomRadius, theta2),
               n2     = Numbers_Complex .Polar (nz .imag, theta2);

            const
               u3     = (i + 1) / xDimension,
               theta3 = 2 * Math .PI * u3,
               p3     = Numbers_Complex .Polar (-bottomRadius, theta3),
               n3     = Numbers_Complex .Polar (nz .imag, theta3);

            /*    p1
             *   /  \
             *  /    \
             * p2 -- p3
             */

            // p1
            texCoordArray .push (u1, 1, 0, 1);
            normalArray   .push (n1 .imag, nz .real, n1 .real);
            vertexArray   .push (0, y1, 0, 1);

            // p2
            texCoordArray .push (u2, 0, 0, 1);
            normalArray   .push (n2 .imag, nz .real, n2 .real);
            vertexArray   .push (p2 .imag, y2, p2 .real, 1);

            // p3
            texCoordArray .push (u3, 0, 0, 1);
            normalArray   .push (n3 .imag , nz .real, n3 .real);
            vertexArray   .push (p3 .imag, y2, p3 .real, 1);
         }
      }

      if (this ._bottom .getValue ())
      {
         const
            texCoord = [ ],
            points   = [ ];

         for (let i = xDimension - 1; i > -1; -- i)
         {
            const
               u     = i / xDimension,
               theta = 2 * Math .PI * u,
               t     = Numbers_Complex .Polar (-1, theta),
               p     = t .copy () .multiply (bottomRadius);

            texCoord .push (new Numbers_Vector2 ((t .imag + 1) / 2, (t .real + 1) / 2));
            points   .push (new Numbers_Vector3 (p .imag, y2, p .real));
         }

         const
            t0 = texCoord [0],
            p0 = points [0];

         for (let i = 1, length = points .length - 1; i < length; ++ i)
         {
            const
               t1 = texCoord [i],
               t2 = texCoord [i + 1],
               p1 = points [i],
               p2 = points [i + 1];

            texCoordArray .push (t0 .x, t0 .y, 0, 1);
            normalArray   .push (0, -1, 0);
            vertexArray   .push (p0 .x, p0 .y, p0 .z, 1);

            texCoordArray .push (t1 .x, t1 .y, 0, 1);
            normalArray   .push (0, -1, 0);
            vertexArray   .push (p1 .x, p1 .y, p1 .z, 1);

            texCoordArray .push (t2 .x, t2 .y, 0, 1);
            normalArray   .push (0, -1, 0);
            vertexArray   .push (p2 .x, p2 .y, p2 .z, 1);
         }
      }

      this .setSolid (this ._solid .getValue ());
      this .setExtents ();
   },
   setExtents ()
   {
      const
         bottomRadius = this ._bottomRadius .getValue (),
         y1           = this ._height .getValue () / 2,
         y2           = -y1;

      if (!this ._side .getValue () && !this ._bottom .getValue ())
      {
         this .getMin () .set (0, 0, 0);
         this .getMax () .set (0, 0, 0);
      }
      else if (! this ._side .getValue ())
      {
         this .getMin () .set (-bottomRadius, y2, -bottomRadius);
         this .getMax () .set ( bottomRadius, y2,  bottomRadius);
      }
      else
      {
         this .getMin () .set (-bottomRadius, y2, -bottomRadius);
         this .getMax () .set ( bottomRadius, y1, bottomRadius);
      }
   },
});

Object .defineProperties (Cone,
{
   typeName:
   {
      value: "Cone",
      enumerable: true,
   },
   componentName:
   {
      value: "Geometry3D",
      enumerable: true,
   },
   containerField:
   {
      value: "geometry",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",     new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "side",         new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "bottom",       new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "height",       new x_ite_Fields .SFFloat (2)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bottomRadius", new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "solid",        new x_ite_Fields .SFBool (true)),
      ]),
      enumerable: true,
   },
});

const Cone_default_ = Cone;
;

x_ite_Namespace .add ("Cone", "x_ite/Components/Geometry3D/Cone", Cone_default_);
/* harmony default export */ const Geometry3D_Cone = (Cone_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Geometry3D/Cylinder.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










function Cylinder (executionContext)
{
   Rendering_X3DGeometryNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Cylinder);

   this ._height .setUnit ("length");
   this ._radius .setUnit ("length");
}

Object .assign (Object .setPrototypeOf (Cylinder .prototype, Rendering_X3DGeometryNode .prototype),
{
   set_live__ ()
   {
      Rendering_X3DGeometryNode .prototype .set_live__ .call (this);

      if (this .getLive () .getValue ())
         this .getBrowser () .getCylinderOptions () .addInterest ("requestRebuild", this);
      else
         this .getBrowser () .getCylinderOptions () .removeInterest ("requestRebuild", this);
   },
   build ()
   {
      const
         options       = this .getBrowser () .getCylinderOptions (),
         xDimension    = options ._xDimension .getValue (),
         texCoordArray = this .getTexCoords (),
         normalArray   = this .getNormals (),
         vertexArray   = this .getVertices ();

      this .getMultiTexCoords () .push (texCoordArray);

      const
         radius = this ._radius .getValue (),
         y1     = this ._height .getValue () / 2,
         y2     = -y1;

      if (this ._side .getValue ())
      {
         for (let i = 0; i < xDimension; ++ i)
         {
            const
               u1     = i / xDimension,
               theta1 = 2 * Math .PI * u1,
               n1     = Numbers_Complex .Polar (-1, theta1),
               p1     = n1 .copy () .multiply (radius);

            const
               u2     = (i + 1) / xDimension,
               theta2 = 2 * Math .PI * u2,
               n2     = Numbers_Complex .Polar (-1, theta2),
               p2     = n2 .copy () .multiply (radius);

            // p1 - p4
            //  | \ |
            // p2 - p3

            // Triangle one

            // p1
            texCoordArray .push (u1, 1, 0, 1);
            normalArray   .push (n1 .imag,  0, n1 .real);
            vertexArray   .push (p1 .imag, y1, p1 .real, 1);

            // p2
            texCoordArray .push (u1, 0, 0, 1);
            normalArray   .push (n1 .imag,  0, n1 .real);
            vertexArray   .push (p1 .imag, y2, p1 .real, 1);

            // p3
            texCoordArray .push (u2, 0, 0, 1);
            normalArray   .push (n2 .imag,  0, n2 .real);
            vertexArray   .push (p2 .imag, y2, p2 .real, 1);

            // Triangle two

            // p1
            texCoordArray .push (u1, 1, 0, 1);
            normalArray   .push (n1 .imag,  0, n1 .real);
            vertexArray   .push (p1 .imag, y1, p1 .real, 1);

            // p3
            texCoordArray .push (u2, 0, 0, 1);
            normalArray   .push (n2 .imag,  0, n2 .real);
            vertexArray   .push (p2 .imag, y2, p2 .real, 1);

            // p4
            texCoordArray .push (u2, 1, 0, 1);
            normalArray   .push (n2 .imag,  0, n2 .real);
            vertexArray   .push (p2 .imag, y1, p2 .real, 1);
         }
      }

      if (this ._top .getValue ())
      {
         const
            texCoord = [ ],
            points   = [ ];

         for (let i = 0; i < xDimension; ++ i)
         {
            const
               u     = i / xDimension,
               theta = 2 * Math .PI * u,
               t     = Numbers_Complex .Polar (-1, theta);

            texCoord .push (new Numbers_Vector2 ((t .imag + 1) / 2, -(t .real - 1) / 2));
            points   .push (new Numbers_Vector3 (t .imag * radius, y1, t .real * radius));
         }

         const
            t0 = texCoord [0],
            p0 = points [0];

         for (let i = 1, length = points .length - 1; i < length; ++ i)
         {
            const
               t1 = texCoord [i],
               t2 = texCoord [i + 1],
               p1 = points [i],
               p2 = points [i + 1];

            texCoordArray .push (t0 .x, t0 .y, 0, 1);
            normalArray   .push (0, 1, 0);
            vertexArray   .push (p0 .x, p0 .y, p0 .z, 1);

            texCoordArray .push (t1 .x, t1 .y, 0, 1);
            normalArray   .push (0, 1, 0);
            vertexArray   .push (p1 .x, p1 .y, p1 .z, 1);

            texCoordArray .push (t2 .x, t2 .y, 0, 1);
            normalArray   .push (0, 1, 0);
            vertexArray   .push (p2 .x, p2 .y, p2 .z, 1);
         }
      }

      if (this ._bottom .getValue ())
      {
         const
            texCoord = [ ],
            points   = [ ];

         for (let i = xDimension - 1; i > -1; -- i)
         {
            const
               u     = i / xDimension,
               theta = 2 * Math .PI * u,
               t     = Numbers_Complex .Polar (-1, theta);

            texCoord .push (new Numbers_Vector2 ((t .imag + 1) / 2, (t .real + 1) / 2));
            points   .push (new Numbers_Vector3 (t .imag * radius, y2, t .real * radius));
         }

         const
            t0 = texCoord [0],
            p0 = points [0];

         for (let i = 1, length = points .length - 1; i < length; ++ i)
         {
            const
               t1 = texCoord [i],
               t2 = texCoord [i + 1],
               p1 = points [i],
               p2 = points [i + 1];

            texCoordArray .push (t0 .x, t0 .y, 0, 1);
            normalArray   .push (0, -1, 0);
            vertexArray   .push (p0 .x, p0 .y, p0 .z, 1);

            texCoordArray .push (t1 .x, t1 .y, 0, 1);
            normalArray   .push (0, -1, 0);
            vertexArray   .push (p1 .x, p1 .y, p1 .z, 1);

            texCoordArray .push (t2 .x, t2 .y, 0, 1);
            normalArray   .push (0, -1, 0);
            vertexArray   .push (p2 .x, p2 .y, p2 .z, 1);
         }
      }

      this .setSolid (this ._solid .getValue ());
      this .setExtents ();
   },
   setExtents ()
   {
      const
         radius = this ._radius .getValue (),
         y1     = this ._height .getValue () / 2,
         y2     = -y1;

      if (! this ._top .getValue () && ! this ._side .getValue () && ! this ._bottom .getValue ())
      {
         this .getMin () .set (0, 0, 0);
         this .getMax () .set (0, 0, 0);
      }

      else if (! this ._top .getValue () && ! this ._side .getValue ())
      {
         this .getMin () .set (-radius, y2, -radius);
         this .getMax () .set ( radius, y2,  radius);
      }

      else if (! this ._bottom .getValue () && ! this ._side .getValue ())
      {
         this .getMin () .set (-radius, y1, -radius);
         this .getMax () .set ( radius, y1,  radius);
      }

      else
      {
         this .getMin () .set (-radius, y2, -radius);
         this .getMax () .set ( radius, y1,  radius);
      }
   },
});

Object .defineProperties (Cylinder,
{
   typeName:
   {
      value: "Cylinder",
      enumerable: true,
   },
   componentName:
   {
      value: "Geometry3D",
      enumerable: true,
   },
   containerField:
   {
      value: "geometry",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "top",      new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "side",     new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "bottom",   new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "height",   new x_ite_Fields .SFFloat (2)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "radius",   new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "solid",    new x_ite_Fields .SFBool (true)),
      ]),
      enumerable: true,
   },
});

const Cylinder_default_ = Cylinder;
;

x_ite_Namespace .add ("Cylinder", "x_ite/Components/Geometry3D/Cylinder", Cylinder_default_);
/* harmony default export */ const Geometry3D_Cylinder = (Cylinder_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Geometry3D/ElevationGrid.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/











function ElevationGrid (executionContext)
{
   Rendering_X3DGeometryNode .call (this, executionContext);

   this .addType (Base_X3DConstants .ElevationGrid);

   this ._xSpacing    .setUnit ("length");
   this ._zSpacing    .setUnit ("length");
   this ._creaseAngle .setUnit ("angle");
   this ._height      .setUnit ("length");

   this .fogCoordNode = null;
   this .colorNode    = null;
   this .texCoordNode = null;
   this .normalNode   = null;
   this .coordNode    = null;
}

Object .assign (Object .setPrototypeOf (ElevationGrid .prototype, Rendering_X3DGeometryNode .prototype),
{
   initialize ()
   {
      Rendering_X3DGeometryNode .prototype .initialize .call (this);

      this ._set_height .addFieldInterest (this ._height);
      this ._attrib     .addInterest ("set_attrib__",   this);
      this ._fogCoord   .addInterest ("set_fogCoord__", this);
      this ._color      .addInterest ("set_color__",    this);
      this ._texCoord   .addInterest ("set_texCoord__", this);
      this ._normal     .addInterest ("set_normal__",   this);

      this .set_attrib__ ();
      this .set_fogCoord__ ();
      this .set_color__ ();
      this .set_texCoord__ ();
      this .set_normal__ ();
   },
   set_attrib__ ()
   {
      const attribNodes = this .getAttrib ();

      for (const attribNode of attribNodes)
      {
         attribNode .removeInterest ("requestRebuild", this);
         attribNode ._attribute_changed .removeInterest ("updateVertexArrays", this);
      }

      attribNodes .length = 0;

      for (const node of this ._attrib)
      {
         const attribNode = Base_X3DCast (Base_X3DConstants .X3DVertexAttributeNode, node);

         if (attribNode)
            attribNodes .push (attribNode);
      }

      for (const attribNode of attribNodes)
      {
         attribNode .addInterest ("requestRebuild", this);
         attribNode ._attribute_changed .addInterest ("updateVertexArrays", this);
      }

      this .updateVertexArrays ();
   },
   set_fogCoord__ ()
   {
      this .fogCoordNode ?.removeInterest ("requestRebuild", this);

      this .fogCoordNode = Base_X3DCast (Base_X3DConstants .FogCoordinate, this ._fogCoord);

      this .fogCoordNode ?.addInterest ("requestRebuild", this);
   },
   set_color__ ()
   {
      this .colorNode ?.removeInterest ("requestRebuild", this);

      this .colorNode = Base_X3DCast (Base_X3DConstants .X3DColorNode, this ._color);

      this .colorNode ?.addInterest ("requestRebuild", this);

      this .setTransparent (this .colorNode ?.isTransparent () ?? false);
   },
   set_texCoord__ ()
   {
      this .texCoordNode ?.removeInterest ("requestRebuild", this);

      this .texCoordNode = Base_X3DCast (Base_X3DConstants .X3DTextureCoordinateNode, this ._texCoord);

      this .texCoordNode ?.addInterest ("requestRebuild", this);

      this .setTextureCoordinate (this .texCoordNode);
   },
   set_normal__ ()
   {
      this .normalNode ?.removeInterest ("requestRebuild", this);

      this .normalNode = Base_X3DCast (Base_X3DConstants .X3DNormalNode, this ._normal);

      this .normalNode ?.addInterest ("requestRebuild", this);
   },
   getColor ()
   {
      return this .colorNode;
   },
   getTexCoord ()
   {
      return this .texCoordNode;
   },
   getNormal ()
   {
      return this .normalNode;
   },
   getHeight (index)
   {
      if (index < this ._height .length)
         return this ._height [index];

      return 0;
   },
   createTexCoords ()
   {
      const
         texCoords  = [ ],
         xDimension = this ._xDimension .getValue (),
         zDimension = this ._zDimension .getValue (),
         xSize      = xDimension - 1,
         zSize      = zDimension - 1;

      for (let z = 0; z < zDimension; ++ z)
      {
         for (let x = 0; x < xDimension; ++ x)
            texCoords .push (new Numbers_Vector2 (x / xSize, z / zSize));
      }

      return texCoords;
   },
   createNormals (points, coordIndex, creaseAngle)
   {
      const
         cw          = ! this ._ccw .getValue (),
         normalIndex = new Map (),
         normals     = [ ];

      for (let p = 0, length = points .length; p < length; ++ p)
         normalIndex .set (p, [ ]);

      for (let c = 0, length = coordIndex .length; c < length; c += 3)
      {
         const
            c0 = coordIndex [c],
            c1 = coordIndex [c + 1],
            c2 = coordIndex [c + 2];

         normalIndex .get (c0) .push (normals .length);
         normalIndex .get (c1) .push (normals .length + 1);
         normalIndex .get (c2) .push (normals .length + 2);

         const normal = Geometry_Triangle3 .normal (points [c0], points [c1], points [c2], new Numbers_Vector3 (0, 0, 0));

         if (cw)
            normal .negate ();

         normals .push (normal);
         normals .push (normal);
         normals .push (normal);
      }

      if (!this ._normalPerVertex .getValue ())
         return normals;

      return this .refineNormals (normalIndex, normals, this ._creaseAngle .getValue ());
   },
   createCoordIndex ()
   {
      // p1 - p4
      //  | \ |
      // p2 - p3

      const
         coordIndex = [ ],
         xDimension = this ._xDimension .getValue (),
         zDimension = this ._zDimension .getValue (),
         xSize      = xDimension - 1,
         zSize      = zDimension - 1;

      for (let z = 0; z < zSize; ++ z)
      {
         for (let x = 0; x < xSize; ++ x)
         {
            const
               i1 =       z * xDimension + x,
               i2 = (z + 1) * xDimension + x,
               i3 = (z + 1) * xDimension + (x + 1),
               i4 =       z * xDimension + (x + 1);

            coordIndex .push (i1); // p1
            coordIndex .push (i2); // p2
            coordIndex .push (i3); // p3

            coordIndex .push (i1); // p1
            coordIndex .push (i3); // p3
            coordIndex .push (i4); // p4
         }
      }

      return coordIndex;
   },
   createPoints ()
   {
      const
         points     = [ ],
         xDimension = this ._xDimension .getValue (),
         zDimension = this ._zDimension .getValue (),
         xSpacing   = this ._xSpacing .getValue (),
         zSpacing   = this ._zSpacing .getValue ();

      for (let z = 0; z < zDimension; ++ z)
      {
         for (let x = 0; x < xDimension; ++ x)
         {
            points .push (new Numbers_Vector3 (xSpacing * x,
                                       this .getHeight (x + z * xDimension),
                                       zSpacing * z));
         }
      }

      return points;
   },
   build ()
   {
      if (this ._xDimension .getValue () < 2 || this ._zDimension .getValue () < 2)
         return;

      const
         colorPerVertex     = this ._colorPerVertex .getValue (),
         normalPerVertex    = this ._normalPerVertex .getValue (),
         coordIndex         = this .createCoordIndex (),
         coordIndicesArray  = this .getCoordIndices (),
         attribNodes        = this .getAttrib (),
         numAttribNodes     = attribNodes .length,
         attribArrays       = this .getAttribs (),
         fogCoordNode       = this .fogCoordNode,
         colorNode          = this .getColor (),
         texCoordNode       = this .getTexCoord (),
         normalNode         = this .getNormal (),
         points             = this .createPoints (),
         fogDepthArray      = this .getFogDepths (),
         colorArray         = this .getColors (),
         multiTexCoordArray = this .getMultiTexCoords (),
         normalArray        = this .getNormals (),
         vertexArray        = this .getVertices ();

      let face = 0;

      if (texCoordNode)
      {
         texCoordNode .init (multiTexCoordArray);
      }
      else
      {
         var
            texCoords     = this .createTexCoords (),
            texCoordArray = this .getTexCoords ();

         multiTexCoordArray .push (texCoordArray);
      }

      // Build geometry

      for (let c = 0, numCoordIndices = coordIndex .length; c < numCoordIndices; ++ face)
      {
         for (let p = 0; p < 6; ++ p, ++ c)
         {
            const
               index = coordIndex [c],
               point = points [index];

            coordIndicesArray .push (index);

            for (let a = 0; a < numAttribNodes; ++ a)
               attribNodes [a] .addValue (index, attribArrays [a]);

            fogCoordNode ?.addDepth (index, fogDepthArray);

            if (colorNode)
            {
               if (colorPerVertex)
                  colorNode .addColor (index, colorArray);
               else
                  colorNode .addColor (face, colorArray);
            }

            if (texCoordNode)
            {
               texCoordNode .addPoint (index, multiTexCoordArray);
            }
            else
            {
               const t = texCoords [index];

               texCoordArray .push (t .x, t .y, 0, 1);
            }

            if (normalNode)
            {
               if (normalPerVertex)
                  normalNode .addVector (index, normalArray);

               else
                  normalNode .addVector (face, normalArray);
            }

            vertexArray .push (point .x, point .y, point .z, 1);
         }
      }

      // Add auto-generated normals if needed.

      if (!normalNode)
      {
         const normals = this .createNormals (points, coordIndex);

         for (const normal of normals)
         {
            normalArray .push (normal .x, normal .y, normal .z);
         }
      }

      this .setSolid (this ._solid .getValue ());
      this .setCCW (this ._ccw .getValue ());
   },
});

Object .defineProperties (ElevationGrid,
{
   typeName:
   {
      value: "ElevationGrid",
      enumerable: true,
   },
   componentName:
   {
      value: "Geometry3D",
      enumerable: true,
   },
   containerField:
   {
      value: "geometry",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_height",      new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "xDimension",      new x_ite_Fields .SFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "zDimension",      new x_ite_Fields .SFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "xSpacing",        new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "zSpacing",        new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "solid",           new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "ccw",             new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "creaseAngle",     new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "colorPerVertex",  new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "normalPerVertex", new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "attrib",          new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "fogCoord",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "color",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "texCoord",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "normal",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "height",          new x_ite_Fields .MFFloat ()),
      ]),
      enumerable: true,
   },
});

const ElevationGrid_default_ = ElevationGrid;
;

x_ite_Namespace .add ("ElevationGrid", "x_ite/Components/Geometry3D/ElevationGrid", ElevationGrid_default_);
/* harmony default export */ const Geometry3D_ElevationGrid = (ElevationGrid_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Geometry3D/Extrusion.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/












function Extrusion (executionContext)
{
   Rendering_X3DGeometryNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Extrusion);

   this ._creaseAngle  .setUnit ("angle");
   this ._crossSection .setUnit ("length");
   this ._spine        .setUnit ("length");
}

Object .assign (Object .setPrototypeOf (Extrusion .prototype, Rendering_X3DGeometryNode .prototype),
{
   initialize ()
   {
      Rendering_X3DGeometryNode .prototype .initialize .call (this);

      this ._set_crossSection .addFieldInterest (this ._crossSection);
      this ._set_orientation  .addFieldInterest (this ._orientation);
      this ._set_scale        .addFieldInterest (this ._scale);
      this ._set_spine        .addFieldInterest (this ._spine);
   },
   getClosedOrientation ()
   {
      const orientation = this ._orientation;

      if (orientation .length)
      {
         const
            firstOrientation = orientation [0] .getValue (),
            lastOrientation  = orientation [orientation .length - 1] .getValue ();

         return firstOrientation .equals (lastOrientation);
      }

      return true;
   },
   createPoints: (() =>
   {
      const scale3 = new Numbers_Vector3 (1, 1, 1);

      return function ()
      {
         const
            crossSection = this ._crossSection,
            orientation  = this ._orientation,
            scale        = this ._scale,
            spine        = this ._spine,
            points       = [ ];

         // calculate SCP rotations

         const rotations = this .createRotations ();

         // calculate vertices.

         for (let i = 0, length = spine .length; i < length; ++ i)
         {
            const matrix = rotations [i];

            if (orientation .length)
               matrix .rotate (orientation [Math .min (i, orientation .length - 1)] .getValue ());

            if (scale .length)
            {
               const s = scale [Math .min (i, scale .length - 1)] .getValue ();
               matrix .scale (scale3 .set (s .x, 1, s .y));
            }

            for (let cs = 0, csLength = crossSection .length; cs < csLength; ++ cs)
            {
               const vector = crossSection [cs] .getValue ();
               points .push (matrix .multVecMatrix (new Numbers_Vector3 (vector .x, 0, vector .y)));
            }
         }

         return points;
      };
   })(),
   createRotations: (() =>
   {
      const rotations = [ ];

      const
         SCPxAxis = new Numbers_Vector3 (0, 0, 0),
         SCPyAxis = new Numbers_Vector3 (0, 0, 0),
         SCPzAxis = new Numbers_Vector3 (0, 0, 0);

         const
         SCPyAxisPrevious = new Numbers_Vector3 (0, 0, 0),
         SCPzAxisPrevious = new Numbers_Vector3 (0, 0, 0);

         const
         vector3  = new Numbers_Vector3 (0, 0, 0),
         rotation = new Numbers_Rotation4 ();

      return function ()
      {
         // calculate SCP rotations

         const
            spine       = this ._spine,
            numSpines   = spine .length,
            firstSpine  = spine [0] .getValue (),
            lastSpine   = spine [spine .length - 1] .getValue (),
            closedSpine = firstSpine .equals (lastSpine) && this .getClosedOrientation ();

         // Extend or shrink static rotations array:
         for (let i = rotations .length; i < numSpines; ++ i)
            rotations [i] = new Numbers_Matrix4 ();

         rotations .length = numSpines;

         // SCP axes:
         SCPxAxis .set (0, 0, 0);
         SCPyAxis .set (0, 0, 0);
         SCPzAxis .set (0, 0, 0);

         // SCP for the first point:
         if (closedSpine)
         {
            const s = firstSpine;

            // Find first defined Y-axis.
            for (let i = 1, length = numSpines - 2; i < length; ++ i)
            {
               SCPyAxis .assign (spine [i] .getValue ()) .subtract (s) .normalize ()
                  .subtract (vector3 .assign (spine [length] .getValue ()) .subtract (s) .normalize ())
                  .normalize ();

               if (! SCPyAxis .equals (Numbers_Vector3 .Zero))
                  break;
            }

            // Find first defined Z-axis.
            for (let i = 0, length = numSpines - 2; i < length; ++ i)
            {
               SCPzAxis .assign (spine [i + 1] .getValue ()) .subtract (spine [i] .getValue ())
                          .cross (vector3 .assign (spine [length] .getValue ()) .subtract (spine [i] .getValue ()))
                          .normalize ();

               if (! SCPzAxis .equals (Numbers_Vector3 .Zero))
                  break;
            }
         }
         else
         {
            // Find first defined Y-axis.
            for (let i = 0, length = numSpines - 1; i < length; ++ i)
            {
               SCPyAxis .assign (spine [i + 1] .getValue ()) .subtract (spine [i] .getValue ()) .normalize ();

               if (! SCPyAxis .equals (Numbers_Vector3 .Zero))
                  break;
            }

            // Find first defined Z-axis.
            for (let i = 1, length = numSpines - 1; i < length; ++ i)
            {
               SCPzAxis .assign (spine [i + 1] .getValue ()) .subtract (spine [i] .getValue ())
                        .cross (vector3 .assign (spine [i - 1] .getValue ()) .subtract (spine [i] .getValue ()))
                        .normalize ();

               if (! SCPzAxis .equals (Numbers_Vector3 .Zero))
                  break;
            }
         }

         // The entire spine is coincident:
         if (SCPyAxis .equals (Numbers_Vector3 .Zero))
            SCPyAxis .set (0, 1, 0);

         // The entire spine is collinear:
         if (SCPzAxis .equals (Numbers_Vector3 .Zero))
            rotation .setFromToVec (Numbers_Vector3 .yAxis, SCPyAxis) .multVecRot (SCPzAxis .assign (Numbers_Vector3 .zAxis));

         // We do not have to normalize SCPxAxis, as SCPyAxis and SCPzAxis are orthogonal.
         SCPxAxis .assign (SCPyAxis) .cross (SCPzAxis);

         // Get first spine
         const s = firstSpine;

         rotations [0] .set (SCPxAxis .x, SCPxAxis .y, SCPxAxis .z, 0,
                             SCPyAxis .x, SCPyAxis .y, SCPyAxis .z, 0,
                             SCPzAxis .x, SCPzAxis .y, SCPzAxis .z, 0,
                             s .x,        s .y,        s .z,        1);

         // For all points other than the first or last:

         SCPyAxisPrevious .assign (SCPyAxis);
         SCPzAxisPrevious .assign (SCPzAxis);

         for (let i = 1, length = numSpines - 1; i < length; ++ i)
         {
            const s = spine [i] .getValue ();

            SCPyAxis .assign (spine [i + 1] .getValue ()) .subtract (s) .normalize ()
                     .subtract (vector3 .assign (spine [i - 1] .getValue ()) .subtract (s) .normalize ())
                     .normalize ();
            SCPzAxis .assign (spine [i + 1] .getValue ()) .subtract (s)
                     .cross (vector3 .assign (spine [i - 1] .getValue ()) .subtract (s))
                     .normalize ();

            // g.
            if (SCPzAxisPrevious .dot (SCPzAxis) < 0)
               SCPzAxis .negate ();

            // The two points used in computing the Y-axis are coincident.
            if (SCPyAxis .equals (Numbers_Vector3 .Zero))
               SCPyAxis .assign (SCPyAxisPrevious);
            else
               SCPyAxisPrevious .assign (SCPyAxis);

            // The three points used in computing the Z-axis are collinear.
            if (SCPzAxis .equals (Numbers_Vector3 .Zero))
               SCPzAxis .assign (SCPzAxisPrevious);
            else
               SCPzAxisPrevious .assign (SCPzAxis);

            // We do not have to normalize SCPxAxis, as SCPyAxis and SCPzAxis are orthogonal.
            SCPxAxis .assign (SCPyAxis) .cross (SCPzAxis);

            rotations [i] .set (SCPxAxis .x, SCPxAxis .y, SCPxAxis .z, 0,
                                SCPyAxis .x, SCPyAxis .y, SCPyAxis .z, 0,
                                SCPzAxis .x, SCPzAxis .y, SCPzAxis .z, 0,
                                s .x,        s .y,        s .z,        1);
         }

         // SCP for the last point
         if (closedSpine)
         {
            // The SCPs for the first and last points are the same.
            rotations [numSpines - 1] .assign (rotations [0]);
         }
         else
         {
            const s = lastSpine;

            SCPyAxis .assign (s) .subtract (spine [numSpines - 2] .getValue ()) .normalize ();

            if (numSpines > 2)
            {
               SCPzAxis .assign (s) .subtract (spine [numSpines - 2] .getValue ())
                        .cross (vector3 .assign (spine [numSpines - 3] .getValue ()) .subtract (spine [numSpines - 2] .getValue ()))
                        .normalize ();
            }

            // g.
            if (SCPzAxisPrevious .dot (SCPzAxis) < 0)
               SCPzAxis .negate ();

            // The two points used in computing the Y-axis are coincident.
            if (SCPyAxis .equals (Numbers_Vector3 .Zero))
               SCPyAxis .assign (SCPyAxisPrevious);

            // The three points used in computing the Z-axis are collinear.
            if (SCPzAxis .equals (Numbers_Vector3 .Zero))
               SCPzAxis .assign (SCPzAxisPrevious);

            // We do not have to normalize SCPxAxis, as SCPyAxis and SCPzAxis are orthogonal.
            SCPxAxis .assign (SCPyAxis) .cross (SCPzAxis);

            rotations [numSpines - 1] .set (SCPxAxis .x, SCPxAxis .y, SCPxAxis .z, 0,
                                            SCPyAxis .x, SCPyAxis .y, SCPyAxis .z, 0,
                                            SCPzAxis .x, SCPzAxis .y, SCPzAxis .z, 0,
                                            s .x,        s .y,        s .z,        1);
         }

         return rotations;
      };
   })(),
   build: (() =>
   {
      const
         min     = new Numbers_Vector2 (0, 0, 0),
         max     = new Numbers_Vector2 (0, 0, 0),
         vector2 = new Numbers_Vector2 (0, 0, 0);

      return function ()
      {
         const
            cw                = ! this ._ccw .getValue (),
            crossSection      = this ._crossSection,
            spine             = this ._spine,
            numSpines         = spine .length,
            coordIndicesArray = this .getCoordIndices (),
            texCoordArray     = this .getTexCoords ();

         if (numSpines < 2 || crossSection .length < 2)
            return;

         this .getMultiTexCoords () .push (texCoordArray);

         const crossSectionSize = crossSection .length; // This one is used only in the INDEX macro.

         function INDEX (n, k) { return n * crossSectionSize + k; }

         const
            firstSpine  = spine [0] .getValue (),
            lastSpine   = spine [numSpines - 1] .getValue (),
            closedSpine = firstSpine .equals (lastSpine) && this .getClosedOrientation ();

         const
            firstCrossSection  = crossSection [0] .getValue (),
            lastCrossSection   = crossSection [crossSection .length - 1] .getValue (),
            closedCrossSection = firstCrossSection .equals (lastCrossSection);

         // For caps calculation

         min .assign (crossSection [0] .getValue ());
         max .assign (crossSection [0] .getValue ());

         for (let k = 1, length = crossSection .length; k < length; ++ k)
         {
            min .min (crossSection [k] .getValue ());
            max .max (crossSection [k] .getValue ());
         }

         const
            capSize      = vector2 .assign (max) .subtract (min),
            capMax       = Math .max (capSize .x, capSize .y),
            numCapPoints = closedCrossSection ? crossSection .length - 1 : crossSection .length;

         // Create

         const
            normalIndex = new Map (),
            normals     = [ ],
            points      = this .createPoints ();

         for (let p = 0, length = points .length; p < length; ++ p)
            normalIndex .set (p, [ ]);

         // Build body.

         const
            normalArray = this .getNormals (),
            vertexArray = this .getVertices ();

         const
            numCrossSection_1 = crossSection .length - 1,
            numSpine_1        = numSpines - 1;

         let
            indexLeft  = INDEX (0, 0),
            indexRight = INDEX (0, closedCrossSection ? 0 : numCrossSection_1);

         for (let n = 0; n < numSpine_1; ++ n)
         {
            for (let k = 0; k < numCrossSection_1; ++ k)
            {
               const
                  n1 = closedSpine && n === numSpines - 2 ? 0 : n + 1,
                  k1 = closedCrossSection && k === crossSection .length - 2 ? 0 : k + 1;

               // k      k+1
               //
               // p4 ----- p3   n+1
               //  |     / |
               //  |   /   |
               //  | /     |
               // p1 ----- p2   n

               let
                  i1 = INDEX (n,  k),
                  i2 = INDEX (n,  k1),
                  i3 = INDEX (n1, k1),
                  i4 = INDEX (n1, k),
                  p1 = points [i1],
                  p2 = points [i2],
                  p3 = points [i3],
                  p4 = points [i4],
                  l1 = p2 .distance (p3) >= 1e-7,
                  l2 = p4 .distance (p1) >= 1e-7;

               if (cw)
               {
                  var
                     normal1 = Geometry_Triangle3 .normal (p3, p2, p1, new Numbers_Vector3 (0, 0, 0)),
                     normal2 = Geometry_Triangle3 .normal (p4, p3, p1, new Numbers_Vector3 (0, 0, 0));
               }
               else
               {
                  var
                     normal1 = Geometry_Triangle3 .normal (p1, p2, p3, new Numbers_Vector3 (0, 0, 0)),
                     normal2 = Geometry_Triangle3 .normal (p1, p3, p4, new Numbers_Vector3 (0, 0, 0));
               }

               // Merge points on the left and right side if spine is coincident for better normal generation.

               if (k == 0)
               {
                  if (l2)
                  {
                     indexLeft = i1;
                  }
                  else
                  {
                     i1 = indexLeft;
                     p1 = points [i1];
                  }
               }

               if (k == crossSection .length - 2)
               {
                  if (l1)
                  {
                     indexRight = i2;
                  }
                  else
                  {
                     i3 = indexRight;
                     p3 = points [i3];
                  }
               }

               // If there are coincident spine points then one length can be zero.

               // Triangle one

               if (l1)
               {
                  coordIndicesArray .push (i1, i2, i3);

                  // p1
                  if (l2)
                  {
                     texCoordArray .push (k / numCrossSection_1, n / numSpine_1, 0, 1);
                  }
                  else
                  {
                     // Cone case: ((texCoord1 + texCoord4) / 2)
                     const y = (n / numSpine_1 + (n + 1) / numSpine_1) / 2;

                     texCoordArray .push (k / numCrossSection_1, y, 0, 1);
                  }

                  normalIndex .get (i1) .push (normals .length);
                  normals .push (normal1);
                  vertexArray .push (p1 .x, p1 .y, p1 .z, 1);

                  // p2
                  texCoordArray .push ((k + 1) / numCrossSection_1, n / numSpine_1, 0, 1);
                  normalIndex .get (i2) .push (normals .length);
                  normals .push (normal1);
                  vertexArray .push (p2 .x, p2 .y, p2 .z, 1);

                  // p3
                  texCoordArray .push ((k + 1) / numCrossSection_1, (n + 1) / numSpine_1, 0, 1);
                  normalIndex .get (i3) .push (normals .length);
                  normals .push (normal1);
                  vertexArray .push (p3 .x, p3 .y, p3 .z, 1);
               }

               // Triangle two

               if (l2)
               {
                  coordIndicesArray .push (i1, i3, i4);

                  // p1
                  texCoordArray .push (k / numCrossSection_1, n / numSpine_1, 0, 1);
                  normalIndex .get (i1) .push (normals .length);
                  normals .push (normal2);
                  vertexArray .push (p1 .x, p1 .y, p1 .z, 1);

                  // p3
                  if (l1)
                  {
                     texCoordArray .push ((k + 1) / numCrossSection_1, (n + 1) / numSpine_1, 0, 1);
                  }
                  else
                  {
                     // Cone case: ((texCoord3 + texCoord2) / 2)
                     const y = ((n + 1) / numSpine_1 + n / numSpine_1) / 2;

                     texCoordArray .push ((k + 1) / numCrossSection_1, y, 0, 1);
                  }

                  normalIndex .get (i3) .push (normals .length);
                  normals .push (normal2);
                  vertexArray .push (p3 .x, p3 .y, p3 .z, 1);

                  // p4
                  texCoordArray .push (k / numCrossSection_1, (n + 1) / numSpine_1, 0, 1);
                  normalIndex .get (i4) .push (normals .length);
                  normals .push (normal2);
                  vertexArray .push (p4 .x, p4 .y, p4 .z, 1);
               }
            }
         }

         // Refine body normals and add them.

         const refinedNormals = this .refineNormals (normalIndex, normals, this ._creaseAngle .getValue ());

         for (const normal of refinedNormals)
            normalArray .push (normal .x, normal .y, normal .z);

         // Build caps

         if (capMax && numCapPoints > 2)
         {
            if (this ._beginCap .getValue ())
            {
               const
                  j         = 0, // spine
                  convex    = this ._convex .getValue (),
                  texCoord  = { },
                  polygon   = [ ],
                  triangles = [ ];

               for (let k = 0; k < numCapPoints; ++ k)
               {
                  const
                     index = INDEX (j, numCapPoints - 1 - k),
                     point = points [index] .copy ();

                  point .index     = index;
                  texCoord [index] = crossSection [numCapPoints - 1 - k] .getValue () .copy () .subtract (min) .divide (capMax);
                  polygon .push (convex ? index : point);
               }

               if (convex)
                  Geometry_Triangle3 .triangulateConvexPolygon (polygon, triangles);

               else
                  Geometry_Triangle3 .triangulatePolygon (polygon, triangles);

               if (triangles .length >= 3)
               {
                  const normal = Geometry_Triangle3 .normal (points [triangles [0]],
                                                    points [triangles [1]],
                                                    points [triangles [2]],
                                                    new Numbers_Vector3 (0, 0, 0));

                  if (cw)
                     normal .negate ();

                  this .addCap (texCoordArray, texCoord, normal, points, triangles);
               }
            }

            if (this ._endCap .getValue ())
            {
               const
                  j         = numSpines - 1, // spine
                  convex    = this ._convex .getValue (),
                  texCoord  = { },
                  polygon   = [ ],
                  triangles = [ ];

               for (let k = 0; k < numCapPoints; ++ k)
               {
                  const
                     index = INDEX (j, k),
                     point = points [index] .copy ();

                  point .index     = index;
                  texCoord [index] = crossSection [k] .getValue () .copy () .subtract (min) .divide (capMax);
                  polygon .push (convex ? index : point);
               }

               if (convex)
                  Geometry_Triangle3 .triangulateConvexPolygon (polygon, triangles);

               else
                  Geometry_Triangle3 .triangulatePolygon (polygon, triangles);

               if (triangles .length >= 3)
               {
                  const normal = Geometry_Triangle3 .normal (points [triangles [0]],
                                                    points [triangles [1]],
                                                    points [triangles [2]],
                                                    new Numbers_Vector3 (0, 0, 0));

                  if (cw)
                     normal .negate ();

                  this .addCap (texCoordArray, texCoord, normal, points, triangles);
               }
            }
         }

         this .setSolid (this ._solid .getValue ());
         this .setCCW (this ._ccw .getValue ());
      };
   })(),
   addCap (texCoordArray, texCoord, normal, vertices, triangles)
   {
      const
         coordIndicesArray = this .getCoordIndices (),
         normalArray       = this .getNormals (),
         vertexArray       = this .getVertices ();

      for (let i = 0, length = triangles .length; i < length; i += 3)
      {
         const
            i1 = triangles [i],
            i2 = triangles [i + 1],
            i3 = triangles [i + 2],
            p0 = vertices [i1],
            p1 = vertices [i2],
            p2 = vertices [i3],
            t0 = texCoord [i1],
            t1 = texCoord [i2],
            t2 = texCoord [i3];

         coordIndicesArray .push (i1, i2, i3);

         texCoordArray .push (t0 .x, t0 .y, 0, 1);
         texCoordArray .push (t1 .x, t1 .y, 0, 1);
         texCoordArray .push (t2 .x, t2 .y, 0, 1);

         normalArray .push (normal .x, normal .y, normal .z,
                            normal .x, normal .y, normal .z,
                            normal .x, normal .y, normal .z);

         vertexArray .push (p0 .x, p0 .y, p0 .z, 1,
                            p1 .x, p1 .y, p1 .z, 1,
                            p2 .x, p2 .y, p2 .z, 1);
      }
   },
});

Object .defineProperties (Extrusion,
{
   typeName:
   {
      value: "Extrusion",
      enumerable: true,
   },
   componentName:
   {
      value: "Geometry3D",
      enumerable: true,
   },
   containerField:
   {
      value: "geometry",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",         new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_crossSection", new x_ite_Fields .MFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_orientation",  new x_ite_Fields .MFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_scale",        new x_ite_Fields .MFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_spine",        new x_ite_Fields .MFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "beginCap",         new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "endCap",           new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "solid",            new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "ccw",              new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "convex",           new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "creaseAngle",      new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "crossSection",     new x_ite_Fields .MFVec2f (new Numbers_Vector2 (1, 1), new Numbers_Vector2 (1, -1), new Numbers_Vector2 (-1, -1), new Numbers_Vector2 (-1, 1), new Numbers_Vector2 (1, 1))),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "orientation",      new x_ite_Fields .MFRotation (new Numbers_Rotation4 ())),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "scale",            new x_ite_Fields .MFVec2f (new Numbers_Vector2 (1, 1))),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "spine",            new x_ite_Fields .MFVec3f (new Numbers_Vector3 (0, 0, 0), new Numbers_Vector3 (0, 1, 0))),
      ]),
      enumerable: true,
   },
});

const Extrusion_default_ = Extrusion;
;

x_ite_Namespace .add ("Extrusion", "x_ite/Components/Geometry3D/Extrusion", Extrusion_default_);
/* harmony default export */ const Geometry3D_Extrusion = (Extrusion_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/X3DComposedGeometryNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






function X3DComposedGeometryNode (executionContext)
{
   Rendering_X3DGeometryNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DComposedGeometryNode);

   this .fogCoordNode = null;
   this .colorNode    = null;
   this .texCoordNode = null;
   this .normalNode   = null;
   this .coordNode    = null;
}

Object .assign (Object .setPrototypeOf (X3DComposedGeometryNode .prototype, Rendering_X3DGeometryNode .prototype),
{
   initialize ()
   {
      Rendering_X3DGeometryNode .prototype .initialize .call (this);

      this ._attrib   .addInterest ("set_attrib__",   this);
      this ._fogCoord .addInterest ("set_fogCoord__", this);
      this ._color    .addInterest ("set_color__",    this);
      this ._texCoord .addInterest ("set_texCoord__", this);
      this ._normal   .addInterest ("set_normal__",   this);
      this ._coord    .addInterest ("set_coord__",    this);

      this .set_attrib__ ();
      this .set_fogCoord__ ();
      this .set_color__ ();
      this .set_texCoord__ ();
      this .set_normal__ ();
      this .set_coord__ ();
   },
   getFogCoord ()
   {
      return this .fogCoordNode;
   },
   getColor ()
   {
      return this .colorNode;
   },
   getTexCoord ()
   {
      return this .texCoordNode;
   },
   getNormal ()
   {
      return this .normalNode;
   },
   getCoord ()
   {
      return this .coordNode;
   },
   set_attrib__ ()
   {
      const attribNodes = this .getAttrib ();

      for (const attribNode of attribNodes)
      {
         attribNode .removeInterest ("requestRebuild", this);
         attribNode ._attribute_changed .removeInterest ("updateVertexArrays", this);
      }

      attribNodes .length = 0;

      for (const node of this ._attrib)
      {
         const attribNode = Base_X3DCast (Base_X3DConstants .X3DVertexAttributeNode, node);

         if (attribNode)
            attribNodes .push (attribNode);
      }

      for (const attribNode of attribNodes)
      {
         attribNode .addInterest ("requestRebuild", this);
         attribNode ._attribute_changed .addInterest ("updateVertexArrays", this);
      }

      this .updateVertexArrays ();
   },
   set_fogCoord__ ()
   {
      this .fogCoordNode ?.removeInterest ("requestRebuild", this);

      this .fogCoordNode = Base_X3DCast (Base_X3DConstants .FogCoordinate, this ._fogCoord);

      this .fogCoordNode ?.addInterest ("requestRebuild", this);
   },
   set_color__ ()
   {
      this .colorNode ?.removeInterest ("requestRebuild", this);

      this .colorNode = Base_X3DCast (Base_X3DConstants .X3DColorNode, this ._color);

      this .colorNode ?.addInterest ("requestRebuild", this);

      this .setTransparent (this .colorNode ?.isTransparent () ?? false);
   },
   set_texCoord__ ()
   {
      this .texCoordNode ?.removeInterest ("requestRebuild", this);

      this .texCoordNode = Base_X3DCast (Base_X3DConstants .X3DTextureCoordinateNode, this ._texCoord);

      this .texCoordNode ?.addInterest ("requestRebuild", this);

      this .setTextureCoordinate (this .texCoordNode);
   },
   set_normal__ ()
   {
      this .normalNode ?.removeInterest ("requestRebuild", this);

      this .normalNode = Base_X3DCast (Base_X3DConstants .X3DNormalNode, this ._normal);

      this .normalNode ?.addInterest ("requestRebuild", this);
   },
   set_coord__ ()
   {
      this .coordNode ?.removeInterest ("requestRebuild", this);

      this .coordNode = Base_X3DCast (Base_X3DConstants .X3DCoordinateNode, this ._coord);

      this .coordNode ?.addInterest ("requestRebuild", this);
   },
   getPolygonIndex (index)
   {
      return index;
   },
   getTriangleIndex (index)
   {
      return index;
   },
   build (verticesPerPolygon, polygonsSize, verticesPerFace, trianglesSize)
   {
      if (!this .coordNode || this .coordNode .isEmpty ())
         return;

      // Set size to a multiple of verticesPerPolygon.

      polygonsSize  -= polygonsSize  % verticesPerPolygon;
      trianglesSize -= trianglesSize % verticesPerFace;

      const
         colorPerVertex     = this ._colorPerVertex .getValue (),
         normalPerVertex    = this ._normalPerVertex .getValue (),
         coordIndicesArray  = this .getCoordIndices (),
         attribNodes        = this .getAttrib (),
         numAttribNodes     = attribNodes .length,
         attribArrays       = this .getAttribs (),
         fogCoordNode       = this .getFogCoord (),
         colorNode          = this .getColor (),
         texCoordNode       = this .getTexCoord (),
         normalNode         = this .getNormal (),
         coordNode          = this .getCoord (),
         fogDepthArray      = this .getFogDepths (),
         colorArray         = this .getColors (),
         multiTexCoordArray = this .getMultiTexCoords (),
         normalArray        = this .getNormals (),
         vertexArray        = this .getVertices ();

      texCoordNode ?.init (multiTexCoordArray);

      // Fill GeometryNode

      for (let i = 0; i < trianglesSize; ++ i)
      {
         const
            face  = Math .floor (i / verticesPerFace),
            index = this .getPolygonIndex (this .getTriangleIndex (i));

         coordIndicesArray .push (index);

         for (let a = 0; a < numAttribNodes; ++ a)
            attribNodes [a] .addValue (index, attribArrays [a]);

         fogCoordNode ?.addDepth (index, fogDepthArray);

         if (colorNode)
         {
            if (colorPerVertex)
               colorNode .addColor (index, colorArray);
            else
               colorNode .addColor (face, colorArray);
         }

         texCoordNode ?.addPoint (index, multiTexCoordArray);

         if (normalNode)
         {
            if (normalPerVertex)
               normalNode .addVector (index, normalArray);
            else
               normalNode .addVector (face, normalArray);
         }

         coordNode .addPoint (index, vertexArray);
      }

      // Autogenerate normal if not specified.

      if (!this .getNormal ())
         this .buildNormals (verticesPerPolygon, polygonsSize, trianglesSize);

      this .setSolid (this ._solid .getValue ());
      this .setCCW (this ._ccw .getValue ());
   },
   buildNormals (verticesPerPolygon, polygonsSize, trianglesSize)
   {
      const
         normals     = this .createNormals (verticesPerPolygon, polygonsSize),
         normalArray = this .getNormals ();

      for (let i = 0; i < trianglesSize; ++ i)
      {
         const normal = normals [this .getTriangleIndex (i)];

         normalArray .push (normal .x, normal .y, normal .z);
      }
   },
   createNormals (verticesPerPolygon, polygonsSize)
   {
      const normals = this .createFaceNormals (verticesPerPolygon, polygonsSize);

      if (!this ._normalPerVertex .getValue ())
         return normals;

      const normalIndex = new Map ();

      for (let i = 0; i < polygonsSize; ++ i)
      {
         const index = this .getPolygonIndex (i);

         let pointIndex = normalIndex .get (index);

         if (!pointIndex)
            normalIndex .set (index, pointIndex = [ ]);

         pointIndex .push (i);
      }

      return this .refineNormals (normalIndex, normals, Math .PI);
   },
   createFaceNormals (verticesPerPolygon, polygonsSize)
   {
      const
         cw      = !this ._ccw .getValue (),
         coord   = this .coordNode,
         normals = [ ];

      for (let i = 0; i < polygonsSize; i += verticesPerPolygon)
      {
         const normal = this .getPolygonNormal (i, verticesPerPolygon, coord);

         if (cw)
            normal .negate ();

         for (let n = 0; n < verticesPerPolygon; ++ n)
            normals .push (normal);
      }

      return normals;
   },
   getPolygonNormal: (() =>
   {
      let
         current = new Numbers_Vector3 (0, 0, 0),
         next    = new Numbers_Vector3 (0, 0, 0);

      return function (index, verticesPerPolygon, coord)
      {
         // Determine polygon normal.
         // We use Newell's method https://www.opengl.org/wiki/Calculating_a_Surface_Normal here:

         const normal = new Numbers_Vector3 (0, 0, 0);

         coord .get1Point (this .getPolygonIndex (index), next);

         for (let i = 0; i < verticesPerPolygon; ++ i)
         {
            const tmp = current;
            current = next;
            next    = tmp;

            coord .get1Point (this .getPolygonIndex (index + (i + 1) % verticesPerPolygon), next);

            normal .x += (current .y - next .y) * (current .z + next .z);
            normal .y += (current .z - next .z) * (current .x + next .x);
            normal .z += (current .x - next .x) * (current .y + next .y);
         }

         return normal .normalize ();
      };
   })(),
});

Object .defineProperties (X3DComposedGeometryNode,
{
   typeName:
   {
      value: "X3DComposedGeometryNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
});

const X3DComposedGeometryNode_default_ = X3DComposedGeometryNode;
;

x_ite_Namespace .add ("X3DComposedGeometryNode", "x_ite/Components/Rendering/X3DComposedGeometryNode", X3DComposedGeometryNode_default_);
/* harmony default export */ const Rendering_X3DComposedGeometryNode = (X3DComposedGeometryNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Geometry3D/IndexedFaceSet.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










function IndexedFaceSet (executionContext)
{
   Rendering_X3DComposedGeometryNode .call (this, executionContext);

   this .addType (Base_X3DConstants .IndexedFaceSet);

   this ._creaseAngle .setUnit ("angle");
}

Object .assign (Object .setPrototypeOf (IndexedFaceSet .prototype, Rendering_X3DComposedGeometryNode .prototype),
{
   initialize ()
   {
      Rendering_X3DComposedGeometryNode .prototype .initialize .call (this);

      this ._set_colorIndex    .addFieldInterest (this ._colorIndex);
      this ._set_texCoordIndex .addFieldInterest (this ._texCoordIndex);
      this ._set_normalIndex   .addFieldInterest (this ._normalIndex);
      this ._set_coordIndex    .addFieldInterest (this ._coordIndex);
   },
   getTexCoordPerVertexIndex (index)
   {
      if (index < this ._texCoordIndex .length)
         return this ._texCoordIndex [index];

      return this ._coordIndex [index];
   },
   getColorPerVertexIndex (index)
   {
      if (index < this ._colorIndex .length)
         return this ._colorIndex [index];

      return this ._coordIndex [index];
   },
   getColorIndex (index)
   {
      if (index < this ._colorIndex .length)
         return this ._colorIndex [index];

      return index;
   },
   getNormalPerVertexIndex (index)
   {
      if (index < this ._normalIndex .length)
         return this ._normalIndex [index];

      return this ._coordIndex [index];
   },
   getNormalIndex (index)
   {
      if (index < this ._normalIndex .length)
         return this ._normalIndex [index];

      return index;
   },
   build ()
   {
      // Triangulate

      const polygons = this .triangulate ();

      // Build arrays

      if (polygons .length === 0)
         return;

      // Fill GeometryNode

      const
         colorPerVertex     = this ._colorPerVertex .getValue (),
         normalPerVertex    = this ._normalPerVertex .getValue (),
         coordIndex         = this ._coordIndex .getValue (),
         coordIndicesArray  = this .getCoordIndices (),
         attribNodes        = this .getAttrib (),
         numAttribNodes     = attribNodes .length,
         attribArrays       = this .getAttribs (),
         fogCoordNode       = this .getFogCoord (),
         colorNode          = this .getColor (),
         texCoordNode       = this .getTexCoord (),
         normalNode         = this .getNormal (),
         coordNode          = this .getCoord (),
         fogDepthArray      = this .getFogDepths (),
         colorArray         = this .getColors (),
         multiTexCoordArray = this .getMultiTexCoords (),
         normalArray        = this .getNormals (),
         vertexArray        = this .getVertices ();

      texCoordNode ?.init (multiTexCoordArray);

      for (const polygon of polygons)
      {
         const { triangles, face } = polygon;

         for (const i of triangles)
         {
            const index = coordIndex [i];

            coordIndicesArray .push (index);

            for (let a = 0; a < numAttribNodes; ++ a)
               attribNodes [a] .addValue (index, attribArrays [a]);

            fogCoordNode ?.addDepth (index, fogDepthArray);

            if (colorNode)
            {
               if (colorPerVertex)
                  colorNode .addColor (this .getColorPerVertexIndex (i), colorArray);
               else
                  colorNode .addColor (this .getColorIndex (face), colorArray);
            }

            texCoordNode ?.addPoint (this .getTexCoordPerVertexIndex (i), multiTexCoordArray);

            if (normalNode)
            {
               if (normalPerVertex)
                  normalNode .addVector (this .getNormalPerVertexIndex (i), normalArray);

               else
                  normalNode .addVector (this .getNormalIndex (face), normalArray);
            }

            coordNode .addPoint (index, vertexArray);
         }
      }

      // Autogenerate normal if not specified.

      if (!this .getNormal ())
         this .buildNormals (polygons);

      this .setSolid (this ._solid .getValue ());
      this .setCCW (this ._ccw .getValue ());
   },
   triangulate ()
   {
      const
         convex      = this ._convex .getValue (),
         coordLength = this ._coordIndex .length,
         polygons    = [ ];

      if (!this .getCoord ())
         return polygons;

      // Add -1 (polygon end marker) to coordIndex if not present.
      if (coordLength && this ._coordIndex [coordLength - 1] > -1)
         this ._coordIndex .push (-1);

      if (coordLength)
      {
         const
            coordIndex  = this ._coordIndex .getValue (),
            coordLength = this ._coordIndex .length;

         // Construct triangle array and determine the number of used points.

         for (let i = 0, face = 0, vertices = [ ]; i < coordLength; ++ i)
         {
            const index = coordIndex [i];

            if (index > -1)
            {
               // Add vertex index.
               vertices .push (i);
            }
            else
            {
               // Negative index.

               switch (vertices .length)
               {
                  case 0:
                  case 1:
                  case 2:
                  {
                     vertices .length = 0;
                     break;
                  }
                  case 3:
                  {
                     // Add polygon with one triangle.
                     polygons .push ({ vertices: vertices, triangles: vertices, face: face });
                     vertices = [ ];
                     break;
                  }
                  default:
                  {
                     // Triangulate polygon.

                     const
                        triangles = [ ],
                        polygon   = { vertices: vertices, triangles: triangles, face: face };

                     if (convex)
                        Geometry_Triangle3 .triangulateConvexPolygon (vertices, triangles);
                     else
                        this .triangulatePolygon (vertices, triangles);

                     if (triangles .length < 3)
                     {
                        vertices .length = 0;
                     }
                     else
                     {
                        polygons .push (polygon);
                        vertices = [ ];
                     }

                     break;
                  }
               }

               ++ face;
            }
         }
      }

      return polygons;
   },
   triangulatePolygon: (() =>
   {
      const polygon = [ ];

      return function (vertices, triangles)
      {
         const
            coordIndex = this ._coordIndex .getValue (),
            coord      = this .getCoord (),
            length     = vertices .length;

         for (let i = polygon .length; i < length; ++ i)
            polygon .push (new Numbers_Vector3 (0, 0, 0));

         for (let i = 0; i < length; ++ i)
         {
            const
               index = vertices [i],
               point = polygon [i];

            point .index = index;

            coord .get1Point (coordIndex [index], point);
         }

         polygon .length = length;

         Geometry_Triangle3 .triangulatePolygon (polygon, triangles);
      };
   })(),
   buildNormals (polygons)
   {
      const
         normals     = this .createNormals (polygons),
         normalArray = this .getNormals ();

      for (const polygon of polygons)
      {
         for (const i of polygon .triangles)
         {
            const normal = normals [i];

            normalArray .push (normal .x, normal .y, normal .z);
         }
      }
   },
   createNormals (polygons)
   {
      const
         cw          = !this ._ccw .getValue (),
         coordIndex  = this ._coordIndex .getValue (),
         coord       = this .getCoord (),
         normalIndex = new Map (),
         normals     = [ ];

      for (const polygon of polygons)
      {
         const
            vertices = polygon .vertices,
            length   = vertices .length;

         switch (length)
         {
            case 3:
            {
               var normal = coord .getNormal (coordIndex [vertices [0]],
                                              coordIndex [vertices [1]],
                                              coordIndex [vertices [2]]);
               break;
            }
            case 4:
            {
               var normal = coord .getQuadNormal (coordIndex [vertices [0]],
                                                  coordIndex [vertices [1]],
                                                  coordIndex [vertices [2]],
                                                  coordIndex [vertices [3]]);
               break;
            }
            default:
            {
               var normal = this .getPolygonNormal (vertices, coordIndex, coord);
               break;
            }
         }

         // Add a normal index for each point.

         for (const index of vertices)
         {
            const point = coordIndex [index];

            let pointNormals = normalIndex .get (point);

            if (!pointNormals)
               normalIndex .set (point, pointNormals = [ ]);

            pointNormals .push (index);

            normals [index] = normal;
         }

         if (cw)
            normal .negate ();
      }

      if (!this ._normalPerVertex .getValue ())
         return normals;

      return this .refineNormals (normalIndex, normals, this ._creaseAngle .getValue ());
   },
   getPolygonNormal: (() =>
   {
      let
         current = new Numbers_Vector3 (0, 0, 0),
         next    = new Numbers_Vector3 (0, 0, 0);

      return function (vertices, coordIndex, coord)
      {
         // Determine polygon normal.
         // We use Newell's method https://www.opengl.org/wiki/Calculating_a_Surface_Normal here:

         const normal = new Numbers_Vector3 (0, 0, 0);

         coord .get1Point (coordIndex [vertices [0]], next);

         for (let i = 0, length = vertices .length; i < length; ++ i)
         {
            const tmp = current;
            current = next;
            next    = tmp;

            coord .get1Point (coordIndex [vertices [(i + 1) % length]], next);

            normal .x += (current .y - next .y) * (current .z + next .z);
            normal .y += (current .z - next .z) * (current .x + next .x);
            normal .z += (current .x - next .x) * (current .y + next .y);
         }

         return normal .normalize ();
      };
   })(),
});

Object .defineProperties (IndexedFaceSet,
{
   typeName:
   {
      value: "IndexedFaceSet",
      enumerable: true,
   },
   componentName:
   {
      value: "Geometry3D",
      enumerable: true,
   },
   containerField:
   {
      value: "geometry",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_colorIndex",    new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_texCoordIndex", new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_normalIndex",   new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_coordIndex",    new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "solid",             new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "ccw",               new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "convex",            new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "creaseAngle",       new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "colorPerVertex",    new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "normalPerVertex",   new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "colorIndex",        new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "texCoordIndex",     new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "normalIndex",       new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "coordIndex",        new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "attrib",            new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "fogCoord",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "color",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "texCoord",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "normal",            new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "coord",             new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const IndexedFaceSet_default_ = IndexedFaceSet;
;

x_ite_Namespace .add ("IndexedFaceSet", "x_ite/Components/Geometry3D/IndexedFaceSet", IndexedFaceSet_default_);
/* harmony default export */ const Geometry3D_IndexedFaceSet = (IndexedFaceSet_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Geometry3D/Sphere.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function Sphere (executionContext)
{
   Rendering_X3DGeometryNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Sphere);

   this ._radius .setUnit ("length");
}

Object .assign (Object .setPrototypeOf (Sphere .prototype, Rendering_X3DGeometryNode .prototype),
{
   set_live__ ()
   {
      Rendering_X3DGeometryNode .prototype .set_live__ .call (this);

      if (this .getLive () .getValue ())
         this .getBrowser () .getSphereOptions () .addInterest ("requestRebuild", this);
      else
         this .getBrowser () .getSphereOptions () .removeInterest ("requestRebuild", this);
   },
   build ()
   {
      const
         options  = this .getBrowser () .getSphereOptions (),
         geometry = options .getGeometry (),
         radius   = Math .abs (this ._radius .getValue ());

      this .setMultiTexCoords (geometry .getMultiTexCoords ());
      this .setNormals        (geometry .getNormals ());

      if (radius === 1)
      {
         this .setVertices (geometry .getVertices ());

         this .getMin () .assign (geometry .getMin ());
         this .getMax () .assign (geometry .getMax ());
      }
      else
      {
         const
            defaultVertices = geometry .getVertices () .getValue (),
            vertexArray     = this .getVertices ();

         for (let i = 0, length = defaultVertices .length; i < length; i += 4)
         {
            vertexArray .push (radius * defaultVertices [i],
                               radius * defaultVertices [i + 1],
                               radius * defaultVertices [i + 2],
                               1);
         }

         this .getMin () .set (-radius, -radius, -radius);
         this .getMax () .set ( radius,  radius,  radius);
      }

      this .setSolid (this ._solid .getValue ());
   },
});

Object .defineProperties (Sphere,
{
   typeName:
   {
      value: "Sphere",
      enumerable: true,
   },
   componentName:
   {
      value: "Geometry3D",
      enumerable: true,
   },
   containerField:
   {
      value: "geometry",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "radius",   new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "solid",    new x_ite_Fields .SFBool (true)),
      ]),
      enumerable: true,
   },
});

const Sphere_default_ = Sphere;
;

x_ite_Namespace .add ("Sphere", "x_ite/Components/Geometry3D/Sphere", Sphere_default_);
/* harmony default export */ const Geometry3D_Sphere = (Sphere_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Geometry3D.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









const Geometry3D_default_ = {
   name: "Geometry3D",
   concreteNodes:
   [
      Geometry3D_Box,
      Geometry3D_Cone,
      Geometry3D_Cylinder,
      Geometry3D_ElevationGrid,
      Geometry3D_Extrusion,
      Geometry3D_IndexedFaceSet,
      Geometry3D_Sphere,
   ],
   abstractNodes:
   [
   ],
};
;

x_ite_Namespace .add ("Geometry3D", "x_ite/Components/Geometry3D", Geometry3D_default_);
/* harmony default export */ const Geometry3D = (Geometry3D_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Grouping/StaticGroup.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/












// No support for X3DBindableNode nodes, local lights. X3DLocalFog, local ClipPlane nodes, LOD, Billboard, Switch node.

const
   _pointingShapes    = Symbol (),
   _collisionShapes   = Symbol (),
   _shadowShapes      = Symbol (),
   _opaqueShapes      = Symbol (),
   _transparentShapes = Symbol ();

function StaticGroup (executionContext)
{
   Core_X3DChildNode     .call (this, executionContext);
   Grouping_X3DBoundedObject .call (this, executionContext);

   this .addType (Base_X3DConstants .StaticGroup);

   this .groupNode  = new Grouping_Group (this .getExecutionContext ());
   this .bbox       = new Geometry_Box3 ();
   this .shadowBBox = new Geometry_Box3 ();
}

Object .assign (Object .setPrototypeOf (StaticGroup .prototype, Core_X3DChildNode .prototype),
   Grouping_X3DBoundedObject .prototype,
{
   initialize ()
   {
      Core_X3DChildNode     .prototype .initialize .call (this);
      Grouping_X3DBoundedObject .prototype .initialize .call (this);

      this ._bboxSize   .addFieldInterest (this .groupNode ._bboxSize);
      this ._bboxCenter .addFieldInterest (this .groupNode ._bboxCenter);
      this ._children   .addFieldInterest (this .groupNode ._children);

      this .groupNode ._bboxSize   = this ._bboxSize;
      this .groupNode ._bboxCenter = this ._bboxCenter;
      this .groupNode ._children   = this ._children;
      this .groupNode .setPrivate (true);
      this .groupNode .setup ();

      // Connect after Group setup.
      this .groupNode ._isCameraObject   .addFieldInterest (this ._isCameraObject);
      this .groupNode ._isPickableObject .addFieldInterest (this ._isPickableObject);
      this .groupNode ._children         .addInterest ("set_children__", this);

      this .setCameraObject   (this .groupNode .isCameraObject ());
      this .setPickableObject (this .groupNode .isPickableObject ());

      this .set_children__ ();
   },
   getBBox (bbox, shadows)
   {
      return bbox .assign (shadows ? this .shadowBBox : this .bbox);
   },
   set_children__ ()
   {
      this .groupNode .getBBox (this .bbox);
      this .groupNode .getBBox (this .shadowBBox, true);

      this [_pointingShapes]    = null;
      this [_collisionShapes]   = null;
      this [_shadowShapes]      = null;
      this [_opaqueShapes]      = null;
      this [_transparentShapes] = null;
   },
   traverse (type, renderObject)
   {
      switch (type)
      {
         case Rendering_TraverseType .CAMERA:
         {
            return;
         }
         case Rendering_TraverseType .POINTER:
         {
            this .traverseObjects (_pointingShapes, "Pointing", type, renderObject);
            return;
         }
         case Rendering_TraverseType .COLLISION:
         {
            this .traverseObjects (_collisionShapes, "Collision", type, renderObject);
            return;
         }
         case Rendering_TraverseType .SHADOW:
         {
            this .traverseObjects (_shadowShapes, "Shadow", type, renderObject);
            return;
         }
         case Rendering_TraverseType .DISPLAY:
         {
            this .traverseObjects (_opaqueShapes,      "Opaque",      type, renderObject);
            this .traverseObjects (_transparentShapes, "Transparent", type, renderObject);
            return;
         }
      }
   },
   traverseObjects: (() =>
   {
      const viewVolume = new Geometry_ViewVolume ();

      viewVolume .intersectsSphere = function () { return true; };

      return function (staticShapes, Static, type, renderObject)
      {
         if (!this [staticShapes])
         {
            //console .log (`Rebuilding StaticGroup ${Static}.`);

            const
               viewVolumes      = renderObject .getViewVolumes (),
               viewport         = renderObject .getViewport (),
               projectionMatrix = renderObject .getProjectionMatrix (),
               modelViewMatrix  = renderObject .getModelViewMatrix (),
               firstShape       = renderObject [`getNum${Static}Shapes`] ();

            viewVolumes .push (viewVolume .set (projectionMatrix, viewport, viewport));

            modelViewMatrix .push ();
            modelViewMatrix .identity ();

            this .groupNode .traverse (type, renderObject);

            modelViewMatrix .pop ();
            viewVolumes     .pop ();

            const lastShape = renderObject [`getNum${Static}Shapes`] ();

            this [staticShapes] = renderObject [`get${Static}Shapes`] () .splice (firstShape, lastShape - firstShape);

            renderObject [`setNum${Static}Shapes`] (firstShape);
         }

         const modelViewMatrix = renderObject .getModelViewMatrix ();

         for (const { modelViewMatrix: modelMatrix, shapeNode } of this [staticShapes])
         {
            modelViewMatrix .push ();
            modelViewMatrix .multLeft (modelMatrix);
            shapeNode .traverse (type, renderObject);
            modelViewMatrix .pop ();
         }
      };
   })(),
   dispose ()
   {
      Grouping_X3DBoundedObject .prototype .dispose .call (this);
      Core_X3DChildNode     .prototype .dispose .call (this);
   },
});

Object .defineProperties (StaticGroup,
{
   typeName:
   {
      value: "StaticGroup",
      enumerable: true,
   },
   componentName:
   {
      value: "Grouping",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",    new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "visible",     new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "bboxDisplay", new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxSize",    new x_ite_Fields .SFVec3f (-1, -1, -1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxCenter",  new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "children",    new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const StaticGroup_default_ = StaticGroup;
;

x_ite_Namespace .add ("StaticGroup", "x_ite/Components/Grouping/StaticGroup", StaticGroup_default_);
/* harmony default export */ const Grouping_StaticGroup = (StaticGroup_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Grouping/Switch.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









function Switch (executionContext)
{
   Grouping_X3DGroupingNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Switch);

   if (executionContext .getSpecificationVersion () == 2.0)
      this .addAlias ("choice", this ._children);

   this .childNode     = null;
   this .visibleNode   = null;
   this .boundedObject = null;
}

Object .assign (Object .setPrototypeOf (Switch .prototype, Grouping_X3DGroupingNode .prototype),
{
   initialize ()
   {
      Grouping_X3DGroupingNode .prototype .initialize .call (this);

      this ._whichChoice .addInterest ("set_child__", this);
      this ._children    .addInterest ("set_child__", this);

      this .set_child__ ();
   },
   getSubBBox (bbox, shadows)
   {
      if (this ._bboxSize .getValue () .equals (this .getDefaultBBoxSize ()))
      {
         const boundedObject = Base_X3DCast (Base_X3DConstants .X3DBoundedObject, this .visibleNode);

         return boundedObject ?.getBBox (bbox, shadows) ?? bbox .set ();
      }

      return bbox .set (this ._bboxSize .getValue (), this ._bboxCenter .getValue ());
   },
   clear () { },
   add () { },
   remove () { },
   set_child__ ()
   {
      if (this .childNode)
      {
         this .childNode ._isCameraObject   .removeInterest ("set_cameraObject__",     this);
         this .childNode ._isPickableObject .removeInterest ("set_transformSensors__", this);
      }

      if (Base_X3DCast (Base_X3DConstants .X3DBoundedObject, this .childNode))
      {
         this .childNode ._display     .removeInterest ("set_display__",     this);
         this .childNode ._bboxDisplay .removeInterest ("set_bboxDisplay__", this);
      }

      const whichChoice = this ._whichChoice .getValue ();

      if (whichChoice >= 0 && whichChoice < this ._children .length)
      {
         this .childNode = Base_X3DCast (Base_X3DConstants .X3DChildNode, this ._children [whichChoice]);

         if (this .childNode)
         {
            this .childNode ._isCameraObject   .addInterest ("set_cameraObject__",     this);
            this .childNode ._isPickableObject .addInterest ("set_transformSensors__", this);

            if (Base_X3DCast (Base_X3DConstants .X3DBoundedObject, this .childNode))
            {
               this .childNode ._display     .addInterest ("set_display__",     this);
               this .childNode ._bboxDisplay .addInterest ("set_bboxDisplay__", this);
            }

            delete this .traverse;
         }
      }
      else
      {
         this .childNode = null;

         this .traverse = Function .prototype;
      }

      this .set_display__ ();
      this .set_bboxDisplay__ ();
   },
   set_cameraObject__ ()
   {
      this .setCameraObject (!!this .visibleNode ?.isCameraObject ());
   },
   set_transformSensors__ ()
   {
      this .setPickableObject (!!(this .getTransformSensors () .size || this .visibleNode ?.isPickableObject ()));
   },
   set_display__ ()
   {
      if (Base_X3DCast (Base_X3DConstants .X3DBoundedObject, this .childNode))
         this .visibleNode = this .childNode ._display .getValue () ? this .childNode : null;
      else
         this .visibleNode = this .childNode;

      this .set_cameraObject__ ();
      this .set_transformSensors__ ();
   },
   set_bboxDisplay__ ()
   {
      if (Base_X3DCast (Base_X3DConstants .X3DBoundedObject, this .childNode))
         this .boundedObject = this .childNode ._bboxDisplay .getValue () ? this .childNode : null;
      else
         this .boundedObject = null;
   },
   traverse (type, renderObject)
   {
      switch (type)
      {
         case Rendering_TraverseType .POINTER:
         case Rendering_TraverseType .CAMERA:
         case Rendering_TraverseType .SHADOW:
         {
            this .visibleNode ?.traverse (type, renderObject);
            return;
         }
         case Rendering_TraverseType .PICKING:
         {
            if (this .getTransformSensors () .size)
            {
               const modelMatrix = renderObject .getModelViewMatrix () .get ();

               for (const transformSensorNode of this .getTransformSensors ())
                  transformSensorNode .collect (modelMatrix);
            }

            const visibleNode = this .visibleNode;

            if (visibleNode)
            {
               const
                  browser          = this .getBrowser (),
                  pickingHierarchy = browser .getPickingHierarchy ();

               pickingHierarchy .push (this);

               visibleNode .traverse (type, renderObject);

               pickingHierarchy .pop ();
            }

            return;
         }
         case Rendering_TraverseType .COLLISION:
         {
            this .visibleNode ?.traverse (type, renderObject);
            return;
         }
         case Rendering_TraverseType .DISPLAY:
         {
            this .visibleNode ?.traverse (type, renderObject);

            this .boundedObject ?.displayBBox (type, renderObject);
            return;
         }
      }
   },
});

Object .defineProperties (Switch,
{
   typeName:
   {
      value: "Switch",
      enumerable: true,
   },
   componentName:
   {
      value: "Grouping",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",       new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "whichChoice",    new x_ite_Fields .SFInt32 (-1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "visible",        new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "bboxDisplay",    new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxSize",       new x_ite_Fields .SFVec3f (-1, -1, -1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxCenter",     new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "addChildren",    new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "removeChildren", new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "children",       new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const Switch_default_ = Switch;
;

x_ite_Namespace .add ("Switch", "x_ite/Components/Grouping/Switch", Switch_default_);
/* harmony default export */ const Grouping_Switch = (Switch_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Grouping/X3DTransformMatrix3DNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function X3DTransformMatrix3DNode (executionContext)
{
   Grouping_X3DGroupingNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DTransformMatrix3DNode);

   this .matrix = new Numbers_Matrix4 ();
}

Object .assign (Object .setPrototypeOf (X3DTransformMatrix3DNode .prototype, Grouping_X3DGroupingNode .prototype),
{
   setMatrix (matrix)
   {
      if (matrix .equals (Numbers_Matrix4 .Identity))
      {
         this .matrix .identity ();

         this .getBBox  = this .getSubBBox;
         this .traverse = this .groupTraverse;
      }
      else
      {
         this .matrix .assign (matrix);

         delete this .getBBox;
         delete this .traverse;
      }
   },
   getMatrix ()
   {
      return this .matrix;
   },
   setTransform (t, r, s, so, c)
   {
      if (t .equals (Numbers_Vector3 .Zero) && r .equals (Numbers_Rotation4 .Identity) && s .equals (Numbers_Vector3 .One))
      {
         this .matrix .identity ();

         this .getBBox  = this .getSubBBox;
         this .traverse = this .groupTraverse;
      }
      else
      {
         this .matrix .set (t, r, s, so, c);

         delete this .getBBox;
         delete this .traverse;
      }
   },
   getBBox (bbox, shadows)
   {
      return this .getSubBBox (bbox, shadows) .multRight (this .matrix);
   },
   traverse (type, renderObject)
   {
      const modelViewMatrix = renderObject .getModelViewMatrix ();

      modelViewMatrix .push ();
      modelViewMatrix .multLeft (this .matrix);

      Grouping_X3DGroupingNode .prototype .traverse .call (this, type, renderObject);

      modelViewMatrix .pop ();
   },
   groupTraverse: Grouping_X3DGroupingNode .prototype .traverse,
});

Object .defineProperties (X3DTransformMatrix3DNode,
{
   typeName:
   {
      value: "X3DTransformMatrix3DNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Grouping",
      enumerable: true,
   },
});

const X3DTransformMatrix3DNode_default_ = X3DTransformMatrix3DNode;
;

x_ite_Namespace .add ("X3DTransformMatrix3DNode", "x_ite/Components/Grouping/X3DTransformMatrix3DNode", X3DTransformMatrix3DNode_default_);
/* harmony default export */ const Grouping_X3DTransformMatrix3DNode = (X3DTransformMatrix3DNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Grouping/X3DTransformNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function X3DTransformNode (executionContext)
{
   Grouping_X3DTransformMatrix3DNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DTransformNode);

   this ._translation .setUnit ("length");
   this ._center      .setUnit ("length");
}

Object .assign (Object .setPrototypeOf (X3DTransformNode .prototype, Grouping_X3DTransformMatrix3DNode .prototype),
{
   initialize ()
   {
      Grouping_X3DTransformMatrix3DNode .prototype .initialize .call (this);

      this .addInterest ("eventsProcessed", this);

      this .eventsProcessed ();
   },
   eventsProcessed ()
   {
      this .setTransform (this ._translation      .getValue (),
                          this ._rotation         .getValue (),
                          this ._scale            .getValue (),
                          this ._scaleOrientation .getValue (),
                          this ._center           .getValue ());
   },
});

Object .defineProperties (X3DTransformNode,
{
   typeName:
   {
      value: "X3DTransformNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Grouping",
      enumerable: true,
   },
});

const X3DTransformNode_default_ = X3DTransformNode;
;

x_ite_Namespace .add ("X3DTransformNode", "x_ite/Components/Grouping/X3DTransformNode", X3DTransformNode_default_);
/* harmony default export */ const Grouping_X3DTransformNode = (X3DTransformNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Grouping/Transform.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function Transform (executionContext)
{
   Grouping_X3DTransformNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Transform);
}

Object .setPrototypeOf (Transform .prototype, Grouping_X3DTransformNode .prototype);

Object .defineProperties (Transform,
{
   typeName:
   {
      value: "Transform",
      enumerable: true,
   },
   componentName:
   {
      value: "Grouping",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",         new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "translation",      new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "rotation",         new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "scale",            new x_ite_Fields .SFVec3f (1, 1, 1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "scaleOrientation", new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "center",           new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "visible",          new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "bboxDisplay",      new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxSize",         new x_ite_Fields .SFVec3f (-1, -1, -1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxCenter",       new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "addChildren",      new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "removeChildren",   new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "children",         new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const Transform_default_ = Transform;
;

x_ite_Namespace .add ("Transform", "x_ite/Components/Grouping/Transform", Transform_default_);
/* harmony default export */ const Grouping_Transform = (Transform_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Grouping.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










const Grouping_default_ = {
   name: "Grouping",
   concreteNodes:
   [
      Grouping_Group,
      Grouping_StaticGroup,
      Grouping_Switch,
      Grouping_Transform,
   ],
   abstractNodes:
   [
      Grouping_X3DBoundedObject,
      Grouping_X3DGroupingNode,
      Grouping_X3DTransformMatrix3DNode,
      Grouping_X3DTransformNode,
   ],
};
;

x_ite_Namespace .add ("Grouping", "x_ite/Components/Grouping", Grouping_default_);
/* harmony default export */ const Grouping = (Grouping_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Interpolation/ColorInterpolator.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function ColorInterpolator (executionContext)
{
   Interpolation_X3DInterpolatorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .ColorInterpolator);

   this .hsv = [ ];
}

Object .assign (Object .setPrototypeOf (ColorInterpolator .prototype, Interpolation_X3DInterpolatorNode .prototype),
{
   initialize ()
   {
      Interpolation_X3DInterpolatorNode .prototype .initialize .call (this);

      this ._keyValue .addInterest ("set_keyValue__", this);
   },
   set_keyValue__ ()
   {
      const keyValue = this ._keyValue;

      if (keyValue .length < this ._key .length)
         this ._keyValue .resize (this ._key .length, keyValue .length ? keyValue [this ._keyValue .length - 1] : new x_ite_Fields .SFColor ());

      this .hsv .length = 0;

      for (const value of keyValue)
         this .hsv .push (value .getHSV ());
   },
   interpolate: (() =>
   {
      const value = [ ];

      return function (index0, index1, weight)
      {
         Numbers_Color3 .lerp (this .hsv [index0], this .hsv [index1], weight, value);

         this ._value_changed .setHSV (value [0], value [1], value [2]);
      };
   })(),
});

Object .defineProperties (ColorInterpolator,
{
   typeName:
   {
      value: "ColorInterpolator",
      enumerable: true,
   },
   componentName:
   {
      value: "Interpolation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",      new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_fraction",  new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "key",           new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "keyValue",      new x_ite_Fields .MFColor ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "value_changed", new x_ite_Fields .SFColor ()),
      ]),
      enumerable: true,
   },
});

const ColorInterpolator_default_ = ColorInterpolator;
;

x_ite_Namespace .add ("ColorInterpolator", "x_ite/Components/Interpolation/ColorInterpolator", ColorInterpolator_default_);
/* harmony default export */ const Interpolation_ColorInterpolator = (ColorInterpolator_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Interpolation/CoordinateInterpolator.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function CoordinateInterpolator (executionContext)
{
   Interpolation_X3DInterpolatorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .CoordinateInterpolator);
}

Object .assign (Object .setPrototypeOf (CoordinateInterpolator .prototype, Interpolation_X3DInterpolatorNode .prototype),
{
   set_keyValue__ () { },
   interpolate (index0, index1, weight)
   {
      const keyValue = this ._keyValue .getValue ();

      let size = this ._key .length ? Math .floor (this ._keyValue .length / this ._key .length) : 0;

      this ._value_changed .length = size;

      const value_changed = this ._value_changed .getValue ();

      index0 *= size;
      index1  = index0 + (this ._key .length > 1 ? size : 0);

      index0 *= 3;
      index1 *= 3;
      size   *= 3;

      for (let i0 = 0; i0 < size; i0 += 3)
      {
         const
            i1 = i0 + 1,
            i2 = i0 + 2;

         value_changed [i0] = Math_Algorithm .lerp (keyValue [index0 + i0], keyValue [index1 + i0], weight);
         value_changed [i1] = Math_Algorithm .lerp (keyValue [index0 + i1], keyValue [index1 + i1], weight);
         value_changed [i2] = Math_Algorithm .lerp (keyValue [index0 + i2], keyValue [index1 + i2], weight);
      }

      this ._value_changed .addEvent ();
   },
});

Object .defineProperties (CoordinateInterpolator,
{
   typeName:
   {
      value: "CoordinateInterpolator",
      enumerable: true,
   },
   componentName:
   {
      value: "Interpolation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",      new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_fraction",  new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "key",           new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "keyValue",      new x_ite_Fields .MFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "value_changed", new x_ite_Fields .MFVec3f ()),
      ]),
      enumerable: true,
   },
});

const CoordinateInterpolator_default_ = CoordinateInterpolator;
;

x_ite_Namespace .add ("CoordinateInterpolator", "x_ite/Components/Interpolation/CoordinateInterpolator", CoordinateInterpolator_default_);
/* harmony default export */ const Interpolation_CoordinateInterpolator = (CoordinateInterpolator_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Interpolation/CoordinateInterpolator2D.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function CoordinateInterpolator2D (executionContext)
{
   Interpolation_X3DInterpolatorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .CoordinateInterpolator2D);
}

Object .assign (Object .setPrototypeOf (CoordinateInterpolator2D .prototype, Interpolation_X3DInterpolatorNode .prototype),
{
   set_keyValue__ () { },
   interpolate (index0, index1, weight)
   {
      const keyValue = this ._keyValue .getValue ();

      let size = this ._key .length ? Math .floor (this ._keyValue .length / this ._key .length) : 0;

      this ._value_changed .length = size;

      const value_changed = this ._value_changed .getValue ();

      index0 *= size;
      index1  = index0 + (this ._key .length > 1 ? size : 0);

      index0 *= 2;
      index1 *= 2;
      size   *= 2;

      for (let i0 = 0; i0 < size; i0 += 2)
      {
         const i1 = i0 + 1;

         value_changed [i0] = Math_Algorithm .lerp (keyValue [index0 + i0], keyValue [index1 + i0], weight);
         value_changed [i1] = Math_Algorithm .lerp (keyValue [index0 + i1], keyValue [index1 + i1], weight);
      }

      this ._value_changed .addEvent ();
   },
});

Object .defineProperties (CoordinateInterpolator2D,
{
   typeName:
   {
      value: "CoordinateInterpolator2D",
      enumerable: true,
   },
   componentName:
   {
      value: "Interpolation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",      new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_fraction",  new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "key",           new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "keyValue",      new x_ite_Fields .MFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "value_changed", new x_ite_Fields .MFVec2f ()),
      ]),
      enumerable: true,
   },
});

const CoordinateInterpolator2D_default_ = CoordinateInterpolator2D;
;

x_ite_Namespace .add ("CoordinateInterpolator2D", "x_ite/Components/Interpolation/CoordinateInterpolator2D", CoordinateInterpolator2D_default_);
/* harmony default export */ const Interpolation_CoordinateInterpolator2D = (CoordinateInterpolator2D_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Interpolation/NormalInterpolator.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









function NormalInterpolator (executionContext)
{
   Interpolation_X3DInterpolatorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .NormalInterpolator);
}

Object .assign (Object .setPrototypeOf (NormalInterpolator .prototype, Interpolation_X3DInterpolatorNode .prototype),
{
   initialize ()
   {
      Interpolation_X3DInterpolatorNode .prototype .initialize .call (this);

      this ._keyValue .addInterest ("set_keyValue__", this);
   },
   set_keyValue__ () { },
   interpolate: (() =>
   {
      const
         keyValue0 = new Numbers_Vector3 (0, 0, 0),
         keyValue1 = new Numbers_Vector3 (0, 0, 0);

      return function (index0, index1, weight)
      {
         const keyValue = this ._keyValue .getValue ();

         let size = this ._key .length > 1 ? Math .floor (this ._keyValue .length / this ._key .length) : 0;

         this ._value_changed .length = size;

         const value_changed = this ._value_changed .getValue ();

         index0 *= size;
         index1  = index0 + size;

         index0 *= 3;
         index1 *= 3;
         size   *= 3;

         for (let i0 = 0; i0 < size; i0 += 3)
         {
            try
            {
               const
                  i1 = i0 + 1,
                  i2 = i0 + 2;

               keyValue0 .set (keyValue [index0 + i0], keyValue [index0 + i1], keyValue [index0 + i2]);
               keyValue1 .set (keyValue [index1 + i0], keyValue [index1 + i1], keyValue [index1 + i2]);

               const value = Math_Algorithm .simpleSlerp (keyValue0, keyValue1, weight);

               value_changed [i0] = value [0];
               value_changed [i1] = value [1];
               value_changed [i2] = value [2];
            }
            catch (error)
            {
               //console .log (error);
            }
         }

         this ._value_changed .addEvent ();
      };
   })(),
});

Object .defineProperties (NormalInterpolator,
{
   typeName:
   {
      value: "NormalInterpolator",
      enumerable: true,
   },
   componentName:
   {
      value: "Interpolation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",      new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_fraction",  new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "key",           new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "keyValue",      new x_ite_Fields .MFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "value_changed", new x_ite_Fields .MFVec3f ()),
      ]),
      enumerable: true,
   },
});

const NormalInterpolator_default_ = NormalInterpolator;
;

x_ite_Namespace .add ("NormalInterpolator", "x_ite/Components/Interpolation/NormalInterpolator", NormalInterpolator_default_);
/* harmony default export */ const Interpolation_NormalInterpolator = (NormalInterpolator_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Interpolation/PositionInterpolator2D.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function PositionInterpolator2D (executionContext)
{
   Interpolation_X3DInterpolatorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .PositionInterpolator2D);
}

Object .assign (Object .setPrototypeOf (PositionInterpolator2D .prototype, Interpolation_X3DInterpolatorNode .prototype),
{
   initialize ()
   {
      Interpolation_X3DInterpolatorNode .prototype .initialize .call (this);

      this ._keyValue .addInterest ("set_keyValue__", this);
   },
   set_keyValue__ ()
   {
      const
         key      = this ._key,
         keyValue = this ._keyValue;

      if (keyValue .length < key .length)
         keyValue .resize (key .length, keyValue .length ? keyValue [keyValue .length - 1] : new x_ite_Fields .SFVec2f ());
   },
   interpolate:  (() =>
   {
      const keyValue = new Numbers_Vector2 (0, 0);

      return function (index0, index1, weight)
      {
         this ._value_changed = keyValue .assign (this ._keyValue [index0] .getValue ()) .lerp (this ._keyValue [index1] .getValue (), weight);
      };
   })(),
});

Object .defineProperties (PositionInterpolator2D,
{
   typeName:
   {
      value: "PositionInterpolator2D",
      enumerable: true,
   },
   componentName:
   {
      value: "Interpolation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",      new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_fraction",  new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "key",           new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "keyValue",      new x_ite_Fields .MFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "value_changed", new x_ite_Fields .SFVec2f ()),
      ]),
      enumerable: true,
   },
});

const PositionInterpolator2D_default_ = PositionInterpolator2D;
;

x_ite_Namespace .add ("PositionInterpolator2D", "x_ite/Components/Interpolation/PositionInterpolator2D", PositionInterpolator2D_default_);
/* harmony default export */ const Interpolation_PositionInterpolator2D = (PositionInterpolator2D_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Interpolation/CatmullRomSplineInterpolator.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function CatmullRomSplineInterpolator ()
{
   this .T0 = [ ];
   this .T1 = [ ];
}

Object .assign (CatmullRomSplineInterpolator .prototype,
{
   generate: (() =>
   {
      const
         T  = [ ],
         Fp = [ ],
         Fm = [ ];

      return function (closed, key, keyValue, keyVelocity, normalizeVelocity)
      {
         const
            T0 = this .T0,
            T1 = this .T1;

         T0 .length = 0;
         T1 .length = 0;

         T  .length = 0;
         Fp .length = 0;
         Fm .length = 0;

         if (key .length > 1)
         {
            // T

            if (keyVelocity .length === 0)
            {
               if (closed)
                  T .push (this .divide (this .subtract (keyValue [1], keyValue [keyValue .length - 2]), 2));

               else
                  T .push (this .create ());

               for (let i = 1, length = keyValue .length - 1; i < length; ++ i)
                  T .push (this .divide (this .subtract (keyValue [i + 1], keyValue [i - 1]), 2));

               T .push (this .copy (T [0]));
            }
            else
            {
               for (let i = 0, length = keyVelocity .length; i < length; ++ i)
                  T .push (this .copy (keyVelocity [i]));

               if (normalizeVelocity)
               {
                  let Dtot = 0;

                  for (let i = 0, length = keyValue .length - 1; i < length; ++ i)
                     Dtot += this .magnitude (this .subtract (keyValue [i], keyValue [i + 1]));

                  for (let i = 0, length = T .length - 1; i < length; ++ i)
                  {
                     const Tia = this .magnitude (T [i]);

                     if (Tia)
                        T [i] = this .multiply (T [i], Dtot / Tia);
                  }
               }
            }

            // Fm, Fp

            if (closed)
            {
               const i_1 = key .length - 1;
               const i_2 = key .length - 2;

               const d = key [1] - key [0] + key [i_1] - key [i_2];

               Fm .push (2 * (key [1]   - key [0])   / d);
               Fp .push (2 * (key [i_1] - key [i_2]) / d);
            }
            else
            {
               Fm .push (1);
               Fp .push (1);
            }

            for (let i = 1, length = key .length - 1; i < length; ++ i)
            {
               const d = key [i + 1] - key [i - 1];

               Fm .push (2 * (key [i + 1] - key [i])     / d);
               Fp .push (2 * (key [i]     - key [i - 1]) / d);
            }

            Fm .push (Fm [0]);
            Fp .push (Fp [0]);

            // T0, T1

            for (let i = 0, length = T .length; i < length; ++ i)
            {
               T0 .push (this .multiply (T [i], Fp [i]));
               T1 .push (this .multiply (T [i], Fm [i]));
            }
         }
         else
         {
            T0 .push (this .create ());
            T1 .push (this .create ());
         }
      };
   })(),
   interpolate: (() =>
   {
      const S = new Numbers_Vector4 (0, 0, 0, 0);

      const H = new Numbers_Matrix4 ( 2, -2,  1,  1,
                             -3,  3, -2, -1,
                              0,  0,  1,  0,
                              1,  0,  0,  0);

      return function (index0, index1, weight, keyValue)
      {
         S .set (weight ** 3, weight ** 2, weight, 1);

         // Taking dot product from SH and C;

         return this .dot (H .multVecMatrix (S),
                           keyValue [index0],
                           keyValue [index1],
                           this .T0 [index0],
                           this .T1 [index1]);
      };
   })(),
});

const CatmullRomSplineInterpolator_default_ = CatmullRomSplineInterpolator;
;

x_ite_Namespace .add ("CatmullRomSplineInterpolator", "x_ite/Browser/Interpolation/CatmullRomSplineInterpolator", CatmullRomSplineInterpolator_default_);
/* harmony default export */ const Interpolation_CatmullRomSplineInterpolator = (CatmullRomSplineInterpolator_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Interpolation/CatmullRomSplineInterpolatorTemplate.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function CatmullRomSplineInterpolatorTemplate (Type)
{
   function CatmullRomSplineInterpolatorInstance ()
   {
      this .T0 = [ ];
      this .T1 = [ ];
   }

   Object .assign (Object .setPrototypeOf (CatmullRomSplineInterpolatorInstance .prototype, Interpolation_CatmullRomSplineInterpolator .prototype),
   {
      create ()
      {
         return Type .Zero .copy ();
      },
      copy (value)
      {
         return value .copy ();
      },
      subtract (lhs, rhs)
      {
         return lhs .copy () .subtract (rhs);
      },
      multiply (lhs, rhs)
      {
         return lhs .copy () .multiply (rhs);
      },
      divide (lhs, rhs)
      {
         return lhs .copy () .divide (rhs);
      },
      magnitude (value)
      {
         return value .magnitude ();
      },
      dot: (() =>
      {
         const
            c0 = new Type (0, 0, 0, 0),
            c1 = new Type (0, 0, 0, 0),
            c2 = new Type (0, 0, 0, 0),
            c3 = new Type (0, 0, 0, 0);

         return function (SH, C0, C1, C2, C3)
         {
            c0 .assign (C0) .multiply (SH [0]);
            c1 .assign (C1) .multiply (SH [1]);
            c2 .assign (C2) .multiply (SH [2]);
            c3 .assign (C3) .multiply (SH [3]);

            return c0 .add (c1) .add (c2) .add (c3);
         };
      })(),
   });

   return CatmullRomSplineInterpolatorInstance;
}

const CatmullRomSplineInterpolatorTemplate_default_ = CatmullRomSplineInterpolatorTemplate;
;

x_ite_Namespace .add ("CatmullRomSplineInterpolatorTemplate", "x_ite/Browser/Interpolation/CatmullRomSplineInterpolatorTemplate", CatmullRomSplineInterpolatorTemplate_default_);
/* harmony default export */ const Interpolation_CatmullRomSplineInterpolatorTemplate = (CatmullRomSplineInterpolatorTemplate_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Interpolation/CatmullRomSplineInterpolator3.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




const CatmullRomSplineInterpolator3 = Interpolation_CatmullRomSplineInterpolatorTemplate (Numbers_Vector3);

const CatmullRomSplineInterpolator3_default_ = CatmullRomSplineInterpolator3;
;

x_ite_Namespace .add ("CatmullRomSplineInterpolator3", "x_ite/Browser/Interpolation/CatmullRomSplineInterpolator3", CatmullRomSplineInterpolator3_default_);
/* harmony default export */ const Interpolation_CatmullRomSplineInterpolator3 = (CatmullRomSplineInterpolator3_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Interpolation/SplinePositionInterpolator.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function SplinePositionInterpolator (executionContext)
{
   Interpolation_X3DInterpolatorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .SplinePositionInterpolator);

   this .spline = new Interpolation_CatmullRomSplineInterpolator3 ();
}

Object .assign (Object .setPrototypeOf (SplinePositionInterpolator .prototype, Interpolation_X3DInterpolatorNode .prototype),
{
   initialize ()
   {
      Interpolation_X3DInterpolatorNode .prototype .initialize .call (this);

      this ._keyValue          .addInterest ("set_keyValue__",          this);
      this ._keyVelocity       .addInterest ("set_keyVelocity__",       this);
      this ._normalizeVelocity .addInterest ("set_normalizeVelocity__", this);
   },
   set_keyValue__ ()
   {
      const
         key      = this ._key,
         keyValue = this ._keyValue;

      if (keyValue .length < key .length)
         keyValue .resize (key .length, keyValue .length ? keyValue [keyValue .length - 1] : new x_ite_Fields .SFVec3f ());

      this .set_keyVelocity__ ();
   },
   set_keyVelocity__ ()
   {
      if (this ._keyVelocity .length)
      {
         if (this ._keyVelocity .length < this ._key .length)
            this ._keyVelocity .resize (this ._key .length, new x_ite_Fields .SFVec3f ());
      }

      this .set_normalizeVelocity__ ();
   },
   set_normalizeVelocity__ ()
   {
      this .spline .generate (this ._closed .getValue (),
                              this ._key,
                              this ._keyValue,
                              this ._keyVelocity,
                              this ._normalizeVelocity .getValue ());
   },
   interpolate (index0, index1, weight)
   {
      this ._value_changed = this .spline .interpolate (index0, index1, weight, this ._keyValue);
   },
});

Object .defineProperties (SplinePositionInterpolator,
{
   typeName:
   {
      value: "SplinePositionInterpolator",
      enumerable: true,
   },
   componentName:
   {
      value: "Interpolation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_fraction",      new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "closed",            new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "key",               new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "keyValue",          new x_ite_Fields .MFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "keyVelocity",       new x_ite_Fields .MFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "normalizeVelocity", new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "value_changed",     new x_ite_Fields .SFVec3f ()),
      ]),
      enumerable: true,
   },
});

const SplinePositionInterpolator_default_ = SplinePositionInterpolator;
;

x_ite_Namespace .add ("SplinePositionInterpolator", "x_ite/Components/Interpolation/SplinePositionInterpolator", SplinePositionInterpolator_default_);
/* harmony default export */ const Interpolation_SplinePositionInterpolator = (SplinePositionInterpolator_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Interpolation/CatmullRomSplineInterpolator2.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




const CatmullRomSplineInterpolator2 = Interpolation_CatmullRomSplineInterpolatorTemplate (Numbers_Vector2);

const CatmullRomSplineInterpolator2_default_ = CatmullRomSplineInterpolator2;
;

x_ite_Namespace .add ("CatmullRomSplineInterpolator2", "x_ite/Browser/Interpolation/CatmullRomSplineInterpolator2", CatmullRomSplineInterpolator2_default_);
/* harmony default export */ const Interpolation_CatmullRomSplineInterpolator2 = (CatmullRomSplineInterpolator2_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Interpolation/SplinePositionInterpolator2D.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function SplinePositionInterpolator2D (executionContext)
{
   Interpolation_X3DInterpolatorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .SplinePositionInterpolator2D);

   this .spline = new Interpolation_CatmullRomSplineInterpolator2 ();
}

Object .assign (Object .setPrototypeOf (SplinePositionInterpolator2D .prototype, Interpolation_X3DInterpolatorNode .prototype),
{
   initialize ()
   {
      Interpolation_X3DInterpolatorNode .prototype .initialize .call (this);

      this ._keyValue          .addInterest ("set_keyValue__",          this);
      this ._keyVelocity       .addInterest ("set_keyVelocity__",       this);
      this ._normalizeVelocity .addInterest ("set_normalizeVelocity__", this);
   },
   set_keyValue__ ()
   {
      const
         key      = this ._key,
         keyValue = this ._keyValue;

      if (keyValue .length < key .length)
         keyValue .resize (key .length, keyValue .length ? keyValue [keyValue .length - 1] : new x_ite_Fields .SFVec2f ());

      this .set_keyVelocity__ ();
   },
   set_keyVelocity__ ()
   {
      if (this ._keyVelocity .length)
      {
         if (this ._keyVelocity .length < this ._key .length)
            this ._keyVelocity .resize (this ._key .length, new x_ite_Fields .SFVec2f ());
      }

      this .set_normalizeVelocity__ ();
   },
   set_normalizeVelocity__ ()
   {
      this .spline .generate (this ._closed .getValue (),
                              this ._key,
                              this ._keyValue,
                              this ._keyVelocity,
                              this ._normalizeVelocity .getValue ());
   },
   interpolate (index0, index1, weight)
   {
      this ._value_changed = this .spline .interpolate (index0, index1, weight, this ._keyValue);
   },
});

Object .defineProperties (SplinePositionInterpolator2D,
{
   typeName:
   {
      value: "SplinePositionInterpolator2D",
      enumerable: true,
   },
   componentName:
   {
      value: "Interpolation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_fraction",      new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "closed",            new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "key",               new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "keyValue",          new x_ite_Fields .MFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "keyVelocity",       new x_ite_Fields .MFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "normalizeVelocity", new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "value_changed",     new x_ite_Fields .SFVec2f ()),
      ]),
      enumerable: true,
   },
});

const SplinePositionInterpolator2D_default_ = SplinePositionInterpolator2D;
;

x_ite_Namespace .add ("SplinePositionInterpolator2D", "x_ite/Components/Interpolation/SplinePositionInterpolator2D", SplinePositionInterpolator2D_default_);
/* harmony default export */ const Interpolation_SplinePositionInterpolator2D = (SplinePositionInterpolator2D_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Interpolation/CatmullRomSplineInterpolator1.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function CatmullRomSplineInterpolator1 ()
{
   Interpolation_CatmullRomSplineInterpolator .call (this);
}

Object .assign (Object .setPrototypeOf (CatmullRomSplineInterpolator1 .prototype, Interpolation_CatmullRomSplineInterpolator .prototype),
{
   create ()
   {
      return 0;
   },
   copy (value)
   {
      return value;
   },
   subtract (lhs, rhs)
   {
      return lhs - rhs;
   },
   multiply (lhs, rhs)
   {
      return lhs * rhs;
   },
   divide (lhs, rhs)
   {
      return lhs / rhs;
   },
   magnitude (value)
   {
      return Math .abs (value);
   },
   dot (SH, C0, C1, C2, C3)
   {
      return C0 * SH [0] + C1 * SH [1] + C2 * SH [2] + C3 * SH [3];
   },
});

const CatmullRomSplineInterpolator1_default_ = CatmullRomSplineInterpolator1;
;

x_ite_Namespace .add ("CatmullRomSplineInterpolator1", "x_ite/Browser/Interpolation/CatmullRomSplineInterpolator1", CatmullRomSplineInterpolator1_default_);
/* harmony default export */ const Interpolation_CatmullRomSplineInterpolator1 = (CatmullRomSplineInterpolator1_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Interpolation/SplineScalarInterpolator.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function SplineScalarInterpolator (executionContext)
{
   Interpolation_X3DInterpolatorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .SplineScalarInterpolator);

   this .spline = new Interpolation_CatmullRomSplineInterpolator1 ();
}

Object .assign (Object .setPrototypeOf (SplineScalarInterpolator .prototype, Interpolation_X3DInterpolatorNode .prototype),
{
   initialize ()
   {
      Interpolation_X3DInterpolatorNode .prototype .initialize .call (this);

      this ._keyValue          .addInterest ("set_keyValue__",          this);
      this ._keyVelocity       .addInterest ("set_keyVelocity__",       this);
      this ._normalizeVelocity .addInterest ("set_normalizeVelocity__", this);
   },
   set_keyValue__ ()
   {
      const
         key      = this ._key,
         keyValue = this ._keyValue;

      if (keyValue .length < key .length)
         keyValue .resize (key .length, keyValue .length ? keyValue [keyValue .length - 1] : new x_ite_Fields .SFFloat ());

      this .set_keyVelocity__ ();
   },
   set_keyVelocity__ ()
   {
      if (this ._keyVelocity .length)
      {
         if (this ._keyVelocity .length < this ._key .length)
            this ._keyVelocity .resize (this ._key .length, new x_ite_Fields .SFFloat ());
      }

      this .set_normalizeVelocity__ ();
   },
   set_normalizeVelocity__ ()
   {
      this .spline .generate (this ._closed .getValue (),
                              this ._key,
                              this ._keyValue,
                              this ._keyVelocity,
                              this ._normalizeVelocity .getValue ());
   },
   interpolate (index0, index1, weight)
   {
      this ._value_changed = this .spline .interpolate (index0, index1, weight, this ._keyValue);
   },
});

Object .defineProperties (SplineScalarInterpolator,
{
   typeName:
   {
      value: "SplineScalarInterpolator",
      enumerable: true,
   },
   componentName:
   {
      value: "Interpolation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_fraction",      new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "closed",            new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "key",               new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "keyValue",          new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "keyVelocity",       new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "normalizeVelocity", new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "value_changed",     new x_ite_Fields .SFFloat ()),
      ]),
      enumerable: true,
   },
});

const SplineScalarInterpolator_default_ = SplineScalarInterpolator;
;

x_ite_Namespace .add ("SplineScalarInterpolator", "x_ite/Components/Interpolation/SplineScalarInterpolator", SplineScalarInterpolator_default_);
/* harmony default export */ const Interpolation_SplineScalarInterpolator = (SplineScalarInterpolator_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Interpolation/SquatInterpolator.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function SquatInterpolator ()
{
   this .s = [ ];
}

Object .assign (SquatInterpolator .prototype,
{
   generate (closed, key, keyValue)
   {
      const s = this .s;

      s .length = 0;

      if (key .length > 1)
      {
         if (closed)
         {
            s .push (Numbers_Rotation4 .spline (keyValue [key .length - 2] .getValue (),
                                        keyValue [0] .getValue (),
                                        keyValue [1] .getValue ()));
         }
         else
         {
            s .push (keyValue [0] .getValue ());
         }

         for (let i = 1, length = key .length - 1; i < length; ++ i)
         {
            s .push (Numbers_Rotation4 .spline (keyValue [i - 1] .getValue (),
                                        keyValue [i]     .getValue (),
                                        keyValue [i + 1] .getValue ()));
         }

         if (closed)
         {
            s .push (Numbers_Rotation4 .spline (keyValue [key .length - 2] .getValue (),
                                        keyValue [key .length - 1] .getValue (),
                                        keyValue [1] .getValue ()));
         }
         else
         {
            s .push (keyValue [key .length - 1] .getValue ());
         }
      }
      else if (key .length > 0)
      {
         s .push (keyValue [0] .getValue () .copy ());
      }
   },
   interpolate: (() =>
   {
      const result = new Numbers_Rotation4 ();

      return function (index0, index1, weight, keyValue)
      {
         return result .assign (keyValue [index0] .getValue ()) .squad (this .s [index0],
                                                                        this .s [index1],
                                                                        keyValue [index1] .getValue (), weight);
      };
   })(),
});

const SquatInterpolator_default_ = SquatInterpolator;
;

x_ite_Namespace .add ("SquatInterpolator", "x_ite/Browser/Interpolation/SquatInterpolator", SquatInterpolator_default_);
/* harmony default export */ const Interpolation_SquatInterpolator = (SquatInterpolator_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Interpolation/SquadOrientationInterpolator.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function SquadOrientationInterpolator (executionContext)
{
   Interpolation_X3DInterpolatorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .SquadOrientationInterpolator);

   this ._keyValue      .setUnit ("angle");
   this ._value_changed .setUnit ("angle");

   this .squad = new Interpolation_SquatInterpolator ();
}

Object .assign (Object .setPrototypeOf (SquadOrientationInterpolator .prototype, Interpolation_X3DInterpolatorNode .prototype),
{
   initialize ()
   {
      Interpolation_X3DInterpolatorNode .prototype .initialize .call (this);

      this ._keyValue .addInterest ("set_keyValue__", this);
   },
   set_keyValue__ ()
   {
      const
         key      = this ._key,
         keyValue = this ._keyValue;

      if (keyValue .length < key .length)
         keyValue .resize (key .length, keyValue .length ? keyValue [keyValue .length - 1] : new x_ite_Fields .SFRotation ());

      this .squad .generate (this ._closed .getValue (),
                             this ._key,
                             this ._keyValue);
   },
   interpolate (index0, index1, weight)
   {
      try
      {
         this ._value_changed = this .squad .interpolate (index0, index1, weight, this ._keyValue);
      }
      catch (error)
      {
         console .error (error);
      }
   },
});

Object .defineProperties (SquadOrientationInterpolator,
{
   typeName:
   {
      value: "SquadOrientationInterpolator",
      enumerable: true,
   },
   componentName:
   {
      value: "Interpolation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",      new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_fraction",  new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "closed",        new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "key",           new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "keyValue",      new x_ite_Fields .MFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "value_changed", new x_ite_Fields .SFRotation ()),
      ]),
      enumerable: true,
   },
});

const SquadOrientationInterpolator_default_ = SquadOrientationInterpolator;
;

x_ite_Namespace .add ("SquadOrientationInterpolator", "x_ite/Components/Interpolation/SquadOrientationInterpolator", SquadOrientationInterpolator_default_);
/* harmony default export */ const Interpolation_SquadOrientationInterpolator = (SquadOrientationInterpolator_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Interpolation.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/
















const Interpolation_default_ = {
   name: "Interpolation",
   concreteNodes:
   [
      Interpolation_ColorInterpolator,
      Interpolation_CoordinateInterpolator,
      Interpolation_CoordinateInterpolator2D,
      Interpolation_EaseInEaseOut,
      Interpolation_NormalInterpolator,
      Interpolation_OrientationInterpolator,
      Interpolation_PositionInterpolator,
      Interpolation_PositionInterpolator2D,
      Interpolation_ScalarInterpolator,
      Interpolation_SplinePositionInterpolator,
      Interpolation_SplinePositionInterpolator2D,
      Interpolation_SplineScalarInterpolator,
      Interpolation_SquadOrientationInterpolator,
   ],
   abstractNodes:
   [
      Interpolation_X3DInterpolatorNode,
   ],
};
;

x_ite_Namespace .add ("Interpolation", "x_ite/Components/Interpolation", Interpolation_default_);
/* harmony default export */ const Interpolation = (Interpolation_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Layering/X3DViewportNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function X3DViewportNode (executionContext)
{
   Grouping_X3DGroupingNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DViewportNode);
}

Object .setPrototypeOf (X3DViewportNode .prototype, Grouping_X3DGroupingNode .prototype);

Object .defineProperties (X3DViewportNode,
{
   typeName:
   {
      value: "X3DViewportNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Layering",
      enumerable: true,
   },
});

const X3DViewportNode_default_ = X3DViewportNode;
;

x_ite_Namespace .add ("X3DViewportNode", "x_ite/Components/Layering/X3DViewportNode", X3DViewportNode_default_);
/* harmony default export */ const Layering_X3DViewportNode = (X3DViewportNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Layering/Viewport.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/











const ViewVolumes = Utility_ObjectCache (Geometry_ViewVolume);

function Viewport (executionContext)
{
   Layering_X3DViewportNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Viewport);

   this .rectangle = new Numbers_Vector4 (0, 0, 0, 0);
}

Object .assign (Object .setPrototypeOf (Viewport .prototype, Layering_X3DViewportNode .prototype),
{
   getRectangle ()
   {
      const
         viewport = this .getBrowser () .getViewport (),
         left     = Math .floor (viewport [2] * this .getLeft ()),
         right    = Math .floor (viewport [2] * this .getRight ()),
         bottom   = Math .floor (viewport [3] * this .getBottom ()),
         top      = Math .floor (viewport [3] * this .getTop ());

      this .rectangle .set (left,
                            bottom,
                            Math .max (0, right - left),
                            Math .max (0, top - bottom));

      return this .rectangle;
   },
   getLeft ()
   {
      return this ._clipBoundary .length > 0 ? this ._clipBoundary [0] : 0;
   },
   getRight ()
   {
      return this ._clipBoundary .length > 1 ? this ._clipBoundary [1] : 1;
   },
   getBottom ()
   {
      return this ._clipBoundary .length > 2 ? this ._clipBoundary [2] : 0;
   },
   getTop ()
   {
      return this ._clipBoundary .length > 3 ? this ._clipBoundary [3] : 1;
   },
   traverse (type, renderObject)
   {
      this .push (renderObject);

      switch (type)
      {
         case Rendering_TraverseType .POINTER:
         {
            if (this .getBrowser () .isPointerInRectangle (this .rectangle))
               Layering_X3DViewportNode .prototype .traverse .call (this, type, renderObject);

            break;
         }
         default:
            Layering_X3DViewportNode .prototype .traverse .call (this, type, renderObject);
            break;
      }

      this .pop (renderObject);
   },
   push (renderObject)
   {
      const
         viewVolumes = renderObject .getViewVolumes (),
         rectangle   = this .getRectangle (),
         viewport    = viewVolumes .length ? viewVolumes .at (-1) .getViewport () : rectangle,
         viewVolume  = ViewVolumes .pop ();

      viewVolume .set (renderObject .getProjectionMatrix () .get (), viewport, rectangle);

      viewVolumes .push (viewVolume);
   },
   pop (renderObject)
   {
      ViewVolumes .push (renderObject .getViewVolumes () .pop ());
   },
});

Object .defineProperties (Viewport,
{
   typeName:
   {
      value: "Viewport",
      enumerable: true,
   },
   componentName:
   {
      value: "Layering",
      enumerable: true,
   },
   containerField:
   {
      value: "viewport",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",       new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "clipBoundary",   new x_ite_Fields .MFFloat (0, 1, 0, 1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "visible",        new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "bboxDisplay",    new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxSize",       new x_ite_Fields .SFVec3f (-1, -1, -1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxCenter",     new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "addChildren",    new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "removeChildren", new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "children",       new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const Viewport_default_ = Viewport;
;

x_ite_Namespace .add ("Viewport", "x_ite/Components/Layering/Viewport", Viewport_default_);
/* harmony default export */ const Layering_Viewport = (Viewport_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Layering.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







const Layering_default_ = {
   name: "Layering",
   concreteNodes:
   [
      Layering_Layer,
      Layering_LayerSet,
      Layering_Viewport,
   ],
   abstractNodes:
   [
      Layering_X3DLayerNode,
      Layering_X3DViewportNode,
   ],
};
;

x_ite_Namespace .add ("Layering", "x_ite/Components/Layering", Layering_default_);
/* harmony default export */ const Layering = (Layering_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Lighting/X3DLightNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






function X3DLightNode (executionContext)
{
   Core_X3DChildNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DLightNode);
}

Object .assign (Object .setPrototypeOf (X3DLightNode .prototype, Core_X3DChildNode .prototype),
{
   initialize ()
   {
      Core_X3DChildNode .prototype .initialize .call (this);

      this ._on        .addInterest ("set_on__", this);
      this ._intensity .addInterest ("set_on__", this);

      this .set_on__ ();
   },
   set_on__ ()
   {
      if (this ._on .getValue () && this .getIntensity () > 0)
      {
         delete this .push;
         delete this .pop;
      }
      else
      {
         this .push = Function .prototype;
         this .pop  = Function .prototype;
      }
   },
   getGlobal ()
   {
      return this ._global .getValue ();
   },
   getColor ()
   {
      return this ._color .getValue ();
   },
   getIntensity ()
   {
      return Math .max (this ._intensity .getValue (), 0);
   },
   getAmbientIntensity ()
   {
      return Math_Algorithm .clamp (this ._ambientIntensity .getValue (), 0, 1);
   },
   getDirection ()
   {
      return this ._direction .getValue ();
   },
   getShadows ()
   {
      return this ._shadows .getValue ();
   },
   getShadowColor ()
   {
      return this ._shadowColor .getValue ();
   },
   getShadowIntensity ()
   {
      return this .getShadows () ? Math_Algorithm .clamp (this ._shadowIntensity .getValue (), 0, 1) : 0;
   },
   getShadowBias ()
   {
      return Math_Algorithm .clamp (this ._shadowBias .getValue (), 0, 1);
   },
   getShadowMapSize ()
   {
      return Math .min (this ._shadowMapSize .getValue (), this .getBrowser () .getMaxTextureSize ());
   },
   getBiasMatrix: (() =>
   {
      // Transforms normalized coords from range (-1, 1) to (0, 1).
      const biasMatrix = new Numbers_Matrix4 (0.5, 0.0, 0.0, 0.0,
                                      0.0, 0.5, 0.0, 0.0,
                                      0.0, 0.0, 0.5, 0.0,
                                      0.5, 0.5, 0.5, 1.0);

      return function ()
      {
         return biasMatrix;
      };
   })(),
   push (renderObject, groupNode)
   {
      if (renderObject .isIndependent ())
      {
         const lightContainer = this .getLights () .pop ();

         if (this ._global .getValue ())
         {
            lightContainer .set (this,
                                 renderObject .getLayer () .getGroup (),
                                 renderObject .getModelViewMatrix () .get ());

            renderObject .getGlobalObjects () .push (lightContainer);
            renderObject .getLights ()        .push (lightContainer);

            renderObject .pushGlobalShadows (!! this .getShadowIntensity ());
         }
         else
         {
            lightContainer .set (this,
                                 groupNode,
                                 renderObject .getModelViewMatrix () .get ());

            renderObject .getLocalObjects () .push (lightContainer);
            renderObject .getLights ()       .push (lightContainer);

            renderObject .pushLocalShadows (!! this .getShadowIntensity ());

            ++ renderObject .getLocalObjectsCount () [1];
         }
      }
      else
      {
         const lightContainer = renderObject .getLightContainer ();

         lightContainer .modelViewMatrix .pushMatrix (renderObject .getModelViewMatrix () .get ());

         if (this ._global .getValue ())
         {
            renderObject .getGlobalObjects () .push (lightContainer);
            renderObject .getLights ()        .push (lightContainer);

            renderObject .pushGlobalShadows (!! this .getShadowIntensity ());
         }
         else
         {
            renderObject .getLocalObjects () .push (lightContainer);
            renderObject .getLights ()       .push (lightContainer);

            renderObject .pushLocalShadows (!! this .getShadowIntensity ());

            ++ renderObject .getLocalObjectsCount () [1];
         }
      }
   },
   pop (renderObject)
   {
      if (this ._global .getValue ())
         return;

      const lightContainer = renderObject .getLocalObjects () .pop ();

      if (renderObject .isIndependent ())
         this .getBrowser () .getLocalObjects () .push (lightContainer);

      renderObject .popLocalShadows ();

      -- renderObject .getLocalObjectsCount () [1];
   },
});

Object .defineProperties (X3DLightNode,
{
   typeName:
   {
      value: "X3DLightNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Lighting",
      enumerable: true,
   },
});

const X3DLightNode_default_ = X3DLightNode;
;

x_ite_Namespace .add ("X3DLightNode", "x_ite/Components/Lighting/X3DLightNode", X3DLightNode_default_);
/* harmony default export */ const Lighting_X3DLightNode = (X3DLightNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Lighting/DirectionalLight.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/


















const DirectionalLights = Utility_ObjectCache (DirectionalLightContainer);

function DirectionalLightContainer ()
{
   this .direction                     = new Numbers_Vector3 (0, 0, 0);
   this .shadowBuffer                  = null;
   this .bbox                          = new Geometry_Box3 ();
   this .viewVolume                    = new Geometry_ViewVolume ();
   this .viewport                      = new Numbers_Vector4 (0, 0, 0, 0);
   this .projectionMatrix              = new Numbers_Matrix4 ();
   this .modelViewMatrix               = new Utility_MatrixStack (Numbers_Matrix4);
   this .modelMatrix                   = new Numbers_Matrix4 ();
   this .invLightSpaceMatrix           = new Numbers_Matrix4 ();
   this .invLightSpaceProjectionMatrix = new Numbers_Matrix4 ();
   this .shadowMatrix                  = new Numbers_Matrix4 ();
   this .shadowMatrixArray             = new Float32Array (16);
   this .rotation                      = new Numbers_Rotation4 ();
   this .textureUnit                   = undefined;
}

Object .assign (DirectionalLightContainer .prototype,
{
   set (lightNode, groupNode, modelViewMatrix)
   {
      const shadowMapSize = lightNode .getShadowMapSize ();

      this .browser   = lightNode .getBrowser ();
      this .lightNode = lightNode;
      this .groupNode = groupNode;
      this .global    = lightNode .getGlobal ();

      this .modelViewMatrix .pushMatrix (modelViewMatrix);

      // Get shadow buffer from browser.

      if (lightNode .getShadowIntensity () > 0 && shadowMapSize > 0)
      {
         this .shadowBuffer = this .browser .popShadowBuffer (shadowMapSize);

         if (! this .shadowBuffer)
            console .warn ("Couldn't create shadow buffer.");
      }
   },
   renderShadowMap (renderObject)
   {
      if (! this .shadowBuffer)
         return;

      const
         lightNode            = this .lightNode,
         cameraSpaceMatrix    = renderObject .getCameraSpaceMatrix () .get (),
         modelMatrix          = this .modelMatrix .assign (this .modelViewMatrix .get ()) .multRight (cameraSpaceMatrix),
         invLightSpaceMatrix  = this .invLightSpaceMatrix .assign (this .global ? modelMatrix : Numbers_Matrix4 .Identity);

      invLightSpaceMatrix .rotate (this .rotation .setFromToVec (Numbers_Vector3 .zAxis, this .direction .assign (lightNode .getDirection ()) .negate ()));
      invLightSpaceMatrix .inverse ();

      const
         groupBBox        = this .groupNode .getSubBBox (this .bbox, true), // Group bbox.
         lightBBox        = groupBBox .multRight (invLightSpaceMatrix),     // Group bbox from the perspective of the light.
         shadowMapSize    = lightNode .getShadowMapSize (),
         viewport         = this .viewport .set (0, 0, shadowMapSize, shadowMapSize),
         projectionMatrix = Geometry_Camera .orthoBox (lightBBox, this .projectionMatrix);

      this .shadowBuffer .bind ();

      renderObject .getViewVolumes      () .push (this .viewVolume .set (projectionMatrix, viewport, viewport));
      renderObject .getProjectionMatrix () .pushMatrix (projectionMatrix);
      renderObject .getModelViewMatrix  () .pushMatrix (invLightSpaceMatrix);

      renderObject .render (Rendering_TraverseType .SHADOW, Grouping_X3DGroupingNode .prototype .traverse, this .groupNode);

      renderObject .getModelViewMatrix  () .pop ();
      renderObject .getProjectionMatrix () .pop ();
      renderObject .getViewVolumes      () .pop ();

      this .shadowBuffer .unbind ();

      if (!this .global)
         invLightSpaceMatrix .multLeft (modelMatrix .inverse ());

      this .invLightSpaceProjectionMatrix .assign (invLightSpaceMatrix) .multRight (projectionMatrix) .multRight (lightNode .getBiasMatrix ());
   },
   setGlobalVariables (renderObject)
   {
      this .modelViewMatrix .get () .multDirMatrix (this .direction .assign (this .lightNode .getDirection ())) .normalize ();

      if (! this .shadowBuffer)
         return;

      this .shadowMatrix .assign (renderObject .getCameraSpaceMatrix () .get ()) .multRight (this .invLightSpaceProjectionMatrix);
      this .shadowMatrixArray .set (this .shadowMatrix);
   },
   setShaderUniforms (gl, shaderObject)
   {
      const i = shaderObject .numLights ++;

      if (this .shadowBuffer)
      {
         const textureUnit = this .global
            ? (this .textureUnit = this .textureUnit ?? this .browser .popTexture2DUnit ())
            : this .browser .getTexture2DUnit ();

         if (textureUnit !== undefined)
         {
            gl .activeTexture (gl .TEXTURE0 + textureUnit);

            if (gl .HAS_FEATURE_DEPTH_TEXTURE)
               gl .bindTexture (gl .TEXTURE_2D, this .shadowBuffer .getDepthTexture ());
            else
               gl .bindTexture (gl .TEXTURE_2D, this .shadowBuffer .getColorTexture ());

            gl .uniform1i (shaderObject .x3d_ShadowMap [i], textureUnit);
         }
         else
         {
            console .warn ("Not enough combined texture units for shadow map available.");
         }
      }

      if (shaderObject .hasLight (i, this))
         return;

      const
         lightNode = this .lightNode,
         color     = lightNode .getColor (),
         direction = this .direction;

      gl .uniform1i (shaderObject .x3d_LightType [i],             1);
      gl .uniform3f (shaderObject .x3d_LightColor [i],            color .r, color .g, color .b);
      gl .uniform1f (shaderObject .x3d_LightIntensity [i],        lightNode .getIntensity ());
      gl .uniform1f (shaderObject .x3d_LightAmbientIntensity [i], lightNode .getAmbientIntensity ());
      gl .uniform3f (shaderObject .x3d_LightDirection [i],        direction .x, direction .y, direction .z);
      gl .uniform1f (shaderObject .x3d_LightRadius [i],           -1);

      if (this .shadowBuffer)
      {
         const shadowColor = lightNode .getShadowColor ();

         gl .uniform3f        (shaderObject .x3d_ShadowColor [i],         shadowColor .r, shadowColor .g, shadowColor .b);
         gl .uniform1f        (shaderObject .x3d_ShadowIntensity [i],     lightNode .getShadowIntensity ());
         gl .uniform1f        (shaderObject .x3d_ShadowBias [i],          lightNode .getShadowBias ());
         gl .uniformMatrix4fv (shaderObject .x3d_ShadowMatrix [i], false, this .shadowMatrixArray);
         gl .uniform1i        (shaderObject .x3d_ShadowMapSize [i],       lightNode .getShadowMapSize ());
      }
      else
      {
         gl .uniform1f (shaderObject .x3d_ShadowIntensity [i], 0);
      }
   },
   dispose ()
   {
      this .browser .pushShadowBuffer (this .shadowBuffer);
      this .browser .pushTexture2DUnit (this .textureUnit);

      this .modelViewMatrix .clear ();

      this .shadowBuffer = null;
      this .textureUnit  = undefined;

      // Return container

      DirectionalLights .push (this);
   },
});

function DirectionalLight (executionContext)
{
   Lighting_X3DLightNode .call (this, executionContext);

   this .addType (Base_X3DConstants .DirectionalLight);

   if (executionContext .getSpecificationVersion () == 2.0)
      this ._global = true;
}

Object .assign (Object .setPrototypeOf (DirectionalLight .prototype, Lighting_X3DLightNode .prototype),
{
   getLights ()
   {
      return DirectionalLights;
   },
});

Object .defineProperties (DirectionalLight,
{
   typeName:
   {
      value: "DirectionalLight",
      enumerable: true,
   },
   componentName:
   {
      value: "Lighting",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",         new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "global",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "on",               new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "color",            new x_ite_Fields .SFColor (1, 1, 1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "intensity",        new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "ambientIntensity", new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "direction",        new x_ite_Fields .SFVec3f (0, 0, -1)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "shadows",         new  x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "shadowColor",     new  x_ite_Fields .SFColor ()),        // Color of shadows.
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "shadowIntensity", new  x_ite_Fields .SFFloat (1)),       // Intensity of shadow color in the range (0, 1).
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "shadowBias",      new  x_ite_Fields .SFFloat (0.005)),   // Bias of the shadow.
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "shadowMapSize",   new  x_ite_Fields .SFInt32 (1024)),    // Size of the shadow map in pixels in the range (0, inf).
      ]),
      enumerable: true,
   },
});

const DirectionalLight_default_ = DirectionalLight;
;

x_ite_Namespace .add ("DirectionalLight", "x_ite/Components/Lighting/DirectionalLight", DirectionalLight_default_);
/* harmony default export */ const Lighting_DirectionalLight = (DirectionalLight_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Lighting/EnvironmentLight.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










const EnvironmentLights = Utility_ObjectCache (EnvironmentLightContainer);

function EnvironmentLightContainer ()
{
   this .modelViewMatrix = new Utility_MatrixStack (Numbers_Matrix4);
}

Object .assign (EnvironmentLightContainer .prototype,
{
   set (lightNode, groupNode, modelViewMatrix)
   {
   },
   getModelViewMatrix ()
   {
      return this .modelViewMatrix;
   },
   renderShadowMap (renderObject)
   {
   },
   setGlobalVariables (renderObject)
   {
   },
   setShaderUniforms (gl, shaderObject)
   {
   },
   dispose ()
   {
      // Return container

      EnvironmentLights .push (this);
   },
});

function EnvironmentLight (executionContext)
{
   Lighting_X3DLightNode .call (this, executionContext);

   this .addType (Base_X3DConstants .EnvironmentLight);
}

Object .assign (Object .setPrototypeOf (EnvironmentLight .prototype, Lighting_X3DLightNode .prototype),
{
   getLights ()
   {
      return EnvironmentLights;
   },
});

Object .defineProperties (EnvironmentLight,
{
   typeName:
   {
      value: "EnvironmentLight",
      enumerable: true,
   },
   componentName:
   {
      value: "Lighting",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",            new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "global",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "on",                  new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "rotation",            new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "color",               new x_ite_Fields .SFColor (1, 1, 1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "intensity",           new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "ambientIntensity",    new x_ite_Fields .SFFloat ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "diffuseCoefficients", new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "diffuse",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "diffuseTexture",      new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "specularTexture",     new x_ite_Fields .SFNode ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "shadows",             new  x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "shadowColor",         new  x_ite_Fields .SFColor ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "shadowIntensity",     new  x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "shadowBias",          new  x_ite_Fields .SFFloat (0.005)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "shadowMapSize",       new  x_ite_Fields .SFInt32 (1024)),
      ]),
      enumerable: true,
   },
});

const EnvironmentLight_default_ = EnvironmentLight;
;

x_ite_Namespace .add ("EnvironmentLight", "x_ite/Components/Lighting/EnvironmentLight", EnvironmentLight_default_);
/* harmony default export */ const Lighting_EnvironmentLight = (EnvironmentLight_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Lighting/PointLight.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



















// Shadow map layout
// Compact layout:
//
// xzXZ		Char: Axis
// yyYY		Case: Sign

const orientationMatrices = [
   new Numbers_Matrix4 () .setRotation (new Numbers_Rotation4 (new Numbers_Vector3 ( 1,  0,  0), Numbers_Vector3 .zAxis)), // left
   new Numbers_Matrix4 () .setRotation (new Numbers_Rotation4 (new Numbers_Vector3 (-1,  0,  0), Numbers_Vector3 .zAxis)), // right
   new Numbers_Matrix4 () .setRotation (new Numbers_Rotation4 (new Numbers_Vector3 ( 0,  0, -1), Numbers_Vector3 .zAxis)), // front
   new Numbers_Matrix4 () .setRotation (new Numbers_Rotation4 (new Numbers_Vector3 ( 0,  0,  1), Numbers_Vector3 .zAxis)), // back
   new Numbers_Matrix4 () .setRotation (new Numbers_Rotation4 (new Numbers_Vector3 ( 0,  1,  0), Numbers_Vector3 .zAxis)), // bottom
   new Numbers_Matrix4 () .setRotation (new Numbers_Rotation4 (new Numbers_Vector3 ( 0, -1,  0), Numbers_Vector3 .zAxis)), // top
];

const viewports = [
   new Numbers_Vector4 (0,    0.5, 0.25, 0.5), // left
   new Numbers_Vector4 (0.5,  0.5, 0.25, 0.5), // right
   new Numbers_Vector4 (0.75, 0.5, 0.25, 0.5), // front
   new Numbers_Vector4 (0.25, 0.5, 0.25, 0.5), // back
   new Numbers_Vector4 (0.0,  0,   0.5,  0.5), // bottom
   new Numbers_Vector4 (0.5,  0,   0.5,  0.5), // top
];

const PointLights = Utility_ObjectCache (PointLightContainer);

function PointLightContainer ()
{
   this .location                      = new Numbers_Vector3 (0, 0, 0);
   this .matrixArray                   = new Float32Array (9);
   this .shadowBuffer                  = null;
   this .viewVolume                    = new Geometry_ViewVolume ();
   this .viewport                      = new Numbers_Vector4 (0, 0, 0, 0);
   this .projectionMatrix              = new Numbers_Matrix4 ();
   this .modelViewMatrix               = new Utility_MatrixStack (Numbers_Matrix4);
   this .modelMatrix                   = new Numbers_Matrix4 ();
   this .invLightSpaceMatrix           = new Numbers_Matrix4 ();
   this .invLightSpaceProjectionMatrix = new Numbers_Matrix4 ();
   this .shadowMatrix                  = new Numbers_Matrix4 ();
   this .shadowMatrixArray             = new Float32Array (16);
   this .rotation                      = new Numbers_Rotation4 ();
   this .rotationMatrix                = new Numbers_Matrix4 ();
   this .textureUnit                   = undefined;
}

Object .assign (PointLightContainer .prototype,
{
   set (lightNode, groupNode, modelViewMatrix)
   {
      const shadowMapSize = lightNode .getShadowMapSize ();

      this .browser   = lightNode .getBrowser ();
      this .lightNode = lightNode;
      this .groupNode = groupNode;
      this .global    = lightNode .getGlobal ();

      this .matrixArray .set (modelViewMatrix .submatrix .inverse ());

      this .modelViewMatrix .pushMatrix (modelViewMatrix);

      // Get shadow buffer from browser.

      if (lightNode .getShadowIntensity () > 0 && shadowMapSize > 0)
      {
         this .shadowBuffer = this .browser .popShadowBuffer (shadowMapSize);

         if (!this .shadowBuffer)
            console .warn ("Couldn't create shadow buffer.");
      }
   },
   renderShadowMap (renderObject)
   {
      if (! this .shadowBuffer)
         return;

      const
         lightNode           = this .lightNode,
         cameraSpaceMatrix   = renderObject .getCameraSpaceMatrix () .get (),
         modelMatrix         = this .modelMatrix .assign (this .modelViewMatrix .get ()) .multRight (cameraSpaceMatrix),
         invLightSpaceMatrix = this .invLightSpaceMatrix .assign (this .global ? modelMatrix : Numbers_Matrix4 .Identity);

      invLightSpaceMatrix .translate (lightNode .getLocation ());
      invLightSpaceMatrix .inverse ();

      const shadowMapSize  = lightNode .getShadowMapSize ();

      this .shadowBuffer .bind ();

      for (let i = 0; i < 6; ++ i)
      {
         const
            v                = viewports [i],
            viewport         = this .viewport .set (v [0] * shadowMapSize, v [1] * shadowMapSize, v [2] * shadowMapSize, v [3] * shadowMapSize),
            projectionMatrix = Geometry_Camera .perspective2 (Math_Algorithm .radians (90), 0.125, 10000, viewport [2], viewport [3], this .projectionMatrix); // Use higher far value for better precision.

         renderObject .getViewVolumes      () .push (this .viewVolume .set (projectionMatrix, viewport, viewport));
         renderObject .getProjectionMatrix () .pushMatrix (this .projectionMatrix);
         renderObject .getModelViewMatrix  () .pushMatrix (orientationMatrices [i]);
         renderObject .getModelViewMatrix  () .multLeft (invLightSpaceMatrix);

         renderObject .render (Rendering_TraverseType .SHADOW, Grouping_X3DGroupingNode .prototype .traverse, this .groupNode);

         renderObject .getModelViewMatrix  () .pop ();
         renderObject .getProjectionMatrix () .pop ();
         renderObject .getViewVolumes () .pop ();
      }

      this .shadowBuffer .unbind ();

      if (!this .global)
         invLightSpaceMatrix .multLeft (modelMatrix .inverse ());

      this .invLightSpaceProjectionMatrix .assign (invLightSpaceMatrix);
   },
   setGlobalVariables (renderObject)
   {
      this .modelViewMatrix .get () .multVecMatrix (this .location .assign (this .lightNode ._location .getValue ()));

      if (! this .shadowBuffer)
         return;

      this .shadowMatrix .assign (renderObject .getCameraSpaceMatrix () .get ()) .multRight (this .invLightSpaceProjectionMatrix);
      this .shadowMatrixArray .set (this .shadowMatrix);
   },
   setShaderUniforms (gl, shaderObject)
   {
      const i = shaderObject .numLights ++;

      if (this .shadowBuffer)
      {
         const textureUnit = this .global
            ? (this .textureUnit = this .textureUnit ?? this .browser .popTexture2DUnit ())
            : this .browser .getTexture2DUnit ();

         if (textureUnit !== undefined)
         {
            gl .activeTexture (gl .TEXTURE0 + textureUnit);

            if (gl .HAS_FEATURE_DEPTH_TEXTURE)
               gl .bindTexture (gl .TEXTURE_2D, this .shadowBuffer .getDepthTexture ());
            else
               gl .bindTexture (gl .TEXTURE_2D, this .shadowBuffer .getColorTexture ());

            gl .uniform1i (shaderObject .x3d_ShadowMap [i], textureUnit);
         }
         else
         {
            console .warn ("Not enough combined texture units for shadow map available.");
         }
      }

      if (shaderObject .hasLight (i, this))
         return;

      const
         lightNode   = this .lightNode,
         color       = lightNode .getColor (),
         attenuation = lightNode .getAttenuation (),
         location    = this .location;

      gl .uniform1i        (shaderObject .x3d_LightType [i],             2);
      gl .uniform3f        (shaderObject .x3d_LightColor [i],            color .r, color .g, color .b);
      gl .uniform1f        (shaderObject .x3d_LightIntensity [i],        lightNode .getIntensity ());
      gl .uniform1f        (shaderObject .x3d_LightAmbientIntensity [i], lightNode .getAmbientIntensity ());
      gl .uniform3f        (shaderObject .x3d_LightAttenuation [i],      Math .max (0, attenuation .x), Math .max (0, attenuation .y), Math .max (0, attenuation .z));
      gl .uniform3f        (shaderObject .x3d_LightLocation [i],         location .x, location .y, location .z);
      gl .uniform1f        (shaderObject .x3d_LightRadius [i],           lightNode .getRadius ());
      gl .uniformMatrix3fv (shaderObject .x3d_LightMatrix [i], false,    this .matrixArray);

      if (this .shadowBuffer)
      {
         const shadowColor = lightNode .getShadowColor ();

         gl .uniform3f        (shaderObject .x3d_ShadowColor [i],         shadowColor .r, shadowColor .g, shadowColor .b);
         gl .uniform1f        (shaderObject .x3d_ShadowIntensity [i],     lightNode .getShadowIntensity ());
         gl .uniform1f        (shaderObject .x3d_ShadowBias [i],          lightNode .getShadowBias ());
         gl .uniformMatrix4fv (shaderObject .x3d_ShadowMatrix [i], false, this .shadowMatrixArray);
         gl .uniform1i        (shaderObject .x3d_ShadowMapSize [i],       lightNode .getShadowMapSize ());
      }
      else
      {
         gl .uniform1f (shaderObject .x3d_ShadowIntensity [i], 0);
      }
   },
   dispose ()
   {
      this .browser .pushShadowBuffer (this .shadowBuffer);
      this .browser .pushTexture2DUnit (this .textureUnit);

      this .modelViewMatrix .clear ();

      this .shadowBuffer = null;
      this .textureUnit  = undefined;

      // Return container

      PointLights .push (this);
   },
});

function PointLight (executionContext)
{
   Lighting_X3DLightNode .call (this, executionContext);

   this .addType (Base_X3DConstants .PointLight);

   this ._location .setUnit ("length");
   this ._radius   .setUnit ("length");
}

Object .assign (Object .setPrototypeOf (PointLight .prototype, Lighting_X3DLightNode .prototype),
{
   getAttenuation ()
   {
      return this ._attenuation .getValue ();
   },
   getLocation ()
   {
      return this ._location .getValue ();
   },
   getRadius ()
   {
      // Negative values mean infinity.
      return this ._radius .getValue ();
   },
   getLights ()
   {
      return PointLights;
   },
});

Object .defineProperties (PointLight,
{
   typeName:
   {
      value: "PointLight",
      enumerable: true,
   },
   componentName:
   {
      value: "Lighting",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",         new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "global",           new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "on",               new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "color",            new x_ite_Fields .SFColor (1, 1, 1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "intensity",        new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "ambientIntensity", new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "attenuation",      new x_ite_Fields .SFVec3f (1, 0, 0)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "location",         new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "radius",           new x_ite_Fields .SFFloat (100)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "shadows",         new  x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "shadowColor",     new  x_ite_Fields .SFColor ()),        // Color of shadows.
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "shadowIntensity", new  x_ite_Fields .SFFloat (1)),        // Intensity of shadow color in the range (0, 1).
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "shadowBias",      new  x_ite_Fields .SFFloat (0.005)),   // Bias of the shadow.
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "shadowMapSize",   new  x_ite_Fields .SFInt32 (1024)),    // Size of the shadow map in pixels in the range (0, inf).
      ]),
      enumerable: true,
   },
});

const PointLight_default_ = PointLight;
;

x_ite_Namespace .add ("PointLight", "x_ite/Components/Lighting/PointLight", PointLight_default_);
/* harmony default export */ const Lighting_PointLight = (PointLight_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Lighting/SpotLight.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




















const SpotLights = Utility_ObjectCache (SpotLightContainer);

function SpotLightContainer ()
{
   this .location                      = new Numbers_Vector3 (0, 0, 0);
   this .direction                     = new Numbers_Vector3 (0, 0, 0);
   this .matrixArray                   = new Float32Array (9);
   this .renderShadow                  = true;
   this .shadowBuffer                  = null;
   this .bbox                          = new Geometry_Box3 ();
   this .viewVolume                    = new Geometry_ViewVolume ();
   this .viewport                      = new Numbers_Vector4 (0, 0, 0, 0);
   this .projectionMatrix              = new Numbers_Matrix4 ();
   this .modelViewMatrix               = new Utility_MatrixStack (Numbers_Matrix4);
   this .modelMatrix                   = new Numbers_Matrix4 ();
   this .invLightSpaceMatrix           = new Numbers_Matrix4 ();
   this .invLightSpaceProjectionMatrix = new Numbers_Matrix4 ();
   this .shadowMatrix                  = new Numbers_Matrix4 ();
   this .shadowMatrixArray             = new Float32Array (16);
   this .rotation                      = new Numbers_Rotation4 ();
   this .lightBBoxMin                  = new Numbers_Vector3 (0, 0, 0);
   this .lightBBoxMax                  = new Numbers_Vector3 (0, 0, 0);
   this .textureUnit                   = undefined;
}

Object .assign (SpotLightContainer .prototype,
{
   set (lightNode, groupNode, modelViewMatrix)
   {
      const shadowMapSize = lightNode .getShadowMapSize ();

      this .browser   = lightNode .getBrowser ();
      this .lightNode = lightNode;
      this .groupNode = groupNode;
      this .global    = lightNode .getGlobal ();

      this .matrixArray .set (modelViewMatrix .submatrix .inverse ());

      this .modelViewMatrix .pushMatrix (modelViewMatrix);

      // Get shadow buffer from browser.

      if (lightNode .getShadowIntensity () > 0 && shadowMapSize > 0)
      {
         this .shadowBuffer = this .browser .popShadowBuffer (shadowMapSize);

         if (!this .shadowBuffer)
            console .warn ("Couldn't create shadow buffer.");
      }
   },
   renderShadowMap (renderObject)
   {
      if (! this .shadowBuffer)
         return;

      const
         lightNode            = this .lightNode,
         cameraSpaceMatrix    = renderObject .getCameraSpaceMatrix () .get (),
         modelMatrix          = this .modelMatrix .assign (this .modelViewMatrix .get ()) .multRight (cameraSpaceMatrix),
         invLightSpaceMatrix  = this .invLightSpaceMatrix .assign (this .global ? modelMatrix : Numbers_Matrix4 .Identity);

      invLightSpaceMatrix .translate (lightNode .getLocation ());
      invLightSpaceMatrix .rotate (this .rotation .setFromToVec (Numbers_Vector3 .zAxis, this .direction .assign (lightNode .getDirection ()) .negate ()));
      invLightSpaceMatrix .inverse ();

      const
         groupBBox        = this .groupNode .getSubBBox (this .bbox, true),                 // Group bbox.
         lightBBox        = groupBBox .multRight (invLightSpaceMatrix),                     // Group bbox from the perspective of the light.
         lightBBoxExtents = lightBBox .getExtents (this .lightBBoxMin, this .lightBBoxMax), // Result not used, but arguments.
         shadowMapSize    = lightNode .getShadowMapSize (),
         farValue         = Math .min (lightNode .getRadius (), -this .lightBBoxMin .z),
         viewport         = this .viewport .set (0, 0, shadowMapSize, shadowMapSize),
         projectionMatrix = Geometry_Camera .perspective (lightNode .getCutOffAngle () * 2, 0.125, Math .max (10000, farValue), shadowMapSize, shadowMapSize, this .projectionMatrix); // Use higher far value for better precision.

      this .renderShadow = farValue > 0;

      this .shadowBuffer .bind ();

      renderObject .getViewVolumes      () .push (this .viewVolume .set (projectionMatrix, viewport, viewport));
      renderObject .getProjectionMatrix () .pushMatrix (projectionMatrix);
      renderObject .getModelViewMatrix  () .pushMatrix (invLightSpaceMatrix);

      renderObject .render (Rendering_TraverseType .SHADOW, Grouping_X3DGroupingNode .prototype .traverse, this .groupNode);

      renderObject .getModelViewMatrix  () .pop ();
      renderObject .getProjectionMatrix () .pop ();
      renderObject .getViewVolumes      () .pop ();

      this .shadowBuffer .unbind ();

      if (!this .global)
         invLightSpaceMatrix .multLeft (modelMatrix .inverse ());

      this .invLightSpaceProjectionMatrix .assign (invLightSpaceMatrix) .multRight (projectionMatrix) .multRight (lightNode .getBiasMatrix ());
   },
   setGlobalVariables (renderObject)
   {
      const
         lightNode       = this .lightNode,
         modelViewMatrix = this .modelViewMatrix .get ();

      modelViewMatrix .multVecMatrix (this .location  .assign (lightNode ._location  .getValue ()));
      modelViewMatrix .multDirMatrix (this .direction .assign (lightNode ._direction .getValue ())) .normalize ();

      if (! this .shadowBuffer)
         return;

      this .shadowMatrix .assign (renderObject .getCameraSpaceMatrix () .get ()) .multRight (this .invLightSpaceProjectionMatrix);
      this .shadowMatrixArray .set (this .shadowMatrix);
   },
   setShaderUniforms (gl, shaderObject)
   {
      const i = shaderObject .numLights ++;

      if (this .shadowBuffer)
      {
         const textureUnit = this .global
            ? (this .textureUnit = this .textureUnit ?? this .browser .popTexture2DUnit ())
            : this .browser .getTexture2DUnit ();

         if (textureUnit !== undefined)
         {
            gl .activeTexture (gl .TEXTURE0 + textureUnit);

            if (gl .HAS_FEATURE_DEPTH_TEXTURE)
               gl .bindTexture (gl .TEXTURE_2D, this .shadowBuffer .getDepthTexture ());
            else
               gl .bindTexture (gl .TEXTURE_2D, this .shadowBuffer .getColorTexture ());

            gl .uniform1i (shaderObject .x3d_ShadowMap [i], textureUnit);
         }
         else
         {
            console .warn ("Not enough combined texture units for shadow map available.");
         }
      }

      if (shaderObject .hasLight (i, this))
         return;

      const
         lightNode   = this .lightNode,
         color       = lightNode .getColor (),
         attenuation = lightNode .getAttenuation (),
         location    = this .location,
         direction   = this .direction;

      gl .uniform1i        (shaderObject .x3d_LightType [i],             3);
      gl .uniform3f        (shaderObject .x3d_LightColor [i],            color .r, color .g, color .b);
      gl .uniform1f        (shaderObject .x3d_LightIntensity [i],        lightNode .getIntensity ());
      gl .uniform1f        (shaderObject .x3d_LightAmbientIntensity [i], lightNode .getAmbientIntensity ());
      gl .uniform3f        (shaderObject .x3d_LightAttenuation [i],      Math .max (0, attenuation .x), Math .max (0, attenuation .y), Math .max (0, attenuation .z));
      gl .uniform3f        (shaderObject .x3d_LightLocation [i],         location .x, location .y, location .z);
      gl .uniform3f        (shaderObject .x3d_LightDirection [i],        direction .x, direction .y, direction .z);
      gl .uniform1f        (shaderObject .x3d_LightRadius [i],           lightNode .getRadius ());
      gl .uniform1f        (shaderObject .x3d_LightBeamWidth [i],        lightNode .getBeamWidth ());
      gl .uniform1f        (shaderObject .x3d_LightCutOffAngle [i],      lightNode .getCutOffAngle ());
      gl .uniformMatrix3fv (shaderObject .x3d_LightMatrix [i], false,    this .matrixArray);

      if (this .renderShadow && this .shadowBuffer)
      {
         const shadowColor = lightNode .getShadowColor ();

         gl .uniform3f        (shaderObject .x3d_ShadowColor [i],         shadowColor .r, shadowColor .g, shadowColor .b);
         gl .uniform1f        (shaderObject .x3d_ShadowIntensity [i],     lightNode .getShadowIntensity ());
         gl .uniform1f        (shaderObject .x3d_ShadowBias [i],          lightNode .getShadowBias ());
         gl .uniformMatrix4fv (shaderObject .x3d_ShadowMatrix [i], false, this .shadowMatrixArray);
         gl .uniform1i        (shaderObject .x3d_ShadowMapSize [i],       lightNode .getShadowMapSize ());
      }
      else
      {
         gl .uniform1f (shaderObject .x3d_ShadowIntensity [i], 0);
      }
   },
   dispose ()
   {
      this .browser .pushShadowBuffer (this .shadowBuffer);
      this .browser .pushTexture2DUnit (this .textureUnit);

      this .modelViewMatrix .clear ();

      this .shadowBuffer = null;
      this .textureUnit  = undefined;

      // Return container

      SpotLights .push (this);
   },
});

function SpotLight (executionContext)
{
   Lighting_X3DLightNode .call (this, executionContext);

   this .addType (Base_X3DConstants .SpotLight);

   if (executionContext .getSpecificationVersion () <= 3.2)
   {
      this ._beamWidth   = 1.5708;
      this ._cutOffAngle = 0.785398;
   }

   this ._location    .setUnit ("length");
   this ._radius      .setUnit ("length");
   this ._beamWidth   .setUnit ("angle");
   this ._cutOffAngle .setUnit ("angle");
}

Object .assign (Object .setPrototypeOf (SpotLight .prototype, Lighting_X3DLightNode .prototype),
{
   getAttenuation ()
   {
      return this ._attenuation .getValue ();
   },
   getLocation ()
   {
      return this ._location .getValue ();
   },
   getRadius ()
   {
      // Negative values mean infinity.
      return this ._radius .getValue ();
   },
   getBeamWidth ()
   {
      // If the beamWidth is greater than the cutOffAngle, beamWidth is defined to be equal to the cutOffAngle.

      const
         beamWidth   = this ._beamWidth .getValue (),
         cutOffAngle = this .getCutOffAngle ();

      if (beamWidth > cutOffAngle)
         return cutOffAngle;

      return Math_Algorithm .clamp (beamWidth, 0, Math .PI / 2);
   },
   getCutOffAngle ()
   {
      return Math_Algorithm .clamp (this ._cutOffAngle .getValue (), 0, Math .PI / 2);
   },
   getLights ()
   {
      return SpotLights;
   },
});

Object .defineProperties (SpotLight,
{
   typeName:
   {
      value: "SpotLight",
      enumerable: true,
   },
   componentName:
   {
      value: "Lighting",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",         new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "global",           new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "on",               new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "color",            new x_ite_Fields .SFColor (1, 1, 1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "intensity",        new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "ambientIntensity", new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "attenuation",      new x_ite_Fields .SFVec3f (1, 0, 0)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "location",         new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "direction",        new x_ite_Fields .SFVec3f (0, 0, -1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "radius",           new x_ite_Fields .SFFloat (100)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "beamWidth",        new x_ite_Fields .SFFloat (0.785398)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "cutOffAngle",      new x_ite_Fields .SFFloat (1.5708)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "shadows",         new  x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "shadowColor",     new  x_ite_Fields .SFColor ()),        // Color of shadows.
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "shadowIntensity", new  x_ite_Fields .SFFloat (1)),       // Intensity of shadow color in the range (0, 1).
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "shadowBias",      new  x_ite_Fields .SFFloat (0.005)),   // Bias of the shadow.
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "shadowMapSize",   new  x_ite_Fields .SFInt32 (1024)),    // Size of the shadow map in pixels in the range (0, inf).
      ]),
      enumerable: true,
   },
});

const SpotLight_default_ = SpotLight;
;

x_ite_Namespace .add ("SpotLight", "x_ite/Components/Lighting/SpotLight", SpotLight_default_);
/* harmony default export */ const Lighting_SpotLight = (SpotLight_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Lighting.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







const Lighting_default_ = {
   name: "Lighting",
   concreteNodes:
   [
      Lighting_DirectionalLight,
      Lighting_EnvironmentLight,
      Lighting_PointLight,
      Lighting_SpotLight,
   ],
   abstractNodes:
   [
      Lighting_X3DLightNode,
   ],
};
;

x_ite_Namespace .add ("Lighting", "x_ite/Components/Lighting", Lighting_default_);
/* harmony default export */ const Lighting = (Lighting_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Navigation/Billboard.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/











function Billboard (executionContext)
{
   Grouping_X3DGroupingNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Billboard);

   this .matrix = new Numbers_Matrix4 ();
}

Object .assign (Object .setPrototypeOf (Billboard .prototype, Grouping_X3DGroupingNode .prototype),
{
   getBBox (bbox, shadows)
   {
      return Grouping_X3DGroupingNode .prototype .getBBox .call (this, bbox, shadows) .multRight (this .matrix);
   },
   getMatrix ()
   {
      return this .matrix;
   },
   rotate: (() =>
   {
      const
         inverseModelViewMatrix = new Numbers_Matrix4 (),
         viewerYAxis            = new Numbers_Vector3 (0, 0, 0),
         y                      = new Numbers_Vector3 (0, 0, 0),
         N1                     = new Numbers_Vector3 (0, 0, 0),
         N2                     = new Numbers_Vector3 (0, 0, 0),
         rotation               = new Numbers_Rotation4 ();

      return function (modelViewMatrix)
      {
         // throws domain error

         inverseModelViewMatrix .assign (modelViewMatrix) .inverse ();

         const billboardToViewer = inverseModelViewMatrix .origin .normalize (); // Normalized to get work with Geo

         if (this ._axisOfRotation .getValue () .equals (Numbers_Vector3 .Zero))
         {
            inverseModelViewMatrix .multDirMatrix (viewerYAxis .assign (Numbers_Vector3 .yAxis)) .normalize (); // Normalized to get work with Geo

            const x = viewerYAxis .cross (billboardToViewer);
            y .assign (billboardToViewer) .cross (x);
            const z = billboardToViewer;

            // Compose rotation

            x .normalize ();
            y .normalize ();

            this .matrix .set (x .x, x .y, x .z, 0,
                               y .x, y .y, y .z, 0,
                               z .x, z .y, z .z, 0,
                               0,    0,    0,    1);
         }
         else
         {
            N1 .assign (this ._axisOfRotation .getValue ()) .cross (billboardToViewer); // Normal vector of plane as in specification
            N2 .assign (this ._axisOfRotation .getValue ()) .cross (Numbers_Vector3 .zAxis);    // Normal vector of plane between axisOfRotation and zAxis

            this .matrix .setRotation (rotation .setFromToVec (N2, N1));                // Rotate zAxis in plane
         }

         return this .matrix;
      };
   })(),
   traverse (type, renderObject)
   {
      const modelViewMatrix = renderObject .getModelViewMatrix ();

      modelViewMatrix .push ();

      switch (type)
      {
         case Rendering_TraverseType .CAMERA:
         case Rendering_TraverseType .PICKING:
         case Rendering_TraverseType .SHADOW:
            // No clone support for shadows, generated cube map texture, and bbox
            modelViewMatrix .multLeft (this .matrix);
            break;
         default:
            modelViewMatrix .multLeft (this .rotate (modelViewMatrix .get ()));
            break;
      }

      Grouping_X3DGroupingNode .prototype .traverse .call (this, type, renderObject);

      modelViewMatrix .pop ();
   },
});

Object .defineProperties (Billboard,
{
   typeName:
   {
      value: "Billboard",
      enumerable: true,
   },
   componentName:
   {
      value: "Navigation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",       new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "axisOfRotation", new x_ite_Fields .SFVec3f (0, 1, 0)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "visible",        new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "bboxDisplay",    new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxSize",       new x_ite_Fields .SFVec3f (-1, -1, -1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxCenter",     new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "addChildren",    new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "removeChildren", new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "children",       new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const Billboard_default_ = Billboard;
;

x_ite_Namespace .add ("Billboard", "x_ite/Components/Navigation/Billboard", Billboard_default_);
/* harmony default export */ const Navigation_Billboard = (Billboard_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Navigation/Collision.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










function Collision (executionContext)
{
   Grouping_X3DGroupingNode .call (this, executionContext);
   Core_X3DSensorNode   .call (this, executionContext);

   this .addType (Base_X3DConstants .Collision);

   if (executionContext .getSpecificationVersion () == 2.0)
      this .addAlias ("collide", this ._enabled); // VRML2
}

Object .assign (Object .setPrototypeOf (Collision .prototype, Grouping_X3DGroupingNode .prototype),
   Core_X3DSensorNode .prototype,
{
   initialize ()
   {
      Grouping_X3DGroupingNode .prototype .initialize .call (this);
      // X3DSensorNode .prototype .initialize .call (this); // We can only call the base of a *Objects.

      this .getLive () .addInterest ("set_live__", this);
      this ._enabled  .addInterest ("set_live__", this);
      this ._proxy    .addInterest ("set_proxy__", this);

      this .set_live__ ();
      this .set_proxy__ ();
   },
   set_live__ ()
   {
      if (this .getLive () .getValue () && this ._enabled .getValue ())
         this .getBrowser () .addCollision (this);

      else
         this .getBrowser () .removeCollision (this);
   },
   set_active (value)
   {
      if (this ._isActive .getValue () !== value)
      {
         this ._isActive = value;

         if (value)
            this ._collideTime = this .getBrowser () .getCurrentTime ();
      }
   },
   set_proxy__ ()
   {
      this .proxyNode = Base_X3DCast (Base_X3DConstants .X3DChildNode, this ._proxy);
   },
   traverse (type, renderObject)
   {
      switch (type)
      {
         case Rendering_TraverseType .COLLISION:
         {
            if (this ._enabled .getValue ())
            {
               const collisions = renderObject .getCollisions ();

               collisions .push (this);

               if (this .proxyNode)
                  this .proxyNode .traverse (type, renderObject);

               else
                  Grouping_X3DGroupingNode .prototype .traverse .call (this, type, renderObject);

               collisions .pop ();
            }

            return;
         }
         default:
         {
            Grouping_X3DGroupingNode .prototype .traverse .call (this, type, renderObject);
            return;
         }
      }
   },
   dispose ()
   {
      // X3DSensorNode .prototype .dispose .call (this); // We can only call the base of a *Objects.
      Grouping_X3DGroupingNode .prototype .dispose .call (this);
   },
});

Object .defineProperties (Collision,
{
   typeName:
   {
      value: "Collision",
      enumerable: true,
   },
   componentName:
   {
      value: "Navigation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",       new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "enabled",        new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isActive",       new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "collideTime",    new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "visible",        new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "bboxDisplay",    new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxSize",       new x_ite_Fields .SFVec3f (-1, -1, -1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxCenter",     new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "proxy",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "addChildren",    new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "removeChildren", new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "children",       new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const Collision_default_ = Collision;
;

x_ite_Namespace .add ("Collision", "x_ite/Components/Navigation/Collision", Collision_default_);
/* harmony default export */ const Navigation_Collision = (Collision_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Navigation/LOD.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/











function LOD (executionContext)
{
   Grouping_X3DGroupingNode .call (this, executionContext);

   this .addType (Base_X3DConstants .LOD);

   if (executionContext .getSpecificationVersion () == 2.0)
      this .addAlias ("level", this ._children); // VRML2

   this ._center .setUnit ("length");
   this ._range  .setUnit ("length");

   this .frameRate        = 60;
   this .keepCurrentLevel = false;
   this .childNode        = null;
   this .visibleNode      = null;
   this .boundedObject    = null;
}

Object .assign (Object .setPrototypeOf (LOD .prototype, Grouping_X3DGroupingNode .prototype),
{
   initialize ()
   {
      Grouping_X3DGroupingNode .prototype .initialize .call (this);

      this ._children .addInterest ("set_child__", this);
   },
   getSubBBox (bbox, shadows)
   {
      if (this ._bboxSize .getValue () .equals (this .getDefaultBBoxSize ()))
      {
         const boundedObject = Base_X3DCast (Base_X3DConstants .X3DBoundedObject, this .visibleNode);

         return boundedObject ?.getBBox (bbox, shadows) ?? bbox .set ();
      }

      return bbox .set (this ._bboxSize .getValue (), this ._bboxCenter .getValue ());
   },
   clear () { },
   add () { },
   remove () { },
   set_child__ ()
   {
      this .set_level__ (Math .min (this ._level_changed .getValue (), this ._children .length - 1));
   },
   set_level__ (level)
   {
      if (this .childNode)
      {
         this .childNode ._isCameraObject   .removeInterest ("set_cameraObject__",     this);
         this .childNode ._isPickableObject .removeInterest ("set_transformSensors__", this);
      }

      if (Base_X3DCast (Base_X3DConstants .X3DBoundedObject, this .childNode))
      {
         this .childNode ._display     .removeInterest ("set_display__",     this);
         this .childNode ._bboxDisplay .removeInterest ("set_bboxDisplay__", this);
      }

      if (level >= 0 && level < this ._children .length)
      {
         this .childNode = Base_X3DCast (Base_X3DConstants .X3DChildNode, this ._children [level]);

         if (this .childNode)
         {
            this .childNode ._isCameraObject   .addInterest ("set_cameraObject__",     this);
            this .childNode ._isPickableObject .addInterest ("set_transformSensors__", this);

            if (Base_X3DCast (Base_X3DConstants .X3DBoundedObject, this .childNode))
            {
               this .childNode ._display     .addInterest ("set_display__",     this);
               this .childNode ._bboxDisplay .addInterest ("set_bboxDisplay__", this);
            }

            //delete this .traverse;
         }
      }
      else
      {
         this .childNode = null;

         //this .traverse = Function .prototype; // Don't do that.
      }

      this .set_display__ ();
      this .set_bboxDisplay__ ();
   },
   set_cameraObject__ ()
   {
      this .setCameraObject (!!this .visibleNode ?.isCameraObject ());
   },
   set_transformSensors__ ()
   {
      this .setPickableObject (!!(this .getTransformSensors () .size || this .visibleNode ?.isPickableObject ()));
   },
   set_display__ ()
   {
      if (Base_X3DCast (Base_X3DConstants .X3DBoundedObject, this .childNode))
         this .visibleNode = this .childNode ._display .getValue () ? this .childNode : null;
      else
         this .visibleNode = this .childNode;

      this .set_cameraObject__ ();
      this .set_transformSensors__ ();
   },
   set_bboxDisplay__ ()
   {
      if (Base_X3DCast (Base_X3DConstants .X3DBoundedObject, this .childNode))
      {
         this .boundedObject = this .childNode ._bboxDisplay .getValue () ? this .childNode : null;
      }
      else
      {
         this .boundedObject = null;
      }
   },
   getLevel: (() =>
   {
      const
         FRAMES         = 180, // Number of frames after wich a level change takes in affect.
         FRAME_RATE_MIN = 20,  // Lowest level of detail.
         FRAME_RATE_MAX = 55;  // Highest level of detail.

      return function (browser, modelViewMatrix)
      {
         if (this ._range .length === 0)
         {
            this .frameRate = ((FRAMES - 1) * this .frameRate + browser .currentFrameRate) / FRAMES;

            const size = this ._children .length;

            switch (size)
            {
               case 0:
                  return -1;
               case 1:
                  return 0;
               case 2:
                  return +(this .frameRate > FRAME_RATE_MAX);
               default:
               {
                  const fraction = 1 - Math_Algorithm .clamp ((this .frameRate - FRAME_RATE_MIN) / (FRAME_RATE_MAX - FRAME_RATE_MIN), 0, 1);

                  return Math .min (Math .floor (fraction * size), size - 1);
               }
            }
         }

         const distance = modelViewMatrix .translate (this ._center .getValue ()) .origin .magnitude ();

         return Math_Algorithm .upperBound (this ._range, 0, this ._range .length, distance);
      };
   })(),
   traverse: (() =>
   {
      const modelViewMatrix = new Numbers_Matrix4 ();

      return function (type, renderObject)
      {
         switch (type)
         {
            case Rendering_TraverseType .POINTER:
            case Rendering_TraverseType .CAMERA:
            case Rendering_TraverseType .SHADOW:
            {
               this .visibleNode ?.traverse (type, renderObject);
               return;
            }
            case Rendering_TraverseType .PICKING:
            {
               if (this .getTransformSensors () .size)
               {
                  const modelMatrix = renderObject .getModelViewMatrix () .get ();

                  for (const transformSensorNode of this .getTransformSensors ())
                     transformSensorNode .collect (modelMatrix);
               }

               const visibleNode = this .visibleNode;

               if (visibleNode)
               {
                  const
                     browser          = this .getBrowser (),
                     pickingHierarchy = browser .getPickingHierarchy ();

                  pickingHierarchy .push (this);

                  visibleNode .traverse (type, renderObject);

                  pickingHierarchy .pop ();
               }

               return;
            }
            case Rendering_TraverseType .COLLISION:
            {
               this .visibleNode ?.traverse (type, renderObject);
               return;
            }
            case Rendering_TraverseType .DISPLAY:
            {
               if (! this .keepCurrentLevel)
               {
                  let
                     level        = this .getLevel (this .getBrowser (), modelViewMatrix .assign (renderObject .getModelViewMatrix () .get ())),
                     currentLevel = this ._level_changed .getValue ();

                  if (this ._forceTransitions .getValue ())
                  {
                     if (level > currentLevel)
                        level = currentLevel + 1;

                     else if (level < currentLevel)
                        level = currentLevel - 1;
                  }

                  if (level !== currentLevel)
                  {
                     this ._level_changed = level;

                     this .set_level__ (Math .min (level, this ._children .length - 1));
                  }
               }

               this .visibleNode ?.traverse (type, renderObject);

               this .boundedObject ?.displayBBox (type, renderObject);
               return;
            }
         }
      };
   })(),
});

Object .defineProperties (LOD,
{
   typeName:
   {
      value: "LOD",
      enumerable: true,
   },
   componentName:
   {
      value: "Navigation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",         new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "forceTransitions", new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "center",           new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "range",            new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "level_changed",    new x_ite_Fields .SFInt32 (-1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "visible",          new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "bboxDisplay",      new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxSize",         new x_ite_Fields .SFVec3f (-1, -1, -1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxCenter",       new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "addChildren",      new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "removeChildren",   new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "children",         new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const LOD_default_ = LOD;
;

x_ite_Namespace .add ("LOD", "x_ite/Components/Navigation/LOD", LOD_default_);
/* harmony default export */ const Navigation_LOD = (LOD_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Navigation/OrthoViewpoint.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/











function OrthoViewpoint (executionContext)
{
   Navigation_X3DViewpointNode .call (this, executionContext);

   this .addType (Base_X3DConstants .OrthoViewpoint);

   this .addChildObjects (Base_X3DConstants .inputOutput, "fieldOfViewOffset", new x_ite_Fields .MFFloat (0, 0, 0, 0));

   this ._position         .setUnit ("length");
   this ._centerOfRotation .setUnit ("length");
   this ._fieldOfView      .setUnit ("length");

   this .projectionMatrix               = new Numbers_Matrix4 ();
   this .fieldOfViewOffsetInterpolator0 = new Interpolation_ScalarInterpolator (this .getBrowser () .getPrivateScene ());
   this .fieldOfViewOffsetInterpolator1 = new Interpolation_ScalarInterpolator (this .getBrowser () .getPrivateScene ());
   this .fieldOfViewOffsetInterpolator2 = new Interpolation_ScalarInterpolator (this .getBrowser () .getPrivateScene ());
   this .fieldOfViewOffsetInterpolator3 = new Interpolation_ScalarInterpolator (this .getBrowser () .getPrivateScene ());
}

Object .assign (Object .setPrototypeOf (OrthoViewpoint .prototype, Navigation_X3DViewpointNode .prototype),
{
   initialize ()
   {
      Navigation_X3DViewpointNode .prototype .initialize .call (this);

      this .fieldOfViewOffsetInterpolator0 ._key = new x_ite_Fields .MFFloat (0, 1);
      this .fieldOfViewOffsetInterpolator1 ._key = new x_ite_Fields .MFFloat (0, 1);
      this .fieldOfViewOffsetInterpolator2 ._key = new x_ite_Fields .MFFloat (0, 1);
      this .fieldOfViewOffsetInterpolator3 ._key = new x_ite_Fields .MFFloat (0, 1);

      this .fieldOfViewOffsetInterpolator0 .setup ();
      this .fieldOfViewOffsetInterpolator1 .setup ();
      this .fieldOfViewOffsetInterpolator2 .setup ();
      this .fieldOfViewOffsetInterpolator3 .setup ();

      this .easeInEaseOut ._modifiedFraction_changed .addFieldInterest (this .fieldOfViewOffsetInterpolator0 ._set_fraction);
      this .easeInEaseOut ._modifiedFraction_changed .addFieldInterest (this .fieldOfViewOffsetInterpolator1 ._set_fraction);
      this .easeInEaseOut ._modifiedFraction_changed .addFieldInterest (this .fieldOfViewOffsetInterpolator2 ._set_fraction);
      this .easeInEaseOut ._modifiedFraction_changed .addFieldInterest (this .fieldOfViewOffsetInterpolator3 ._set_fraction);

      this .fieldOfViewOffsetInterpolator0 ._value_changed .addInterest ("set_fieldOfViewOffset__", this);
      this .fieldOfViewOffsetInterpolator1 ._value_changed .addInterest ("set_fieldOfViewOffset__", this);
      this .fieldOfViewOffsetInterpolator2 ._value_changed .addInterest ("set_fieldOfViewOffset__", this);
      this .fieldOfViewOffsetInterpolator3 ._value_changed .addInterest ("set_fieldOfViewOffset__", this);
   },
   set_fieldOfViewOffset__ ()
   {
      this ._fieldOfViewOffset [0] = this .fieldOfViewOffsetInterpolator0 ._value_changed .getValue ();
      this ._fieldOfViewOffset [1] = this .fieldOfViewOffsetInterpolator1 ._value_changed .getValue ();
      this ._fieldOfViewOffset [2] = this .fieldOfViewOffsetInterpolator2 ._value_changed .getValue ();
      this ._fieldOfViewOffset [3] = this .fieldOfViewOffsetInterpolator3 ._value_changed .getValue ();
   },
   resetUserOffsets ()
   {
      Navigation_X3DViewpointNode .prototype .resetUserOffsets .call (this);

      this ._fieldOfViewOffset [0] = 0;
      this ._fieldOfViewOffset [1] = 0;
      this ._fieldOfViewOffset [2] = 0;
      this ._fieldOfViewOffset [3] = 0;
   },
   getRelativeTransformation (fromViewpointNode)
   {
      const relative = Navigation_X3DViewpointNode .prototype .getRelativeTransformation .call (this, fromViewpointNode);

      if (fromViewpointNode .constructor === this .constructor)
      {
         relative .userMinimumX = fromViewpointNode .getUserMinimumX ();
         relative .userMinimumY = fromViewpointNode .getUserMinimumY ();
         relative .userMaximumX = fromViewpointNode .getUserMaximumX ();
         relative .userMaximumY = fromViewpointNode .getUserMaximumY ();
      }

      return relative;
   },
   setInterpolators (fromViewpointNode, relative)
   {
      if (fromViewpointNode .constructor === this .constructor)
      {
         const
            offset0 = relative .userMinimumX - this .getMinimumX (),
            offset1 = relative .userMinimumY - this .getMinimumY (),
            offset2 = relative .userMaximumX - this .getMaximumX (),
            offset3 = relative .userMaximumY - this .getMaximumY ();

         this .fieldOfViewOffsetInterpolator0 ._keyValue = new x_ite_Fields .MFFloat (offset0, this ._fieldOfViewOffset [0]);
         this .fieldOfViewOffsetInterpolator1 ._keyValue = new x_ite_Fields .MFFloat (offset1, this ._fieldOfViewOffset [1]);
         this .fieldOfViewOffsetInterpolator2 ._keyValue = new x_ite_Fields .MFFloat (offset2, this ._fieldOfViewOffset [2]);
         this .fieldOfViewOffsetInterpolator3 ._keyValue = new x_ite_Fields .MFFloat (offset3, this ._fieldOfViewOffset [3]);
         this .fieldOfViewScaleInterpolator   ._keyValue = new x_ite_Fields .MFFloat (1, this ._fieldOfViewScale .getValue ());

         this ._fieldOfViewOffset [0] = relative .offset0;
         this ._fieldOfViewOffset [1] = relative .offset1;
         this ._fieldOfViewOffset [2] = relative .offset2;
         this ._fieldOfViewOffset [3] = relative .offset3;
         this ._fieldOfViewScale      = 1;
      }
      else
      {
         this .fieldOfViewOffsetInterpolator0 ._keyValue = new x_ite_Fields .MFFloat (this ._fieldOfViewOffset [0], this ._fieldOfViewOffset [0]);
         this .fieldOfViewOffsetInterpolator1 ._keyValue = new x_ite_Fields .MFFloat (this ._fieldOfViewOffset [1], this ._fieldOfViewOffset [1]);
         this .fieldOfViewOffsetInterpolator2 ._keyValue = new x_ite_Fields .MFFloat (this ._fieldOfViewOffset [2], this ._fieldOfViewOffset [2]);
         this .fieldOfViewOffsetInterpolator3 ._keyValue = new x_ite_Fields .MFFloat (this ._fieldOfViewOffset [3], this ._fieldOfViewOffset [3]);
         this .fieldOfViewScaleInterpolator   ._keyValue = new x_ite_Fields .MFFloat (1, this ._fieldOfViewOffset .getValue ());

         this ._fieldOfViewOffset = this ._fieldOfViewOffset .getValue ();
         this ._fieldOfViewScale  = 1;
      }
   },
   getLogarithmicDepthBuffer ()
   {
      return false;
   },
   getMinimumX ()
   {
      return this ._fieldOfView .length > 0 ? this ._fieldOfView [0] : -1;
   },
   getUserMinimumX ()
   {
      return (this .getMinimumX () + this ._fieldOfViewOffset [0]) * this ._fieldOfViewScale .getValue ();
   },
   getMinimumY ()
   {
      return this ._fieldOfView .length > 1 ? this ._fieldOfView [1] : -1;
   },
   getUserMinimumY ()
   {
      return (this .getMinimumY () + this ._fieldOfViewOffset [1]) * this ._fieldOfViewScale .getValue ();
   },
   getMaximumX ()
   {
      return this ._fieldOfView .length > 2 ? this ._fieldOfView [2] : 1;
   },
   getUserMaximumX ()
   {
      return (this .getMaximumX () + this ._fieldOfViewOffset [2]) * this ._fieldOfViewScale .getValue ();
   },
   getMaximumY ()
   {
      return this ._fieldOfView .length > 3 ? this ._fieldOfView [3] : 1;
   },
   getUserMaximumY ()
   {
      return (this .getMaximumY () + this ._fieldOfViewOffset [3]) * this ._fieldOfViewScale .getValue ();
   },
   getSizeX ()
   {
      return this .getMaximumX () - this .getMinimumX ();
   },
   getUserSizeX ()
   {
      return this .getUserMaximumX () - this .getUserMinimumX ();
   },
   getSizeY ()
   {
      return this .getMaximumY () - this .getMinimumY ();
   },
   getUserSizeY ()
   {
      return this .getUserMaximumY () - this .getUserMinimumY ();
   },
   getMaxFarValue ()
   {
      return 1e4;
   },
   getScreenScale (point, viewport, screenScale)
   {
      const
         width  = viewport [2],
         height = viewport [3],
         sizeX  = this .getUserSizeX (),
         sizeY  = this .getUserSizeY (),
         aspect = width / height;

      if (aspect > sizeX / sizeY)
      {
         const s = sizeY / height;

         return screenScale .set (s, s, s);
      }
      else
      {
         const s = sizeX / width;

         return screenScale .set (s, s, s);
      }
   },
   getViewportSize: (() =>
   {
      const viewportSize = new Numbers_Vector2 (0, 0);

      return function (viewport, nearValue)
      {
         const
            width  = viewport [2],
            height = viewport [3],
            sizeX  = this .getUserSizeX (),
            sizeY  = this .getUserSizeY (),
            aspect = width / height;

         if (aspect > sizeX / sizeY)
            return viewportSize .set (sizeY * aspect, sizeY);

         return viewportSize .set (sizeX, sizeX / aspect);
      };
   })(),
   getLookAtDistance (bbox)
   {
      return bbox .size .magnitude () / 2 + 10;
   },
   getProjectionMatrixWithLimits (nearValue, farValue, viewport)
   {
      const
         width  = viewport [2],
         height = viewport [3],
         aspect = width / height,
         sizeX  = this .getUserSizeX (),
         sizeY  = this .getUserSizeY ();

      if (aspect > sizeX / sizeY)
      {
         const
            center  = (this .getUserMinimumX () + this .getUserMaximumX ()) / 2,
            size1_2 = (sizeY * aspect) / 2;

         return Geometry_Camera .ortho (center - size1_2, center + size1_2, this .getUserMinimumY (), this .getUserMaximumY (), nearValue, farValue, this .projectionMatrix);
      }
      else
      {
         const
            center  = (this .getUserMinimumY () + this .getUserMaximumY ()) / 2,
            size1_2 = (sizeX / aspect) / 2;

         return Geometry_Camera .ortho (this .getUserMinimumX (), this .getUserMaximumX (), center - size1_2, center + size1_2, nearValue, farValue, this .projectionMatrix);
      }
   },
   viewAll (bbox)
   {
      Navigation_X3DViewpointNode .prototype .viewAll .call (this, bbox);

      const
         size   = bbox .size,
         scaleX = size .x / this .getSizeX (),
         scaleY = size .y / this .getSizeY (),
         scale  = Math .max (scaleX, scaleY) * 1.1;

      this ._fieldOfViewOffset [0] = this .getMinimumX () * scale - this .getMinimumX ();
      this ._fieldOfViewOffset [1] = this .getMinimumY () * scale - this .getMinimumY ();
      this ._fieldOfViewOffset [2] = this .getMaximumX () * scale - this .getMaximumX ();
      this ._fieldOfViewOffset [3] = this .getMaximumY () * scale - this .getMaximumY ();
   },
});

Object .defineProperties (OrthoViewpoint,
{
   typeName:
   {
      value: "OrthoViewpoint",
      enumerable: true,
   },
   componentName:
   {
      value: "Navigation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,   "set_bind",          new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",       new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "position",          new x_ite_Fields .SFVec3f (0, 0, 10)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "orientation",       new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "centerOfRotation",  new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "fieldOfView",       new x_ite_Fields .MFFloat (-1, -1, 1, 1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "nearDistance",      new x_ite_Fields .SFFloat (-1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "farDistance",       new x_ite_Fields .SFFloat (-1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "viewAll",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "jump",              new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "retainUserOffsets", new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isBound",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "bindTime",          new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "navigationInfo",    new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const OrthoViewpoint_default_ = OrthoViewpoint;
;

x_ite_Namespace .add ("OrthoViewpoint", "x_ite/Components/Navigation/OrthoViewpoint", OrthoViewpoint_default_);
/* harmony default export */ const Navigation_OrthoViewpoint = (OrthoViewpoint_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Navigation/ViewpointGroup.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/











function ViewpointGroup (executionContext)
{
   Core_X3DChildNode .call (this, executionContext);

   this .addType (Base_X3DConstants .ViewpointGroup);

   this ._size   .setUnit ("length");
   this ._center .setUnit ("length");

   this .setCameraObject (true);

   this .proximitySensor  = new EnvironmentalSensor_ProximitySensor (executionContext);
   this .cameraObjects    = [ ];
   this .viewpointGroups  = [ ];
}

Object .assign (Object .setPrototypeOf (ViewpointGroup .prototype, Core_X3DChildNode .prototype),
{
   initialize ()
   {
      Core_X3DChildNode .prototype .initialize .call (this);

      this .proximitySensor .setup ();

      this ._size   .addFieldInterest (this .proximitySensor ._size);
      this ._center .addFieldInterest (this .proximitySensor ._center);

      this .proximitySensor ._size   = this ._size;
      this .proximitySensor ._center = this ._center;

      this ._size      .addInterest ("set_size__",     this);
      this ._children  .addInterest ("set_children__", this);

      this .set_size__ ();
      this .set_children__ ();
   },
   set_size__ ()
   {
      this .proximitySensor ._enabled = !this ._size .getValue () .equals (Numbers_Vector3 .Zero);
   },
   set_children__ ()
   {
      this .cameraObjects   .length = 0;
      this .viewpointGroups .length = 0;

      for (const child of this ._children)
      {
         const childNode = Base_X3DCast (Base_X3DConstants .X3DChildNode, child);

         if (!childNode)
            continue;

         const type = childNode .getType ();

         for (let t = type .length - 1; t >= 0; -- t)
         {
            switch (type [t])
            {
               case Base_X3DConstants .X3DViewpointNode:
               {
                  this .cameraObjects .push (childNode);
                  break;
               }
               case Base_X3DConstants .ViewpointGroup:
               {
                  this .cameraObjects   .push (childNode);
                  this .viewpointGroups .push (childNode);
                  break;
               }
            }
         }
      }
   },
   traverse (type, renderObject)
   {
      const proximitySensor = this .proximitySensor;

      switch (type)
      {
         case Rendering_TraverseType .CAMERA:
         {
            proximitySensor .traverse (type, renderObject);

            if (proximitySensor ._isActive .getValue () || !proximitySensor ._enabled .getValue ())
            {
               renderObject .getViewpointGroups () .push (this);

               for (const cameraObject of this .cameraObjects)
                  cameraObject .traverse (type, renderObject);

               renderObject .getViewpointGroups () .pop ();
            }

            return;
         }
         case Rendering_TraverseType .DISPLAY:
         {
            proximitySensor .traverse (type, renderObject);

            if (proximitySensor ._isActive .getValue () || !proximitySensor ._enabled .getValue ())
            {
               for (const viewpointGroup of this .viewpointGroups)
                  viewpointGroup .traverse (type, renderObject);
            }

            return;
         }
      }
   },
});

Object .defineProperties (ViewpointGroup,
{
   typeName:
   {
      value: "ViewpointGroup",
      enumerable: true,
   },
   componentName:
   {
      value: "Navigation",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",       new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "displayed",         new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "retainUserOffsets", new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "size",              new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "center",            new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "children",          new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const ViewpointGroup_default_ = ViewpointGroup;
;

x_ite_Namespace .add ("ViewpointGroup", "x_ite/Components/Navigation/ViewpointGroup", ViewpointGroup_default_);
/* harmony default export */ const Navigation_ViewpointGroup = (ViewpointGroup_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Navigation.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










const Navigation_default_ = {
   name: "Navigation",
   concreteNodes:
   [
      Navigation_Billboard,
      Navigation_Collision,
      Navigation_LOD,
      Navigation_NavigationInfo,
      Navigation_OrthoViewpoint,
      Navigation_Viewpoint,
      Navigation_ViewpointGroup,
   ],
   abstractNodes:
   [
      Navigation_X3DViewpointNode,
   ],
};
;

x_ite_Namespace .add ("Navigation", "x_ite/Components/Navigation", Navigation_default_);
/* harmony default export */ const Navigation = (Navigation_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/PointingDeviceSensor/PointingDeviceSensorContainer.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function PointingDeviceSensorContainer (node, modelViewMatrix, projectionMatrix, viewport)
{
   this .node             = null;
   this .modelViewMatrix  = new Numbers_Matrix4 ();
   this .projectionMatrix = new Numbers_Matrix4 ();
   this .viewport         = new Numbers_Vector4 (0, 0, 0, 0);

   this .set (node, modelViewMatrix, projectionMatrix, viewport);
}

Object .assign (PointingDeviceSensorContainer .prototype,
{
   set (node, modelViewMatrix, projectionMatrix, viewport)
   {
      this .node = node;

      this .modelViewMatrix  .assign (modelViewMatrix);
      this .projectionMatrix .assign (projectionMatrix);
      this .viewport         .assign (viewport);
   },
   set_over__ (over, hit)
   {
      this .node .set_over__ (over, hit, this .modelViewMatrix, this .projectionMatrix, this .viewport);
   },
   set_active__ (active, hit)
   {
      this .node .set_active__ (active, hit, this .modelViewMatrix, this .projectionMatrix, this .viewport);
   },
   set_motion__ (hit)
   {
      this .node .set_motion__ (hit, this .modelViewMatrix, this .projectionMatrix, this .viewport);
   },
});

const PointingDeviceSensorContainer_default_ = PointingDeviceSensorContainer;
;

x_ite_Namespace .add ("PointingDeviceSensorContainer", "x_ite/Browser/PointingDeviceSensor/PointingDeviceSensorContainer", PointingDeviceSensorContainer_default_);
/* harmony default export */ const PointingDeviceSensor_PointingDeviceSensorContainer = (PointingDeviceSensorContainer_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/PointingDeviceSensor/X3DPointingDeviceSensorNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function X3DPointingDeviceSensorNode (executionContext)
{
   Core_X3DSensorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DPointingDeviceSensorNode);
}

Object .assign (Object .setPrototypeOf (X3DPointingDeviceSensorNode .prototype, Core_X3DSensorNode .prototype),
{
   initialize ()
   {
      Core_X3DSensorNode .prototype .initialize .call (this);

      this .getLive () .addInterest ("set_live__", this);

      this ._enabled .addInterest ("set_live__", this);

      this .set_live__ ();
   },
   set_live__ ()
   {
      if (this .getLive () .getValue () && this ._enabled .getValue ())
      {
         this .getBrowser () .addPointingDeviceSensor (this);

         delete this .push;
      }
      else
      {
         this .getBrowser () .removePointingDeviceSensor (this);

         if (this ._isActive .getValue ())
            this ._isActive = false;

         if (this ._isOver .getValue ())
            this ._isOver = false;

         this .push = Function .prototype;
      }
   },
   set_over__ (over, hit)
   {
      if (over !== this ._isOver .getValue ())
      {
         this ._isOver = over;

         if (over)
            this .getBrowser () .getNotification () ._string = this ._description;
      }
   },
   set_active__ (active, hit)
   {
      if (active !== this ._isActive .getValue ())
         this ._isActive = active
   },
   set_motion__ (hit)
   { },
   push (renderObject, sensors)
   {
      sensors .push (new PointingDeviceSensor_PointingDeviceSensorContainer (this,
                                                        renderObject .getModelViewMatrix  () .get (),
                                                        renderObject .getProjectionMatrix () .get (),
                                                        renderObject .getViewVolume () .getViewport ()));
   },
});

Object .defineProperties (X3DPointingDeviceSensorNode,
{
   typeName:
   {
      value: "X3DPointingDeviceSensorNode",
      enumerable: true,
   },
   componentName:
   {
      value: "PointingDeviceSensor",
      enumerable: true,
   },
});

const X3DPointingDeviceSensorNode_default_ = X3DPointingDeviceSensorNode;
;

x_ite_Namespace .add ("X3DPointingDeviceSensorNode", "x_ite/Components/PointingDeviceSensor/X3DPointingDeviceSensorNode", X3DPointingDeviceSensorNode_default_);
/* harmony default export */ const PointingDeviceSensor_X3DPointingDeviceSensorNode = (X3DPointingDeviceSensorNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/PointingDeviceSensor/X3DTouchSensorNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






function X3DTouchSensorNode (executionContext)
{
   PointingDeviceSensor_X3DPointingDeviceSensorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DTouchSensorNode);
}

Object .assign (Object .setPrototypeOf (X3DTouchSensorNode .prototype, PointingDeviceSensor_X3DPointingDeviceSensorNode .prototype),
{
   set_active__ (active, hit)
   {
      PointingDeviceSensor_X3DPointingDeviceSensorNode .prototype .set_active__ .call (this, active, hit);

      if (this ._enabled .getValue () && this ._isOver .getValue () && ! active)
         this ._touchTime = this .getBrowser () .getCurrentTime ();
   },
   set_over__: (() =>
   {
      const
         invModelViewMatrix = new Numbers_Matrix4 (),
         texCoord           = new Numbers_Vector2 (0, 0);

      return function (over, hit, modelViewMatrix, projectionMatrix, viewport)
      {
         PointingDeviceSensor_X3DPointingDeviceSensorNode .prototype .set_over__ .call (this, over, hit, modelViewMatrix, projectionMatrix, viewport);

         if (this ._isOver .getValue ())
         {
            texCoord .set (hit .texCoord .x, hit .texCoord .y) .divide (hit .texCoord .w);
            invModelViewMatrix .assign (modelViewMatrix) .inverse ();

            this ._hitTexCoord_changed = texCoord;
            this ._hitNormal_changed   = modelViewMatrix .multMatrixDir (hit .normal .copy ()) .normalize ();
            this ._hitPoint_changed    = invModelViewMatrix .multVecMatrix (hit .point .copy ());
         }
      };
   })(),
});

Object .defineProperties (X3DTouchSensorNode,
{
   typeName:
   {
      value: "X3DTouchSensorNode",
      enumerable: true,
   },
   componentName:
   {
      value: "PointingDeviceSensor",
      enumerable: true,
   },
});

const X3DTouchSensorNode_default_ = X3DTouchSensorNode;
;

x_ite_Namespace .add ("X3DTouchSensorNode", "x_ite/Components/PointingDeviceSensor/X3DTouchSensorNode", X3DTouchSensorNode_default_);
/* harmony default export */ const PointingDeviceSensor_X3DTouchSensorNode = (X3DTouchSensorNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/PointingDeviceSensor/TouchSensor.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function TouchSensor (executionContext)
{
   PointingDeviceSensor_X3DTouchSensorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .TouchSensor);

   this ._hitPoint_changed .setUnit ("length");
}

Object .setPrototypeOf (TouchSensor .prototype, PointingDeviceSensor_X3DTouchSensorNode .prototype);

Object .defineProperties (TouchSensor,
{
   typeName:
   {
      value: "TouchSensor",
      enumerable: true,
   },
   componentName:
   {
      value: "PointingDeviceSensor",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",            new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",         new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",             new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "hitTexCoord_changed", new x_ite_Fields .SFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "hitNormal_changed",   new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "hitPoint_changed",    new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isOver",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",            new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "touchTime",           new x_ite_Fields .SFTime ()),
      ]),
      enumerable: true,
   },
});

const TouchSensor_default_ = TouchSensor;
;

x_ite_Namespace .add ("TouchSensor", "x_ite/Components/PointingDeviceSensor/TouchSensor", TouchSensor_default_);
/* harmony default export */ const PointingDeviceSensor_TouchSensor = (TouchSensor_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Networking/Anchor.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/











function Anchor (executionContext)
{
   Grouping_X3DGroupingNode .call (this, executionContext);
   Networking_X3DUrlObject    .call (this, executionContext);

   this .addType (Base_X3DConstants .Anchor);

   this .touchSensorNode = new PointingDeviceSensor_TouchSensor (executionContext);
   this .anchorSensors   = [ ];
}

Object .assign (Object .setPrototypeOf (Anchor .prototype, Grouping_X3DGroupingNode .prototype),
   Networking_X3DUrlObject .prototype,
{
   initialize ()
   {
      Grouping_X3DGroupingNode .prototype .initialize .call (this);
      Networking_X3DUrlObject    .prototype .initialize .call (this);

      this ._description .addFieldInterest (this .touchSensorNode ._description);
      this ._load        .addFieldInterest (this .touchSensorNode ._enabled);

      this .touchSensorNode ._description = this ._description;
      this .touchSensorNode ._enabled     = this ._load;
      this .touchSensorNode .setup ();

      // Modify set_active__ to get immediate response to user action (click event),
      // otherwise links are not opened in this window.

      this .touchSensorNode .set_active__ = (active, hit) =>
      {
         PointingDeviceSensor_TouchSensor .prototype .set_active__ .call (this .touchSensorNode, active, hit);

         if (this .touchSensorNode ._isOver .getValue () && !active)
            this .requestImmediateLoad () .catch (Function .prototype);
      };
   },
   set_load__ ()
   { },
   set_url__ ()
   { },
   requestImmediateLoad (cache = true)
   {
      this .setCache (cache);
      this .setLoadState (Base_X3DConstants .IN_PROGRESS_STATE, false);

      return new Promise ((resolve, reject) =>
      {
         new InputOutput_FileLoader (this) .createX3DFromURL (this ._url, this ._parameter,
         (scene) =>
         {
            if (scene)
            {
               this .getBrowser () .replaceWorld (scene);
               this .setLoadState (Base_X3DConstants .COMPLETE_STATE, false);
               resolve ();
            }
            else
            {
               this .setLoadState (Base_X3DConstants .FAILED_STATE, false);
               reject ();
            }
         },
         (viewpointName) =>
         {
            this .getBrowser () .changeViewpoint (viewpointName);
            this .setLoadState (Base_X3DConstants .COMPLETE_STATE, false);
            resolve ();
         },
         (url, target) =>
         {
            if (target)
               window .open (url, target);
            else
               location = url;

            this .setLoadState (Base_X3DConstants .COMPLETE_STATE, false);
            resolve ();
         });
      });
   },
   requestUnload ()
   { },
   traverse (type, renderObject)
   {
      if (type === Rendering_TraverseType .POINTER)
      {
         const sensors = this .anchorSensors;

         sensors .length = 0;

         this .touchSensorNode .push (renderObject, sensors);

         if (sensors .length)
         {
            renderObject .getSensors () .push (sensors);

            Grouping_X3DGroupingNode .prototype .traverse .call (this, type, renderObject);

            renderObject .getSensors () .pop ();
         }
         else
         {
            Grouping_X3DGroupingNode .prototype .traverse .call (this, type, renderObject);
         }
       }
      else
      {
         Grouping_X3DGroupingNode .prototype .traverse .call (this, type, renderObject);
      }
   },
   dispose ()
   {
      Networking_X3DUrlObject    .prototype .dispose .call (this);
      Grouping_X3DGroupingNode .prototype .dispose .call (this);
   },
});

Object .defineProperties (Anchor,
{
   typeName:
   {
      value: "Anchor",
      enumerable: true,
   },
   componentName:
   {
      value: "Networking",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "description",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "load",                 new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "url",                  new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "parameter",            new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "autoRefresh",          new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "autoRefreshTimeLimit", new x_ite_Fields .SFTime (3600)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "visible",              new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "bboxDisplay",          new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxSize",             new x_ite_Fields .SFVec3f (-1, -1, -1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxCenter",           new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "addChildren",          new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "removeChildren",       new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "children",             new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const Anchor_default_ = Anchor;
;

x_ite_Namespace .add ("Anchor", "x_ite/Components/Networking/Anchor", Anchor_default_);
/* harmony default export */ const Networking_Anchor = (Anchor_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Networking/Inline.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/












function Inline (executionContext)
{
   Core_X3DChildNode     .call (this, executionContext);
   Networking_X3DUrlObject     .call (this, executionContext);
   Grouping_X3DBoundedObject .call (this, executionContext);

   this .addType (Base_X3DConstants .Inline);

   if (executionContext .getSpecificationVersion () < 4.0)
      this ._global = true;

   this .scene        = this .getBrowser () .getDefaultScene ();
   this .groupNode    = new Grouping_Group (executionContext);
   this .localObjects = [ ];
   this .localShadows = false;
}

Object .assign (Object .setPrototypeOf (Inline .prototype, Core_X3DChildNode .prototype),
   Networking_X3DUrlObject .prototype,
   Grouping_X3DBoundedObject .prototype,
{
   initialize ()
   {
      Core_X3DChildNode     .prototype .initialize .call (this);
      Networking_X3DUrlObject     .prototype .initialize .call (this);
      Grouping_X3DBoundedObject .prototype .initialize .call (this);

      this .groupNode .setPrivate (true);
      this .groupNode .setup ();

      this .groupNode ._isCameraObject   .addFieldInterest (this ._isCameraObject);
      this .groupNode ._isPickableObject .addFieldInterest (this ._isPickableObject);

      this .requestImmediateLoad () .catch (Function .prototype);
   },
   getBBox (bbox, shadows)
   {
      if (this ._bboxSize .getValue () .equals (this .getDefaultBBoxSize ()))
         return this .groupNode .getBBox (bbox, shadows);

      return bbox .set (this ._bboxSize .getValue (), this ._bboxCenter .getValue ());
   },
   set_live__ ()
   {
      Networking_X3DUrlObject .prototype .set_live__ .call (this);

      this .scene .setLive (this .getLive () .getValue ());
   },
   unloadData ()
   {
      this .abortLoading ();
      this .setInternalScene (this .getBrowser () .getDefaultScene ());
   },
   loadData ()
   {
      this .abortLoading ();
      this .fileLoader = new InputOutput_FileLoader (this) .createX3DFromURL (this ._url, null, this .setInternalSceneAsync .bind (this));
   },
   abortLoading ()
   {
      this .scene ._loadCount .removeInterest ("checkLoadCount", this);

      if (this .fileLoader)
         this .fileLoader .abort ();
   },
   setInternalSceneAsync (scene)
   {
      if (scene)
      {
         scene ._loadCount .addInterest ("checkLoadCount", this);
         this .setInternalScene (scene);
         this .checkLoadCount (scene ._loadCount);
      }
      else
      {
         this .setInternalScene (this .getBrowser () .getDefaultScene ());
         this .setLoadState (Base_X3DConstants .FAILED_STATE);
      }
   },
   checkLoadCount (loadCount)
   {
      if (loadCount .getValue ())
         return;

      loadCount .removeInterest ("checkLoadCount", this);

      this .setLoadState (Base_X3DConstants .COMPLETE_STATE);
   },
   setInternalScene (scene)
   {
      this .scene .setLive (false);
      this .scene .rootNodes .removeFieldInterest (this .groupNode ._children);

      // Set new scene.

      this .scene = scene;
      this .scene .setExecutionContext (this .getExecutionContext ());

      this .scene .rootNodes .addFieldInterest (this .groupNode ._children);
      this .groupNode ._children = this .scene .rootNodes;

      this .set_live__ ();

      this .getBrowser () .addBrowserEvent ();
   },
   getInternalScene ()
   {
      ///  Returns the internal X3DScene of this inline, that is loaded from the url given.
      ///  If the load field was false an empty scene is returned.  This empty scene is the same for all Inline
      ///  nodes (due to performance reasons).

      return this .scene;
   },
   traverse (type, renderObject)
   {
      switch (type)
      {
         case Rendering_TraverseType .PICKING:
         {
            const
               browser          = this .getBrowser (),
               pickingHierarchy = browser .getPickingHierarchy ();

            pickingHierarchy .push (this);

            this .groupNode .traverse (type, renderObject);

            pickingHierarchy .pop ();
            return;
         }
         case Rendering_TraverseType .DISPLAY:
         {
            if (this ._global .getValue ())
            {
               this .groupNode .traverse (type, renderObject);
            }
            else
            {
               const
                  globalObjects        = renderObject .getGlobalObjects (),
                  globalShadows        = renderObject .getGlobalShadows (),
                  globalsBegin         = globalObjects .length,
                  shadowsBegin         = globalShadows .length,
                  localObjects         = this .localObjects,
                  numLocalObjects      = localObjects .length,
                  numLights            = localObjects .reduce ((n, c) => n + !!c .lightNode, 0),
                  numTextureProjectors = localObjects .reduce ((n, c) => n + !!c .textureProjectorNode, 0);

               if (numLocalObjects)
               {
                  renderObject .getLocalObjects () .push (... localObjects);
                  renderObject .pushLocalShadows (this .localShadows);
                  renderObject .getLocalObjectsCount () [1] += numLights;
                  renderObject .getLocalObjectsCount () [2] += numTextureProjectors;
               }

               this .groupNode .traverse (type, renderObject);

               if (numLocalObjects)
               {
                  if (renderObject .isIndependent ())
                  {
                     const browser = this .getBrowser ();

                     for (let i = 0; i < numLocalObjects; ++ i)
                        browser .getLocalObjects () .push (renderObject .getLocalObjects () .pop ());
                  }
                  else
                  {
                     for (let i = 0; i < numLocalObjects; ++ i)
                        renderObject .getLocalObjects () .pop ();
                  }

                  renderObject .popLocalShadows ();
                  renderObject .getLocalObjectsCount () [1] -= numLights;
                  renderObject .getLocalObjectsCount () [2] -= numTextureProjectors;
               }

               const numGlobalObjects = globalObjects .length - globalsBegin;

               for (let i = 0; i < numGlobalObjects; ++ i)
               {
                  const globalObject = globalObjects [globalsBegin + i];

                  globalObject .groupNode = this .groupNode;
                  globalObject .global    = false;

                  localObjects [i] = globalObject;
               }

               localObjects .length = numGlobalObjects;
               this .localShadows   = globalShadows .at (-1);

               globalObjects .length = globalsBegin;
               globalShadows .length = shadowsBegin;
            }

            return;
         }
         default:
         {
            this .groupNode .traverse (type, renderObject);
            return;
         }
      }
   },
   dispose ()
   {
      Grouping_X3DBoundedObject .prototype .dispose .call (this);
      Networking_X3DUrlObject     .prototype .dispose .call (this);
      Core_X3DChildNode     .prototype .dispose .call (this);
   },
});

Object .defineProperties (Inline,
{
   typeName:
   {
      value: "Inline",
      enumerable: true,
   },
   componentName:
   {
      value: "Networking",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "description",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "global",               new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "load",                 new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "url",                  new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "autoRefresh",          new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "autoRefreshTimeLimit", new x_ite_Fields .SFTime (3600)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "visible",              new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "bboxDisplay",          new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxSize",             new x_ite_Fields .SFVec3f (-1, -1, -1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxCenter",           new x_ite_Fields .SFVec3f ()),
      ]),
      enumerable: true,
   },
});

const Inline_default_ = Inline;
;

x_ite_Namespace .add ("Inline", "x_ite/Components/Networking/Inline", Inline_default_);
/* harmony default export */ const Networking_Inline = (Inline_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Networking/X3DNetworkSensorNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function X3DNetworkSensorNode (executionContext)
{
   Core_X3DSensorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DNetworkSensorNode);
}

Object .setPrototypeOf (X3DNetworkSensorNode .prototype, Core_X3DSensorNode .prototype);

Object .defineProperties (X3DNetworkSensorNode,
{
   typeName:
   {
      value: "X3DNetworkSensorNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Networking",
      enumerable: true,
   },
});

const X3DNetworkSensorNode_default_ = X3DNetworkSensorNode;
;

x_ite_Namespace .add ("X3DNetworkSensorNode", "x_ite/Components/Networking/X3DNetworkSensorNode", X3DNetworkSensorNode_default_);
/* harmony default export */ const Networking_X3DNetworkSensorNode = (X3DNetworkSensorNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Networking/LoadSensor.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function LoadSensor (executionContext)
{
   Networking_X3DNetworkSensorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .LoadSensor);

   if (executionContext .getSpecificationVersion () <= 3.3)
      this .addAlias ("watchList", this ._children);

   this .urlObjects = [ ];
   this .aborted    = false;
   this .timeOutId  = undefined;
}

Object .assign (Object .setPrototypeOf (LoadSensor .prototype, Networking_X3DNetworkSensorNode .prototype),
{
   initialize ()
   {
      Networking_X3DNetworkSensorNode .prototype .initialize .call (this);

      this ._enabled  .addInterest ("set_enabled__",  this);
      this ._timeOut  .addInterest ("set_timeOut__",  this);
      this ._children .addInterest ("set_children__", this);

      this .set_children__ ();
   },
   set_enabled__ ()
   {
      if (this ._enabled .getValue ())
         this .reset ();

      else
      {
         this .abort ();
         this .remove ();
      }
   },
   set_timeOut__ ()
   {
      if (this ._isActive .getValue ())
      {
         this .clearTimeout ();

         this .aborted = false;

         if (this ._timeOut .getValue () > 0)
            this .timeOutId = setTimeout (this .abort .bind (this), this ._timeOut .getValue () * 1000);
      }
   },
   set_children__ ()
   {
      this .reset ();
   },
   set_loadState__ (urlObject)
   {
      switch (urlObject .checkLoadState ())
      {
         case Base_X3DConstants .NOT_STARTED_STATE:
            break;
         case Base_X3DConstants .IN_PROGRESS_STATE:
         case Base_X3DConstants .COMPLETE_STATE:
         case Base_X3DConstants .FAILED_STATE:
         {
            this .count ();
            break;
         }
      }
   },
   count ()
   {
      const urlObjects = this .urlObjects;

      if (urlObjects .length)
      {
         let
            complete = 0,
            failed   = 0;

         for (const urlObject of urlObjects)
         {
            complete += urlObject .checkLoadState () == Base_X3DConstants .COMPLETE_STATE;
            failed   += urlObject .checkLoadState () == Base_X3DConstants .FAILED_STATE;
         }

         const
            loaded   = complete === urlObjects .length,
            progress = complete / urlObjects .length;

         if (this .aborted || failed || loaded)
         {
            this .clearTimeout ();

            this ._isActive = false;
            this ._isLoaded = loaded;
            this ._progress = progress;

            if (loaded)
               this ._loadTime = this .getBrowser () .getCurrentTime ();
         }
         else
         {
            if (this ._isActive .getValue ())
            {
               this ._progress = progress;
            }
            else
            {
               this ._isActive = true;
               this ._progress = progress;

               this .set_timeOut__ ();
            }
         }
      }
      else
      {
         this ._isActive = false;
         this ._isLoaded = false;
         this ._progress = 0;
      }
   },
   abort ()
   {
      this .clearTimeout ();

      this .aborted = true;

      if (this ._enabled .getValue ())
         this .count ();
   },
   reset ()
   {
      this .remove ();

      if (! this ._enabled .getValue ())
         return;

      const urlObjects = this .urlObjects;

      for (const node of this ._children)
      {
         const urlObject = Base_X3DCast (Base_X3DConstants .X3DUrlObject, node);

         if (urlObject)
         {
            urlObjects .push (urlObject);

            urlObject ._loadState .addInterest ("set_loadState__", this, urlObject);
         }
      }

      this .count ();
   },
   remove ()
   {
      this .clearTimeout ();

      const urlObjects = this .urlObjects;

      for (const urlObject of urlObjects)
         urlObject ._loadState .removeInterest ("set_loadState__", this);

      urlObjects .length = 0;
   },
   clearTimeout ()
   {
      clearTimeout (this .timeOutId);

      this .timeOutId = undefined;
   },
});

Object .defineProperties (LoadSensor,
{
   typeName:
   {
      value: "LoadSensor",
      enumerable: true,
   },
   componentName:
   {
      value: "Networking",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",  new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "timeOut",  new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive", new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isLoaded", new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "progress", new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "loadTime", new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "children", new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const LoadSensor_default_ = LoadSensor;
;

x_ite_Namespace .add ("LoadSensor", "x_ite/Components/Networking/LoadSensor", LoadSensor_default_);
/* harmony default export */ const Networking_LoadSensor = (LoadSensor_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Networking.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







const Networking_default_ = {
   name: "Networking",
   concreteNodes:
   [
      Networking_Anchor,
      Networking_Inline,
      Networking_LoadSensor,
   ],
   abstractNodes:
   [
      Networking_X3DNetworkSensorNode,
      Networking_X3DUrlObject,
   ],
};
;

x_ite_Namespace .add ("Networking", "x_ite/Components/Networking", Networking_default_);
/* harmony default export */ const Networking = (Networking_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/PointingDeviceSensor/X3DDragSensorNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function X3DDragSensorNode (executionContext)
{
   PointingDeviceSensor_X3DPointingDeviceSensorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DDragSensorNode);

   this ._trackPoint_changed .setUnit ("length");
}

Object .setPrototypeOf (X3DDragSensorNode .prototype, PointingDeviceSensor_X3DPointingDeviceSensorNode .prototype);

Object .defineProperties (X3DDragSensorNode,
{
   typeName:
   {
      value: "X3DDragSensorNode",
      enumerable: true,
   },
   componentName:
   {
      value: "PointingDeviceSensor",
      enumerable: true,
   },
});

const X3DDragSensorNode_default_ = X3DDragSensorNode;
;

x_ite_Namespace .add ("X3DDragSensorNode", "x_ite/Components/PointingDeviceSensor/X3DDragSensorNode", X3DDragSensorNode_default_);
/* harmony default export */ const PointingDeviceSensor_X3DDragSensorNode = (X3DDragSensorNode_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Geometry/Cylinder3.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






function Cylinder3 (axis, radius)
{
   this .axis   = axis .copy ();
   this .radius = radius;
}

Object .assign (Cylinder3 .prototype,
{
   intersectsLine (line, enter, exit)
   {
      ////////////////////////////////////////////////////////////////////////
      //
      // Description:
      //  Intersect given line with this cylinder, returning the
      //  results in enter and exit. Returns TRUE if there was an
      //  intersection (and results are valid).
      //
      // Taken from Inventor SbCylinder.c++

      // The intersection will actually be done on a radius 1 cylinder
      // aligned with the y axis, so we transform the line into that
      // space, then intersect, then transform the results back.

      // rotation to y axis
      const
         rotToYAxis = new Numbers_Rotation4 (this .axis .direction, new Numbers_Vector3 (0, 1, 0)),
         mtxToYAxis = Numbers_Matrix4 .Rotation (rotToYAxis);

      // scale to unit space
      const
         scaleFactor    = 1 / this .radius,
         toUnitCylSpace = new Numbers_Matrix4 ();

      toUnitCylSpace .scale (new Numbers_Vector3 (scaleFactor, scaleFactor, scaleFactor));
      toUnitCylSpace .multLeft (mtxToYAxis);

      // find the given line un-translated
      const
         point             = line .point .copy () .subtract (this .axis .point),
         noTranslationLine = new Geometry_Line3 (point, line .direction);

      // find the un-translated line in unit cylinder's space
      const cylLine = noTranslationLine .multLineMatrix (toUnitCylSpace);

      // find the intersection on the unit cylinder
      const intersected = this .unitCylinderIntersectsLine (cylLine, enter, exit);

      if (intersected)
      {
         // transform back to original space
         const fromUnitCylSpace = toUnitCylSpace .inverse ();

         fromUnitCylSpace .multVecMatrix (enter);
         enter .add (this .axis .point);

         fromUnitCylSpace .multVecMatrix (exit);
         exit .add (this .axis .point);
      }

      return intersected;
   },
   unitCylinderIntersectsLine (line, enter, exit)
   {
      let t0, t1;

      const
         pos = line .point,
         dir = line .direction;

      const
         A = dir [0] * dir [0] + dir [2] * dir [2],
         B = 2 * (pos [0] * dir [0] + pos [2] * dir [2]),
         C = pos [0] * pos [0] + pos [2] * pos [2] - 1;

      // discriminant = B^2 - 4AC
      const discr = B * B - 4 * A * C;

      // if discriminant is negative, no intersection
      if (discr < 0)
         return false;

         const sqroot = Math .sqrt (discr);

      // magic to stabilize the answer
      if (B > 0)
      {
         t0 = -(2 * C) / (sqroot + B);
         t1 = -(sqroot + B) / (2 * A);
      }
      else
      {
         t0 = (2 * C) / (sqroot - B);
         t1 = (sqroot - B) / (2 * A);
      }

      enter .assign (dir) .multiply (t0) .add (pos);
      exit  .assign (dir) .multiply (t1) .add (pos);

      return true;
   },
   toString ()
   {
      return `${this .axis}, ${this .radius}`;
   },
});

const Cylinder3_default_ = Cylinder3;
;

x_ite_Namespace .add ("Cylinder3", "standard/Math/Geometry/Cylinder3", Cylinder3_default_);
/* harmony default export */ const Geometry_Cylinder3 = (Cylinder3_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/PointingDeviceSensor/CylinderSensor.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/














function CylinderSensor (executionContext)
{
   PointingDeviceSensor_X3DDragSensorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .CylinderSensor);

   this ._diskAngle .setUnit ("angle");
   this ._minAngle  .setUnit ("angle");
   this ._maxAngle  .setUnit ("angle");
   this ._offset    .setUnit ("angle");
}

Object .assign (Object .setPrototypeOf (CylinderSensor .prototype, PointingDeviceSensor_X3DDragSensorNode .prototype),
{
   initialize ()
   {
      PointingDeviceSensor_X3DDragSensorNode .prototype .initialize .call (this);

      this .modelViewMatrix    = new Numbers_Matrix4 ();
      this .invModelViewMatrix = new Numbers_Matrix4 ();

      this .cylinder    = new Geometry_Cylinder3 (new Geometry_Line3 (new Numbers_Vector3 (0, 0, 0), new Numbers_Vector3 (0, 0, 0)), 0);
      this .disk        = false;
      this .yPlane      = null;
      this .zPlane      = null;
      this .sxPlane     = null;
      this .szNormal    = null;
      this .behind      = false;
      this .fromVector  = new Numbers_Vector3 (0, 0, 0);
      this .startOffset = new Numbers_Rotation4 ();
   },
   isBehind (hitRay, hitPoint)
   {
      const
         enter = new Numbers_Vector3 (0, 0 ,0),
         exit  = new Numbers_Vector3 (0, 0, 0);

      this .cylinder .intersectsLine (hitRay, enter, exit);

      return hitPoint .distance (enter) > hitPoint .distance (exit);
   },
   getTrackPoint (hitRay, trackPoint)
   {
      const zPoint = new Numbers_Vector3 (0, 0, 0);

      this .zPlane .intersectsLine (hitRay, zPoint);

      const
         axisPoint = zPoint .copy () .add (this .cylinder .axis .getPerpendicularVectorToPoint (zPoint, new Numbers_Vector3 (0, 0, 0))),
         distance  = this .sxPlane .getDistanceToPoint (zPoint) / this .cylinder .radius,
         section   = Math .floor ((distance + 1) / 2);

      // Use asin on the cylinder and outside linear angle.
      const
         sinp  = Math_Algorithm .interval (distance, -1, 1),
         phi   = section === 0 ? Math .asin (sinp) : sinp * Math .PI / 2,
         angle = phi + section * Math .PI;

      const rotation = new Numbers_Rotation4 (this .cylinder .axis .direction, angle);

      rotation .multVecRot (trackPoint .assign (this .szNormal) .multiply (this .cylinder .radius));
      trackPoint .add (axisPoint);
   },
   getAngle (rotation)
   {
      if (rotation .getAxis (new Numbers_Vector3 (0, 0, 0)) .dot (this .cylinder .axis .direction) > 0)
         return rotation .angle;

      else
         return -rotation .angle;
   },
   set_active__ (active, hit, modelViewMatrix, projectionMatrix, viewport)
   {
      PointingDeviceSensor_X3DDragSensorNode .prototype .set_active__ .call (this, active, hit, modelViewMatrix, projectionMatrix, viewport);

      if (this ._isActive .getValue ())
      {
         this .modelViewMatrix    .assign (modelViewMatrix);
         this .invModelViewMatrix .assign (modelViewMatrix) .inverse ();

         const
            hitRay   = hit .hitRay .copy () .multLineMatrix (this .invModelViewMatrix),
            hitPoint = this .invModelViewMatrix .multVecMatrix (hit .point .copy ());

         const
            yAxis      = this ._axisRotation .getValue () .multVecRot (new Numbers_Vector3 (0, 1, 0)),
            cameraBack = this .invModelViewMatrix .multDirMatrix (new Numbers_Vector3 (0, 0, 1)) .normalize ();

         const
            axis   = new Geometry_Line3 (new Numbers_Vector3 (0, 0, 0), yAxis),
            radius = axis .getPerpendicularVectorToPoint (hitPoint, new Numbers_Vector3 (0, 0, 0)) .magnitude ();

         this .cylinder = new Geometry_Cylinder3 (axis, radius);
         this .disk     = Math .abs (cameraBack .dot (yAxis)) > Math .cos (this ._diskAngle .getValue ());
         this .behind   = this .isBehind (hitRay, hitPoint);
         this .yPlane   = new Geometry_Plane3 (hitPoint, yAxis);             // Sensor aligned y-plane
         this .zPlane   = new Geometry_Plane3 (hitPoint, cameraBack);        // Screen aligned z-plane

         // Compute normal like in Billboard with yAxis as axis of rotation.
         const
            billboardToViewer = this .invModelViewMatrix .origin,
            sxNormal          = yAxis .copy () .cross (billboardToViewer) .normalize ();

         this .sxPlane  = new Geometry_Plane3 (new Numbers_Vector3 (0, 0, 0), sxNormal);   // Billboarded special x-plane made parallel to sensors axis.
         this .szNormal = sxNormal .copy () .cross (yAxis) .normalize (); // Billboarded special z-normal made parallel to sensors axis.

         const trackPoint = new Numbers_Vector3 (0, 0, 0);

         if (this .disk)
            this .yPlane .intersectsLine (hitRay, trackPoint);
         else
            this .getTrackPoint (hitRay, trackPoint);

         this .fromVector  = this .cylinder .axis .getPerpendicularVectorToPoint (trackPoint, new Numbers_Vector3 (0, 0, 0)) .negate ();
         this .startOffset = new Numbers_Rotation4 (yAxis, this ._offset .getValue ());

         this ._trackPoint_changed = trackPoint;
         this ._rotation_changed   = this .startOffset;

         // For min/max angle.

         this .angle       = this ._offset .getValue ();
         this .startVector = this ._rotation_changed .getValue () .multVecRot (this ._axisRotation .getValue () .multVecRot (new Numbers_Vector3 (0, 0, 1)));
      }
      else
      {
         if (this ._autoOffset .getValue ())
            this ._offset = this .getAngle (this ._rotation_changed .getValue ());
      }
   },
   set_motion__ (hit)
   {
      const
         hitRay     = hit .hitRay .copy () .multLineMatrix (this .invModelViewMatrix),
         trackPoint = new Numbers_Vector3 (0, 0, 0);

      if (this .disk)
         this .yPlane .intersectsLine (hitRay, trackPoint);
      else
         this .getTrackPoint (hitRay, trackPoint);

      this ._trackPoint_changed = trackPoint;

      const
         toVector = this .cylinder .axis .getPerpendicularVectorToPoint (trackPoint, new Numbers_Vector3 (0, 0, 0)) .negate (),
         rotation = new Numbers_Rotation4 (this .fromVector, toVector);

      if (this .disk)
      {
         // The trackpoint can swap behind the viewpoint if viewpoint is a Viewpoint node
         // as the viewing volume is not a cube where the picking ray goes straight up.
         // This phenomenon is very clear on the viewport corners.

         const trackPoint_ = this .modelViewMatrix .multVecMatrix (trackPoint .copy ());

         if (trackPoint_ .z > 0)
            rotation .multRight (new Numbers_Rotation4 (this .yPlane .normal, Math .PI));
      }
      else
      {
         if (this .behind)
            rotation .inverse ();
      }

      rotation .multLeft (this .startOffset);

      if (this ._minAngle .getValue () > this ._maxAngle .getValue ())
      {
         this ._rotation_changed = rotation;
      }
      else
      {
         const
            endVector     = rotation .multVecRot (this ._axisRotation .getValue () .multVecRot (new Numbers_Vector3 (0, 0, 1))),
            deltaRotation = new Numbers_Rotation4 (this .startVector, endVector),
            axis          = this ._axisRotation .getValue () .multVecRot (new Numbers_Vector3 (0, 1, 0)),
            sign          = axis .dot (deltaRotation .getAxis (new Numbers_Vector3 (0, 0, 0))) > 0 ? 1 : -1,
            min           = this ._minAngle .getValue (),
            max           = this ._maxAngle .getValue ();

         this .angle += sign * deltaRotation .angle;

         this .startVector .assign (endVector);

         //console .log (this .angle, min, max);

         if (this .angle < min)
            rotation .setAxisAngle (this .cylinder .axis .direction, min);
         else if (this .angle > max)
            rotation .setAxisAngle (this .cylinder .axis .direction, max);
         else
            rotation .setAxisAngle (this .cylinder .axis .direction, this .angle);

         if (! this ._rotation_changed .getValue () .equals (rotation))
            this ._rotation_changed = rotation;
      }
   },
});

Object .defineProperties (CylinderSensor,
{
   typeName:
   {
      value: "CylinderSensor",
      enumerable: true,
   },
   componentName:
   {
      value: "PointingDeviceSensor",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",        new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",            new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "axisRotation",       new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "diskAngle",          new x_ite_Fields .SFFloat (0.261792)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "minAngle",           new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "maxAngle",           new x_ite_Fields .SFFloat (-1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "offset",             new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "autoOffset",         new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "trackPoint_changed", new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "rotation_changed",   new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isOver",             new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",           new x_ite_Fields .SFBool ()),
      ]),
      enumerable: true,
   },
});

const CylinderSensor_default_ = CylinderSensor;
;

x_ite_Namespace .add ("CylinderSensor", "x_ite/Components/PointingDeviceSensor/CylinderSensor", CylinderSensor_default_);
/* harmony default export */ const PointingDeviceSensor_CylinderSensor = (CylinderSensor_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Geometry/Line2.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function Line2 (point, direction)
{
   this .point     = point     .copy ();
   this .direction = direction .copy ();
}

Object .assign (Line2 .prototype,
{
   copy ()
   {
      const copy = Object .create (Line2 .prototype);
      copy .point     = this .point .copy ();
      copy .direction = this .direction .copy ();
      return copy;
   },
   assign (line)
   {
      this .point     .assign (line .point);
      this .direction .assign (line .direction);
      return this;
   },
   set (point, direction)
   {
      this .point     .assign (point);
      this .direction .assign (direction);
      return this;
   },
   setPoints (point1, point2)
   {
      this .point .assign (point1);
      this .direction .assign (point2) .subtract (point1) .normalize ();
      return this;
   },
   multMatrixLine (matrix)
   {
      matrix .multMatrixVec (this .point);
      matrix .multMatrixDir (this .direction) .normalize ();
      return this;
   },
   multLineMatrix (matrix)
   {
      matrix .multVecMatrix (this .point);
      matrix .multDirMatrix (this .direction) .normalize ();
      return this;
   },
   getClosestPointToPoint (point, result)
   {
      const
         r = result .assign (point) .subtract (this .point),
         d = r .dot (this .direction);

      return result .assign (this .direction) .multiply (d) .add (this .point);
   },
   getPerpendicularVectorToPoint: (() =>
   {
      const t = new Numbers_Vector2 (0, 0);

      return function (point, result)
      {
         result .assign (this .point) .subtract (point);

         return result .subtract (t .assign (this .direction) .multiply (result .dot (this .direction)));
      };
   })(),
   intersectsLine: (() =>
   {
      const u = new Numbers_Vector2 (0, 0);

      return function (line, point)
      {
         const
            { point: p1, direction: d1 } = this,
            { point: p2, direction: d2 } = line;

         const theta = d1 .dot (d2); // angle between both lines

         if (Math .abs (theta) >= 1)
            return false; // lines are parallel

         u .assign (p2) .subtract (p1);

         const t = (u .dot (d1) - theta * u .dot (d2)) / (1 - theta * theta);

         point .assign (d1) .multiply (t) .add (p1);

         return true;
      };
   })(),
   toString ()
   {
      return `${this .point}, ${this .direction}`;
   },
});

Object .assign (Line2,
{
   Points (point1, point2)
   {
      const line = Object .create (Line2 .prototype);
      line .point     = point1 .copy ();
      line .direction = point2 .copy () .subtract (point1) .normalize ();
      return line;
   },
});

const Line2_default_ = Line2;
;

x_ite_Namespace .add ("Line2", "standard/Math/Geometry/Line2", Line2_default_);
/* harmony default export */ const Geometry_Line2 = (Line2_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/PointingDeviceSensor/PlaneSensor.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

















const
   screenLine     = new Geometry_Line2 (Numbers_Vector2 .Zero, Numbers_Vector2 .Zero),
   trackPoint1    = new Numbers_Vector2 (0, 0, 0),
   trackPointLine = new Geometry_Line3 (Numbers_Vector3 .Zero, Numbers_Vector3 .Zero);

function PlaneSensor (executionContext)
{
   PointingDeviceSensor_X3DDragSensorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .PlaneSensor);

   this ._offset              .setUnit ("length");
   this ._minPosition         .setUnit ("length");
   this ._maxPosition         .setUnit ("length");
   this ._translation_changed .setUnit ("length");
}

Object .assign (Object .setPrototypeOf (PlaneSensor .prototype, PointingDeviceSensor_X3DDragSensorNode .prototype),
{
   initialize ()
   {
      PointingDeviceSensor_X3DDragSensorNode .prototype .initialize .call (this);

      this .modelViewMatrix    = new Numbers_Matrix4 ();
      this .invModelViewMatrix = new Numbers_Matrix4 ();
      this .projectionMatrix   = new Numbers_Matrix4 ();
      this .viewport           = new Numbers_Vector4 ();

      this .planeSensor = true;
      this .plane       = null;
      this .line        = null;
      this .startOffset = new Numbers_Vector3 (0, 0, 0);
      this .startPoint  = new Numbers_Vector3 (0, 0, 0);
   },
   getLineTrackPoint (hit, line, trackPoint)
   {
      Geometry_ViewVolume .projectLine (line, this .modelViewMatrix, this .projectionMatrix, this .viewport, screenLine);
      screenLine .getClosestPointToPoint (hit .pointer, trackPoint1);
      Geometry_ViewVolume .unProjectRay (trackPoint1 .x, trackPoint1 .y, this .modelViewMatrix, this .projectionMatrix, this .viewport, trackPointLine);

      return line .getClosestPointToLine (trackPointLine, trackPoint);
   },
   set_active__ (active, hit, modelViewMatrix, projectionMatrix, viewport)
   {
      PointingDeviceSensor_X3DDragSensorNode .prototype .set_active__ .call (this, active, hit, modelViewMatrix, projectionMatrix, viewport);

      if (this ._isActive .getValue ())
      {
         this .modelViewMatrix    .assign (modelViewMatrix);
         this .projectionMatrix   .assign (projectionMatrix);
         this .viewport           .assign (viewport);
         this .invModelViewMatrix .assign (modelViewMatrix) .inverse ();

         const
            hitRay   = hit .hitRay .copy () .multLineMatrix (this .invModelViewMatrix),
            hitPoint = this .invModelViewMatrix .multVecMatrix (hit .point .copy ());

         const axisRotation = this ._axisRotation .getValue ();

         if (this ._minPosition .x === this ._maxPosition .x)
         {
            this .planeSensor = false;

            const direction = axisRotation .multVecRot (new Numbers_Vector3 (0, Math .abs (this ._maxPosition .y - this ._minPosition .y), 0));

            this .line = new Geometry_Line3 (hitPoint, direction .normalize ());
         }
         else if (this ._minPosition .y === this ._maxPosition .y)
         {
            this .planeSensor = false;

            const direction = axisRotation .multVecRot (new Numbers_Vector3 (Math .abs (this ._maxPosition .x - this ._minPosition .x), 0, 0));

            this .line = new Geometry_Line3 (hitPoint, direction .normalize ());
         }
         else
         {
            this .planeSensor = true;
            this .plane       = new Geometry_Plane3 (hitPoint, axisRotation .multVecRot (new Numbers_Vector3 (0, 0, 1)));
         }

         if (this .planeSensor)
         {
            if (this .plane .intersectsLine (hitRay, this .startPoint))
            {
               this .trackStart (this .startPoint);
            }

//						new Plane3 (new Vector3 (0, 0, 0), this .plane .normal) .intersectsLine (hitRay, trackPoint);
         }
         else
         {
            if (this .getLineTrackPoint (hit, this .line, this .startPoint))
            {
               const trackPoint = new Numbers_Vector3 (0, 0, 0);

               try
               {
                  this .getLineTrackPoint (hit, new Geometry_Line3 (this .line .direction, this .line .direction), trackPoint);
               }
               catch
               {
                  trackPoint .assign (this .startPoint);
               }

               this .trackStart (trackPoint);
            }
         }
      }
      else
      {
         if (this ._autoOffset .getValue ())
            this ._offset = this ._translation_changed;
      }
   },
   trackStart (trackPoint)
   {
      this .startOffset .assign (this ._offset .getValue ());

      this ._trackPoint_changed  = trackPoint;
      this ._translation_changed = this ._offset .getValue ();
   },
   set_motion__ (hit)
   {
      try
      {
         if (this .planeSensor)
         {
            const
               hitRay   = hit .hitRay .copy () .multLineMatrix (this .invModelViewMatrix),
               endPoint = new Numbers_Vector3 (0, 0, 0);

            if (this .plane .intersectsLine (hitRay, endPoint))
            {
               this .track (endPoint, endPoint .copy ());
            }
            else
               throw new Error ("Plane and line are parallel.");
         }
         else
         {
            const
               endPoint   = new Numbers_Vector3 (0, 0, 0),
               trackPoint = new Numbers_Vector3 (0, 0, 0);

            if (this .getLineTrackPoint (hit, this .line, endPoint))
            {
               try
               {
                  this .getLineTrackPoint (hit, new Geometry_Line3 (Numbers_Vector3 .Zero, this .line .direction), trackPoint);
               }
               catch
               {
                  trackPoint .assign (endPoint);
               }

               this .track (endPoint, trackPoint);
            }
            else
               throw new Error ("Lines are parallel.");
         }
      }
      catch
      {
         this ._trackPoint_changed  .addEvent ();
         this ._translation_changed .addEvent ();
      }
   },
   track (endPoint, trackPoint)
   {
      const
         axisRotation = this ._axisRotation .getValue (),
         translation  = axisRotation .copy () .inverse () .multVecRot (endPoint .add (this .startOffset) .subtract (this .startPoint));

      // X component

      if (! (this ._minPosition .x > this ._maxPosition .x))
         translation .x = Math_Algorithm .clamp (translation .x, this ._minPosition .x, this ._maxPosition .x);

      // Y component

      if (! (this ._minPosition .y > this ._maxPosition .y))
         translation .y = Math_Algorithm .clamp (translation .y, this ._minPosition .y, this ._maxPosition .y);

      axisRotation .multVecRot (translation);

      if (! this ._trackPoint_changed .getValue () .equals (trackPoint))
         this ._trackPoint_changed = trackPoint;

      if (! this ._translation_changed .getValue () .equals (translation))
         this ._translation_changed = translation;
   },
});

Object .defineProperties (PlaneSensor,
{
   typeName:
   {
      value: "PlaneSensor",
      enumerable: true,
   },
   componentName:
   {
      value: "PointingDeviceSensor",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",            new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",         new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",             new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "axisRotation",        new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "autoOffset",          new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "offset",              new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "minPosition",         new x_ite_Fields .SFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "maxPosition",         new x_ite_Fields .SFVec2f (-1, -1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "trackPoint_changed",  new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "translation_changed", new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isOver",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",            new x_ite_Fields .SFBool ()),
      ]),
      enumerable: true,
   },
});

const PlaneSensor_default_ = PlaneSensor;
;

x_ite_Namespace .add ("PlaneSensor", "x_ite/Components/PointingDeviceSensor/PlaneSensor", PlaneSensor_default_);
/* harmony default export */ const PointingDeviceSensor_PlaneSensor = (PlaneSensor_default_);
;// CONCATENATED MODULE: ./src/standard/Math/Geometry/Sphere3.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function Sphere3 (radius, center)
{
   this .radius = radius;
   this .center = center .copy ();
}

Object .assign (Sphere3 .prototype,
{
   set (radius, center)
   {
      this .radius = radius;
      this .center .assign (center);
   },
   intersectsLine (line, enterPoint, exitPoint)
   {
      // https://github.com/Alexpux/Coin3D/blob/master/src/base/SbSphere.cpp

      const
         { point, direction } = line,
         { center, radius }   = this;

      const
         b = 2 * (point .dot (direction) - center .dot (direction)),
         c = (point .x * point .x + point .y * point .y + point .z * point .z) +
             (center .x * center .x + center .y * center .y + center .z * center .z) -
             2 * point .dot (center) - radius * radius;

      const core = b * b - 4 * c;

      if (core >= 0)
      {
         let
            t1 = (-b + Math .sqrt (core)) / 2,
            t2 = (-b - Math .sqrt (core)) / 2;

         if (t1 > t2)
         {
            const tmp = t1;
            t1 = t2;
            t2 = tmp;
         }

         enterPoint .assign (direction) .multiply (t1) .add (point);
         exitPoint  .assign (direction) .multiply (t2) .add (point);

         return true;
      }
      else
      {
         return false;
      }
   },
   intersectsTriangle: (() =>
   {
      const
         AB = new Numbers_Vector3 (0, 0, 0),
         AC = new Numbers_Vector3 (0, 0, 0),
         BC = new Numbers_Vector3 (0, 0, 0),
         CA = new Numbers_Vector3 (0, 0, 0),
         Q1 = new Numbers_Vector3 (0, 0, 0),
         Q2 = new Numbers_Vector3 (0, 0, 0),
         Q3 = new Numbers_Vector3 (0, 0, 0);

      return function (A, B, C)
      {
         const
            P = this .center,
            r = this .radius;

         A .subtract (P);
         B .subtract (P);
         C .subtract (P);

         // Testing if sphere lies outside the triangle plane.

         AB .assign (B) .subtract (A);
         AC .assign (C) .subtract (A);

         const
            rr   = r * r,
            V    = AB .cross (AC),
            d    = A .dot (V),
            e    = V .dot (V),
            sep1 = d * d > rr * e;

         if (sep1)
            return false;

         // Testing if sphere lies outside a triangle vertex.
         const
            aa   = A .dot (A),
            ab   = A .dot (B),
            ac   = A .dot (C),
            bb   = B .dot (B),
            bc   = B .dot (C),
            cc   = C .dot (C),
            sep2 = (aa > rr) && (ab > aa) && (ac > aa),
            sep3 = (bb > rr) && (ab > bb) && (bc > bb),
            sep4 = (cc > rr) && (ac > cc) && (bc > cc);

         if (sep2 || sep3 || sep4)
            return false;

         // Testing if sphere lies outside a triangle edge.

         AB .assign (B) .subtract (A);
         BC .assign (C) .subtract (B);
         CA .assign (A) .subtract (C);

         const
            d1   = ab - aa,
            d2   = bc - bb,
            d3   = ac - cc,
            e1   = AB .dot (AB),
            e2   = BC .dot (BC),
            e3   = CA .dot (CA);

         Q1 .assign (A) .multiply (e1) .subtract (AB .multiply (d1));
         Q2 .assign (B) .multiply (e2) .subtract (BC .multiply (d2));
         Q3 .assign (C) .multiply (e3) .subtract (CA .multiply (d3));

         const
            QC   = C .multiply (e1) .subtract (Q1),
            QA   = A .multiply (e2) .subtract (Q2),
            QB   = B .multiply (e3) .subtract (Q3),
            sep5 = (Q1 .dot (Q1) > rr * e1 * e1) && (Q1 .dot (QC) > 0),
            sep6 = (Q2 .dot (Q2) > rr * e2 * e2) && (Q2 .dot (QA) > 0),
            sep7 = (Q3 .dot (Q3) > rr * e3 * e3) && (Q3 .dot (QB) > 0);

         if (sep5 || sep6 || sep7)
            return false;

         return true;
      };
   })(),
   toString ()
   {
      return `${this .radius} ${this .center}`;
   },
});

const Sphere3_default_ = Sphere3;
;

x_ite_Namespace .add ("Sphere3", "standard/Math/Geometry/Sphere3", Sphere3_default_);
/* harmony default export */ const Geometry_Sphere3 = (Sphere3_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/PointingDeviceSensor/SphereSensor.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/














function SphereSensor (executionContext)
{
   PointingDeviceSensor_X3DDragSensorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .SphereSensor);
}

Object .assign (Object .setPrototypeOf (SphereSensor .prototype, PointingDeviceSensor_X3DDragSensorNode .prototype),
{
   initialize ()
   {
      PointingDeviceSensor_X3DDragSensorNode .prototype .initialize .call (this);

      this .modelViewMatrix    = new Numbers_Matrix4 ();
      this .invModelViewMatrix = new Numbers_Matrix4 ();

      this .sphere      = null;
      this .zPlane      = null;
      this .behind      = false;
      this .fromVector  = new Numbers_Vector3 (0, 0, 0);
      this .startPoint  = new Numbers_Vector3 (0, 0, 0);
      this .startOffset = new Numbers_Rotation4 ();
   },
   getTrackPoint (hitRay, trackPoint, behind)
   {
      const exit = new Numbers_Vector3 (0, 0, 0);

      if (this .sphere .intersectsLine (hitRay, trackPoint, exit))
      {
         if ((hitRay .point .distance (exit) < hitRay .point .distance (trackPoint)) - behind)
            trackPoint .assign (exit);

         return true;
      }

      return false;
   },
   set_active__ (active, hit, modelViewMatrix, projectionMatrix, viewport)
   {
      PointingDeviceSensor_X3DDragSensorNode .prototype .set_active__ .call (this, active, hit, modelViewMatrix, projectionMatrix, viewport);

      if (this ._isActive .getValue ())
      {
         this .modelViewMatrix    .assign (modelViewMatrix);
         this .invModelViewMatrix .assign (modelViewMatrix) .inverse ();

         const
            hitPoint = this .invModelViewMatrix .multVecMatrix (hit .point .copy ()),
            center   = new Numbers_Vector3 (0, 0, 0);

         this .zPlane = new Geometry_Plane3 (center, this .invModelViewMatrix .multDirMatrix (new Numbers_Vector3 (0, 0, 1)) .normalize ()); // Screen aligned Z-plane
         this .sphere = new Geometry_Sphere3 (hitPoint .magnitude (), center);
         this .behind = this .zPlane .getDistanceToPoint (hitPoint) < 0;

         this .fromVector  .assign (hitPoint);
         this .startPoint  .assign (hitPoint);
         this .startOffset .assign (this ._offset .getValue ());

         this ._trackPoint_changed = hitPoint;
         this ._rotation_changed   = this ._offset .getValue ();
      }
      else
      {
         if (this ._autoOffset .getValue ())
            this ._offset = this ._rotation_changed;
      }
   },
   set_motion__ (hit)
   {
      const
         hitRay     = hit .hitRay .copy () .multLineMatrix (this .invModelViewMatrix),
         trackPoint = new Numbers_Vector3 (0, 0, 0);

      if (this .getTrackPoint (hitRay, trackPoint, this .behind))
      {
         const zAxis = this .invModelViewMatrix .multDirMatrix (new Numbers_Vector3 (0, 0, 1)) .normalize (); // Camera direction

         this .zPlane = new Geometry_Plane3 (trackPoint, zAxis); // Screen aligned Z-plane
      }
      else
      {
         // Find trackPoint on the plane with sphere

         const tangentPoint = new Numbers_Vector3 (0, 0, 0);

         this .zPlane .intersectsLine (hitRay, tangentPoint);

         hitRay .set (tangentPoint, this .sphere .center .copy () .subtract (tangentPoint) .normalize ());

         //console .log (hitRay .toString ());

         this .getTrackPoint (hitRay, trackPoint, false);

         // Find trackPoint behind sphere

         const
            triNormal     = Geometry_Triangle3 .normal (this .sphere .center, trackPoint, this .startPoint, new Numbers_Vector3 (0, 0, 0)),
            dirFromCenter = trackPoint .copy () .subtract (this .sphere .center) .normalize (),
            normal        = triNormal .copy () .cross (dirFromCenter) .normalize ();

         const point1 = trackPoint .copy () .subtract (normal .multiply (tangentPoint .copy () .subtract (trackPoint) .magnitude ()));

         hitRay .set (point1, this .sphere .center .copy () .subtract (point1) .normalize ());

         this .getTrackPoint (hitRay, trackPoint, false);
      }

      this ._trackPoint_changed = trackPoint;

      const
         toVector = trackPoint .copy () .subtract (this .sphere .center),
         rotation = new Numbers_Rotation4 (this .fromVector, toVector);

      if (this .behind)
         rotation .inverse ();

      this ._rotation_changed = this .startOffset .copy () .multRight (rotation);
   },
});

Object .defineProperties (SphereSensor,
{
   typeName:
   {
      value: "SphereSensor",
      enumerable: true,
   },
   componentName:
   {
      value: "PointingDeviceSensor",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",        new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",            new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "autoOffset",         new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "offset",             new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "trackPoint_changed", new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "rotation_changed",   new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isOver",             new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",           new x_ite_Fields .SFBool ()),
      ]),
      enumerable: true,
   },
});

const SphereSensor_default_ = SphereSensor;
;

x_ite_Namespace .add ("SphereSensor", "x_ite/Components/PointingDeviceSensor/SphereSensor", SphereSensor_default_);
/* harmony default export */ const PointingDeviceSensor_SphereSensor = (SphereSensor_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/PointingDeviceSensor.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









const PointingDeviceSensor_default_ = {
   name: "PointingDeviceSensor",
   concreteNodes:
   [
      PointingDeviceSensor_CylinderSensor,
      PointingDeviceSensor_PlaneSensor,
      PointingDeviceSensor_SphereSensor,
      PointingDeviceSensor_TouchSensor,
   ],
   abstractNodes:
   [
      PointingDeviceSensor_X3DDragSensorNode,
      PointingDeviceSensor_X3DPointingDeviceSensorNode,
      PointingDeviceSensor_X3DTouchSensorNode,
   ],
};
;

x_ite_Namespace .add ("PointingDeviceSensor", "x_ite/Components/PointingDeviceSensor", PointingDeviceSensor_default_);
/* harmony default export */ const PointingDeviceSensor = (PointingDeviceSensor_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/ClipPlane.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/











const ClipPlanes = Utility_ObjectCache (ClipPlaneContainer);

function ClipPlaneContainer ()
{
   this .plane = new Geometry_Plane3 (Numbers_Vector3 .Zero, Numbers_Vector3 .Zero);
}

Object .assign (ClipPlaneContainer .prototype,
{
   isClipped (point)
   {
      return this .plane .getDistanceToPoint (point) < 0;
   },
   set (clipPlane, modelViewMatrix)
   {
      const
         plane      = this .plane,
         localPlane = clipPlane .plane;

      plane .normal .assign (localPlane);
      plane .distanceFromOrigin = -localPlane .w;

      plane .multRight (modelViewMatrix);
   },
   setShaderUniforms (gl, shaderObject)
   {
      const
         plane  = this .plane,
         normal = plane .normal;

      gl .uniform4f (shaderObject .x3d_ClipPlane [shaderObject .numClipPlanes ++], normal .x, normal .y, normal .z, plane .distanceFromOrigin);
   },
   dispose ()
   {
      ClipPlanes .push (this);
   },
});

function ClipPlane (executionContext)
{
   Core_X3DChildNode .call (this, executionContext);

   this .addType (Base_X3DConstants .ClipPlane);

   this .enabled = false;
   this .plane   = new Numbers_Vector4 (0, 0, 0, 0);
}

Object .assign (Object .setPrototypeOf (ClipPlane .prototype, Core_X3DChildNode .prototype),
{
   initialize ()
   {
      Core_X3DChildNode .prototype .initialize .call (this);

      this ._enabled .addInterest ("set_enabled__", this);
      this ._plane   .addInterest ("set_enabled__", this);

      this .set_enabled__ ();
   },
   set_enabled__ ()
   {
      this .plane .assign (this ._plane .getValue ());

      this .enabled = this ._enabled .getValue () && ! this .plane .equals (Numbers_Vector4 .Zero);
   },
   push (renderObject)
   {
      if (this .enabled)
      {
         const clipPlaneContainer = ClipPlanes .pop ();

         clipPlaneContainer .set (this, renderObject .getModelViewMatrix () .get ());

         renderObject .getLocalObjects () .push (clipPlaneContainer);

         ++ renderObject .getLocalObjectsCount () [0];
      }
   },
   pop (renderObject)
   {
      if (this .enabled)
      {
         this .getBrowser () .getLocalObjects () .push (renderObject .getLocalObjects () .pop ());

         -- renderObject .getLocalObjectsCount () [0];
      }
   },
});

Object .defineProperties (ClipPlane,
{
   typeName:
   {
      value: "ClipPlane",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",  new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "plane",    new x_ite_Fields .SFVec4f (0, 1, 0, 0)),
      ]),
      enumerable: true,
   },
});

const ClipPlane_default_ = ClipPlane;
;

x_ite_Namespace .add ("ClipPlane", "x_ite/Components/Rendering/ClipPlane", ClipPlane_default_);
/* harmony default export */ const Rendering_ClipPlane = (ClipPlane_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/X3DColorNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function X3DColorNode (executionContext)
{
   Rendering_X3DGeometricPropertyNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DColorNode);

   this .addChildObjects (Base_X3DConstants .outputOnly, "transparent", new x_ite_Fields .SFBool ());
}

Object .assign (Object .setPrototypeOf (X3DColorNode .prototype, Rendering_X3DGeometricPropertyNode .prototype),
{
   setTransparent (value)
   {
      if (value !== this ._transparent .getValue ())
         this ._transparent = value;
   },
   isTransparent ()
   {
      return this ._transparent .getValue ();
   },
});

Object .defineProperties (X3DColorNode,
{
   typeName:
   {
      value: "X3DColorNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
});

const X3DColorNode_default_ = X3DColorNode;
;

x_ite_Namespace .add ("X3DColorNode", "x_ite/Components/Rendering/X3DColorNode", X3DColorNode_default_);
/* harmony default export */ const Rendering_X3DColorNode = (X3DColorNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/Color.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function Color (executionContext)
{
   Rendering_X3DColorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Color);
}

Object .assign (Object .setPrototypeOf (Color .prototype, Rendering_X3DColorNode .prototype),
{
   initialize ()
   {
      Rendering_X3DColorNode .prototype .initialize .call (this);

      this ._color .addInterest ("set_color__", this);

      this .set_color__ ();
   },
   set_color__ ()
   {
      this .color  = this ._color .getValue ();
      this .length = this ._color .length;
   },
   addColor (index, array)
   {
      if (index >= 0 && this .length)
      {
         const
            color = this .color,
            i     = (index % this .length) * 3;

         return array .push (color [i], color [i + 1], color [i + 2], 1);
      }
      else
      {
         array .push (1, 1, 1, 1);
      }
   },
   addColors (array, min = this .length)
   {
      const length = this .length;

      if (length)
      {
         const color = this .color;

         for (let index = 0; index < min; ++ index)
         {
            const i = (index % length) * 3;

            array .push (color [i], color [i + 1], color [i + 2], 1);
         }
      }
      else
      {
         for (let index = 0; index < min; ++ index)
            array .push (1, 1, 1, 1);
      }

      return array;
   },
});

Object .defineProperties (Color,
{
   typeName:
   {
      value: "Color",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
   containerField:
   {
      value: "color",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "color",    new x_ite_Fields .MFColor ()),
      ]),
      enumerable: true,
   },
});

const Color_default_ = Color;
;

x_ite_Namespace .add ("Color", "x_ite/Components/Rendering/Color", Color_default_);
/* harmony default export */ const Rendering_Color = (Color_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/ColorRGBA.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function ColorRGBA (executionContext)
{
   Rendering_X3DColorNode .call (this, executionContext);

   this .addType (Base_X3DConstants .ColorRGBA);

   this .setTransparent (true);
}

Object .assign (Object .setPrototypeOf (ColorRGBA .prototype, Rendering_X3DColorNode .prototype),
{
   initialize ()
   {
      Rendering_X3DColorNode .prototype .initialize .call (this);

      this ._color .addInterest ("set_color__", this);

      this .set_color__ ();
   },
   set_color__ ()
   {
      this .color  = this ._color .getValue ();
      this .length = this ._color .length;
   },
   addColor (index, array)
   {
      if (index >= 0 && this .length)
      {
         const
            color = this .color,
            i     = (index % this .length) * 4;

         return array .push (color [i], color [i + 1], color [i + 2], color [i + 3]);
      }
      else
      {
         array .push (1, 1, 1, 1);
      }
   },
   addColors (array, min = this .length)
   {
      const length = this .length;

      if (length)
      {
         const color = this .color;

         for (let index = 0; index < min; ++ index)
         {
            const i = (index % length) * 4;

            array .push (color [i], color [i + 1], color [i + 2], color [i + 3]);
         }
      }
      else
      {
         for (let index = 0; index < min; ++ index)
            array .push (1, 1, 1, 1);
      }

      return array;
   },
});

Object .defineProperties (ColorRGBA,
{
   typeName:
   {
      value: "ColorRGBA",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
   containerField:
   {
      value: "color",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "color",    new x_ite_Fields .MFColorRGBA ()),
      ]),
      enumerable: true,
   },
});

const ColorRGBA_default_ = ColorRGBA;
;

x_ite_Namespace .add ("ColorRGBA", "x_ite/Components/Rendering/ColorRGBA", ColorRGBA_default_);
/* harmony default export */ const Rendering_ColorRGBA = (ColorRGBA_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/X3DCoordinateNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






function X3DCoordinateNode (executionContext)
{
   Rendering_X3DGeometricPropertyNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DCoordinateNode);
}

Object .assign (Object .setPrototypeOf (X3DCoordinateNode .prototype, Rendering_X3DGeometricPropertyNode .prototype),
{
   initialize ()
   {
      Rendering_X3DGeometricPropertyNode .prototype .initialize .call (this);

      this ._point .addInterest ("set_point__", this);

      this .set_point__ ();
   },
   set_point__ ()
   {
      this .point  = this ._point .getValue ();
      this .length = this ._point .length;
   },
   isEmpty ()
   {
      return this .length === 0;
   },
   getSize ()
   {
      return this .length;
   },
   set1Point (index, point)
   {
      this ._point [index] = point;
   },
   get1Point (index, result)
   {
      if (index < this .length)
      {
         const point = this .point;

         index *= 3;

         return result .set (point [index], point [index + 1], point [index + 2]);
      }
      else
      {
         return result .set (0, 0, 0);
      }
   },
   addPoint (index, array)
   {
      if (index < this .length)
      {
         const point = this .point;

         index *= 3;

         array .push (point [index], point [index + 1], point [index + 2], 1);
      }
      else
      {
         array .push (0, 0, 0, 1);
      }
   },
   addPoints (array)
   {
      const
         point  = this .point,
         length = this .length * 3;

      for (let index = 0; index < length; index += 3)
         array .push (point [index], point [index + 1], point [index + 2], 1);

      return array;
   },
   getNormal: (() =>
   {
      const
         point1 = new Numbers_Vector3 (0, 0, 0),
         point2 = new Numbers_Vector3 (0, 0, 0),
         point3 = new Numbers_Vector3 (0, 0, 0);

      return function (index1, index2, index3)
      {
         // The index[1,2,3] cannot be less than 0.

         const length = this .length;

         if (index1 < length && index2 < length && index3 < length)
         {
            return Geometry_Triangle3 .normal (this .get1Point (index1, point1),
                                      this .get1Point (index2, point2),
                                      this .get1Point (index3, point3),
                                      new Numbers_Vector3 (0, 0, 0));
         }

         return new Numbers_Vector3 (0, 0, 0);
      };
   })(),
   getQuadNormal: (() =>
   {
      const
         point1 = new Numbers_Vector3 (0, 0, 0),
         point2 = new Numbers_Vector3 (0, 0, 0),
         point3 = new Numbers_Vector3 (0, 0, 0),
         point4 = new Numbers_Vector3 (0, 0, 0);

      return function (index1, index2, index3, index4)
      {
         // The index[1,2,3,4] cannot be less than 0.

         const length = this .length;

         if (index1 < length && index2 < length && index3 < length && index4 < length)
         {
            return Geometry_Triangle3 .quadNormal (this .get1Point (index1, point1),
                                          this .get1Point (index2, point2),
                                          this .get1Point (index3, point3),
                                          this .get1Point (index4, point4),
                                          new Numbers_Vector3 (0, 0, 0));
         }

         return new Numbers_Vector3 (0, 0, 0);
      };
   })(),
});

Object .defineProperties (X3DCoordinateNode,
{
   typeName:
   {
      value: "X3DCoordinateNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
});

const X3DCoordinateNode_default_ = X3DCoordinateNode;
;

x_ite_Namespace .add ("X3DCoordinateNode", "x_ite/Components/Rendering/X3DCoordinateNode", X3DCoordinateNode_default_);
/* harmony default export */ const Rendering_X3DCoordinateNode = (X3DCoordinateNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/Coordinate.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function Coordinate (executionContext)
{
   Rendering_X3DCoordinateNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Coordinate);

   this ._point .setUnit ("length");
}

Object .setPrototypeOf (Coordinate .prototype, Rendering_X3DCoordinateNode .prototype);

Object .defineProperties (Coordinate,
{
   typeName:
   {
      value: "Coordinate",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
   containerField:
   {
      value: "coord",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "point",    new x_ite_Fields .MFVec3f ()),
      ]),
      enumerable: true,
   },
});

const Coordinate_default_ = Coordinate;
;

x_ite_Namespace .add ("Coordinate", "x_ite/Components/Rendering/Coordinate", Coordinate_default_);
/* harmony default export */ const Rendering_Coordinate = (Coordinate_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/X3DLineGeometryNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function X3DLineGeometryNode (executionContext)
{
   if (!this .getExecutionContext ())
      Rendering_X3DGeometryNode .call (this, executionContext);

   const
      browser = this .getBrowser (),
      gl      = browser .getContext ();

   this .lineStipples           = new Float32Array ();
   this .lineStippleBuffer      = gl .createBuffer ();
   this .trianglesBuffer        = gl .createBuffer ();
   this .thickVertexArrayObject = new Rendering_VertexArray (gl);

   this .setGeometryType (1);
   this .setPrimitiveMode (gl .LINES);
   this .setSolid (false);
}

Object .assign (Object .setPrototypeOf (X3DLineGeometryNode .prototype, Rendering_X3DGeometryNode .prototype),
{
   intersectsLine ()
   {
      return false;
   },
   intersectsBox ()
   {
      return false;
   },
   updateVertexArrays ()
   {
      Rendering_X3DGeometryNode .prototype .updateVertexArrays .call (this);

      this .thickVertexArrayObject .update ();
   },
   buildTexCoords ()
   {
      // Line stipple support.

      if (this .lineStipples .length / 6 === this .getVertices () .length / 8)
         return;

      const
         gl       = this .getBrowser () .getContext (),
         numLines = this .getVertices () .length / 8;

      this .lineStipples = new Float32Array (numLines * 6);

      gl .bindBuffer (gl .ARRAY_BUFFER, this .lineStippleBuffer);
      gl .bufferData (gl .ARRAY_BUFFER, this .lineStipples, gl .DYNAMIC_DRAW);

      gl .bindBuffer (gl .ARRAY_BUFFER, this .trianglesBuffer);
      gl .bufferData (gl .ARRAY_BUFFER, new Float32Array (16 * 6 * numLines), gl .DYNAMIC_DRAW);
   },
   updateLengthSoFar: (() =>
   {
      const
         modelViewProjectionMatrix = new Numbers_Matrix4 (),
         point0                    = new Numbers_Vector4 (0, 0, 0, 0),
         point1                    = new Numbers_Vector4 (0, 0, 0, 0),
         projectedPoint0           = new Numbers_Vector2 (0, 0),
         projectedPoint1           = new Numbers_Vector2 (0, 0);

      return function (gl, renderContext)
      {
         const
            viewport         = renderContext .renderObject .getViewVolume () .getViewport (),
            projectionMatrix = renderContext .renderObject .getProjectionMatrix () .get (),
            lineStipples     = this .lineStipples,
            vertices         = this .getVertices () .getValue (),
            numVertices      = vertices .length;

         modelViewProjectionMatrix .assign (renderContext .modelViewMatrix) .multRight (projectionMatrix);

         let lengthSoFar = 0;

         for (let i = 0, l = 0; i < numVertices; i += 8, l += 6)
         {
            point0 .set (vertices [i],     vertices [i + 1], vertices [i + 2], vertices [i + 3]);
            point1 .set (vertices [i + 4], vertices [i + 5], vertices [i + 6], vertices [i + 7]);

            Geometry_ViewVolume .projectPointMatrix (point0, modelViewProjectionMatrix, viewport, projectedPoint0);
            Geometry_ViewVolume .projectPointMatrix (point1, modelViewProjectionMatrix, viewport, projectedPoint1);

            lineStipples [l]     = projectedPoint1 .x;
            lineStipples [l + 1] = projectedPoint1 .y;

            lineStipples [l + 3] = projectedPoint0 .x;
            lineStipples [l + 4] = projectedPoint0 .y;
            lineStipples [l + 5] = lengthSoFar;

            lengthSoFar += projectedPoint1 .subtract (projectedPoint0) .magnitude ();
         }

         gl .bindBuffer (gl .ARRAY_BUFFER, this .lineStippleBuffer);
         gl .bufferData (gl .ARRAY_BUFFER, lineStipples, gl .DYNAMIC_DRAW);
      };
   })(),
   displaySimple (gl, renderContext, shaderNode)
   {
      const linePropertiesNode = renderContext .shapeNode .getAppearance () .getStyleProperties (1);

      if (linePropertiesNode)
      {
         if (linePropertiesNode .getTransformLines ())
         {
            // Setup vertex attributes.

            if (this .thickVertexArrayObject .enable (shaderNode))
            {
               const
                  stride            = 16 * Float32Array .BYTES_PER_ELEMENT,
                  coordIndexOffset  = 0,
                  lineStippleOffset = 1 * Float32Array .BYTES_PER_ELEMENT,
                  normalOffset      = 9 * Float32Array .BYTES_PER_ELEMENT,
                  vertexOffset      = 12 * Float32Array .BYTES_PER_ELEMENT;

               shaderNode .enableCoordIndexAttribute  (gl, this .trianglesBuffer, stride, coordIndexOffset);
               shaderNode .enableLineStippleAttribute (gl, this .trianglesBuffer, stride, lineStippleOffset);

               if (this .hasNormals)
                  shaderNode .enableNormalAttribute (gl, this .trianglesBuffer, stride, normalOffset);

               shaderNode .enableVertexAttribute (gl, this .trianglesBuffer, stride, vertexOffset);

               gl .bindBuffer (gl .ARRAY_BUFFER, null);
            }

            gl .frontFace (gl .CCW);
            gl .enable (gl .CULL_FACE);
            gl .drawArrays (gl .TRIANGLES, 0, this .vertexCount * 3);

            return;
         }
      }

      if (this .vertexArrayObject .enable (shaderNode))
      {
         if (this .coordIndices .length)
            shaderNode .enableCoordIndexAttribute (gl, this .coordIndexBuffer, 0, 0);

         shaderNode .enableLineStippleAttribute (gl, this .lineStippleBuffer, 0, 0);

         if (this .hasNormals)
            shaderNode .enableNormalAttribute (gl, this .normalBuffer, 0, 0);

         shaderNode .enableVertexAttribute (gl, this .vertexBuffer, 0, 0);
      }

      gl .drawArrays (this .primitiveMode, 0, this .vertexCount);
      gl .lineWidth (1);
   },
   display: (() =>
   {
      const
         matrix                            = new Numbers_Matrix4 (),
         modelViewProjectionMatrixArray    = new Float32Array (16),
         invModelViewProjectionMatrixArray = new Float32Array (16);

      return function (gl, renderContext)
      {
         const
            browser            = this .getBrowser (),
            appearanceNode     = renderContext .appearanceNode,
            linePropertiesNode = appearanceNode .getLineProperties (),
            shaderNode         = appearanceNode .getShader (this, renderContext),
            blendModeNode      = appearanceNode .getBlendMode (),
            attribNodes        = this .getAttrib (),
            attribBuffers      = this .getAttribBuffers ();

         if (linePropertiesNode)
         {
            if (linePropertiesNode .getApplied () && linePropertiesNode .getLinetype () !== 1)
               this .updateLengthSoFar (gl, renderContext);

            if (linePropertiesNode .getTransformLines ())
            {
               const
                  renderObject        = renderContext .renderObject,
                  viewport            = renderObject .getViewVolume () .getViewport (),
                  projectionMatrix    = renderObject .getProjectionMatrix () .get (),
                  primitiveMode       = browser .getWireframe () ? gl .TRIANGLES : browser .getPrimitiveMode (gl .TRIANGLES),
                  transformShaderNode = browser .getLineTransformShader ();

               modelViewProjectionMatrixArray .set (matrix .assign (renderContext .modelViewMatrix) .multRight (projectionMatrix));
               invModelViewProjectionMatrixArray .set (matrix .inverse ());

               // Start

               transformShaderNode .enable (gl);

               gl .uniform4f (transformShaderNode .viewport, viewport .x, viewport .y, viewport .z, viewport .w);
               gl .uniformMatrix4fv (transformShaderNode .modelViewProjectionMatrix,    false, modelViewProjectionMatrixArray);
               gl .uniformMatrix4fv (transformShaderNode .invModelViewProjectionMatrix, false, invModelViewProjectionMatrixArray);
               gl .uniform1f (transformShaderNode .scale, linePropertiesNode .getLinewidthScaleFactor () / 2);

               // Setup vertex attributes.

               if (this .thickVertexArrayObject .enable (transformShaderNode))
               {
                  const
                     coordIndexStride   = 2 * Float32Array .BYTES_PER_ELEMENT,
                     coordIndexOffset0  = 0,
                     coordIndexOffset1  = 1 * Float32Array .BYTES_PER_ELEMENT,
                     lineStippleStride  = 6 * Float32Array .BYTES_PER_ELEMENT,
                     lineStippleOffset0 = 0,
                     lineStippleOffset1 = 3 * Float32Array .BYTES_PER_ELEMENT,
                     fogDepthStride     = 2 * Float32Array .BYTES_PER_ELEMENT,
                     fogDepthOffset0    = 0,
                     fogDepthOffset1    = 1 * Float32Array .BYTES_PER_ELEMENT,
                     colorStride        = 8 * Float32Array .BYTES_PER_ELEMENT,
                     colorOffset0       = 0,
                     colorOffset1       = 4 * Float32Array .BYTES_PER_ELEMENT,
                     normalStride       = 6 * Float32Array .BYTES_PER_ELEMENT,
                     normalOffset0      = 0,
                     normalOffset1      = 3 * Float32Array .BYTES_PER_ELEMENT,
                     vertexStride       = 8 * Float32Array .BYTES_PER_ELEMENT,
                     vertexOffset0      = 0,
                     vertexOffset1      = 4 * Float32Array .BYTES_PER_ELEMENT;

                  // for (let i = 0, length = attribNodes .length; i < length; ++ i)
                  //    attribNodes [i] .enable (gl, shaderNode, attribBuffers [i]);

                  if (this .coordIndices .length)
                  {
                     transformShaderNode .enableFloatAttrib (gl, "x3d_CoordIndex0", this .coordIndexBuffer, 1, coordIndexStride, coordIndexOffset0);
                     transformShaderNode .enableFloatAttrib (gl, "x3d_CoordIndex1", this .coordIndexBuffer, 1, coordIndexStride, coordIndexOffset1);
                  }

                  transformShaderNode .enableFloatAttrib (gl, "x3d_LineStipple0", this .lineStippleBuffer, 3, lineStippleStride, lineStippleOffset0);
                  transformShaderNode .enableFloatAttrib (gl, "x3d_LineStipple1", this .lineStippleBuffer, 3, lineStippleStride, lineStippleOffset1);

                  if (this .hasFogCoords)
                  {
                     transformShaderNode .enableFloatAttrib (gl, "x3d_FogDepth0", this .fogDepthBuffer, 1, fogDepthStride, fogDepthOffset0);
                     transformShaderNode .enableFloatAttrib (gl, "x3d_FogDepth1", this .fogDepthBuffer, 1, fogDepthStride, fogDepthOffset1);
                  }

                  if (this .colorMaterial)
                  {
                     transformShaderNode .enableFloatAttrib (gl, "x3d_Color0", this .colorBuffer, 4, colorStride, colorOffset0);
                     transformShaderNode .enableFloatAttrib (gl, "x3d_Color1", this .colorBuffer, 4, colorStride, colorOffset1);
                  }

                  if (this .hasNormals)
                  {
                     transformShaderNode .enableFloatAttrib (gl, "x3d_Normal0", this .normalBuffer, 3, normalStride, normalOffset0);
                     transformShaderNode .enableFloatAttrib (gl, "x3d_Normal1", this .normalBuffer, 3, normalStride, normalOffset1);
                  }

                  transformShaderNode .enableFloatAttrib (gl, "x3d_Vertex0", this .vertexBuffer, 4, vertexStride, vertexOffset0);
                  transformShaderNode .enableFloatAttrib (gl, "x3d_Vertex1", this .vertexBuffer, 4, vertexStride, vertexOffset1);
               }

               // Transform lines.

               gl .bindTransformFeedback (gl .TRANSFORM_FEEDBACK, browser .getLineTransformFeedback ());
               gl .bindBufferBase (gl .TRANSFORM_FEEDBACK_BUFFER, 0, this .trianglesBuffer);
               gl .enable (gl .RASTERIZER_DISCARD);
               gl .beginTransformFeedback (gl .POINTS);
               gl .drawArraysInstanced (gl .POINTS, 0, this .vertexCount / 2, 2);
               gl .endTransformFeedback ();
               gl .disable (gl .RASTERIZER_DISCARD);
               gl .bindTransformFeedback (gl .TRANSFORM_FEEDBACK, null);

               // DEBUG

               // const data = new Float32Array (16 * 6 * this .vertexCount / 2);
               // gl .bindBuffer (gl .ARRAY_BUFFER, this .trianglesBuffer);
               // gl .getBufferSubData (gl .ARRAY_BUFFER, 0, data);
               // console .log (data);

               // Render triangles.

               blendModeNode ?.enable (gl);

               // Setup shader.

               shaderNode .enable (gl);
               shaderNode .setUniforms (gl, this, renderContext);

               // Setup vertex attributes.

               if (this .thickVertexArrayObject .enable (shaderNode))
               {
                  const
                     stride            = 16 * Float32Array .BYTES_PER_ELEMENT,
                     coordIndexOffset  = 0,
                     lineStippleOffset = 1 * Float32Array .BYTES_PER_ELEMENT,
                     fogCoordOffset    = 4 * Float32Array .BYTES_PER_ELEMENT,
                     colorOffset       = 5 * Float32Array .BYTES_PER_ELEMENT,
                     normalOffset      = 9 * Float32Array .BYTES_PER_ELEMENT,
                     vertexOffset      = 12 * Float32Array .BYTES_PER_ELEMENT;

                  // for (let i = 0, length = attribNodes .length; i < length; ++ i)
                  //    attribNodes [i] .enable (gl, shaderNode, attribBuffers [i]);

                  shaderNode .enableCoordIndexAttribute (gl, this .trianglesBuffer, stride, coordIndexOffset);
                  shaderNode .enableLineStippleAttribute (gl, this .trianglesBuffer, stride, lineStippleOffset);

                  if (this .hasFogCoords)
                     shaderNode .enableFogDepthAttribute (gl, this .trianglesBuffer, stride, fogCoordOffset);

                  if (this .colorMaterial)
                     shaderNode .enableColorAttribute (gl, this .trianglesBuffer, stride, colorOffset);

                   if (this .hasNormals)
                     shaderNode .enableNormalAttribute (gl, this .trianglesBuffer, stride, normalOffset);

                  shaderNode .enableVertexAttribute (gl, this .trianglesBuffer, stride, vertexOffset);

                  gl .bindBuffer (gl .ARRAY_BUFFER, null);
               }

               gl .frontFace (gl .CCW);
               gl .enable (gl .CULL_FACE);
               gl .drawArrays (primitiveMode, 0, this .vertexCount * 3);

               blendModeNode ?.disable (gl);

               return;
            }
         }

         const primitiveMode = browser .getPrimitiveMode (this .getPrimitiveMode ());

         blendModeNode ?.enable (gl);

         // Setup shader.

         shaderNode .enable (gl);
         shaderNode .setUniforms (gl, this, renderContext);

         // Setup vertex attributes.

         if (this .vertexArrayObject .enable (shaderNode))
         {
            if (this .coordIndices .length)
               shaderNode .enableCoordIndexAttribute (gl, this .coordIndexBuffer, 0, 0);

            for (let i = 0, length = attribNodes .length; i < length; ++ i)
               attribNodes [i] .enable (gl, shaderNode, attribBuffers [i]);

            shaderNode .enableLineStippleAttribute (gl, this .lineStippleBuffer, 0, 0);

            if (this .hasFogCoords)
               shaderNode .enableFogDepthAttribute (gl, this .fogDepthBuffer, 0, 0);

            if (this .colorMaterial)
               shaderNode .enableColorAttribute (gl, this .colorBuffer, 0, 0);

            if (this .hasNormals)
               shaderNode .enableNormalAttribute (gl, this .normalBuffer, 0, 0);

            shaderNode .enableVertexAttribute (gl, this .vertexBuffer, 0, 0);
         }

         gl .drawArrays (primitiveMode, 0, this .vertexCount);

         blendModeNode ?.disable (gl);

         gl .lineWidth (1);
      };
   })(),
   displayParticles (gl, renderContext, particleSystem)
   {
      const
         browser        = this .getBrowser (),
         appearanceNode = renderContext .appearanceNode,
         shaderNode     = appearanceNode .getShader (this, renderContext),
         blendModeNode  = appearanceNode .getBlendMode (),
         attribNodes    = this .getAttrib (),
         attribBuffers  = this .getAttribBuffers (),
         primitiveMode  = browser .getPrimitiveMode (this .getPrimitiveMode ());

      blendModeNode ?.enable (gl);

      // Setup shader.

      shaderNode .enable (gl);
      shaderNode .setUniforms (gl, this, renderContext);

      // Setup vertex attributes.

      const outputParticles = particleSystem .outputParticles;

      if (outputParticles .vertexArrayObject .update (this .updateParticles) .enable (shaderNode))
      {
         const particleStride = particleSystem .particleStride;

         shaderNode .enableParticleAttribute (gl, outputParticles, particleStride, particleSystem .particleOffset, 1);
         shaderNode .enableParticleMatrixAttribute (gl, outputParticles, particleStride, particleSystem .matrixOffset, 1);

         for (let i = 0, length = attribNodes .length; i < length; ++ i)
            attribNodes [i] .enable (gl, shaderNode, attribBuffers [i]);

         if (this .hasFogCoords)
            shaderNode .enableFogDepthAttribute (gl, this .fogDepthBuffer, 0, 0);

         if (this .colorMaterial)
            shaderNode .enableColorAttribute (gl, this .colorBuffer, 0, 0);

         if (this .hasNormals)
            shaderNode .enableNormalAttribute (gl, this .normalBuffer, 0, 0);

         shaderNode .enableVertexAttribute (gl, this .vertexBuffer, 0, 0);

         this .updateParticles = false;
      }

      // Wireframes are always solid so only one drawing call is needed.

      gl .drawArraysInstanced (primitiveMode, 0, this .vertexCount, particleSystem .numParticles);

      blendModeNode ?.disable (gl);

      gl .lineWidth (1);
   },
});

Object .defineProperties (X3DLineGeometryNode,
{
   typeName:
   {
      value: "X3DLineGeometryNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
});

const X3DLineGeometryNode_default_ = X3DLineGeometryNode;
;

x_ite_Namespace .add ("X3DLineGeometryNode", "x_ite/Components/Rendering/X3DLineGeometryNode", X3DLineGeometryNode_default_);
/* harmony default export */ const Rendering_X3DLineGeometryNode = (X3DLineGeometryNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/IndexedLineSet.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function IndexedLineSet (executionContext)
{
   Rendering_X3DLineGeometryNode .call (this, executionContext);

   this .addType (Base_X3DConstants .IndexedLineSet);

   this .fogCoordNode = null;
   this .colorNode    = null;
   this .normalNode   = null;
   this .coordNode    = null;
}

Object .assign (Object .setPrototypeOf (IndexedLineSet .prototype, Rendering_X3DLineGeometryNode .prototype),
{
   initialize ()
   {
      Rendering_X3DLineGeometryNode .prototype .initialize .call (this);

      this ._set_colorIndex .addFieldInterest (this ._colorIndex);
      this ._set_coordIndex .addFieldInterest (this ._coordIndex);
      this ._attrib         .addInterest ("set_attrib__",   this);
      this ._fogCoord       .addInterest ("set_fogCoord__", this);
      this ._color          .addInterest ("set_color__",    this);
      this ._normal         .addInterest ("set_normal__",   this);
      this ._coord          .addInterest ("set_coord__",    this);

      this .set_attrib__ ();
      this .set_fogCoord__ ();
      this .set_color__ ();
      this .set_normal__ ();
      this .set_coord__ ();
   },
   set_attrib__ ()
   {
      const attribNodes = this .getAttrib ();

      for (const attribNode of attribNodes)
      {
         attribNode .removeInterest ("requestRebuild", this);
         attribNode ._attribute_changed .removeInterest ("updateVertexArrays", this);
      }

      attribNodes .length = 0;

      for (const node of this ._attrib)
      {
         const attribNode = Base_X3DCast (Base_X3DConstants .X3DVertexAttributeNode, node);

         if (attribNode)
            attribNodes .push (attribNode);
      }

      for (const attribNode of attribNodes)
      {
         attribNode .addInterest ("requestRebuild", this);
         attribNode ._attribute_changed .addInterest ("updateVertexArrays", this);
      }

      this .updateVertexArrays ();
   },
   set_fogCoord__ ()
   {
      this .fogCoordNode ?.removeInterest ("requestRebuild", this);

      this .fogCoordNode = Base_X3DCast (Base_X3DConstants .FogCoordinate, this ._fogCoord);

      this .fogCoordNode ?.addInterest ("requestRebuild", this);
   },
   set_color__ ()
   {
      this .colorNode ?.removeInterest ("requestRebuild", this);

      this .colorNode = Base_X3DCast (Base_X3DConstants .X3DColorNode, this ._color);

      this .colorNode ?.addInterest ("requestRebuild", this);

      this .setTransparent (this .colorNode ?.isTransparent () ?? false);
   },
   set_normal__ ()
   {
      this .normalNode ?.removeInterest ("requestRebuild", this);

      this .normalNode = Base_X3DCast (Base_X3DConstants .X3DNormalNode, this ._normal);

      this .normalNode ?.addInterest ("requestRebuild", this);
   },
   set_coord__ ()
   {
      this .coordNode ?.removeInterest ("requestRebuild", this);

      this .coordNode = Base_X3DCast (Base_X3DConstants .X3DCoordinateNode, this ._coord);

      this .coordNode ?.addInterest ("requestRebuild", this);
   },
   getColorPerVertexIndex (index)
   {
      if (index < this ._colorIndex .length)
         return this ._colorIndex [index];

      return this ._coordIndex [index];
   },
   getColorIndex (index)
   {
      if (index < this ._colorIndex .length)
         return this ._colorIndex [index];

      return index;
   },
   getPolylineIndices ()
   {
      const
         coordIndex = this ._coordIndex,
         polylines  = [ ];

      let polyline = [ ];

      if (coordIndex .length)
      {
         for (let i = 0, length = coordIndex .length; i < length; ++ i)
         {
            const index = coordIndex [i];

            if (index >= 0)
               // Add vertex.
               polyline .push (i);

            else
            {
               // Negativ index.
               // Add polylines.
               polylines .push (polyline);

               polyline = [ ];
            }
         }

         if (coordIndex [coordIndex .length - 1] >= 0)
         {
            polylines .push (polyline);
         }
      }

      return polylines;
   },
   build ()
   {
      if (! this .coordNode || this .coordNode .isEmpty ())
         return;

      const
         coordIndex        = this ._coordIndex,
         polylines         = this .getPolylineIndices (),
         colorPerVertex    = this ._colorPerVertex .getValue (),
         coordIndicesArray = this .getCoordIndices (),
         attribNodes       = this .getAttrib (),
         numAttribNodes    = attribNodes .length,
         attribArrays      = this .getAttribs (),
         fogCoordNode      = this .fogCoordNode,
         colorNode         = this .colorNode,
         coordNode         = this .coordNode,
         normalNode        = this .normalNode,
         fogDepthArray     = this .getFogDepths (),
         colorArray        = this .getColors (),
         normalArray       = this .getNormals (),
         vertexArray       = this .getVertices ();

      // Fill GeometryNode

      let face = 0;

      for (const polyline of polylines)
      {
         // Create two vertices for each line.

         if (polyline .length > 1)
         {
            for (let line = 0, l_end = polyline .length - 1; line < l_end; ++ line)
            {
               for (let l = line, i_end = line + 2; l < i_end; ++ l)
               {
                  const
                     i     = polyline [l],
                     index = coordIndex [i];

                  coordIndicesArray .push (index);

                  for (let a = 0; a < numAttribNodes; ++ a)
                     attribNodes [a] .addValue (index, attribArrays [a]);

                  fogCoordNode ?.addDepth (index, fogDepthArray);

                  if (colorNode)
                  {
                     if (colorPerVertex)
                        colorNode .addColor (this .getColorPerVertexIndex (i), colorArray);
                     else
                        colorNode .addColor (this .getColorIndex (face), colorArray);
                  }

                  normalNode ?.addVector (index, normalArray);

                  coordNode .addPoint (index, vertexArray);
               }
            }
         }

         ++ face;
      }
   },
});

Object .defineProperties (IndexedLineSet,
{
   typeName:
   {
      value: "IndexedLineSet",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
   containerField:
   {
      value: "geometry",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",       new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_colorIndex", new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_coordIndex", new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "colorPerVertex", new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "colorIndex",     new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "coordIndex",     new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "attrib",         new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "fogCoord",       new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "color",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "normal",         new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "coord",          new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const IndexedLineSet_default_ = IndexedLineSet;
;

x_ite_Namespace .add ("IndexedLineSet", "x_ite/Components/Rendering/IndexedLineSet", IndexedLineSet_default_);
/* harmony default export */ const Rendering_IndexedLineSet = (IndexedLineSet_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/IndexedTriangleFanSet.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function IndexedTriangleFanSet (executionContext)
{
   Rendering_X3DComposedGeometryNode .call (this, executionContext);

   this .addType (Base_X3DConstants .IndexedTriangleFanSet);

   this .triangleIndex = [ ];
}

Object .assign (Object .setPrototypeOf (IndexedTriangleFanSet .prototype, Rendering_X3DComposedGeometryNode .prototype),
{
   initialize ()
   {
      Rendering_X3DComposedGeometryNode .prototype .initialize .call (this);

      this ._set_index .addFieldInterest (this ._index);
      this ._index     .addInterest ("set_index__", this);

      this .set_index__ ();
   },
   set_index__ ()
   {
      // Build coordIndex

      const
         index         = this ._index,
         triangleIndex = this .triangleIndex;

      triangleIndex .length = 0;

      for (let i = 0, length = index .length; i < length; ++ i)
      {
         const first = index [i];

         if (first < 0)
            continue;

         if (++ i < length)
         {
            let second = index [i];

            if (second < 0)
               continue;

            for (++ i; i < length; ++ i)
            {
               const third = index [i];

               if (third < 0)
                  break;

               triangleIndex .push (first, second, third);

               second = third;
            }
         }
      }
   },
   getPolygonIndex (index)
   {
      return this .triangleIndex [index];
   },
   build ()
   {
      Rendering_X3DComposedGeometryNode .prototype .build .call (this, 3, this .triangleIndex .length, 3, this .triangleIndex .length);
   },
});

Object .defineProperties (IndexedTriangleFanSet,
{
   typeName:
   {
      value: "IndexedTriangleFanSet",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
   containerField:
   {
      value: "geometry",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_index",       new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "solid",           new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "ccw",             new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "colorPerVertex",  new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "normalPerVertex", new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "index",           new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "attrib",          new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "fogCoord",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "color",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "texCoord",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "normal",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "coord",           new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const IndexedTriangleFanSet_default_ = IndexedTriangleFanSet;
;

x_ite_Namespace .add ("IndexedTriangleFanSet", "x_ite/Components/Rendering/IndexedTriangleFanSet", IndexedTriangleFanSet_default_);
/* harmony default export */ const Rendering_IndexedTriangleFanSet = (IndexedTriangleFanSet_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/IndexedTriangleSet.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function IndexedTriangleSet (executionContext)
{
   Rendering_X3DComposedGeometryNode .call (this, executionContext);

   this .addType (Base_X3DConstants .IndexedTriangleSet);
}

Object .assign (Object .setPrototypeOf (IndexedTriangleSet .prototype, Rendering_X3DComposedGeometryNode .prototype),
{
   getPolygonIndex (i)
   {
      return this ._index [i];
   },
   initialize ()
   {
      Rendering_X3DComposedGeometryNode .prototype .initialize .call (this);

      this ._set_index .addFieldInterest (this ._index);
   },
   build ()
   {
      Rendering_X3DComposedGeometryNode .prototype .build .call (this, 3, this ._index .length, 3, this ._index .length);
   },
});

Object .defineProperties (IndexedTriangleSet,
{
   typeName:
   {
      value: "IndexedTriangleSet",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
   containerField:
   {
      value: "geometry",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_index",       new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "solid",           new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "ccw",             new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "colorPerVertex",  new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "normalPerVertex", new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "index",           new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "attrib",          new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "fogCoord",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "color",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "texCoord",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "normal",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "coord",           new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const IndexedTriangleSet_default_ = IndexedTriangleSet;
;

x_ite_Namespace .add ("IndexedTriangleSet", "x_ite/Components/Rendering/IndexedTriangleSet", IndexedTriangleSet_default_);
/* harmony default export */ const Rendering_IndexedTriangleSet = (IndexedTriangleSet_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/IndexedTriangleStripSet.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function IndexedTriangleStripSet (executionContext)
{
   Rendering_X3DComposedGeometryNode .call (this, executionContext);

   this .addType (Base_X3DConstants .IndexedTriangleStripSet);

   this .triangleIndex = [ ];
}

Object .assign (Object .setPrototypeOf (IndexedTriangleStripSet .prototype, Rendering_X3DComposedGeometryNode .prototype),
{
   initialize ()
   {
      Rendering_X3DComposedGeometryNode .prototype .initialize .call (this);

      this ._set_index .addFieldInterest (this ._index);
      this ._index     .addInterest ("set_index__", this);

      this .set_index__ ();
   },
   set_index__ ()
   {
      // Build coordIndex

      const
         index         = this ._index,
         triangleIndex = this .triangleIndex;

      triangleIndex .length = 0;

      // Build coordIndex

      for (let i = 0, length = index .length; i < length; ++ i)
      {
         let first = index [i];

         if (first < 0)
            continue;

         if (++ i < length)
         {
            let second = index [i];

            if (second < 0)
               continue;

            ++ i;

            for (let face = 0; i < length; ++ i, ++ face)
            {
               const third = index [i];

               if (third < 0)
                  break;

               triangleIndex .push (first, second, third);

               if (face & 1)
                  second = third;

               else
                  first = third;
            }
         }
      }
   },
   getPolygonIndex (index)
   {
      return this .triangleIndex [index];
   },
   build ()
   {
      Rendering_X3DComposedGeometryNode .prototype .build .call (this, 3, this .triangleIndex .length, 3, this .triangleIndex .length);
   },
});

Object .defineProperties (IndexedTriangleStripSet,
{
   typeName:
   {
      value: "IndexedTriangleStripSet",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
   containerField:
   {
      value: "geometry",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "set_index",       new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "solid",           new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "ccw",             new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "colorPerVertex",  new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "normalPerVertex", new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "index",           new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "attrib",          new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "fogCoord",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "color",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "texCoord",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "normal",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "coord",           new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const IndexedTriangleStripSet_default_ = IndexedTriangleStripSet;
;

x_ite_Namespace .add ("IndexedTriangleStripSet", "x_ite/Components/Rendering/IndexedTriangleStripSet", IndexedTriangleStripSet_default_);
/* harmony default export */ const Rendering_IndexedTriangleStripSet = (IndexedTriangleStripSet_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/LineSet.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function LineSet (executionContext)
{
   Rendering_X3DLineGeometryNode .call (this, executionContext);

   this .addType (Base_X3DConstants .LineSet);

   this .fogCoordNode = null;
   this .colorNode    = null;
   this .normalNode   = null;
   this .coordNode    = null;
}

Object .assign (Object .setPrototypeOf (LineSet .prototype, Rendering_X3DLineGeometryNode .prototype),
{
   initialize ()
   {
      Rendering_X3DLineGeometryNode .prototype .initialize .call (this);

      this ._attrib   .addInterest ("set_attrib__",   this);
      this ._fogCoord .addInterest ("set_fogCoord__", this);
      this ._color    .addInterest ("set_color__",    this);
      this ._normal   .addInterest ("set_normal__",   this);
      this ._coord    .addInterest ("set_coord__",    this);

      this .set_attrib__ ();
      this .set_fogCoord__ ();
      this .set_color__ ();
      this .set_normal__ ();
      this .set_coord__ ();
   },
   set_attrib__ ()
   {
      const attribNodes = this .getAttrib ();

      for (const attribNode of attribNodes)
      {
         attribNode .removeInterest ("requestRebuild", this);
         attribNode ._attribute_changed .removeInterest ("updateVertexArrays", this);
      }

      attribNodes .length = 0;

      for (const node of this ._attrib)
      {
         const attribNode = Base_X3DCast (Base_X3DConstants .X3DVertexAttributeNode, node);

         if (attribNode)
            attribNodes .push (attribNode);
      }

      for (const attribNode of attribNodes)
      {
         attribNode .addInterest ("requestRebuild", this);
         attribNode ._attribute_changed .addInterest ("updateVertexArrays", this);
      }

      this .updateVertexArrays ();
   },
   set_fogCoord__ ()
   {
      this .fogCoordNode ?.removeInterest ("requestRebuild", this);

      this .fogCoordNode = Base_X3DCast (Base_X3DConstants .FogCoordinate, this ._fogCoord);

      this .fogCoordNode ?.addInterest ("requestRebuild", this);
   },
   set_color__ ()
   {
      this .colorNode ?.removeInterest ("requestRebuild", this);

      this .colorNode = Base_X3DCast (Base_X3DConstants .X3DColorNode, this ._color);

      this .colorNode ?.addInterest ("requestRebuild", this);

      this .setTransparent (this .colorNode ?.isTransparent () ?? false);
   },
   set_normal__ ()
   {
      this .normalNode ?.removeInterest ("requestRebuild", this);

      this .normalNode = Base_X3DCast (Base_X3DConstants .X3DNormalNode, this ._normal);

      this .normalNode ?.addInterest ("requestRebuild", this);
   },
   set_coord__ ()
   {
      this .coordNode ?.removeInterest ("requestRebuild", this);

      this .coordNode = Base_X3DCast (Base_X3DConstants .X3DCoordinateNode, this ._coord);

      this .coordNode ?.addInterest ("requestRebuild", this);
   },
   build ()
   {
      if (! this .coordNode || this .coordNode .isEmpty ())
         return;

      // Fill GeometryNode

      const
         vertexCount       = this ._vertexCount,
         coordIndicesArray = this .getCoordIndices (),
         attribNodes       = this .getAttrib (),
         numAttribNodes    = attribNodes .length,
         attribArrays      = this .getAttribs (),
         fogCoordNode      = this .fogCoordNode,
         colorNode         = this .colorNode,
         normalNode        = this .normalNode,
         coordNode         = this .coordNode,
         fogDepthArray     = this .getFogDepths (),
         colorArray        = this .getColors (),
         normalArray       = this .getNormals (),
         vertexArray       = this .getVertices (),
         size              = coordNode .getSize ();

      let index = 0;

      for (let count of vertexCount)
      {
         if (index + count > size)
            break;

         if (count > 1)
         {
            count = 2 * count - 2; // numVertices for line lines trip

            for (let i = 0; i < count; ++ i, index += i & 1)
            {
               coordIndicesArray .push (index);

               for (let a = 0; a < numAttribNodes; ++ a)
                  attribNodes [a] .addValue (index, attribArrays [a]);

               fogCoordNode ?.addDepth  (index, fogDepthArray);
               colorNode    ?.addColor  (index, colorArray);
               normalNode   ?.addVector (index, normalArray);

               coordNode .addPoint (index, vertexArray);
            }

            ++ index;
         }
         else
            index += count;
      }
   },
});

Object .defineProperties (LineSet,
{
   typeName:
   {
      value: "LineSet",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
   containerField:
   {
      value: "geometry",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",    new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "vertexCount", new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "attrib",      new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "fogCoord",    new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "color",       new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "normal",      new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "coord",       new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const LineSet_default_ = LineSet;
;

x_ite_Namespace .add ("LineSet", "x_ite/Components/Rendering/LineSet", LineSet_default_);
/* harmony default export */ const Rendering_LineSet = (LineSet_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/X3DNormalNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function X3DNormalNode (executionContext)
{
   Rendering_X3DGeometricPropertyNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DNormalNode);
}

Object .setPrototypeOf (X3DNormalNode .prototype, Rendering_X3DGeometricPropertyNode .prototype);

Object .defineProperties (X3DNormalNode,
{
   typeName:
   {
      value: "X3DNormalNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
});

const X3DNormalNode_default_ = X3DNormalNode;
;

x_ite_Namespace .add ("X3DNormalNode", "x_ite/Components/Rendering/X3DNormalNode", X3DNormalNode_default_);
/* harmony default export */ const Rendering_X3DNormalNode = (X3DNormalNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/Normal.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function Normal (executionContext)
{
   Rendering_X3DNormalNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Normal);
}

Object .assign (Object .setPrototypeOf (Normal .prototype, Rendering_X3DNormalNode .prototype),
{
   initialize ()
   {
      Rendering_X3DNormalNode .prototype .initialize .call (this);

      this ._vector .addInterest ("set_vector__", this);

      this .set_vector__ ();
   },
   set_vector__ ()
   {
      this .vector = this ._vector .getValue ();
      this .length = this ._vector .length;
   },
   addVector (index, array)
   {
      if (index >= 0 && this .length)
      {
         const
            vector = this .vector,
            i      = (index % this .length) * 3;

         array .push (vector [i], vector [i + 1], vector [i + 2]);
      }
      else
      {
         return array .push (0, 0, 0);
      }
   },
   addNormals (array, min = this .length)
   {
      const length = this .length;

      if (length)
      {
         const vector = this .vector;

         for (let index = 0; index < min; ++ index)
         {
            const i = (index % length) * 3;

            array .push (vector [i], vector [i + 1], vector [i + 2]);
         }
      }
      else
      {
         for (let index = 0; index < min; ++ index)
            array .push (0, 0, 0);
      }

      return array;
   },
});

Object .defineProperties (Normal,
{
   typeName:
   {
      value: "Normal",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
   containerField:
   {
      value: "normal",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "vector",   new x_ite_Fields .MFVec3f ()),
      ]),
      enumerable: true,
   },
});

const Normal_default_ = Normal;
;

x_ite_Namespace .add ("Normal", "x_ite/Components/Rendering/Normal", Normal_default_);
/* harmony default export */ const Rendering_Normal = (Normal_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/X3DPointGeometryNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function X3DPointGeometryNode (executionContext)
{
   Rendering_X3DGeometryNode .call (this, executionContext);

   const browser = this .getBrowser ();

   this .setGeometryType (0);
   this .setPrimitiveMode (browser .getContext () .POINTS);
   this .setSolid (false);
   this .setTransparent (true);
}

Object .assign (Object .setPrototypeOf (X3DPointGeometryNode .prototype, Rendering_X3DGeometryNode .prototype),
{
   intersectsLine ()
   {
      return false;
   },
   intersectsBox ()
   {
      return false;
   },
   buildTexCoords ()
   { },
   display (gl, renderContext)
   {
      const
         appearanceNode = renderContext .appearanceNode,
         shaderNode     = appearanceNode .getShader (this, renderContext),
         blendModeNode  = appearanceNode .getBlendMode (),
         attribNodes    = this .getAttrib (),
         attribBuffers  = this .getAttribBuffers ();

      blendModeNode ?.enable (gl);

      // Setup shader.

      shaderNode .enable (gl);
      shaderNode .setUniforms (gl, this, renderContext);

      // Setup vertex attributes.

      if (this .vertexArrayObject .enable (shaderNode))
      {
         if (this .coordIndices .length)
            shaderNode .enableCoordIndexAttribute (gl, this .coordIndexBuffer, 0, 0);

         for (let i = 0, length = attribNodes .length; i < length; ++ i)
            attribNodes [i] .enable (gl, shaderNode, attribBuffers [i]);

         if (this .hasFogCoords)
            shaderNode .enableFogDepthAttribute (gl, this .fogDepthBuffer, 0, 0);

         if (this .colorMaterial)
            shaderNode .enableColorAttribute (gl, this .colorBuffer, 0, 0);

         if (this .hasNormals)
            shaderNode .enableNormalAttribute (gl, this .normalBuffer, 0, 0);

         shaderNode .enableVertexAttribute (gl, this .vertexBuffer, 0, 0);
      }

      gl .drawArrays (this .primitiveMode, 0, this .vertexCount);

      blendModeNode ?.disable (gl);
   },
   displayParticles (gl, renderContext, particleSystem)
   {
      const
         appearanceNode = renderContext .appearanceNode,
         shaderNode     = appearanceNode .getShader (this, renderContext),
         blendModeNode  = appearanceNode .getBlendMode (),
         attribNodes    = this .getAttrib (),
         attribBuffers  = this .getAttribBuffers ();

      blendModeNode ?.enable (gl);

      // Setup shader.

      shaderNode .enable (gl);
      shaderNode .setUniforms (gl, this, renderContext);

      // Setup vertex attributes.

      const outputParticles = particleSystem .outputParticles;

      if (outputParticles .vertexArrayObject .update (this .updateParticles) .enable (shaderNode))
      {
         const particleStride = particleSystem .particleStride;

         shaderNode .enableParticleAttribute (gl, outputParticles, particleStride, particleSystem .particleOffset, 1);
         shaderNode .enableParticleMatrixAttribute (gl, outputParticles, particleStride, particleSystem .matrixOffset, 1);

         for (let i = 0, length = attribNodes .length; i < length; ++ i)
            attribNodes [i] .enable (gl, shaderNode, attribBuffers [i]);

         if (this .hasFogCoords)
            shaderNode .enableFogDepthAttribute (gl, this .fogDepthBuffer, 0, 0);

         if (this .colorMaterial)
            shaderNode .enableColorAttribute (gl, this .colorBuffer, 0, 0);

         if (this .hasNormals)
            shaderNode .enableNormalAttribute (gl, this .normalBuffer, 0, 0);

         shaderNode .enableVertexAttribute (gl, this .vertexBuffer, 0, 0);

         this .updateParticles = false;
      }

      // Wireframes are always solid so only one drawing call is needed.

      gl .drawArraysInstanced (this .primitiveMode, 0, this .vertexCount, particleSystem .numParticles);

      blendModeNode ?.disable (gl);
   },
});

Object .defineProperties (X3DPointGeometryNode,
{
   typeName:
   {
      value: "X3DPointGeometryNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
});

const X3DPointGeometryNode_default_ = X3DPointGeometryNode;
;

x_ite_Namespace .add ("X3DPointGeometryNode", "x_ite/Components/Rendering/X3DPointGeometryNode", X3DPointGeometryNode_default_);
/* harmony default export */ const Rendering_X3DPointGeometryNode = (X3DPointGeometryNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/PointSet.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function PointSet (executionContext)
{
   Rendering_X3DPointGeometryNode .call (this, executionContext);

   this .addType (Base_X3DConstants .PointSet);

   this .fogCoordNode = null;
   this .colorNode    = null;
   this .normalNode   = null;
   this .coordNode    = null;
}

Object .assign (Object .setPrototypeOf (PointSet .prototype, Rendering_X3DPointGeometryNode .prototype),
{
   initialize ()
   {
      Rendering_X3DPointGeometryNode .prototype .initialize .call (this);

      this ._attrib   .addInterest ("set_attrib__",   this);
      this ._fogCoord .addInterest ("set_fogCoord__", this);
      this ._color    .addInterest ("set_color__",    this);
      this ._normal   .addInterest ("set_normal__",   this);
      this ._coord    .addInterest ("set_coord__",    this);

      this .set_attrib__ ();
      this .set_fogCoord__ ();
      this .set_color__ ();
      this .set_normal__ ();
      this .set_coord__ ();
   },
   getCoord ()
   {
      return this .coordNode;
   },
   set_attrib__ ()
   {
      const attribNodes = this .getAttrib ();

      for (const attribNode of attribNodes)
      {
         attribNode .removeInterest ("requestRebuild", this);
         attribNode ._attribute_changed .removeInterest ("updateVertexArrays", this);
      }

      attribNodes .length = 0;

      for (const node of this ._attrib)
      {
         const attribNode = Base_X3DCast (Base_X3DConstants .X3DVertexAttributeNode, node);

         if (attribNode)
            attribNodes .push (attribNode);
      }

      for (const attribNode of attribNodes)
      {
         attribNode .addInterest ("requestRebuild", this);
         attribNode ._attribute_changed .addInterest ("updateVertexArrays", this);
      }

      this .updateVertexArrays ();
   },
   set_fogCoord__ ()
   {
      this .fogCoordNode ?.removeInterest ("requestRebuild", this);

      this .fogCoordNode = Base_X3DCast (Base_X3DConstants .FogCoordinate, this ._fogCoord);

      this .fogCoordNode ?.addInterest ("requestRebuild", this);
   },
   set_color__ ()
   {
      this .colorNode ?.removeInterest ("requestRebuild", this);

      this .colorNode = Base_X3DCast (Base_X3DConstants .X3DColorNode, this ._color);

      this .colorNode ?.addInterest ("requestRebuild", this);
   },
   set_normal__ ()
   {
      this .normalNode ?.removeInterest ("requestRebuild", this);

      this .normalNode = Base_X3DCast (Base_X3DConstants .X3DNormalNode, this ._normal);

      this .normalNode ?.addInterest ("requestRebuild", this);
   },
   set_coord__ ()
   {
      this .coordNode ?.removeInterest ("requestRebuild", this);

      this .coordNode = Base_X3DCast (Base_X3DConstants .X3DCoordinateNode, this ._coord);

      this .coordNode ?.addInterest ("requestRebuild", this);
   },
   build ()
   {
      if (! this .coordNode || this .coordNode .isEmpty ())
         return;

      const
         coordIndicesArray = this .getCoordIndices (),
         attribNodes       = this .getAttrib (),
         numAttribNodes    = attribNodes .length,
         attribArrays      = this .getAttribs (),
         fogCoordNode      = this .fogCoordNode,
         fogDepthArray     = this .getFogDepths (),
         colorNode         = this .colorNode,
         colorArray        = this .getColors (),
         coordNode         = this .coordNode,
         normalArray       = this .getNormals (),
         normalNode        = this .normalNode,
         vertexArray       = this .getVertices (),
         numPoints         = coordNode ._point .length;

      for (let i = 0; i < numPoints; ++ i)
         coordIndicesArray .push (i);

      for (let a = 0; a < numAttribNodes; ++ a)
      {
         for (let i = 0; i < numPoints; ++ i)
            attribNodes [a] .addValue (i, attribArrays [a]);
      }

      fogCoordNode ?.addDepths  (fogDepthArray, numPoints);
      colorNode    ?.addColors  (colorArray,    numPoints);
      normalNode   ?.addNormals (normalArray,   numPoints);

      coordNode .addPoints (vertexArray);
   },
});

Object .defineProperties (PointSet,
{
   typeName:
   {
      value: "PointSet",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
   containerField:
   {
      value: "geometry",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "attrib",   new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "fogCoord", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "color",    new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "normal",   new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "coord",    new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const PointSet_default_ = PointSet;
;

x_ite_Namespace .add ("PointSet", "x_ite/Components/Rendering/PointSet", PointSet_default_);
/* harmony default export */ const Rendering_PointSet = (PointSet_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/TriangleFanSet.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function TriangleFanSet (executionContext)
{
   Rendering_X3DComposedGeometryNode .call (this, executionContext);

   this .addType (Base_X3DConstants .TriangleFanSet);

   this .triangleIndex = [ ];
}

Object .assign (Object .setPrototypeOf (TriangleFanSet .prototype, Rendering_X3DComposedGeometryNode .prototype),
{
   initialize ()
   {
      Rendering_X3DComposedGeometryNode .prototype .initialize .call (this);

      this ._fanCount .addInterest ("set_fanCount__", this);

      this .set_fanCount__ ();
   },
   set_fanCount__ ()
   {
      // Build coordIndex

      const
         fanCount      = this ._fanCount,
         triangleIndex = this .triangleIndex;

      triangleIndex .length = 0;

      let index = 0;

      for (const vertexCount of fanCount)
      {
         for (let i = 1, length = vertexCount - 1; i < length; ++ i)
         {
            triangleIndex .push (index, index + i, index + i + 1);
         }

         index += vertexCount;
      }
   },
   getPolygonIndex (index)
   {
      return this .triangleIndex [index];
   },
   build ()
   {
      Rendering_X3DComposedGeometryNode .prototype .build .call (this, 3, this .triangleIndex .length, 3, this .triangleIndex .length);
   },
});

Object .defineProperties (TriangleFanSet,
{
   typeName:
   {
      value: "TriangleFanSet",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
   containerField:
   {
      value: "geometry",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "solid",           new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "ccw",             new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "colorPerVertex",  new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "normalPerVertex", new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "fanCount",        new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "attrib",          new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "fogCoord",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "color",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "texCoord",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "normal",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "coord",           new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const TriangleFanSet_default_ = TriangleFanSet;
;

x_ite_Namespace .add ("TriangleFanSet", "x_ite/Components/Rendering/TriangleFanSet", TriangleFanSet_default_);
/* harmony default export */ const Rendering_TriangleFanSet = (TriangleFanSet_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/TriangleSet.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function TriangleSet (executionContext)
{
   Rendering_X3DComposedGeometryNode .call (this, executionContext);

   this .addType (Base_X3DConstants .TriangleSet);
}

Object .assign (Object .setPrototypeOf (TriangleSet .prototype, Rendering_X3DComposedGeometryNode .prototype),
{
   build ()
   {
      if (! this .getCoord ())
         return;

      Rendering_X3DComposedGeometryNode .prototype .build .call (this, 3, this .getCoord () .getSize (), 3, this .getCoord () .getSize ());
   },
   createNormals (verticesPerPolygon, polygonsSize)
   {
      return this .createFaceNormals (verticesPerPolygon, polygonsSize);
   },
});

Object .defineProperties (TriangleSet,
{
   typeName:
   {
      value: "TriangleSet",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
   containerField:
   {
      value: "geometry",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "solid",           new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "ccw",             new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "colorPerVertex",  new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "normalPerVertex", new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "attrib",          new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "fogCoord",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "color",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "texCoord",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "normal",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "coord",           new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const TriangleSet_default_ = TriangleSet;
;

x_ite_Namespace .add ("TriangleSet", "x_ite/Components/Rendering/TriangleSet", TriangleSet_default_);
/* harmony default export */ const Rendering_TriangleSet = (TriangleSet_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering/TriangleStripSet.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function TriangleStripSet (executionContext)
{
   Rendering_X3DComposedGeometryNode .call (this, executionContext);

   this .addType (Base_X3DConstants .TriangleStripSet);

   this .triangleIndex = [ ];
}

Object .assign (Object .setPrototypeOf (TriangleStripSet .prototype, Rendering_X3DComposedGeometryNode .prototype),
{
   initialize ()
   {
      Rendering_X3DComposedGeometryNode .prototype .initialize .call (this);

      this ._stripCount .addInterest ("set_stripCount__", this);

      this .set_stripCount__ ();
   },
   set_stripCount__ ()
   {
      // Build coordIndex

      const
         stripCount    = this ._stripCount,
         triangleIndex = this .triangleIndex;

      triangleIndex .length = 0;

      let index = 0;

      for (const vertexCount of stripCount)
      {
         for (let i = 0, count = vertexCount - 2; i < count; ++ i)
         {
            const is_odd = i & 1;

            triangleIndex .push (index + (is_odd ? i + 1 : i),
                                 index + (is_odd ? i : i + 1),
                                 index + (i + 2));
         }

         index += vertexCount;
      }
   },
   getPolygonIndex (index)
   {
      return this .triangleIndex [index];
   },
   build ()
   {
      Rendering_X3DComposedGeometryNode .prototype .build .call (this, 3, this .triangleIndex .length, 3, this .triangleIndex .length);
   },
});

Object .defineProperties (TriangleStripSet,
{
   typeName:
   {
      value: "TriangleStripSet",
      enumerable: true,
   },
   componentName:
   {
      value: "Rendering",
      enumerable: true,
   },
   containerField:
   {
      value: "geometry",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "solid",           new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "ccw",             new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "colorPerVertex",  new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "normalPerVertex", new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "stripCount",      new x_ite_Fields .MFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "attrib",          new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "fogCoord",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "color",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "texCoord",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "normal",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "coord",           new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const TriangleStripSet_default_ = TriangleStripSet;
;

x_ite_Namespace .add ("TriangleStripSet", "x_ite/Components/Rendering/TriangleStripSet", TriangleStripSet_default_);
/* harmony default export */ const Rendering_TriangleStripSet = (TriangleStripSet_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Rendering.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/























const Rendering_default_ = {
   name: "Rendering",
   concreteNodes:
   [
      Rendering_ClipPlane,
      Rendering_Color,
      Rendering_ColorRGBA,
      Rendering_Coordinate,
      Rendering_IndexedLineSet,
      Rendering_IndexedTriangleFanSet,
      Rendering_IndexedTriangleSet,
      Rendering_IndexedTriangleStripSet,
      Rendering_LineSet,
      Rendering_Normal,
      Rendering_PointSet,
      Rendering_TriangleFanSet,
      Rendering_TriangleSet,
      Rendering_TriangleStripSet,
   ],
   abstractNodes:
   [
      Rendering_X3DColorNode,
      Rendering_X3DComposedGeometryNode,
      Rendering_X3DCoordinateNode,
      Rendering_X3DGeometricPropertyNode,
      Rendering_X3DGeometryNode,
      Rendering_X3DLineGeometryNode,
      Rendering_X3DNormalNode,
   ],
};
;

x_ite_Namespace .add ("Rendering", "x_ite/Components/Rendering", Rendering_default_);
/* harmony default export */ const Rendering = (Rendering_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shaders/X3DShaderNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function X3DShaderNode (executionContext)
{
   Shape_X3DAppearanceChildNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DShaderNode);

   this .valid    = false;
   this .selected = 0;
}

Object .assign (Object .setPrototypeOf (X3DShaderNode .prototype, Shape_X3DAppearanceChildNode .prototype),
{
   setValid (value)
   {
      this ._isValid = this .valid = value;
   },
   isValid ()
   {
      return this .valid;
   },
   select ()
   {
      ++ this .selected;

      if (! this ._isSelected .getValue ())
         this ._isSelected = true;
   },
   deselect ()
   {
      -- this .selected;

      if (this .selected === 0)
      {
         if (this ._isSelected .getValue ())
            this ._isSelected = false;
      }
   },
});

Object .defineProperties (X3DShaderNode,
{
   typeName:
   {
      value: "X3DShaderNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Shaders",
      enumerable: true,
   },
});

const X3DShaderNode_default_ = X3DShaderNode;
;

x_ite_Namespace .add ("X3DShaderNode", "x_ite/Components/Shaders/X3DShaderNode", X3DShaderNode_default_);
/* harmony default export */ const Shaders_X3DShaderNode = (X3DShaderNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shaders/X3DProgrammableShaderObject.js
/* provided dependency */ var X3DProgrammableShaderObject_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





const X3DProgrammableShaderObject_uniformLocation = Symbol .for ("X_ITE.X3DField.uniformLocation");

function X3DProgrammableShaderObject (executionContext)
{
   this .addType (Base_X3DConstants .X3DProgrammableShaderObject);

   this .uniformNames = [ ];

   this .x3d_ClipPlane                           = [ ];
   this .x3d_LightType                           = [ ];
   this .x3d_LightOn                             = [ ];
   this .x3d_LightColor                          = [ ];
   this .x3d_LightIntensity                      = [ ];
   this .x3d_LightAmbientIntensity               = [ ];
   this .x3d_LightAttenuation                    = [ ];
   this .x3d_LightLocation                       = [ ];
   this .x3d_LightDirection                      = [ ];
   this .x3d_LightBeamWidth                      = [ ];
   this .x3d_LightCutOffAngle                    = [ ];
   this .x3d_LightRadius                         = [ ];
   this .x3d_LightMatrix                         = [ ];
   this .x3d_ShadowIntensity                     = [ ];
   this .x3d_ShadowColor                         = [ ];
   this .x3d_ShadowBias                          = [ ];
   this .x3d_ShadowMatrix                        = [ ];
   this .x3d_ShadowMapSize                       = [ ];
   this .x3d_ShadowMap                           = [ ];
   this .x3d_Texture                             = [ ];
   this .x3d_MultiTextureMode                    = [ ];
   this .x3d_MultiTextureAlphaMode               = [ ];
   this .x3d_MultiTextureSource                  = [ ];
   this .x3d_MultiTextureFunction                = [ ];
   this .x3d_TextureCoordinateGeneratorMode      = [ ];
   this .x3d_TextureCoordinateGeneratorParameter = [ ];
   this .x3d_ProjectiveTexture                   = [ ];
   this .x3d_ProjectiveTextureMatrix             = [ ];
   this .x3d_ProjectiveTextureLocation           = [ ];
   this .x3d_TexCoord                            = [ ];
   this .x3d_TextureMatrix                       = [ ];

   this .numClipPlanes               = 0;
   this .fogNode                     = null;
   this .numLights                   = 0;
   this .numGlobalLights             = 0;
   this .lightNodes                  = [ ];
   this .numProjectiveTextures       = 0;
   this .numGlobalProjectiveTextures = 0;
   this .projectiveTextureNodes      = [ ];
   this .textures                    = new Set ();
}

Object .assign (X3DProgrammableShaderObject .prototype,
{
   initialize ()
   {
      const browser = this .getBrowser ();

      browser .getRenderingProperties () ._LogarithmicDepthBuffer .addInterest ("set_logarithmicDepthBuffer__", this);

      this .set_logarithmicDepthBuffer__ ();
   },
   set_logarithmicDepthBuffer__ ()
   {
      this .logarithmicDepthBuffer = this .getBrowser () .getRenderingProperty ("LogarithmicDepthBuffer");
   },
   canUserDefinedFields ()
   {
      return true;
   },
   getUniformNames ()
   {
      return this .uniformNames;
   },
   setUniformNames (value)
   {
      this .uniformNames = value;
   },
   getDefaultUniformsAndAttributes ()
   {
      // Get uniforms and attributes.

      const
         program              = this .getProgram (),
         browser              = this .getBrowser (),
         gl                   = browser .getContext (),
         maxClipPlanes        = browser .getMaxClipPlanes (),
         maxLights            = browser .getMaxLights (),
         maxTextures          = browser .getMaxTextures (),
         maxTextureTransforms = browser .getMaxTextureTransforms (),
         maxTexCoords         = browser .getMaxTexCoords ();

      gl .useProgram (program);

      for (const name of this .uniformNames)
         this [name] = gl .getUniformLocation (program, name);

      /*
       * Uniforms.
       */

      this .x3d_Id                      = gl .getUniformLocation (program, "x3d_Id");
      this .x3d_LogarithmicFarFactor1_2 = gl .getUniformLocation (program, "x3d_LogarithmicFarFactor1_2");

      for (let i = 0; i < maxClipPlanes; ++ i)
         this .x3d_ClipPlane [i] = gl .getUniformLocation (program, "x3d_ClipPlane[" + i + "]");

      this .x3d_FogColor           = this .getUniformLocation (gl, program, "x3d_Fog.color",           "x3d_FogColor");
      this .x3d_FogVisibilityRange = this .getUniformLocation (gl, program, "x3d_Fog.visibilityRange", "x3d_FogVisibilityRange");
      this .x3d_FogMatrix          = this .getUniformLocation (gl, program, "x3d_Fog.matrix",          "x3d_FogMatrix");

      this .x3d_AlphaCutoff = gl .getUniformLocation (program, "x3d_AlphaCutoff");

      this .x3d_PointPropertiesPointSizeScaleFactor = gl .getUniformLocation (program, "x3d_PointProperties.pointSizeScaleFactor");
      this .x3d_PointPropertiesPointSizeMinValue    = gl .getUniformLocation (program, "x3d_PointProperties.pointSizeMinValue");
      this .x3d_PointPropertiesPointSizeMaxValue    = gl .getUniformLocation (program, "x3d_PointProperties.pointSizeMaxValue");
      this .x3d_PointPropertiesAttenuation          = gl .getUniformLocation (program, "x3d_PointProperties.attenuation");

      this .x3d_LinePropertiesLinetype = gl .getUniformLocation (program, "x3d_LineProperties.linetype");
      this .x3d_LineStippleScale       = gl .getUniformLocation (program, "x3d_LineProperties.lineStippleScale");
      this .x3d_LinePropertiesTexture  = gl .getUniformLocation (program, "x3d_LineProperties.texture");

      this .x3d_FillPropertiesFilled     = gl .getUniformLocation (program, "x3d_FillProperties.filled");
      this .x3d_FillPropertiesHatched    = gl .getUniformLocation (program, "x3d_FillProperties.hatched");
      this .x3d_FillPropertiesHatchColor = gl .getUniformLocation (program, "x3d_FillProperties.hatchColor");
      this .x3d_FillPropertiesTexture    = gl .getUniformLocation (program, "x3d_FillProperties.texture");
      this .x3d_FillPropertiesScale      = gl .getUniformLocation (program, "x3d_FillProperties.scale");

      for (let i = 0; i < maxLights; ++ i)
      {
         this .x3d_LightType [i]             = this .getUniformLocation (gl, program, "x3d_LightSource[" + i + "].type",             "x3d_LightType[" + i + "]");
         this .x3d_LightColor [i]            = this .getUniformLocation (gl, program, "x3d_LightSource[" + i + "].color",            "x3d_LightColor[" + i + "]");
         this .x3d_LightAmbientIntensity [i] = this .getUniformLocation (gl, program, "x3d_LightSource[" + i + "].ambientIntensity", "x3d_LightAmbientIntensity[" + i + "]");
         this .x3d_LightIntensity [i]        = this .getUniformLocation (gl, program, "x3d_LightSource[" + i + "].intensity",        "x3d_LightIntensity[" + i + "]");
         this .x3d_LightAttenuation [i]      = this .getUniformLocation (gl, program, "x3d_LightSource[" + i + "].attenuation",      "x3d_LightAttenuation[" + i + "]");
         this .x3d_LightLocation [i]         = this .getUniformLocation (gl, program, "x3d_LightSource[" + i + "].location",         "x3d_LightLocation[" + i + "]");
         this .x3d_LightDirection [i]        = this .getUniformLocation (gl, program, "x3d_LightSource[" + i + "].direction",        "x3d_LightDirection[" + i + "]");
         this .x3d_LightBeamWidth [i]        = this .getUniformLocation (gl, program, "x3d_LightSource[" + i + "].beamWidth",        "x3d_LightBeamWidth[" + i + "]");
         this .x3d_LightCutOffAngle [i]      = this .getUniformLocation (gl, program, "x3d_LightSource[" + i + "].cutOffAngle",      "x3d_LightCutOffAngle[" + i + "]");
         this .x3d_LightRadius [i]           = this .getUniformLocation (gl, program, "x3d_LightSource[" + i + "].radius",           "x3d_LightRadius[" + i + "]");
         this .x3d_LightMatrix [i]           = this .getUniformLocation (gl, program, "x3d_LightSource[" + i + "].matrix",           "x3d_LightMatrix[" + i + "]");

         this .x3d_ShadowIntensity [i] = gl .getUniformLocation (program, "x3d_LightSource[" + i + "].shadowIntensity");
         this .x3d_ShadowColor [i]     = gl .getUniformLocation (program, "x3d_LightSource[" + i + "].shadowColor");
         this .x3d_ShadowBias [i]      = gl .getUniformLocation (program, "x3d_LightSource[" + i + "].shadowBias");
         this .x3d_ShadowMatrix [i]    = gl .getUniformLocation (program, "x3d_LightSource[" + i + "].shadowMatrix");
         this .x3d_ShadowMapSize [i]   = gl .getUniformLocation (program, "x3d_LightSource[" + i + "].shadowMapSize");
         this .x3d_ShadowMap [i]       = gl .getUniformLocation (program, "x3d_ShadowMap[" + i + "]");
      }

      this .x3d_AmbientIntensity  = this .getUniformLocation (gl, program, "x3d_Material.ambientIntensity", "x3d_FrontMaterial.ambientIntensity");
      this .x3d_DiffuseColor      = this .getUniformLocation (gl, program, "x3d_Material.diffuseColor",     "x3d_FrontMaterial.diffuseColor");
      this .x3d_SpecularColor     = this .getUniformLocation (gl, program, "x3d_Material.specularColor",    "x3d_FrontMaterial.specularColor");
      this .x3d_EmissiveColor     = this .getUniformLocation (gl, program, "x3d_Material.emissiveColor",    "x3d_FrontMaterial.emissiveColor");
      this .x3d_Shininess         = this .getUniformLocation (gl, program, "x3d_Material.shininess",        "x3d_FrontMaterial.shininess");
      this .x3d_BaseColor         = gl .getUniformLocation (program, "x3d_Material.baseColor");
      this .x3d_Metallic          = gl .getUniformLocation (program, "x3d_Material.metallic");
      this .x3d_Roughness         = gl .getUniformLocation (program, "x3d_Material.roughness");
      this .x3d_OcclusionStrength = gl .getUniformLocation (program, "x3d_Material.occlusionStrength");
      this .x3d_NormalScale       = gl .getUniformLocation (program, "x3d_Material.normalScale");
      this .x3d_Transparency      = this .getUniformLocation (gl, program, "x3d_Material.transparency",     "x3d_FrontMaterial.transparency");

      const materialTextures = [
         "x3d_AmbientTexture",
         "x3d_DiffuseTexture",
         "x3d_SpecularTexture",
         "x3d_EmissiveTexture",
         "x3d_ShininessTexture",
         "x3d_BaseTexture",
         "x3d_MetallicRoughnessTexture",
         "x3d_OcclusionTexture",
         "x3d_NormalTexture",
      ];

      for (const materialTexture of materialTextures)
      {
         this [materialTexture] = {
            textureTransformMapping:  gl .getUniformLocation (program, materialTexture + ".textureTransformMapping"),
            textureCoordinateMapping: gl .getUniformLocation (program, materialTexture + ".textureCoordinateMapping"),
            texture2D:                gl .getUniformLocation (program, materialTexture + ".texture2D"),
            texture3D:                gl .getUniformLocation (program, materialTexture + ".texture3D"),
            textureCube:              gl .getUniformLocation (program, materialTexture + ".textureCube"),
         };
      }

      this .x3d_MultiTextureColor = gl .getUniformLocation (program, "x3d_MultiTextureColor");

      this .x3d_TexCoord .length = 0;

      for (let i = 0; i < maxTextures; ++ i)
      {
         this .x3d_TextureCoordinateGeneratorMode [i]      = gl .getUniformLocation (program, "x3d_TextureCoordinateGenerator[" + i + "].mode");
         this .x3d_TextureCoordinateGeneratorParameter [i] = gl .getUniformLocation (program, "x3d_TextureCoordinateGenerator[" + i + "].parameter");

         this .x3d_Texture [i] = {
            texture2D: gl .getUniformLocation (program, "x3d_Texture2D[" + i + "]"),
            texture3D: gl .getUniformLocation (program, "x3d_Texture3D[" + i + "]"),
            textureCube: this .getUniformLocation (gl, program, "x3d_TextureCube[" + i + "]", "x3d_CubeMapTexture[" + i + "]"),
         }

         this .x3d_MultiTextureMode [i]      = gl .getUniformLocation (program, "x3d_MultiTexture[" + i + "].mode");
         this .x3d_MultiTextureAlphaMode [i] = gl .getUniformLocation (program, "x3d_MultiTexture[" + i + "].alphaMode");
         this .x3d_MultiTextureSource [i]    = gl .getUniformLocation (program, "x3d_MultiTexture[" + i + "].source");
         this .x3d_MultiTextureFunction [i]  = gl .getUniformLocation (program, "x3d_MultiTexture[" + i + "].function");

         this .x3d_ProjectiveTexture [i]         = gl .getUniformLocation (program, "x3d_ProjectiveTexture[" + i + "]");
         this .x3d_ProjectiveTextureMatrix [i]   = gl .getUniformLocation (program, "x3d_ProjectiveTextureMatrix[" + i + "]");
         this .x3d_ProjectiveTextureLocation [i] = gl .getUniformLocation (program, "x3d_ProjectiveTextureLocation[" + i + "]");
      }

      for (let i = 0; i < maxTextureTransforms; ++ i)
      {
         const uniform = gl .getUniformLocation (program, "x3d_TextureMatrix[" + i + "]");

         if (uniform !== null)
            this .x3d_TextureMatrix [i] = uniform;
      }

      for (let i = 0; i < maxTexCoords; ++ i)
      {
         const x3d_TexCoord = this .getAttribLocation (gl, program, "x3d_TexCoord" + i, i ? "" : "x3d_TexCoord");

         if (x3d_TexCoord !== -1)
            this .x3d_TexCoord .push ([i, x3d_TexCoord]);
      }

      this .x3d_TexCoordRamp         = gl .getUniformLocation (program, "x3d_TexCoordRamp");
      this .x3d_JointsTexture        = gl .getUniformLocation (program, "x3d_JointsTexture");
      this .x3d_DisplacementsTexture = gl .getUniformLocation (program, "x3d_DisplacementsTexture");
      this .x3d_JointMatricesTexture = gl .getUniformLocation (program, "x3d_JointMatricesTexture");

      this .x3d_Viewport          = gl .getUniformLocation (program, "x3d_Viewport");
      this .x3d_ProjectionMatrix  = gl .getUniformLocation (program, "x3d_ProjectionMatrix");
      this .x3d_ModelViewMatrix   = gl .getUniformLocation (program, "x3d_ModelViewMatrix");
      this .x3d_NormalMatrix      = gl .getUniformLocation (program, "x3d_NormalMatrix");
      this .x3d_CameraSpaceMatrix = gl .getUniformLocation (program, "x3d_CameraSpaceMatrix");

      /*
       * Attributes.
       */

      const attributes = [
         "CoordIndex",
         "LineStipple",
         "FogDepth",
         "Color",
         "Normal",
         "Vertex",
         "Particle",
         "ParticleMatrix",
      ];

      for (const name of attributes)
      {
         const attribute = gl .getAttribLocation (program, `x3d_${name}`);

         this [`x3d_${name}`] = attribute;

         if (attribute < 0)
         {
            this [`enable${name}Attribute`]                       = Function .prototype;
            this [`${X3DProgrammableShaderObject_$.toLowerCaseFirst (name)}AttributeDivisor`] = Function .prototype;
         }
         else
         {
            delete this [`enable${name}Attribute`];
            delete this [`${X3DProgrammableShaderObject_$.toLowerCaseFirst (name)}AttributeDivisor`];
         }
      }

      if (this .x3d_TexCoord .length === 0)
      {
         this .enableTexCoordAttribute  = Function .prototype;
         this .texCoordAttributeDivisor = Function .prototype;
      }
      else
      {
         delete this .enableTexCoordAttribute;
         delete this .texCoordAttributeDivisor;
      }

      /*
       * Fill uniforms with defaults.
       */

      // Fill special uniforms with default values, textures for units are created in X3DTexturingContext.

      gl .uniform1i  (this .x3d_LinePropertiesTexture, browser .getDefaultTexture2DUnit ());
      gl .uniform1i  (this .x3d_FillPropertiesTexture, browser .getDefaultTexture2DUnit ());

      for (const materialTexture of materialTextures)
      {
         gl .uniform1i (this [materialTexture] .texture2D,   browser .getDefaultTexture2DUnit ());
         gl .uniform1i (this [materialTexture] .texture3D,   browser .getDefaultTexture3DUnit ());
         gl .uniform1i (this [materialTexture] .textureCube, browser .getDefaultTextureCubeUnit ());
      }

      for (const uniforms of this .x3d_Texture)
      {
         gl .uniform1i (uniforms .texture2D, browser .getDefaultTexture2DUnit ());

         if (gl .getVersion () >= 2)
            gl .uniform1i (uniforms .texture3D, browser .getDefaultTexture3DUnit ());

         gl .uniform1i (uniforms .textureCube, browser .getDefaultTextureCubeUnit ());
      }

      for (const uniform of this .x3d_ShadowMap)
         gl .uniform1i (uniform, browser .getDefaultTexture2DUnit ());

      for (const uniform of this .x3d_ProjectiveTexture)
         gl .uniform1i (uniform, browser .getDefaultTexture2DUnit ());

      gl .uniform1i (this .x3d_TexCoordRamp,         browser .getDefaultTexture2DUnit ());
      gl .uniform1i (this .x3d_JointsTexture,        browser .getDefaultTexture2DUnit ());
      gl .uniform1i (this .x3d_DisplacementsTexture, browser .getDefaultTexture2DUnit ());
      gl .uniform1i (this .x3d_JointMatricesTexture, browser .getDefaultTexture2DUnit ());
   },
   getUniformLocation (gl, program, name, depreciated)
   {
      // Legacy function to get uniform location.

      let location = gl .getUniformLocation (program, name);

      if (location)
         return location;

      // Look for depreciated location.

      if (depreciated)
      {
         location = gl .getUniformLocation (program, depreciated);

         if (location)
         {
            console .warn (this .getTypeName (), this .getName (), "Using uniform location name '" + depreciated + "' is depreciated, use '" + name + "'. See https://create3000.github.io/x_ite/custom-shaders.");
         }

         return location;
      }

      return 0;
   },
   getAttribLocation (gl, program, name, depreciated)
   {
      // Legacy function to get uniform location.

      let location = gl .getAttribLocation (program, name);

      if (location >= 0)
         return location;

      // Look for depreciated location.

      if (depreciated)
      {
         location = gl .getAttribLocation (program, depreciated);

         if (location >= 0)
         {
            console .warn (this .getTypeName (), this .getName (), "Using attribute location name '" + depreciated + "' is depreciated, use '" + name + "'. See https://create3000.github.io/x_ite/custom-shaders.");
         }

         return location;
      }

      return -1;
   },
   addShaderFields ()
   {
      const
         program = this .getProgram (),
         gl      = this .getBrowser () .getContext ();

      gl .useProgram (program);

      this .textures .clear ();

      for (const field of this .getUserDefinedFields ())
      {
         if (field .getAccessType () === Base_X3DConstants .outputOnly)
            continue;

         const location = gl .getUniformLocation (program, field .getName ());

         if (!location)
            continue;

         switch (field .getType ())
         {
            case Base_X3DConstants .SFImage:
            {
               location .array = new Int32Array (3 + field .array .length);
               break;
            }
            case Base_X3DConstants .SFMatrix3d:
            case Base_X3DConstants .SFMatrix3f:
            case Base_X3DConstants .SFRotation:
            {
               location .array = new Float32Array (9);
               break;
            }
            case Base_X3DConstants .SFMatrix4d:
            case Base_X3DConstants .SFMatrix4f:
            {
               location .array = new Float32Array (16);
               break;
            }
            case Base_X3DConstants .SFNode:
            {
               break;
            }
            case Base_X3DConstants .MFBool:
            case Base_X3DConstants .MFInt32:
            {
               location .array = new Int32Array (this .getLocationLength (gl, program, field));
               break;
            }
            case Base_X3DConstants .MFFloat:
            case Base_X3DConstants .MFDouble:
            case Base_X3DConstants .MFTime:
            {
               location .array = new Float32Array (this .getLocationLength (gl, program, field));
               break;
            }
            case Base_X3DConstants .MFImage:
            {
               location .array = new Int32Array (this .getImagesLength (field));
               break;
            }
            case Base_X3DConstants .MFMatrix3d:
            case Base_X3DConstants .MFMatrix3f:
            case Base_X3DConstants .MFRotation:
            {
               location .array = new Float32Array (9 * this .getLocationLength (gl, program, field));
               break;
            }
            case Base_X3DConstants .MFMatrix4d:
            case Base_X3DConstants .MFMatrix4f:
            {
               location .array = new Float32Array (16 * this .getLocationLength (gl, program, field));
               break;
            }
            case Base_X3DConstants .MFNode:
            {
               const locations = location .locations = [ ];

               for (let i = 0;; ++ i)
               {
                  const l = gl .getUniformLocation (program, field .getName () + "[" + i + "]");

                  if (! l)
                     break;

                  locations .push (l);
               }

               break;
            }
            case Base_X3DConstants .MFVec2d:
            case Base_X3DConstants .MFVec2f:
            {
               location .array = new Float32Array (2 * this .getLocationLength (gl, program, field));
               break;
            }
            case Base_X3DConstants .MFVec3d:
            case Base_X3DConstants .MFVec3f:
            case Base_X3DConstants .MFColor:
            {
               location .array = new Float32Array (3 * this .getLocationLength (gl, program, field));
               break;
            }
            case Base_X3DConstants .MFVec4d:
            case Base_X3DConstants .MFVec4f:
            case Base_X3DConstants .MFColorRGBA:
            {
               location .array = new Float32Array (4 * this .getLocationLength (gl, program, field));
               break;
            }
         }

         if (location .array)
            field [X3DProgrammableShaderObject_uniformLocation] = location .array .length ? location : null;
         else
            field [X3DProgrammableShaderObject_uniformLocation] = location;

         field .addInterest ("set_field__", this);

         this .set_field__ (field);
      }
   },
   removeShaderFields ()
   {
      for (const field of this .getUserDefinedFields ())
         field .removeInterest ("set_field__", this);
   },
   set_field__: (() =>
   {
      const rotation = new Float32Array (9);

      return function (field)
      {
         const
            program  = this .getProgram (),
            gl       = this .getBrowser () .getContext (),
            location = field [X3DProgrammableShaderObject_uniformLocation];

         gl .useProgram (program);

         if (!location)
            return;

         switch (field .getType ())
         {
            case Base_X3DConstants .SFBool:
            case Base_X3DConstants .SFInt32:
            {
               gl .uniform1i (location, field .getValue ());
               return;
            }
            case Base_X3DConstants .SFColor:
            {
               const value = field .getValue ();
               gl .uniform3f (location, value .r, value .g, value .b);
               return;
            }
            case Base_X3DConstants .SFColorRGBA:
            {
               const value = field .getValue ();
               gl .uniform4f (location, value .r, value .g, value .b, value .a);
               return;
            }
            case Base_X3DConstants .SFDouble:
            case Base_X3DConstants .SFFloat:
            case Base_X3DConstants .SFTime:
            {
               gl .uniform1f (location, field .getValue ());
               return;
            }
            case Base_X3DConstants .SFImage:
            {
               let array = location .array;

               const
                  pixels = field .array,
                  length = 3 + pixels .length;

               if (length !== array .length)
                  array = location .array = new Int32Array (length);

               array [0] = field .width;
               array [1] = field .height;
               array [2] = field .comp;

               for (let a = 3, p = 0, pl = pixels .length; p < pl; ++ p, ++ a)
                  array [a] = pixels [p];

               gl .uniform1iv (location, array);
               return;
            }
            case Base_X3DConstants .SFMatrix3d:
            case Base_X3DConstants .SFMatrix3f:
            {
               location .array .set (field .getValue ());

               gl .uniformMatrix3fv (location, false, location .array);
               return;
            }
            case Base_X3DConstants .SFMatrix4d:
            case Base_X3DConstants .SFMatrix4f:
            {
               location .array .set (field .getValue ());

               gl .uniformMatrix4fv (location, false, location .array);
               return;
            }
            case Base_X3DConstants .SFNode:
            {
               const texture = Base_X3DCast (Base_X3DConstants .X3DTextureNode, field);

               if (texture)
               {
                  location .name    = field .getName ();
                  location .texture = texture;

                  this .textures .add (location);
               }
               else
               {
                  this .textures .delete (location);
               }

               return;
            }
            case Base_X3DConstants .SFRotation:
            {
               field .getValue () .getMatrix (location .array);

               gl .uniformMatrix3fv (location, false, location .array);
               return;
            }
            case Base_X3DConstants .SFString:
            {
               return;
            }
            case Base_X3DConstants .SFVec2d:
            case Base_X3DConstants .SFVec2f:
            {
               const value = field .getValue ();
               gl .uniform2f (location, value .x, value .y);
               return;
            }
            case Base_X3DConstants .SFVec3d:
            case Base_X3DConstants .SFVec3f:
            {
               const value = field .getValue ();
               gl .uniform3f (location, value .x, value .y, value .z);
               return;
            }
            case Base_X3DConstants .SFVec4d:
            case Base_X3DConstants .SFVec4f:
            {
               const value = field .getValue ();
               gl .uniform4f (location, value .x, value .y, value .z, value .w);
               return;
            }
            case Base_X3DConstants .MFBool:
            case Base_X3DConstants .MFInt32:
            {
               const array = location .array;

               for (var i = 0, length = field .length; i < length; ++ i)
                  array [i] = field [i];

               for (let length = array .length; i < length; ++ i)
                  array [i] = 0;

               gl .uniform1iv (location, array);
               return;
            }
            case Base_X3DConstants .MFColor:
            {
               const array = location .array;

               for (var i = 0, k = 0, length = field .length; i < length; ++ i)
               {
                  const color = field [i];

                  array [k++] = color .r;
                  array [k++] = color .g;
                  array [k++] = color .b;
               }

               for (let length = array .length; k < length; ++ k)
                  array [k] = 0;

               gl .uniform3fv (location, array);
               return;
            }
            case Base_X3DConstants .MFColorRGBA:
            {
               const array = location .array;

               for (var i = 0, k = 0, length = field .length; i < length; ++ i)
               {
                  const color = field [i];

                  array [k++] = color .r;
                  array [k++] = color .g;
                  array [k++] = color .b;
                  array [k++] = color .a;
               }

               for (let length = array .length; k < length; ++ k)
                  array [k] = 0;

               gl .uniform4fv (location, array);
               return;
            }
            case Base_X3DConstants .MFDouble:
            case Base_X3DConstants .MFFloat:
            case Base_X3DConstants .MFTime:
            {
               const array = location .array;

               for (var i = 0, length = field .length; i < length; ++ i)
                  array [i] = field [i];

               for (let length = array .length; i < length; ++ i)
                  array [i] = 0;

               gl .uniform1fv (location, array);
               return;
            }
            case Base_X3DConstants .MFImage:
            {
               const array = location .array;

               for (let i = 0, a = 0, length = field .length; i < length; ++ i)
               {
                  const
                     value  = field [i],
                     pixels = value .array;

                  array [a ++] = value .width;
                  array [a ++] = value .height;
                  array [a ++] = value .comp;

                  for (let p = 0, pl = pixels .length; p < pl; ++ p)
                     array [a ++] = pixels [p];
               }

               gl .uniform1iv (location, array);
               return;
            }
            case Base_X3DConstants .MFMatrix3d:
            case Base_X3DConstants .MFMatrix3f:
            {
               const array = location .array;

               for (var i = 0, k = 0, length = field .length; i < length; ++ i)
               {
                  const matrix = field [i];

                  for (let m = 0; m < 9; ++ m)
                     array [k++] = matrix [m];
               }

               for (let length = array .length; k < length; ++ k)
                  array [k] = 0;

               gl .uniformMatrix3fv (location, false, array);
               return;
            }
            case Base_X3DConstants .MFMatrix4d:
            case Base_X3DConstants .MFMatrix4f:
            {
               const array = location .array;

               for (var i = 0, k = 0, length = field .length; i < length; ++ i)
               {
                  const matrix = field [i];

                  for (let m = 0; m < 16; ++ m)
                     array [k++] = matrix [m];
               }

               for (let length = array .length; k < length; ++ k)
                  array [k] = 0;

               gl .uniformMatrix4fv (location, false, array);
               return;
            }
            case Base_X3DConstants .MFNode:
            {
               const locations = location .locations;

               for (let i = 0, length = field .length; i < length; ++ i)
               {
                  const texture = Base_X3DCast (Base_X3DConstants .X3DTextureNode, field [i]);

                  if (texture)
                  {
                     locations [i] .name    = field .getName ();
                     locations [i] .texture = texture;

                     this .textures .add (locations [i]);
                  }
                  else
                  {
                     this .textures .delete (locations [i]);
                  }
               }

               return;
            }
            case Base_X3DConstants .MFRotation:
            {
               const array = location .array;

               for (var i = 0, k = 0, length = field .length; i < length; ++ i)
               {
                  field [i] .getValue () .getMatrix (rotation);

                  array [k++] = rotation [0];
                  array [k++] = rotation [1];
                  array [k++] = rotation [2];
                  array [k++] = rotation [3];
                  array [k++] = rotation [4];
                  array [k++] = rotation [5];
                  array [k++] = rotation [6];
                  array [k++] = rotation [7];
                  array [k++] = rotation [8];
               }

               for (let length = array .length; k < length; ++ k)
                  array [k] = 0;

               gl .uniformMatrix3fv (location, false, array);
               return;
            }
            case Base_X3DConstants .MFString:
            {
               return;
            }
            case Base_X3DConstants .MFVec2d:
            case Base_X3DConstants .MFVec2f:
            {
               const array = location .array;

               for (var i = 0, k = 0, length = field .length; i < length; ++ i)
               {
                  const vector = field [i];

                  array [k++] = vector .x;
                  array [k++] = vector .y;
               }

               for (let length = array .length; k < length; ++ k)
                  array [k] = 0;

               gl .uniform2fv (location, array);
               return;
            }
            case Base_X3DConstants .MFVec3d:
            case Base_X3DConstants .MFVec3f:
            {
               const array = location .array;

               for (var i = 0, k = 0, length = field .length; i < length; ++ i)
               {
                  const vector = field [i];

                  array [k++] = vector .x;
                  array [k++] = vector .y;
                  array [k++] = vector .z;
               }

               for (let length = array .length; k < length; ++ k)
                  array [k] = 0;

               gl .uniform3fv (location, array);
               return;
            }
            case Base_X3DConstants .MFVec4d:
            case Base_X3DConstants .MFVec4f:
            {
               const array = location .array;

               for (var i = 0, k = 0, length = field .length; i < length; ++ i)
               {
                  const vector = field [i];

                  array [k++] = vector .x;
                  array [k++] = vector .y;
                  array [k++] = vector .z;
                  array [k++] = vector .w;
               }

               for (let length = array .length; k < length; ++ k)
                  array [k] = 0;

               gl .uniform4fv (location, array);
               return;
            }
         }
      };
   })(),
   getImagesLength (field)
   {
      const images = field .getValue ();

      let length = 3 * images .length;

      for (const image of images)
         length += image .array .length;

      return length;
   },
   getLocationLength (gl, program, field)
   {
      const name = field .getName ();

      for (let i = 0; ; ++ i)
      {
         const location = gl .getUniformLocation (program, name + "[" + i + "]");

         if (! location)
            return i;
      }
   },
   hasFog (fogNode)
   {
      if (this .fogNode === fogNode)
         return true;

      this .fogNode = fogNode;

      return false;
   },
   hasLight (i, lightNode)
   {
      if (this .lightNodes [i] === lightNode)
         return true;

      this .lightNodes [i] = lightNode;

      return false;
   },
   hasTextureProjector (i, textureProjectorNode)
   {
      if (this .projectiveTextureNodes [i] === textureProjectorNode)
         return true;

      this .projectiveTextureNodes [i] = textureProjectorNode;

      return false;
   },
   setClipPlanes (gl, clipPlanes)
   {
      this .numClipPlanes = 0;

      for (const clipPlane of clipPlanes)
         clipPlane .setShaderUniforms (gl, this);
   },
   setUniforms: (() =>
   {
      const normalMatrix = new Float32Array (9);

      return function (gl, geometryContext, renderContext, front = true)
      {
         const { renderObject, fogNode, appearanceNode, humanoidNode, modelViewMatrix } = renderContext;

         const
            stylePropertiesNode = appearanceNode .getStyleProperties (geometryContext .geometryType),
            materialNode        = front ? appearanceNode .getMaterial () : appearanceNode .getBackMaterial (),
            textureNode         = renderContext .textureNode || appearanceNode .getTexture ();

         // Set global uniforms.

         if (this .renderCount !== renderObject .getRenderCount ())
         {
            this .renderCount = renderObject .getRenderCount ();

            // Set viewport.

            gl .uniform4iv (this .x3d_Viewport, renderObject .getViewportArray ());

            // Set projection matrix.

            gl .uniformMatrix4fv (this .x3d_ProjectionMatrix,  false, renderObject .getProjectionMatrixArray ());
            gl .uniformMatrix4fv (this .x3d_CameraSpaceMatrix, false, renderObject .getCameraSpaceMatrixArray ());

            // Fog

            this .fogNode = null;

            // Set global lights and global texture projectors.

            this .numLights                      = 0;
            this .numProjectiveTextures          = 0;
            this .lightNodes .length             = 0;
            this .projectiveTextureNodes .length = 0;

            const globalObjects = renderObject .getGlobalObjects ();

            for (const globalObject of globalObjects)
               globalObject .setShaderUniforms (gl, this, renderObject);

            this .numGlobalLights             = this .numLights;
            this .numGlobalProjectiveTextures = this .numProjectiveTextures;

            // Logarithmic depth buffer support

            const viewpoint = renderObject .getViewpoint ();

            if (this .logarithmicDepthBuffer || viewpoint .getLogarithmicDepthBuffer ())
            {
               const navigationInfo = renderObject .getNavigationInfo ();

               gl .uniform1f (this .x3d_LogarithmicFarFactor1_2, 1 / Math .log2 (navigationInfo .getFarValue (viewpoint) + 1));
            }
         }

         // Model view matrix

         gl .uniformMatrix4fv (this .x3d_ModelViewMatrix, false, modelViewMatrix);

         // Normal matrix

         if (geometryContext .hasNormals)
         {
            normalMatrix [0] = modelViewMatrix [0]; normalMatrix [3] = modelViewMatrix [1]; normalMatrix [6] = modelViewMatrix [ 2];
            normalMatrix [1] = modelViewMatrix [4]; normalMatrix [4] = modelViewMatrix [5]; normalMatrix [7] = modelViewMatrix [ 6];
            normalMatrix [2] = modelViewMatrix [8]; normalMatrix [5] = modelViewMatrix [9]; normalMatrix [8] = modelViewMatrix [10];

            Numbers_Matrix3 .prototype .inverse .call (normalMatrix);

            gl .uniformMatrix3fv (this .x3d_NormalMatrix, false, normalMatrix);
         }

         // Fog

         fogNode ?.setShaderUniforms (gl, this);

         // Clip planes and local lights

         this .numClipPlanes         = 0;
         this .numLights             = this .numGlobalLights;
         this .numProjectiveTextures = this .numGlobalProjectiveTextures;

         for (const localObject of renderContext .localObjects)
            localObject .setShaderUniforms (gl, this, renderObject);

         // Alpha

         gl .uniform1f (this .x3d_AlphaCutoff, appearanceNode .getAlphaCutoff ());

         // Style Properties

         stylePropertiesNode ?.setShaderUniforms (gl, this);

         // Material

         materialNode .setShaderUniforms (gl, this, renderObject, appearanceNode .getTextureTransformMapping (), geometryContext .getTextureCoordinateMapping (), front);

         // Texture

         textureNode ?.setShaderUniforms (gl, this, renderObject);

         appearanceNode  .getTextureTransform ()  .setShaderUniforms (gl, this);
         geometryContext .getTextureCoordinate () .setShaderUniforms (gl, this);

         // Skinning

         humanoidNode ?.setShaderUniforms (gl, this);
      };
   })(),
   enable (gl)
   {
      gl .useProgram (this .getProgram ());

      for (const location of this .textures)
      {
         const
            texture     = location .texture,
            textureUnit = this .getBrowser () .getTextureUnit (texture .getTextureType ());

         if (textureUnit === undefined)
         {
            console .warn ("Not enough combined texture units for uniform variable '" + location .name + "' available.");
            return;
         }

         gl .activeTexture (gl .TEXTURE0 + textureUnit);
         gl .bindTexture (texture .getTarget (), texture .getTexture ());
         gl .uniform1i (location, textureUnit);
      }
   },
   enableFloatAttrib (gl, name, buffer, components, stride, offset)
   {
      const location = gl .getAttribLocation (this .getProgram (), name);

      if (location === -1)
         return;

      gl .bindBuffer (gl .ARRAY_BUFFER, buffer);
      gl .enableVertexAttribArray (location);
      gl .vertexAttribPointer (location, components, gl .FLOAT, false, stride, offset);
   },
   enableMatrix3Attrib (gl, name, buffer, stride, offset)
   {
      const location0 = gl .getAttribLocation (this .getProgram (), name);

      if (location0 === -1)
         return;

      stride = stride || 36;

      gl .bindBuffer (gl .ARRAY_BUFFER, buffer);

      for (let i = 0; i < 3; ++ i)
      {
         const location = location0 + i;

         gl .enableVertexAttribArray (location);
         gl .vertexAttribPointer (location, 3, gl .FLOAT, false, stride, offset + 12 * i);
      }
   },
   enableMatrix4Attrib (gl, name, buffer, stride, offset)
   {
      const location0 = gl .getAttribLocation (this .getProgram (), name);

      if (location0 === -1)
         return;

      stride = stride || 64;

      gl .bindBuffer (gl .ARRAY_BUFFER, buffer);

      for (let i = 0; i < 4; ++ i)
      {
         const location = location0 + i;

         gl .enableVertexAttribArray (location);
         gl .vertexAttribPointer (location, 4, gl .FLOAT, false, stride, offset + 16 * i);
      }
   },
   enableCoordIndexAttribute (gl, buffer, stride, offset)
   {
      const location = this .x3d_CoordIndex;

      gl .bindBuffer (gl .ARRAY_BUFFER, buffer);
      gl .enableVertexAttribArray (location);
      gl .vertexAttribPointer (location, 1, gl .FLOAT, false, stride, offset); // gl .UNSIGNED_INT
   },
   enableLineStippleAttribute (gl, buffer, stride, offset)
   {
      const location = this .x3d_LineStipple;

      gl .bindBuffer (gl .ARRAY_BUFFER, buffer);
      gl .enableVertexAttribArray (location);
      gl .vertexAttribPointer (location, 3, gl .FLOAT, false, stride, offset);
   },
   enableFogDepthAttribute (gl, buffer, stride, offset)
   {
      const location = this .x3d_FogDepth;

      gl .bindBuffer (gl .ARRAY_BUFFER, buffer);
      gl .enableVertexAttribArray (location);
      gl .vertexAttribPointer (location, 1, gl .FLOAT, false, stride, offset);
   },
   enableColorAttribute (gl, buffer, stride, offset)
   {
      const location = this .x3d_Color;

      gl .bindBuffer (gl .ARRAY_BUFFER, buffer);
      gl .enableVertexAttribArray (location);
      gl .vertexAttribPointer (location, 4, gl .FLOAT, false, stride, offset);
   },
   colorAttributeDivisor (gl, divisor)
   {
      gl .vertexAttribDivisor (this .x3d_Color, divisor);
   },
   enableTexCoordAttribute (gl, buffers, stride, offset)
   {
      for (const [i, location] of this .x3d_TexCoord)
      {
         gl .bindBuffer (gl .ARRAY_BUFFER, buffers [i]);
         gl .enableVertexAttribArray (location);
         gl .vertexAttribPointer (location, 4, gl .FLOAT, false, stride, offset);
      }
   },
   texCoordAttributeDivisor (gl, divisor)
   {
      for (const [i, location] of this .x3d_TexCoord)
      {
         gl .vertexAttribDivisor (location, divisor);
      }
   },
   enableNormalAttribute (gl, buffer, stride, offset)
   {
      const location = this .x3d_Normal;

      gl .bindBuffer (gl .ARRAY_BUFFER, buffer);
      gl .enableVertexAttribArray (location);
      gl .vertexAttribPointer (location, 3, gl .FLOAT, false, stride, offset);
   },
   normalAttributeDivisor (gl, divisor)
   {
      gl .vertexAttribDivisor (this .x3d_Normal, divisor);
   },
   enableVertexAttribute (gl, buffer, stride, offset)
   {
      const location = this .x3d_Vertex;

      gl .bindBuffer (gl .ARRAY_BUFFER, buffer);
      gl .enableVertexAttribArray (location);
      gl .vertexAttribPointer (location, 4, gl .FLOAT, false, stride, offset);
   },
   vertexAttributeDivisor (gl, divisor)
   {
      gl .vertexAttribDivisor (this .x3d_Vertex, divisor);
   },
   enableParticleAttribute (gl, buffer, stride, offset, divisor)
   {
      const location = this .x3d_Particle;

      gl .bindBuffer (gl .ARRAY_BUFFER, buffer);
      gl .enableVertexAttribArray (location);
      gl .vertexAttribPointer (location, 4, gl .FLOAT, false, stride, offset);
      gl .vertexAttribDivisor (location, divisor);
   },
   enableParticleMatrixAttribute (gl, buffer, stride, offset, divisor)
   {
      const location0 = this .x3d_ParticleMatrix;

      stride = stride || 64;

      gl .bindBuffer (gl .ARRAY_BUFFER, buffer);

      for (let i = 0; i < 4; ++ i)
      {
         const location = location0 + i;

         gl .enableVertexAttribArray (location);
         gl .vertexAttribPointer (location, 4, gl .FLOAT, false, stride, offset + 16 * i);
         gl .vertexAttribDivisor (location, divisor);
      }
   },
   getProgramInfo ()
   {
      function cmp (lhs, rhs) { return lhs < rhs ? -1 : lhs > rhs ? 1 : 0; }

      const
         program = this .getProgram (),
         gl      = this .getBrowser () .getContext ();

      const
         result = {
            attributes: [ ],
            uniforms: [ ],
            attributeCount: 0,
            uniformCount: 0,
         },
         activeUniforms   = gl .getProgramParameter (program, gl .ACTIVE_UNIFORMS),
         activeAttributes = gl .getProgramParameter (program, gl .ACTIVE_ATTRIBUTES);

      // Taken from the WebGl spec:
      // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14
      const enums = {
         0x8B50: 'vec2',
         0x8B51: 'vec3',
         0x8B52: 'vec4',
         0x8B53: 'ivec2',
         0x8B54: 'ivec3',
         0x8B55: 'ivec4',
         0x8B56: 'bool',
         0x8B57: 'bvec2',
         0x8B58: 'bvec3',
         0x8B59: 'bvec4',
         0x8B5A: 'mat2',
         0x8B5B: 'mat3',
         0x8B5C: 'mat4',
         0x8B5E: 'sampler2D',
         0x8B60: 'samplerCube',
         0x1400: 'byte',
         0x1401: 'ubyte',
         0x1402: 'short',
         0x1403: 'ushort',
         0x1404: 'int',
         0x1405: 'uint',
         0x1406: 'float',
      };

      // Loop through active uniforms
      for (let i = 0; i < activeUniforms; ++ i)
      {
         const uniform = gl .getActiveUniform (program, i);
         uniform .typeName = enums [uniform.type];
         result .uniforms .push (Object .assign ({ }, uniform));
         result .uniformCount += uniform .size;
      }

      // Loop through active attributes
      for (let i = 0; i < activeAttributes; ++ i)
      {
         const attribute = gl .getActiveAttrib (program, i);
         attribute .typeName = enums [attribute .type];
         result .attributes .push (Object .assign ({ }, attribute));
         result .attributeCount += attribute .size;
      }

      result .uniforms   .sort ((a, b) => cmp (a .name, b .name));
      result .attributes .sort ((a, b) => cmp (a .name, b .name));

      return result;
   },
   printProgramInfo ()
   {
      const programInfo = this .getProgramInfo ();

      console .log (this .getName ());
      console .table (programInfo .attributes);
      console .log (this .getName (), "attributeCount", programInfo .attributeCount);
      console .log (this .getName ());
      console .table (programInfo .uniforms);
      console .log (this .getName (), "uniformCount", programInfo .uniformCount);
   },
   dispose () { },
});

Object .defineProperties (X3DProgrammableShaderObject,
{
   typeName:
   {
      value: "X3DProgrammableShaderObject",
      enumerable: true,
   },
   componentName:
   {
      value: "Shaders",
      enumerable: true,
   },
});

const X3DProgrammableShaderObject_default_ = X3DProgrammableShaderObject;
;

x_ite_Namespace .add ("X3DProgrammableShaderObject", "x_ite/Components/Shaders/X3DProgrammableShaderObject", X3DProgrammableShaderObject_default_);
/* harmony default export */ const Shaders_X3DProgrammableShaderObject = (X3DProgrammableShaderObject_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shaders/ComposedShader.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










function ComposedShader (executionContext)
{
   Shaders_X3DShaderNode               .call (this, executionContext);
   Shaders_X3DProgrammableShaderObject .call (this, executionContext);

   this .addType (Base_X3DConstants .ComposedShader);

   this .loadSensor                = new Networking_LoadSensor (executionContext);
   this .transformFeedbackVaryings = [ ];
}

Object .assign (Object .setPrototypeOf (ComposedShader .prototype, Shaders_X3DShaderNode .prototype),
   Shaders_X3DProgrammableShaderObject .prototype,
{
   wireframe: false,
   initialize ()
   {
      Shaders_X3DShaderNode               .prototype .initialize .call (this);
      Shaders_X3DProgrammableShaderObject .prototype .initialize .call (this);

      // https://www.web3d.org/documents/specifications/19775-1/V4.0/Part01/shaders_glsl.html#relinkingprograms
      this ._activate .addInterest ("set_activate__", this);

      this ._parts .addFieldInterest (this .loadSensor ._children);

      this .loadSensor ._isLoaded .addInterest ("connectLoaded", this);
      this .loadSensor ._children = this ._parts;
      this .loadSensor .setPrivate (true);
      this .loadSensor .setup ();

      if (this .loadSensor ._isLoaded .getValue ())
         this .set_loaded__ ();
      else
         this .connectLoaded ();
   },
   connectLoaded ()
   {
      this .loadSensor ._isLoaded .removeInterest ("connectLoaded", this);
      this .loadSensor ._isLoaded .addInterest ("set_loaded__", this);
   },
   addUserDefinedField (accessType, name, field)
   {
      const shaderFields = this .isInitialized () && this .isValid ();

      if (shaderFields)
         this .removeShaderFields ();

      Shaders_X3DShaderNode .prototype .addUserDefinedField .call (this, accessType, name, field);

      if (shaderFields)
         this .addShaderFields ();
   },
   removeUserDefinedField (name)
   {
      const shaderFields = this .isInitialized () && this .isValid ();

      if (shaderFields)
         this .removeShaderFields ();

      Shaders_X3DShaderNode .prototype .removeUserDefinedField .call (this, name);

      if (shaderFields)
         this .addShaderFields ();
   },
   setTransformFeedbackVaryings (value)
   {
      this .transformFeedbackVaryings = value;
   },
   getProgram ()
   {
      return this .program;
   },
   set_activate__ ()
   {
      if (!this ._activate .getValue ())
         return;

      this .set_loaded__ ();
   },
   set_loaded__ ()
   {
      if (this .loadSensor ._isLoaded .getValue () && this ._language .getValue () === "GLSL")
      {
         const
            gl      = this .getBrowser () .getContext (),
            program = gl .createProgram ();

         if (this .isValid ())
            this .removeShaderFields ();

         gl .deleteProgram (this .program);

         this .program = program;

         for (const node of this ._parts)
         {
            const partNode = Base_X3DCast (Base_X3DConstants .ShaderPart, node);

            if (partNode ?.getShader ())
               gl .attachShader (program, partNode .getShader ());
         }

         if (this .transformFeedbackVaryings .length)
            gl .transformFeedbackVaryings (program, this .transformFeedbackVaryings, gl .INTERLEAVED_ATTRIBS);

         gl .linkProgram (program);

         if (gl .getProgramParameter (program, gl .LINK_STATUS))
         {
            this .setValid (true);
            this .getDefaultUniformsAndAttributes ();
            this .addShaderFields ();
         }
         else
         {
            this .setValid (false);

            if (this ._parts .length)
            {
               console .warn ("Couldn't initialize " + this .getTypeName () + " '" + this .getName () + "': " + gl .getProgramInfoLog (program));
            }
         }
      }
      else
      {
         this .setValid (false);
      }
   },
   dispose ()
   {
      Shaders_X3DProgrammableShaderObject .prototype .dispose .call (this);
      Shaders_X3DShaderNode               .prototype .dispose .call (this);
   },
});

Object .defineProperties (ComposedShader,
{
   typeName:
   {
      value: "ComposedShader",
      enumerable: true,
   },
   componentName:
   {
      value: "Shaders",
      enumerable: true,
   },
   containerField:
   {
      value: "shaders",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",   new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "activate",   new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isSelected", new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isValid",    new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "language",   new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "parts",      new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const ComposedShader_default_ = ComposedShader;
;

x_ite_Namespace .add ("ComposedShader", "x_ite/Components/Shaders/ComposedShader", ComposedShader_default_);
/* harmony default export */ const Shaders_ComposedShader = (ComposedShader_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shaders/X3DVertexAttributeNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function X3DVertexAttributeNode (executionContext)
{
   Rendering_X3DGeometricPropertyNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DVertexAttributeNode);

   this .addChildObjects (Base_X3DConstants .outputOnly, "attribute_changed", new x_ite_Fields .SFTime ());
}

Object .assign (Object .setPrototypeOf (X3DVertexAttributeNode .prototype, Rendering_X3DGeometricPropertyNode .prototype),
{
   initialize ()
   {
      Rendering_X3DGeometricPropertyNode .prototype .initialize .call (this);

      this ._name .addInterest ("set_attribute__", this);
   },
   set_attribute__ ()
   {
      this ._attribute_changed = this .getBrowser () .getCurrentTime ();
   },
});

Object .defineProperties (X3DVertexAttributeNode,
{
   typeName:
   {
      value: "X3DVertexAttributeNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Shaders",
      enumerable: true,
   },
});

const X3DVertexAttributeNode_default_ = X3DVertexAttributeNode;
;

x_ite_Namespace .add ("X3DVertexAttributeNode", "x_ite/Components/Shaders/X3DVertexAttributeNode", X3DVertexAttributeNode_default_);
/* harmony default export */ const Shaders_X3DVertexAttributeNode = (X3DVertexAttributeNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shaders/FloatVertexAttribute.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function FloatVertexAttribute (executionContext)
{
   Shaders_X3DVertexAttributeNode .call (this, executionContext);

   this .addType (Base_X3DConstants .FloatVertexAttribute);
}

Object .assign (Object .setPrototypeOf (FloatVertexAttribute .prototype, Shaders_X3DVertexAttributeNode .prototype),
{
   initialize ()
   {
      Shaders_X3DVertexAttributeNode .prototype .initialize .call (this);

      this ._numComponents .addInterest ("set_numComponents__", this);
      this ._numComponents .addInterest ("set_attribute__",     this);
      this ._value         .addInterest ("set_value__",         this);

      this .set_numComponents__ ();
      this .set_value__ ();
   },
   set_numComponents__ ()
   {
      this .numComponents = Math_Algorithm .clamp (this ._numComponents .getValue (), 1, 4);
   },
   set_value__ ()
   {
      this .value  = this ._value .getValue ();
      this .length = this ._value .length;
   },
   addValue (index, array)
   {
      const value = this .value;

      let
         first = index * this .numComponents,
         last  = first + this .numComponents;

      if (last <= this .length)
      {
         for (; first < last; ++ first)
            array .push (value [first]);
      }
      else if (this .numComponents <= this .length)
      {
         last  = value .length;
         first = last - this .numComponents;

         for (; first < last; ++ first)
            array .push (value [first]);
      }
      else
      {
         for (; first < last; ++ first)
            array .push (0);
      }
   },
   enable (gl, shaderNode, buffer)
   {
      shaderNode .enableFloatAttrib (gl, this ._name .getValue (), buffer, this .numComponents, 0, 0);
   },
});

Object .defineProperties (FloatVertexAttribute,
{
   typeName:
   {
      value: "FloatVertexAttribute",
      enumerable: true,
   },
   componentName:
   {
      value: "Shaders",
      enumerable: true,
   },
   containerField:
   {
      value: "attrib",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",      new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "name",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "numComponents", new x_ite_Fields .SFInt32 (4)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "value",         new x_ite_Fields .MFFloat ()),
      ]),
      enumerable: true,
   },
});

const FloatVertexAttribute_default_ = FloatVertexAttribute;
;

x_ite_Namespace .add ("FloatVertexAttribute", "x_ite/Components/Shaders/FloatVertexAttribute", FloatVertexAttribute_default_);
/* harmony default export */ const Shaders_FloatVertexAttribute = (FloatVertexAttribute_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shaders/Matrix3VertexAttribute.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function Matrix3VertexAttribute (executionContext)
{
   Shaders_X3DVertexAttributeNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Matrix3VertexAttribute);
}

Object .assign (Object .setPrototypeOf (Matrix3VertexAttribute .prototype, Shaders_X3DVertexAttributeNode .prototype),
{
   initialize ()
   {
      Shaders_X3DVertexAttributeNode .prototype .initialize .call (this);

      this ._value .addInterest ("set_value__", this);

      this .set_value__ ();
   },
   set_value__ ()
   {
      this .value  = this ._value .getValue ();
      this .length = this ._value .length;
   },
   addValue (index, array)
   {
      if (index < this .length)
      {
         const value = this .value;

         for (let i = index * 9, l = i + 9; i < l; ++ i)
            array .push (value [i]);
      }
      else if (this .length)
      {
         const value = this .value;

         index = this .length - 1;

         for (let i = index * 9, l = i + 9; i < l; ++ i)
            array .push (value [i]);
      }
      else
      {
         const value = Numbers_Matrix3 .Identity;

         for (let i = 0; i < 9; ++ i)
            array .push (value [i]);
      }
   },
   enable (gl, shaderNode, buffer)
   {
      shaderNode .enableMatrix3Attrib (gl, this ._name .getValue (), buffer, 0, 0);
   },
});

Object .defineProperties (Matrix3VertexAttribute,
{
   typeName:
   {
      value: "Matrix3VertexAttribute",
      enumerable: true,
   },
   componentName:
   {
      value: "Shaders",
      enumerable: true,
   },
   containerField:
   {
      value: "attrib",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "name",     new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "value",    new x_ite_Fields .MFMatrix3f ()),
      ]),
      enumerable: true,
   },
});

const Matrix3VertexAttribute_default_ = Matrix3VertexAttribute;
;

x_ite_Namespace .add ("Matrix3VertexAttribute", "x_ite/Components/Shaders/Matrix3VertexAttribute", Matrix3VertexAttribute_default_);
/* harmony default export */ const Shaders_Matrix3VertexAttribute = (Matrix3VertexAttribute_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shaders/Matrix4VertexAttribute.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function Matrix4VertexAttribute (executionContext)
{
   Shaders_X3DVertexAttributeNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Matrix4VertexAttribute);
}

Object .assign (Object .setPrototypeOf (Matrix4VertexAttribute .prototype, Shaders_X3DVertexAttributeNode .prototype),
{
   initialize ()
   {
      Shaders_X3DVertexAttributeNode .prototype .initialize .call (this);

      this ._value .addInterest ("set_value__", this);

      this .set_value__ ();
   },
   set_value__ ()
   {
      this .value  = this ._value .getValue ();
      this .length = this ._value .length;
   },
   addValue (index, array)
   {
      if (index < this .length)
      {
         const value = this .value;

         for (let i = index * 16, l = i + 16; i < l; ++ i)
            array .push (value [i]);
      }
      else if (this .length)
      {
         const value = this .value;

         index = this .length - 1;

         for (let i = index * 16, l = i + 16; i < l; ++ i)
            array .push (value [i]);
      }
      else
      {
         const value = Matrix4 .Identity;

         for (let i = 0; i < 16; ++ i)
            array .push (value [i]);
      }
   },
   enable (gl, shaderNode, buffer)
   {
      shaderNode .enableMatrix4Attrib (gl, this ._name .getValue (), buffer, 0, 0);
   },
});

Object .defineProperties (Matrix4VertexAttribute,
{
   typeName:
   {
      value: "Matrix4VertexAttribute",
      enumerable: true,
   },
   componentName:
   {
      value: "Shaders",
      enumerable: true,
   },
   containerField:
   {
      value: "attrib",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "name",     new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "value",    new x_ite_Fields .MFMatrix4f ()),
      ]),
      enumerable: true,
   },
});

const Matrix4VertexAttribute_default_ = Matrix4VertexAttribute;
;

x_ite_Namespace .add ("Matrix4VertexAttribute", "x_ite/Components/Shaders/Matrix4VertexAttribute", Matrix4VertexAttribute_default_);
/* harmony default export */ const Shaders_Matrix4VertexAttribute = (Matrix4VertexAttribute_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shaders/PackagedShader.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









function PackagedShader (executionContext)
{
   Shaders_X3DShaderNode               .call (this, executionContext);
   Networking_X3DUrlObject                .call (this, executionContext);
   Shaders_X3DProgrammableShaderObject .call (this, executionContext);

   this .addType (Base_X3DConstants .PackagedShader);
}

Object .assign (Object .setPrototypeOf (PackagedShader .prototype, Shaders_X3DShaderNode .prototype),
   Networking_X3DUrlObject .prototype,
   Shaders_X3DProgrammableShaderObject .prototype,
{
   getSourceText ()
   {
      return this ._url;
   },
   requestImmediateLoad (cache = true)
   { },
   initialize ()
   {
      Shaders_X3DShaderNode               .prototype .initialize .call (this);
      Networking_X3DUrlObject                .prototype .initialize .call (this);
      Shaders_X3DProgrammableShaderObject .prototype .initialize .call (this);
   },
   dispose ()
   {
      Shaders_X3DProgrammableShaderObject .prototype .dispose .call (this);
      Networking_X3DUrlObject                .prototype .dispose .call (this);
      Shaders_X3DShaderNode               .prototype .dispose .call (this);
   },
});

Object .defineProperties (PackagedShader,
{
   typeName:
   {
      value: "PackagedShader",
      enumerable: true,
   },
   componentName:
   {
      value: "Shaders",
      enumerable: true,
   },
   containerField:
   {
      value: "shaders",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "description",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "activate",             new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isSelected",           new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isValid",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "language",             new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "load",                 new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "url",                  new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "autoRefresh",          new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "autoRefreshTimeLimit", new x_ite_Fields .SFTime (3600)),
      ]),
      enumerable: true,
   },
});

const PackagedShader_default_ = PackagedShader;
;

x_ite_Namespace .add ("PackagedShader", "x_ite/Components/Shaders/PackagedShader", PackagedShader_default_);
/* harmony default export */ const Shaders_PackagedShader = (PackagedShader_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shaders/ProgramShader.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function ProgramShader (executionContext)
{
   Shaders_X3DShaderNode .call (this, executionContext);

   this .addType (Base_X3DConstants .ProgramShader);
}

Object .setPrototypeOf (ProgramShader .prototype, Shaders_X3DShaderNode .prototype);

Object .defineProperties (ProgramShader,
{
   typeName:
   {
      value: "ProgramShader",
      enumerable: true,
   },
   componentName:
   {
      value: "Shaders",
      enumerable: true,
   },
   containerField:
   {
      value: "shaders",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",   new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOnly,      "activate",   new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isSelected", new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isValid",    new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "language",   new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "programs",   new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const ProgramShader_default_ = ProgramShader;
;

x_ite_Namespace .add ("ProgramShader", "x_ite/Components/Shaders/ProgramShader", ProgramShader_default_);
/* harmony default export */ const Shaders_ProgramShader = (ProgramShader_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/Types.glsl.js
const Types_glsl_default_ = /* glsl */ `#if defined(X3D_FOG)
struct x3d_FogParameters{mediump int type;mediump vec3 color;mediump float visibilityRange;mediump mat3 matrix;};
#endif
#if defined(X3D_LIGHTING)
struct x3d_LightSourceParameters{mediump int type;mediump vec3 color;mediump float intensity;mediump float ambientIntensity;mediump vec3 attenuation;mediump vec3 location;mediump vec3 direction;mediump float radius;mediump float beamWidth;mediump float cutOffAngle;mediump mat3 matrix;
#if defined(X3D_SHADOWS)
mediump vec3 shadowColor;mediump float shadowIntensity;mediump float shadowBias;mediump mat4 shadowMatrix;mediump int shadowMapSize;
#endif
};
#endif
#if defined(X3D_GEOMETRY_0D)&&defined(X3D_STYLE_PROPERTIES)
struct x3d_PointPropertiesParameters{mediump float pointSizeScaleFactor;mediump float pointSizeMinValue;mediump float pointSizeMaxValue;mediump vec3 attenuation;};
#endif
#if defined(X3D_GEOMETRY_1D)&&defined(X3D_STYLE_PROPERTIES)
struct x3d_LinePropertiesParameters{mediump int linetype;mediump float lineStippleScale;
#if defined(X3D_STYLE_PROPERTIES_TEXTURE)
sampler2D texture;
#endif
};
#endif
#if(defined(X3D_GEOMETRY_2D)||defined(X3D_GEOMETRY_3D))&&defined(X3D_STYLE_PROPERTIES)
struct x3d_FillPropertiesParameters{bool filled;bool hatched;mediump vec3 hatchColor;
#if defined(X3D_STYLE_PROPERTIES_TEXTURE)
sampler2D texture;
#endif
mediump float scale;};
#endif
#if defined(X3D_UNLIT_MATERIAL)
struct x3d_UnlitMaterialParameters{mediump vec3 emissiveColor;mediump float normalScale;mediump float transparency;};
#endif
#if defined(X3D_MATERIAL)
struct x3d_MaterialParameters{mediump float ambientIntensity;mediump vec3 diffuseColor;mediump vec3 specularColor;mediump vec3 emissiveColor;mediump float shininess;mediump float occlusionStrength;mediump float normalScale;mediump float transparency;};
#endif
#if defined(X3D_PHYSICAL_MATERIAL)
struct x3d_PhysicalMaterialParameters{mediump vec3 baseColor;mediump vec3 emissiveColor;mediump float metallic;mediump float roughness;mediump float occlusionStrength;mediump float normalScale;mediump float transparency;};
#endif
#if defined(X3D_AMBIENT_TEXTURE)
struct x3d_AmbientTextureParameters{mediump int textureTransformMapping;mediump int textureCoordinateMapping;
#if defined(X3D_AMBIENT_TEXTURE_2D)
mediump sampler2D texture2D;
#endif
#if defined(X3D_AMBIENT_TEXTURE_3D)&&__VERSION__!=100
mediump sampler3D texture3D;
#endif
#if defined(X3D_AMBIENT_TEXTURE_CUBE)
mediump samplerCube textureCube;
#endif
};
#endif
#if defined(X3D_DIFFUSE_TEXTURE)
struct x3d_DiffuseTextureParameters{mediump int textureTransformMapping;mediump int textureCoordinateMapping;
#if defined(X3D_DIFFUSE_TEXTURE_2D)
mediump sampler2D texture2D;
#endif
#if defined(X3D_DIFFUSE_TEXTURE_3D)&&__VERSION__!=100
mediump sampler3D texture3D;
#endif
#if defined(X3D_DIFFUSE_TEXTURE_CUBE)
mediump samplerCube textureCube;
#endif
};
#endif
#if defined(X3D_SPECULAR_TEXTURE)
struct x3d_SpecularTextureParameters{mediump int textureTransformMapping;mediump int textureCoordinateMapping;
#if defined(X3D_SPECULAR_TEXTURE_2D)
mediump sampler2D texture2D;
#endif
#if defined(X3D_SPECULAR_TEXTURE_3D)&&__VERSION__!=100
mediump sampler3D texture3D;
#endif
#if defined(X3D_SPECULAR_TEXTURE_CUBE)
mediump samplerCube textureCube;
#endif
};
#endif
#if defined(X3D_EMISSIVE_TEXTURE)
struct x3d_EmissiveTextureParameters{mediump int textureTransformMapping;mediump int textureCoordinateMapping;
#if defined(X3D_EMISSIVE_TEXTURE_2D)
mediump sampler2D texture2D;
#endif
#if defined(X3D_EMISSIVE_TEXTURE_3D)&&__VERSION__!=100
mediump sampler3D texture3D;
#endif
#if defined(X3D_EMISSIVE_TEXTURE_CUBE)
mediump samplerCube textureCube;
#endif
};
#endif
#if defined(X3D_SHININESS_TEXTURE)
struct x3d_ShininessTextureParameters{mediump int textureTransformMapping;mediump int textureCoordinateMapping;
#if defined(X3D_SHININESS_TEXTURE_2D)
mediump sampler2D texture2D;
#endif
#if defined(X3D_SHININESS_TEXTURE_3D)&&__VERSION__!=100
mediump sampler3D texture3D;
#endif
#if defined(X3D_SHININESS_TEXTURE_CUBE)
mediump samplerCube textureCube;
#endif
};
#endif
#if defined(X3D_BASE_TEXTURE)
struct x3d_BaseTextureParameters{mediump int textureTransformMapping;mediump int textureCoordinateMapping;
#if defined(X3D_BASE_TEXTURE_2D)
mediump sampler2D texture2D;
#endif
#if defined(X3D_BASE_TEXTURE_3D)&&__VERSION__!=100
mediump sampler3D texture3D;
#endif
#if defined(X3D_BASE_TEXTURE_CUBE)
mediump samplerCube textureCube;
#endif
};
#endif
#if defined(X3D_METALLIC_ROUGHNESS_TEXTURE)
struct x3d_MetallicRoughnessTextureParameters{mediump int textureTransformMapping;mediump int textureCoordinateMapping;
#if defined(X3D_METALLIC_ROUGHNESS_TEXTURE_2D)
mediump sampler2D texture2D;
#endif
#if defined(X3D_METALLIC_ROUGHNESS_TEXTURE_3D)&&__VERSION__!=100
mediump sampler3D texture3D;
#endif
#if defined(X3D_METALLIC_ROUGHNESS_TEXTURE_CUBE)
mediump samplerCube textureCube;
#endif
};
#endif
#if defined(X3D_OCCLUSION_TEXTURE)
struct x3d_OcclusionTextureParameters{mediump int textureTransformMapping;mediump int textureCoordinateMapping;
#if defined(X3D_OCCLUSION_TEXTURE_2D)
mediump sampler2D texture2D;
#endif
#if defined(X3D_OCCLUSION_TEXTURE_3D)&&__VERSION__!=100
mediump sampler3D texture3D;
#endif
#if defined(X3D_OCCLUSION_TEXTURE_CUBE)
mediump samplerCube textureCube;
#endif
};
#endif
#if defined(X3D_NORMAL_TEXTURE)
struct x3d_NormalTextureParameters{mediump int textureTransformMapping;mediump int textureCoordinateMapping;
#if defined(X3D_NORMAL_TEXTURE_2D)
mediump sampler2D texture2D;
#endif
#if defined(X3D_NORMAL_TEXTURE_3D)&&__VERSION__!=100
mediump sampler3D texture3D;
#endif
#if defined(X3D_NORMAL_TEXTURE_CUBE)
mediump samplerCube textureCube;
#endif
};
#endif
#if defined(X3D_MULTI_TEXTURING)
struct x3d_MultiTextureParameters{mediump int mode;mediump int alphaMode;mediump int source;mediump int function;};
#endif
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
struct x3d_TextureCoordinateGeneratorParameters{mediump int mode;mediump float parameter[6];};
#endif
`
;

x_ite_Namespace .add ("Types.glsl", "assets/shaders/Types.glsl", Types_glsl_default_);
/* harmony default export */ const Types_glsl = (Types_glsl_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Texturing/ModeType.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

let ModeType_i = 0;

const ModeType =
{
   REPLACE:                   ModeType_i ++,
   MODULATE:                  ModeType_i ++,
   MODULATE2X:                ModeType_i ++,
   MODULATE4X:                ModeType_i ++,
   ADD:                       ModeType_i ++,
   ADDSIGNED:                 ModeType_i ++,
   ADDSIGNED2X:               ModeType_i ++,
   ADDSMOOTH:                 ModeType_i ++,
   SUBTRACT:                  ModeType_i ++,
   BLENDDIFFUSEALPHA:         ModeType_i ++,
   BLENDTEXTUREALPHA:         ModeType_i ++,
   BLENDFACTORALPHA:          ModeType_i ++,
   BLENDCURRENTALPHA:         ModeType_i ++,
   MODULATEALPHA_ADDCOLOR:    ModeType_i ++,
   MODULATEINVALPHA_ADDCOLOR: ModeType_i ++,
   MODULATEINVCOLOR_ADDALPHA: ModeType_i ++,
   DOTPRODUCT3:               ModeType_i ++,
   SELECTARG1:                ModeType_i ++,
   SELECTARG2:                ModeType_i ++,
   OFF:                       ModeType_i ++,
};

const ModeType_default_ = ModeType;
;

x_ite_Namespace .add ("ModeType", "x_ite/Browser/Texturing/ModeType", ModeType_default_);
/* harmony default export */ const Texturing_ModeType = (ModeType_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Texturing/SourceType.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

let SourceType_i = 0;

const SourceType =
{
   DEFAULT:  SourceType_i ++,
   DIFFUSE:  SourceType_i ++,
   SPECULAR: SourceType_i ++,
   FACTOR:   SourceType_i ++,
};

const SourceType_default_ = SourceType;
;

x_ite_Namespace .add ("SourceType", "x_ite/Browser/Texturing/SourceType", SourceType_default_);
/* harmony default export */ const Texturing_SourceType = (SourceType_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Texturing/FunctionType.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

let FunctionType_i = 0;

const FunctionType =
{
   DEFAULT:        FunctionType_i ++,
   COMPLEMENT:     FunctionType_i ++,
   ALPHAREPLICATE: FunctionType_i ++,
};

const FunctionType_default_ = FunctionType;
;

x_ite_Namespace .add ("FunctionType", "x_ite/Browser/Texturing/FunctionType", FunctionType_default_);
/* harmony default export */ const Texturing_FunctionType = (FunctionType_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Texturing/TextureCoordinateGeneratorModeType.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

let TextureCoordinateGeneratorModeType_i = 0;

const TextureCoordinateGeneratorModeType_ModeType =
{
   NONE:                        TextureCoordinateGeneratorModeType_i ++,
   SPHERE:                      TextureCoordinateGeneratorModeType_i ++,
   CAMERASPACENORMAL:           TextureCoordinateGeneratorModeType_i ++,
   CAMERASPACEPOSITION:         TextureCoordinateGeneratorModeType_i ++,
   CAMERASPACEREFLECTIONVECTOR: TextureCoordinateGeneratorModeType_i ++,
   SPHERE_LOCAL:                TextureCoordinateGeneratorModeType_i ++,
   COORD:                       TextureCoordinateGeneratorModeType_i ++,
   COORD_EYE:                   TextureCoordinateGeneratorModeType_i ++,
   NOISE:                       TextureCoordinateGeneratorModeType_i ++,
   NOISE_EYE:                   TextureCoordinateGeneratorModeType_i ++,
   SPHERE_REFLECT:              TextureCoordinateGeneratorModeType_i ++,
   SPHERE_REFLECT_LOCAL:        TextureCoordinateGeneratorModeType_i ++,
};

const TextureCoordinateGeneratorModeType_default_ = TextureCoordinateGeneratorModeType_ModeType;
;

x_ite_Namespace .add ("TextureCoordinateGeneratorModeType", "x_ite/Browser/Texturing/TextureCoordinateGeneratorModeType", TextureCoordinateGeneratorModeType_default_);
/* harmony default export */ const TextureCoordinateGeneratorModeType = (TextureCoordinateGeneratorModeType_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Shaders/ShaderSource.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







const ShaderSource =
{
   getSource (gl, browser, source, options)
   {
			const
				COMMENTS     = "\\s+|/\\*[\\s\\S]*?\\*/|//.*?\\n",
				LINE         = "#line\\s+.*?\\n",
				IF           = "#if\\s+.*?\\n",
				ELIF         = "#elif\\s+.*?\\n",
				IFDEF        = "#ifdef\\s+.*?\\n",
				IFNDEF       = "#ifndef\\s+.*?\\n",
				ELSE         = "#else.*?\\n",
				ENDIF        = "#endif.*?\\n",
				DEFINE       = "#define\\s+(?:[^\\n\\\\]|\\\\[^\\r\\n]|\\\\\\r?\\n)*\\n",
				UNDEF        = "#undef\\s+.*?\\n",
				PRAGMA       = "#pragma\\s+.*?\\n",
				PREPROCESSOR =  LINE + "|" + IF + "|" + ELIF + "|" + IFDEF + "|" + IFNDEF + "|" + ELSE + "|" + ENDIF + "|" + DEFINE + "|" + UNDEF + "|" + PRAGMA,
				VERSION      = "#version\\s+.*?\\n",
				EXTENSION    = "#extension\\s+.*?\\n",
				ANY          = "[\\s\\S]*";

			const
				GLSL  = new RegExp ("^((?:" + COMMENTS + "|" + PREPROCESSOR + ")*(?:" + VERSION + ")?(?:" + COMMENTS + "|" + PREPROCESSOR + "|" + EXTENSION + ")*)(" + ANY + ")$"),
				match = source .match (GLSL);

      // const
      //    COMMENTS = "\\s+|/\\*.*?\\*/|//.*?\\n",
      //    VERSION  = "#version\\s+.*?\\n",
      //    ANY      = ".*";

      // const
      //    GLSL  = new RegExp ("^((?:" + COMMENTS + ")?(?:" + VERSION + ")?)(" + ANY + ")$", "s"),
      //    match = source .match (GLSL);

      if (! match)
         return source;

      // Constants

      let constants = "";

      constants += "#define X_ITE\n";

      if (gl .HAS_FEATURE_DEPTH_TEXTURE)
         constants += "#define X3D_DEPTH_TEXTURE\n";

      for (const option of options)
         constants += "#define " + option + "\n";

      // Definitions

      let definitions = "";

      definitions += "#define x3d_None 0\n";

      definitions += "#define x3d_Points      0\n";
      definitions += "#define x3d_Lines       1\n";
      definitions += "#define x3d_Geometry2D  2\n";
      definitions += "#define x3d_Geometry3D  3\n";

      definitions += "#define x3d_MaxClipPlanes  " + browser .getMaxClipPlanes () + "\n";

      definitions += "#define x3d_LinearFog        1\n";
      definitions += "#define x3d_ExponentialFog   2\n";
      definitions += "#define x3d_Exponential2Fog  3\n";

      definitions += "#define x3d_MaxLights         " + browser .getMaxLights () + "\n";
      definitions += "#define x3d_DirectionalLight  1\n";
      definitions += "#define x3d_PointLight        2\n";
      definitions += "#define x3d_SpotLight         3\n";

      definitions += "#define x3d_MaxTextures      " + browser .getMaxTextures () + "\n";
      definitions += "#define x3d_TextureType2D    2\n";
      definitions += "#define x3d_TextureType3D    3\n";
      definitions += "#define x3d_TextureTypeCube  4\n";

      definitions += "#define x3d_Replace                   " + Texturing_ModeType .REPLACE                   + "\n";
      definitions += "#define x3d_Modulate                  " + Texturing_ModeType .MODULATE                  + "\n";
      definitions += "#define x3d_Modulate2X                " + Texturing_ModeType .MODULATE2X                + "\n";
      definitions += "#define x3d_Modulate4X                " + Texturing_ModeType .MODULATE4X                + "\n";
      definitions += "#define x3d_Add                       " + Texturing_ModeType .ADD                       + "\n";
      definitions += "#define x3d_AddSigned                 " + Texturing_ModeType .ADDSIGNED                 + "\n";
      definitions += "#define x3d_AddSigned2X               " + Texturing_ModeType .ADDSIGNED2X               + "\n";
      definitions += "#define x3d_AddSmooth                 " + Texturing_ModeType .ADDSMOOTH                 + "\n";
      definitions += "#define x3d_Subtract                  " + Texturing_ModeType .SUBTRACT                  + "\n";
      definitions += "#define x3d_BlendDiffuseAlpha         " + Texturing_ModeType .BLENDDIFFUSEALPHA         + "\n";
      definitions += "#define x3d_BlendTextureAlpha         " + Texturing_ModeType .BLENDTEXTUREALPHA         + "\n";
      definitions += "#define x3d_BlendFactorAlpha          " + Texturing_ModeType .BLENDFACTORALPHA          + "\n";
      definitions += "#define x3d_BlendCurrentAlpha         " + Texturing_ModeType .BLENDCURRENTALPHA         + "\n";
      definitions += "#define x3d_ModulateAlphaAddColor     " + Texturing_ModeType .MODULATEALPHA_ADDCOLOR    + "\n";
      definitions += "#define x3d_ModulateInvAlphaAddColor  " + Texturing_ModeType .MODULATEINVALPHA_ADDCOLOR + "\n";
      definitions += "#define x3d_ModulateInvColorAddAlpha  " + Texturing_ModeType .MODULATEINVCOLOR_ADDALPHA + "\n";
      definitions += "#define x3d_DotProduct3               " + Texturing_ModeType .DOTPRODUCT3               + "\n";
      definitions += "#define x3d_SelectArg1                " + Texturing_ModeType .SELECTARG1                + "\n";
      definitions += "#define x3d_SelectArg2                " + Texturing_ModeType .SELECTARG2                + "\n";
      definitions += "#define x3d_Off                       " + Texturing_ModeType .OFF                       + "\n";

      definitions += "#define x3d_Diffuse  " + Texturing_SourceType .DIFFUSE  + "\n";
      definitions += "#define x3d_Specular " + Texturing_SourceType .SPECULAR + "\n";
      definitions += "#define x3d_Factor   " + Texturing_SourceType .FACTOR   + "\n";

      definitions += "#define x3d_Complement     " + Texturing_FunctionType .COMPLEMENT     + "\n";
      definitions += "#define x3d_AlphaReplicate " + Texturing_FunctionType .ALPHAREPLICATE + "\n";

      definitions += "#define x3d_Sphere                      " + TextureCoordinateGeneratorModeType .SPHERE                      + "\n";
      definitions += "#define x3d_CameraSpaceNormal           " + TextureCoordinateGeneratorModeType .CAMERASPACENORMAL           + "\n";
      definitions += "#define x3d_CameraSpacePosition         " + TextureCoordinateGeneratorModeType .CAMERASPACEPOSITION         + "\n";
      definitions += "#define x3d_CameraSpaceReflectionVector " + TextureCoordinateGeneratorModeType .CAMERASPACEREFLECTIONVECTOR + "\n";
      definitions += "#define x3d_SphereLocal                 " + TextureCoordinateGeneratorModeType .SPHERE_LOCAL                + "\n";
      definitions += "#define x3d_Coord                       " + TextureCoordinateGeneratorModeType .COORD                       + "\n";
      definitions += "#define x3d_CoordEye                    " + TextureCoordinateGeneratorModeType .COORD_EYE                   + "\n";
      definitions += "#define x3d_Noise                       " + TextureCoordinateGeneratorModeType .NOISE                       + "\n";
      definitions += "#define x3d_NoiseEye                    " + TextureCoordinateGeneratorModeType .NOISE_EYE                   + "\n";
      definitions += "#define x3d_SphereReflect               " + TextureCoordinateGeneratorModeType .SPHERE_REFLECT              + "\n";
      definitions += "#define x3d_SphereReflectLocal          " + TextureCoordinateGeneratorModeType .SPHERE_REFLECT_LOCAL        + "\n";

      // Legacy
      definitions += "#define x3d_GeometryPoints  0\n";
      definitions += "#define x3d_GeometryLines   1\n";
      definitions += "#define x3d_NoneClipPlane   vec4 (88.0, 51.0, 68.0, 33.0)\n";
      definitions += "#define x3d_NoneFog         0\n";
      definitions += "#define x3d_NoneLight       0\n";
      definitions += "#define x3d_NoneTexture     0\n";

      // Adjust precision of struct types;

      const
         matchFloat       = source .match (/\s*precision\s+(lowp|mediump|highp)\s+float\s*;/),
         matchInt         = source .match (/\s*precision\s+(lowp|mediump|highp)\s+int\s*;/),
         precisionFloat   = matchFloat ? matchFloat [1] : "mediump",
         precisionInt     = matchInt   ? matchInt   [1] : "mediump";

      const types = Types_glsl
         .replace (/mediump\s+(float|vec2|vec3|mat3|mat4)/g, precisionFloat + " $1")
         .replace (/mediump\s+(int)/g,                       precisionInt   + " $1");

      const lines = (match [1] .match (/\n/g) || [ ]) .length + 1;

      return match [1] + constants + definitions + types + "#line " + (lines + 1) + " -1\n" + match [2];
   },
};

function depreciatedWarning (source, depreciated, current)
{
   if (source .indexOf (depreciated) === -1)
      return;

   console .warn ("Use of '" + depreciated + "' is depreciated, use '" + current + "' instead. See https://create3000.github.io/x_ite/custom-shaders.");
}

const ShaderSource_default_ = ShaderSource;
;

x_ite_Namespace .add ("ShaderSource", "x_ite/Browser/Shaders/ShaderSource", ShaderSource_default_);
/* harmony default export */ const Shaders_ShaderSource = (ShaderSource_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/common/ClipPlanes1.glsl.js
const ClipPlanes1_glsl_default_ = /* glsl */ `#if defined(X3D_CLIP_PLANES)
uniform vec4 x3d_ClipPlane[X3D_NUM_CLIP_PLANES];void clip(){for(int i=0;i<X3D_NUM_CLIP_PLANES;++i){if(dot(vertex,x3d_ClipPlane[i].xyz)-x3d_ClipPlane[i].w<0.0)discard;}}
#endif
`
;

x_ite_Namespace .add ("ClipPlanes1.glsl", "assets/shaders/webgl1/common/ClipPlanes1.glsl", ClipPlanes1_glsl_default_);
/* harmony default export */ const ClipPlanes1_glsl = (ClipPlanes1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/common/Colors1.glsl.js
const Colors1_glsl_default_ = /* glsl */ `vec4 SRGBtoLINEAR(const in vec4 srgbIn){
#if defined(MANUAL_SRGB)
#if defined(SRGB_FAST_APPROXIMATION)
vec3 linOut=pow(srgbIn.xyz,vec3(2.2));
#else 
vec3 bLess=step(vec3(0.04045),srgbIn.xyz);vec3 linOut=mix(srgbIn.xyz/vec3(12.92),pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)),bLess);
#endif 
return vec4(linOut,srgbIn.w);
#else 
return srgbIn;
#endif 
}
#if defined(MANUAL_SRGB)
vec4 Gamma(const in vec4 color){return vec4(pow(color.rgb,vec3(1.0/2.2)),color.a);}
#else
#define Gamma(color)(color)
#endif
`
;

x_ite_Namespace .add ("Colors1.glsl", "assets/shaders/webgl1/common/Colors1.glsl", Colors1_glsl_default_);
/* harmony default export */ const Colors1_glsl = (Colors1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/common/Fog1.glsl.js
const Fog1_glsl_default_ = /* glsl */ `#if defined(X3D_FOG)
uniform x3d_FogParameters x3d_Fog;float getFogInterpolant(){
#if defined(X3D_FOG_COORDS)
return clamp(1.0-fogDepth,0.0,1.0);
#else
float visibilityRange=x3d_Fog.visibilityRange;float dV=length(x3d_Fog.matrix*vertex);
#if defined(X3D_FOG_LINEAR)
return max(0.0,visibilityRange-dV)/visibilityRange;
#elif defined(X3D_FOG_EXPONENTIAL)
return exp(-dV/max(0.001,visibilityRange-dV));
#endif
#endif
}vec3 getFogColor(const in vec3 color){return mix(x3d_Fog.color,color,getFogInterpolant());}
#endif
`
;

x_ite_Namespace .add ("Fog1.glsl", "assets/shaders/webgl1/common/Fog1.glsl", Fog1_glsl_default_);
/* harmony default export */ const Fog1_glsl = (Fog1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/common/Fragment1.glsl.js
const Fragment1_glsl_default_ = /* glsl */ `#if defined(X3D_NORMAL_TEXTURE)
#extension GL_OES_standard_derivatives:enable
#endif
#if defined(X3D_LOGARITHMIC_DEPTH_BUFFER)
#extension GL_EXT_frag_depth:enable
#endif
#if defined(X3D_ALPHA_MODE_MASK)
uniform float x3d_AlphaCutoff;
#endif
#if defined(X3D_FOG)&&defined(X3D_FOG_COORDS)
varying float fogDepth;
#endif
#if defined(X3D_COLOR_MATERIAL)
varying vec4 color;
#endif
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
#if X3D_NUM_TEXTURE_COORDINATES>0
varying vec4 texCoord0;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>1
varying vec4 texCoord1;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>2
varying vec4 texCoord2;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>3
varying vec4 texCoord3;
#endif
#endif
#else
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
#if X3D_NUM_TEXTURE_COORDINATES>0
vec4 texCoord0=vec4(0.0,0.0,0.0,1.0);
#endif
#if X3D_NUM_TEXTURE_COORDINATES>1
vec4 texCoord1=vec4(0.0,0.0,0.0,1.0);
#endif
#if X3D_NUM_TEXTURE_COORDINATES>2
vec4 texCoord2=vec4(0.0,0.0,0.0,1.0);
#endif
#if X3D_NUM_TEXTURE_COORDINATES>3
vec4 texCoord3=vec4(0.0,0.0,0.0,1.0);
#endif
#endif
#endif
#if defined(X3D_NORMALS)
varying vec3 normal;
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
varying vec3 localNormal;
#endif
#else
const vec3 normal=vec3(0.0,0.0,1.0);
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
const vec3 localNormal=vec3(0.0,0.0,1.0);
#endif
#endif
varying vec3 vertex;
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
varying vec3 localVertex;
#endif
#if defined(X3D_LOGARITHMIC_DEPTH_BUFFER)
uniform float x3d_LogarithmicFarFactor1_2;varying float depth;
#endif
#pragma X3D include "Texture.glsl"
#pragma X3D include "ClipPlanes.glsl"
#pragma X3D include "Point.glsl"
#pragma X3D include "Hatch.glsl"
#pragma X3D include "Fog.glsl"
vec4 getMaterialColor();void fragment_main(){
#if defined(X3D_CLIP_PLANES)
clip();
#endif
#if defined(X3D_GEOMETRY_0D)&&defined(X3D_STYLE_PROPERTIES)
setPointTexCoords();
#endif
vec4 finalColor=getMaterialColor();
#if defined(X3D_GEOMETRY_0D)&&defined(X3D_STYLE_PROPERTIES)
finalColor=getPointColor(finalColor);
#endif
#if(defined(X3D_GEOMETRY_2D)||defined(X3D_GEOMETRY_3D))&&defined(X3D_STYLE_PROPERTIES)
finalColor=getHatchColor(finalColor);
#endif
#if defined(X3D_FOG)
finalColor.rgb=getFogColor(finalColor.rgb);
#endif
#if defined(X3D_ALPHA_MODE_OPAQUE)
finalColor.a=1.0;
#endif
#if defined(X3D_ALPHA_MODE_MASK)
if(finalColor.a<x3d_AlphaCutoff)discard;finalColor.a=1.0;
#endif
gl_FragColor=finalColor;
#if defined(X3D_LOGARITHMIC_DEPTH_BUFFER)
gl_FragDepthEXT=log2(depth)*x3d_LogarithmicFarFactor1_2;
#endif
}
`
;

x_ite_Namespace .add ("Fragment1.glsl", "assets/shaders/webgl1/common/Fragment1.glsl", Fragment1_glsl_default_);
/* harmony default export */ const Fragment1_glsl = (Fragment1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/common/Hatch1.glsl.js
const Hatch1_glsl_default_ = /* glsl */ `#if(defined(X3D_GEOMETRY_2D)||defined(X3D_GEOMETRY_3D))&&defined(X3D_STYLE_PROPERTIES)
uniform x3d_FillPropertiesParameters x3d_FillProperties;vec4 getHatchColor(vec4 color){vec4 finalColor=x3d_FillProperties.filled?color:vec4(0.0);
#if defined(X3D_STYLE_PROPERTIES_TEXTURE)
vec4 hatch=texture2D(x3d_FillProperties.texture,gl_FragCoord.xy/(32.0*x3d_FillProperties.scale));hatch.rgb*=x3d_FillProperties.hatchColor;finalColor=mix(finalColor,hatch,hatch.a);
#endif
return finalColor;}
#endif
`
;

x_ite_Namespace .add ("Hatch1.glsl", "assets/shaders/webgl1/common/Hatch1.glsl", Hatch1_glsl_default_);
/* harmony default export */ const Hatch1_glsl = (Hatch1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/common/Material1.glsl.js
const Material1_glsl_default_ = /* glsl */ `uniform x3d_MaterialParameters x3d_Material;
#if defined(X3D_LIGHTING)
#pragma X3D include "SpotFactor.glsl"
#pragma X3D include "Shadow.glsl"
uniform x3d_LightSourceParameters x3d_LightSource[X3D_NUM_LIGHTS];vec3 getMaterialColor(const in vec3 vertex,const in vec3 N,const in vec3 ambientColor,const in vec3 diffuseColor,const in vec3 specularColor,const in float shininess){vec3 V=normalize(-vertex);vec3 finalColor=vec3(0.0);for(int i=0;i<X3D_NUM_LIGHTS;++i){x3d_LightSourceParameters light=x3d_LightSource[i];vec3 vL=light.location-vertex;float dL=length(light.matrix*vL);bool di=light.type==x3d_DirectionalLight;if(di||dL<=light.radius||light.radius<0.0){vec3 d=light.direction;vec3 c=light.attenuation;vec3 L=di?-d:normalize(vL);vec3 H=normalize(L+V);float lightAngle=max(dot(N,L),0.0);vec3 diffuseTerm=diffuseColor*lightAngle;float specularFactor=shininess>0.0?pow(max(dot(N,H),0.0),shininess*128.0):1.0;vec3 specularTerm=specularColor*specularFactor;float attenuationFactor=di?1.0:1.0/max(dot(c,vec3(1.0,dL,dL*dL)),1.0);float spotFactor=light.type==x3d_SpotLight?getSpotFactor(light.cutOffAngle,light.beamWidth,L,d):1.0;float attenuationSpotFactor=attenuationFactor*spotFactor;vec3 ambientTerm=light.ambientIntensity*ambientColor;vec3 diffuseSpecularTerm=light.intensity*(diffuseTerm+specularTerm);
#if defined(X3D_FRAGMENT_SHADER)&&defined(X3D_SHADOWS)
if(lightAngle>0.0&&light.shadowIntensity>0.0)diffuseSpecularTerm=mix(diffuseSpecularTerm,light.shadowColor,getShadowIntensity(i,light));
#endif
finalColor+=attenuationSpotFactor*light.color*(ambientTerm+diffuseSpecularTerm);}}return finalColor;}
#endif
`
;

x_ite_Namespace .add ("Material1.glsl", "assets/shaders/webgl1/common/Material1.glsl", Material1_glsl_default_);
/* harmony default export */ const Material1_glsl = (Material1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/common/Normal1.glsl.js
const Normal1_glsl_default_ = /* glsl */ `#if defined(X3D_NORMAL_TEXTURE)
mat3 getTBNMatrix(const in vec2 texCoord){vec3 pos_dx=dFdx(vertex);vec3 pos_dy=dFdy(vertex);vec3 tex_dx=dFdx(vec3(texCoord,0.0));vec3 tex_dy=dFdy(vec3(texCoord,0.0));vec3 t=(tex_dy.t*pos_dx-tex_dx.t*pos_dy)/(tex_dx.s*tex_dy.t-tex_dy.s*tex_dx.t);vec3 N=normalize(normal);vec3 T=normalize(t-N*dot(N,t));vec3 B=normalize(cross(N,T));mat3 tbn=mat3(T,B,N);return tbn;}
#endif
#if defined(X3D_NORMAL_TEXTURE)
uniform x3d_NormalTextureParameters x3d_NormalTexture;
#endif
vec3 getNormalVector(const in float normalScale){float facing=gl_FrontFacing?1.0:-1.0;
#if defined(X3D_NORMAL_TEXTURE)&&!defined(X3D_NORMAL_TEXTURE_3D)
vec3 texCoord=getTexCoord(x3d_NormalTexture.textureTransformMapping,x3d_NormalTexture.textureCoordinateMapping);vec3 scale=vec3(vec2(normalScale),1.0);mat3 tbn=getTBNMatrix(texCoord.st);
#if defined(X3D_NORMAL_TEXTURE_2D)
vec3 n=texture2D(x3d_NormalTexture.texture2D,texCoord.st).rgb;
#elif defined(X3D_NORMAL_TEXTURE_CUBE)
vec3 n=textureCube(x3d_NormalTexture.textureCube,texCoord).rgb;
#endif
return normalize(tbn*((n*2.0-1.0)*scale))*facing;
#else
return normalize(normal)*facing;
#endif
}
`
;

x_ite_Namespace .add ("Normal1.glsl", "assets/shaders/webgl1/common/Normal1.glsl", Normal1_glsl_default_);
/* harmony default export */ const Normal1_glsl = (Normal1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/common/Perlin1.glsl.js
const Perlin1_glsl_default_ = /* glsl */ `float rand(const in vec2 co){return fract(sin(dot(co.xy,vec2(12.9898,78.233)))*43758.5453);}float rand(const in vec2 co,const in float l){return rand(vec2(rand(co),l));}float rand(const in vec2 co,const in float l,const in float t){return rand(vec2(rand(co,l),t));}float perlin(const in vec2 p,const in float dim,const in float time){const float M_PI=3.14159265358979323846;vec2 pos=floor(p*dim);vec2 posx=pos+vec2(1.0,0.0);vec2 posy=pos+vec2(0.0,1.0);vec2 posxy=pos+vec2(1.0);float c=rand(pos,dim,time);float cx=rand(posx,dim,time);float cy=rand(posy,dim,time);float cxy=rand(posxy,dim,time);vec2 d=fract(p*dim);d=-0.5*cos(d*M_PI)+0.5;float ccx=mix(c,cx,d.x);float cycxy=mix(cy,cxy,d.x);float center=mix(ccx,cycxy,d.y);return center*2.0-1.0;}vec3 perlin(const in vec3 p){return vec3(perlin(p.xy,1.0,0.0),perlin(p.yz,1.0,0.0),perlin(p.zx,1.0,0.0));}
`
;

x_ite_Namespace .add ("Perlin1.glsl", "assets/shaders/webgl1/common/Perlin1.glsl", Perlin1_glsl_default_);
/* harmony default export */ const Perlin1_glsl = (Perlin1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/common/Point1.glsl.js
const Point1_glsl_default_ = /* glsl */ `#if defined(X3D_GEOMETRY_0D)&&defined(X3D_STYLE_PROPERTIES)
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
void setPointTexCoords(){vec4 texCoord=vec4(gl_PointCoord.x,1.0-gl_PointCoord.y,0.0,1.0);
#if X3D_NUM_TEXTURE_COORDINATES>0
texCoord0=texCoord;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>1
texCoord1=texCoord;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>2
texCoord2=texCoord;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>3
texCoord3=texCoord;
#endif
}
#define getPointColor(color)(color)
#else
#define setPointTexCoords()
varying float pointSize;vec4 getPointColor(in vec4 color){if(pointSize>1.0)color.a*=clamp(pointSize*(0.5-distance(vec2(0.5),gl_PointCoord)),0.0,1.0);else color.a*=pointSize;return color;}
#endif
#endif
`
;

x_ite_Namespace .add ("Point1.glsl", "assets/shaders/webgl1/common/Point1.glsl", Point1_glsl_default_);
/* harmony default export */ const Point1_glsl = (Point1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/common/PointSize1.glsl.js
const PointSize1_glsl_default_ = /* glsl */ `#if defined(X3D_GEOMETRY_0D)&&defined(X3D_STYLE_PROPERTIES)
uniform x3d_PointPropertiesParameters x3d_PointProperties;varying float pointSize;float getPointSize(const in vec3 vertex){float pointSizeMinValue=x3d_PointProperties.pointSizeMinValue;float pointSizeMaxValue=x3d_PointProperties.pointSizeMaxValue;vec3 attenuation=x3d_PointProperties.attenuation;float dL=length(vertex);float pointSize=0.0;pointSize=x3d_PointProperties.pointSizeScaleFactor;pointSize/=dot(attenuation,vec3(1.0,dL,dL*dL));pointSize=clamp(pointSize,pointSizeMinValue,pointSizeMaxValue);
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURE)
return pointSize;
#else
return pointSize+1.0-step(pointSize,1.0);
#endif
}
#endif
`
;

x_ite_Namespace .add ("PointSize1.glsl", "assets/shaders/webgl1/common/PointSize1.glsl", PointSize1_glsl_default_);
/* harmony default export */ const PointSize1_glsl = (PointSize1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/common/Shadow1.glsl.js
const Shadow1_glsl_default_ = /* glsl */ `#if defined(X3D_FRAGMENT_SHADER)&&defined(X3D_SHADOWS)
uniform sampler2D x3d_ShadowMap[X3D_NUM_LIGHTS];float getShadowDepth(const in int index,const in vec2 shadowCoord){
#if X3D_NUM_LIGHTS>0
if(index==0)return texture2D(x3d_ShadowMap[0],shadowCoord).r;
#endif
#if X3D_NUM_LIGHTS>1
if(index==1)return texture2D(x3d_ShadowMap[1],shadowCoord).r;
#endif
#if X3D_NUM_LIGHTS>2
if(index==2)return texture2D(x3d_ShadowMap[2],shadowCoord).r;
#endif
#if X3D_NUM_LIGHTS>3
if(index==3)return texture2D(x3d_ShadowMap[3],shadowCoord).r;
#endif
#if X3D_NUM_LIGHTS>4
if(index==4)return texture2D(x3d_ShadowMap[4],shadowCoord).r;
#endif
#if X3D_NUM_LIGHTS>5
if(index==5)return texture2D(x3d_ShadowMap[5],shadowCoord).r;
#endif
#if X3D_NUM_LIGHTS>6
if(index==6)return texture2D(x3d_ShadowMap[6],shadowCoord).r;
#endif
#if X3D_NUM_LIGHTS>7
if(index==7)return texture2D(x3d_ShadowMap[7],shadowCoord).r;
#endif
return 0.0;}float texture2DCompare(const in int index,const in vec2 texCoord,const in float compare){float shadowDepth=getShadowDepth(index,texCoord);return(1.0-step(1.0,shadowDepth))*step(shadowDepth,compare);}float texture2DShadowLerp(const in int index,const in vec2 texelSize,const in float shadowMapSize,const in vec2 texCoord,const in float compare){const vec2 offset=vec2(0.0,1.0);vec2 centroidTexCoord=floor(texCoord*shadowMapSize+0.5)/shadowMapSize;float lb=texture2DCompare(index,centroidTexCoord+texelSize*offset.xx,compare);float lt=texture2DCompare(index,centroidTexCoord+texelSize*offset.xy,compare);float rb=texture2DCompare(index,centroidTexCoord+texelSize*offset.yx,compare);float rt=texture2DCompare(index,centroidTexCoord+texelSize*offset.yy,compare);vec2 f=fract(texCoord*shadowMapSize+0.5);float a=mix(lb,lt,f.y);float b=mix(rb,rt,f.y);float c=mix(a,b,f.x);return c;}vec2 cubeToUVCompact(in vec3 v,const float texelSizeY){vec3 absV=abs(v);float scaleToCube=1.0/max(absV.x,max(absV.y,absV.z));absV*=scaleToCube;v*=scaleToCube*(1.0-2.0*texelSizeY);vec2 planar=v.xy;float almostATexel=1.5*texelSizeY;float almostOne=1.0-almostATexel;if(absV.z>=almostOne){if(v.z>0.0)planar.x=4.0-v.x;}else if(absV.x>=almostOne){float signX=sign(v.x);planar.x=v.z*signX+2.0*signX;}else if(absV.y>=almostOne){float signY=sign(v.y);planar.x=(v.x+0.5+signY)*2.0;planar.y=v.z*signY-2.0;}return vec2(0.125,0.25)*planar+vec2(0.375,0.75);}mat4 getPointLightRotations(const in vec3 vector){mat4 rotations[6];rotations[0]=mat4(0,0,1,0,0,1,0,0,-1,0,0,0,0,0,0,1);rotations[1]=mat4(0,0,-1,0,0,1,0,0,1,0,0,0,0,0,0,1);rotations[2]=mat4(-1,0,0,0,0,1,0,0,0,0,-1,0,0,0,0,1);rotations[3]=mat4(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);rotations[4]=mat4(1,0,0,0,0,0,1,0,0,-1,0,0,0,0,0,1);rotations[5]=mat4(1,0,0,0,0,0,-1,0,0,1,0,0,0,0,0,1);vec3 a=abs(vector.xyz);if(a.x>a.y){if(a.x>a.z)return vector.x>0.0?rotations[1]:rotations[0];else return vector.z>0.0?rotations[2]:rotations[3];}else{if(a.y>a.z)return vector.y>0.0?rotations[5]:rotations[4];else return vector.z>0.0?rotations[2]:rotations[3];}return rotations[3];}float getShadowIntensity(const in int index,const in x3d_LightSourceParameters light){if(light.type==x3d_PointLight){const mat4 biasMatrix=mat4(0.5,0.0,0.0,0.0,0.0,0.5,0.0,0.0,0.0,0.0,0.5,0.0,0.5,0.5,0.5,1.0);const mat4 projectionMatrix=mat4(1.0,0.0,0.0,0.0,0.0,0.5,0.0,0.0,0.0,0.0,-1.000025000312504,-1.0,0,0.0,-0.25000312503906297,0.0);vec2 texelSize=vec2(1.0)/(float(light.shadowMapSize)*vec2(4.0,2.0));vec4 shadowCoord=light.shadowMatrix*vec4(vertex,1.0);vec3 lightToPosition=shadowCoord.xyz;shadowCoord=biasMatrix*(projectionMatrix*(getPointLightRotations(lightToPosition)*shadowCoord));shadowCoord.z-=light.shadowBias;shadowCoord.xyz/=shadowCoord.w;
#if defined(X3D_PCF_FILTERING)||defined(X3D_PCF_SOFT_FILTERING)
vec2 offset=vec2(-1,1)*(texelSize.y*42.0);float value=(texture2DCompare(index,cubeToUVCompact(lightToPosition+offset.xyy,texelSize.y),shadowCoord.z)+texture2DCompare(index,cubeToUVCompact(lightToPosition+offset.yyy,texelSize.y),shadowCoord.z)+texture2DCompare(index,cubeToUVCompact(lightToPosition+offset.xyx,texelSize.y),shadowCoord.z)+texture2DCompare(index,cubeToUVCompact(lightToPosition+offset.yyx,texelSize.y),shadowCoord.z)+texture2DCompare(index,cubeToUVCompact(lightToPosition,texelSize.y),shadowCoord.z)+texture2DCompare(index,cubeToUVCompact(lightToPosition+offset.xxy,texelSize.y),shadowCoord.z)+texture2DCompare(index,cubeToUVCompact(lightToPosition+offset.yxy,texelSize.y),shadowCoord.z)+texture2DCompare(index,cubeToUVCompact(lightToPosition+offset.xxx,texelSize.y),shadowCoord.z)+texture2DCompare(index,cubeToUVCompact(lightToPosition+offset.yxx,texelSize.y),shadowCoord.z))*(1.0/9.0);return light.shadowIntensity*value;
#else 
float value=texture2DCompare(index,cubeToUVCompact(lightToPosition,texelSize.y),shadowCoord.z);return light.shadowIntensity*value;
#endif
}else{
#if defined(X3D_PCF_FILTERING)
vec2 texelSize=vec2(1.0)/vec2(light.shadowMapSize);vec4 shadowCoord=light.shadowMatrix*vec4(vertex,1.0);shadowCoord.z-=light.shadowBias;shadowCoord.xyz/=shadowCoord.w;if(any(greaterThan(abs(shadowCoord.xy-0.5),vec2(0.5))))return 0.0;vec2 d0=-texelSize;vec2 d1=texelSize;float value=(texture2DCompare(index,shadowCoord.xy+d0,shadowCoord.z)+texture2DCompare(index,shadowCoord.xy+vec2(0.0,d0.y),shadowCoord.z)+texture2DCompare(index,shadowCoord.xy+vec2(d1.x,d0.y),shadowCoord.z)+texture2DCompare(index,shadowCoord.xy+vec2(d0.x,0.0),shadowCoord.z)+texture2DCompare(index,shadowCoord.xy,shadowCoord.z)+texture2DCompare(index,shadowCoord.xy+vec2(d1.x,0.0),shadowCoord.z)+texture2DCompare(index,shadowCoord.xy+vec2(d0.x,d1.y),shadowCoord.z)+texture2DCompare(index,shadowCoord.xy+vec2(0.0,d1.y),shadowCoord.z)+texture2DCompare(index,shadowCoord.xy+d1,shadowCoord.z))*(1.0/9.0);return light.shadowIntensity*value;
#elif defined(X3D_PCF_SOFT_FILTERING)
vec2 texelSize=vec2(1.0)/vec2(light.shadowMapSize);vec4 shadowCoord=light.shadowMatrix*vec4(vertex,1.0);shadowCoord.z-=light.shadowBias;shadowCoord.xyz/=shadowCoord.w;if(any(greaterThan(abs(shadowCoord.xy-0.5),vec2(0.5))))return 0.0;vec2 d0=-texelSize;vec2 d1=texelSize;float value=(texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy+d0,shadowCoord.z)+texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy+vec2(0.0,d0.y),shadowCoord.z)+texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy+vec2(d1.x,d0.y),shadowCoord.z)+texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy+vec2(d0.x,0.0),shadowCoord.z)+texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy,shadowCoord.z)+texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy+vec2(d1.x,0.0),shadowCoord.z)+texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy+vec2(d0.x,d1.y),shadowCoord.z)+texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy+vec2(0.0,d1.y),shadowCoord.z)+texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy+d1,shadowCoord.z))*(1.0/9.0);return light.shadowIntensity*value;
#else 
vec4 shadowCoord=light.shadowMatrix*vec4(vertex,1.0);shadowCoord.z-=light.shadowBias;shadowCoord.xyz/=shadowCoord.w;if(any(greaterThan(abs(shadowCoord.xy-0.5),vec2(0.5))))return 0.0;float value=texture2DCompare(index,shadowCoord.xy,shadowCoord.z);return light.shadowIntensity*value;
#endif
}return 0.0;}
#endif
`
;

x_ite_Namespace .add ("Shadow1.glsl", "assets/shaders/webgl1/common/Shadow1.glsl", Shadow1_glsl_default_);
/* harmony default export */ const Shadow1_glsl = (Shadow1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/common/SpotFactor1.glsl.js
const SpotFactor1_glsl_default_ = /* glsl */ `float getSpotFactor(const in float cutOffAngle,const in float beamWidth,const in vec3 L,const in vec3 d){float spotAngle=acos(clamp(dot(-L,d),-1.0,1.0));if(spotAngle>=cutOffAngle)return 0.0;else if(spotAngle<=beamWidth)return 1.0;return(spotAngle-cutOffAngle)/(beamWidth-cutOffAngle);}
`
;

x_ite_Namespace .add ("SpotFactor1.glsl", "assets/shaders/webgl1/common/SpotFactor1.glsl", SpotFactor1_glsl_default_);
/* harmony default export */ const SpotFactor1_glsl = (SpotFactor1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/common/Texture1.glsl.js
const Texture1_glsl_default_ = /* glsl */ `#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
#pragma X3D include "Perlin.glsl"
uniform mat4 x3d_TextureMatrix[X3D_NUM_TEXTURE_TRANSFORMS];mat4 getTextureMatrix(const in int i){
#if X3D_NUM_TEXTURE_TRANSFORMS>1
mat4 textureMatrix=mat4(0.0);
#if X3D_NUM_TEXTURE_TRANSFORMS>0
if(i==0)textureMatrix=x3d_TextureMatrix[0];
#endif
#if X3D_NUM_TEXTURE_TRANSFORMS>1
else if(i==1)textureMatrix=x3d_TextureMatrix[1];
#endif
#if X3D_NUM_TEXTURE_TRANSFORMS>2
else if(i==2)textureMatrix=x3d_TextureMatrix[2];
#endif
#if X3D_NUM_TEXTURE_TRANSFORMS>3
else if(i==3)textureMatrix=x3d_TextureMatrix[3];
#endif
return textureMatrix;
#else
return x3d_TextureMatrix[0];
#endif
}vec4 getTexCoord(const in int i){
#if X3D_NUM_TEXTURE_COORDINATES>1
vec4 texCoord=vec4(0.0);
#if X3D_NUM_TEXTURE_COORDINATES>0
if(i==0)texCoord=texCoord0;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>1
else if(i==1)texCoord=texCoord1;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>2
else if(i==2)texCoord=texCoord2;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>3
else if(i==3)texCoord=texCoord3;
#endif
return texCoord;
#else
return texCoord0;
#endif
}vec4 getTexCoord(const in x3d_TextureCoordinateGeneratorParameters textureCoordinateGenerator,const in int textureTransformMapping,const in int textureCoordinateMapping){int mode=textureCoordinateGenerator.mode;if(mode==x3d_None){return getTextureMatrix(textureTransformMapping)*getTexCoord(textureCoordinateMapping);}else if(mode==x3d_Sphere){vec2 N=normalize(gl_FrontFacing?normal:-normal).xy;return vec4(N*0.5+0.5,0.0,1.0);}else if(mode==x3d_CameraSpaceNormal){vec3 N=normalize(gl_FrontFacing?normal:-normal);return vec4(N,1.0);}else if(mode==x3d_CameraSpacePosition){return vec4(vertex,1.0);}else if(mode==x3d_CameraSpaceReflectionVector){vec3 N=normalize(gl_FrontFacing?normal:-normal);return vec4(reflect(normalize(vertex),-N),1.0);}else if(mode==x3d_SphereLocal){vec2 N=normalize(gl_FrontFacing?localNormal:-localNormal).xy;return vec4(N*0.5+0.5,0.0,1.0);}else if(mode==x3d_Coord){return vec4(localVertex,1.0);}else if(mode==x3d_CoordEye){return vec4(vertex,1.0);}else if(mode==x3d_Noise){vec3 scale=vec3(textureCoordinateGenerator.parameter[0],textureCoordinateGenerator.parameter[1],textureCoordinateGenerator.parameter[2]);vec3 translation=vec3(textureCoordinateGenerator.parameter[3],textureCoordinateGenerator.parameter[4],textureCoordinateGenerator.parameter[5]);return vec4(perlin(localVertex*scale+translation),1.0);}else if(mode==x3d_NoiseEye){vec3 scale=vec3(textureCoordinateGenerator.parameter[0],textureCoordinateGenerator.parameter[1],textureCoordinateGenerator.parameter[2]);vec3 translation=vec3(textureCoordinateGenerator.parameter[3],textureCoordinateGenerator.parameter[4],textureCoordinateGenerator.parameter[5]);return vec4(perlin(vertex*scale+translation),1.0);}else if(mode==x3d_SphereReflect){vec3 N=normalize(gl_FrontFacing?normal:-normal);float eta=textureCoordinateGenerator.parameter[0];return vec4(refract(normalize(vertex),-N,eta),1.0);}else if(mode==x3d_SphereReflectLocal){vec3 N=normalize(gl_FrontFacing?localNormal:-localNormal);float eta=textureCoordinateGenerator.parameter[0];vec3 eye=vec3(textureCoordinateGenerator.parameter[1],textureCoordinateGenerator.parameter[2],textureCoordinateGenerator.parameter[3]);return vec4(refract(normalize(localVertex-eye),-N,eta),1.0);}return getTextureMatrix(textureTransformMapping)*getTexCoord(textureCoordinateMapping);}uniform x3d_TextureCoordinateGeneratorParameters x3d_TextureCoordinateGenerator[X3D_NUM_TEXTURE_COORDINATES];vec3 getTexCoord(const in int textureTransformMapping,const in int textureCoordinateMapping){vec4 texCoord;
#if X3D_NUM_TEXTURE_COORDINATES>0
if(textureCoordinateMapping==0)texCoord=getTexCoord(x3d_TextureCoordinateGenerator[0],textureTransformMapping,textureCoordinateMapping);
#endif
#if X3D_NUM_TEXTURE_COORDINATES>1
else if(textureCoordinateMapping==1)texCoord=getTexCoord(x3d_TextureCoordinateGenerator[1],textureTransformMapping,textureCoordinateMapping);
#endif
#if X3D_NUM_TEXTURE_COORDINATES>2
else if(textureCoordinateMapping==2)texCoord=getTexCoord(x3d_TextureCoordinateGenerator[2],textureTransformMapping,textureCoordinateMapping);
#endif
#if X3D_NUM_TEXTURE_COORDINATES>3
else if(textureCoordinateMapping==3)texCoord=getTexCoord(x3d_TextureCoordinateGenerator[3],textureTransformMapping,textureCoordinateMapping);
#endif
texCoord.stp/=texCoord.q;
#if defined(X3D_GEOMETRY_2D)
if(gl_FrontFacing==false)texCoord.s=1.0-texCoord.s;
#endif
return texCoord.stp;}
#endif 
#if defined(X3D_TEXTURE)
uniform sampler2D x3d_Texture2D[X3D_NUM_TEXTURES];uniform samplerCube x3d_TextureCube[X3D_NUM_TEXTURES];
#if defined(X3D_MULTI_TEXTURING)
vec4 getTexture(const in int i,const in vec3 texCoord){vec4 textureColor=vec4(0.0);
#if X3D_NUM_TEXTURES>0
if(i==0){
#if defined(X3D_TEXTURE0_2D)
textureColor=texture2D(x3d_Texture2D[0],texCoord.st);
#elif defined(X3D_TEXTURE0_CUBE)
textureColor=textureCube(x3d_TextureCube[0],texCoord.stp);
#endif
}
#endif
#if X3D_NUM_TEXTURES>1
else if(i==1){
#if defined(X3D_TEXTURE0_2D)
textureColor=texture2D(x3d_Texture2D[1],texCoord.st);
#elif defined(X3D_TEXTURE0_CUBE)
textureColor=textureCube(x3d_TextureCube[1],texCoord.stp);
#endif
}
#endif
return textureColor;}
#endif
#if defined(X3D_MULTI_TEXTURING)
uniform vec4 x3d_MultiTextureColor;uniform x3d_MultiTextureParameters x3d_MultiTexture[X3D_NUM_TEXTURES];
#endif
#if defined(X3D_PHYSICAL_MATERIAL)
vec4 sRGBToLinear(const in vec4 srgbIn);
#endif
int minI(const in int a,const in int b){return a<b?a:b;}vec4 getTextureColor(const in vec4 diffuseColor,const in vec4 specularColor){
#if defined(X3D_MULTI_TEXTURING)
vec4 currentColor=diffuseColor;for(int i=0;i<X3D_NUM_TEXTURES;++i){vec3 texCoord=getTexCoord(minI(i,X3D_NUM_TEXTURE_TRANSFORMS-1),minI(i,X3D_NUM_TEXTURE_COORDINATES-1));vec4 textureColor=getTexture(i,texCoord);
#if defined(X3D_PHYSICAL_MATERIAL)
textureColor=sRGBToLinear(textureColor);
#endif
x3d_MultiTextureParameters multiTexture=x3d_MultiTexture[i];vec4 arg1=textureColor;vec4 arg2=currentColor;int source=multiTexture.source;if(source==x3d_Diffuse){arg1=diffuseColor;}else if(source==x3d_Specular){arg1=specularColor;}else if(source==x3d_Factor){arg1=x3d_MultiTextureColor;}int function=multiTexture.function;if(function==x3d_Complement){arg1=1.0-arg1;}else if(function==x3d_AlphaReplicate){arg1.a=arg2.a;}int mode=multiTexture.mode;int alphaMode=multiTexture.alphaMode;if(mode==x3d_Replace){currentColor.rgb=arg1.rgb;}else if(mode==x3d_Modulate){currentColor.rgb=arg1.rgb*arg2.rgb;}else if(mode==x3d_Modulate2X){currentColor.rgb=(arg1.rgb*arg2.rgb)*2.0;}else if(mode==x3d_Modulate4X){currentColor.rgb=(arg1.rgb*arg2.rgb)*4.0;}else if(mode==x3d_Add){currentColor.rgb=arg1.rgb+arg2.rgb;}else if(mode==x3d_AddSigned){currentColor.rgb=arg1.rgb+arg2.rgb-0.5;}else if(mode==x3d_AddSigned2X){currentColor.rgb=(arg1.rgb+arg2.rgb-0.5)*2.0;}else if(mode==x3d_AddSmooth){currentColor.rgb=arg1.rgb+(1.0-arg1.rgb)*arg2.rgb;}else if(mode==x3d_Subtract){currentColor.rgb=arg1.rgb-arg2.rgb;}else if(mode==x3d_BlendDiffuseAlpha){currentColor.rgb=arg1.rgb*diffuseColor.a+arg2.rgb*(1.0-diffuseColor.a);}else if(mode==x3d_BlendTextureAlpha){currentColor.rgb=arg1.rgb*arg1.a+arg2.rgb*(1.0-arg1.a);}else if(mode==x3d_BlendFactorAlpha){currentColor.rgb=arg1.rgb*x3d_MultiTextureColor.a+arg2.rgb*(1.0-x3d_MultiTextureColor.a);}else if(mode==x3d_BlendCurrentAlpha){currentColor.rgb=arg1.rgb*arg2.a+arg2.rgb*(1.0-arg2.a);}else if(mode==x3d_ModulateAlphaAddColor){currentColor.rgb=arg1.rgb+arg1.a*arg2.rgb;}else if(mode==x3d_ModulateInvAlphaAddColor){currentColor.rgb=(1.0-arg1.a)*arg2.rgb+arg1.rgb;}else if(mode==x3d_ModulateInvColorAddAlpha){currentColor.rgb=(1.0-arg1.rgb)*arg2.rgb+arg1.a;}else if(mode==x3d_DotProduct3){currentColor.rgb=vec3(dot(arg1.rgb*2.0-1.0,arg2.rgb*2.0-1.0));}else if(mode==x3d_SelectArg1){currentColor.rgb=arg1.rgb;}else if(mode==x3d_SelectArg2){currentColor.rgb=arg2.rgb;}else if(mode==x3d_Off);if(alphaMode==x3d_Replace){currentColor.a=arg1.a;}else if(alphaMode==x3d_Modulate){currentColor.a=arg1.a*arg2.a;}else if(alphaMode==x3d_Modulate2X){currentColor.a=(arg1.a*arg2.a)*2.0;}else if(alphaMode==x3d_Modulate4X){currentColor.a=(arg1.a*arg2.a)*4.0;}else if(alphaMode==x3d_Add){currentColor.a=arg1.a+arg2.a;}else if(alphaMode==x3d_AddSigned){currentColor.a=arg1.a+arg2.a-0.5;}else if(alphaMode==x3d_AddSigned2X){currentColor.a=(arg1.a+arg2.a-0.5)*2.0;}else if(alphaMode==x3d_AddSmooth){currentColor.a=arg1.a+(1.0-arg1.a)*arg2.a;}else if(alphaMode==x3d_Subtract){currentColor.a=arg1.a-arg2.a;}else if(alphaMode==x3d_BlendDiffuseAlpha){currentColor.a=arg1.a*diffuseColor.a+arg2.a*(1.0-diffuseColor.a);}else if(alphaMode==x3d_BlendTextureAlpha){currentColor.a=arg1.a*arg1.a+arg2.a*(1.0-arg1.a);}else if(alphaMode==x3d_BlendFactorAlpha){currentColor.a=arg1.a*x3d_MultiTextureColor.a+arg2.a*(1.0-x3d_MultiTextureColor.a);}else if(alphaMode==x3d_BlendCurrentAlpha){currentColor.a=arg1.a*arg2.a+arg2.a*(1.0-arg2.a);}else if(alphaMode==x3d_ModulateAlphaAddColor){currentColor.a=arg1.a+arg1.a*arg2.a;}else if(alphaMode==x3d_ModulateInvAlphaAddColor){currentColor.a=(1.0-arg1.a)*arg2.a+arg1.a;}else if(alphaMode==x3d_ModulateInvColorAddAlpha){currentColor.a=(1.0-arg1.a)*arg2.a+arg1.a;}else if(alphaMode==x3d_DotProduct3){currentColor.a=dot(arg1.rgb*2.0-1.0,arg2.rgb*2.0-1.0);}else if(alphaMode==x3d_SelectArg1){currentColor.a=arg1.a;}else if(alphaMode==x3d_SelectArg2){currentColor.a=arg2.a;}else if(alphaMode==x3d_Off);}return currentColor;
#else
vec3 texCoord=getTexCoord(0,0);
#if defined(X3D_TEXTURE0_2D)
vec4 textureColor=texture2D(x3d_Texture2D[0],texCoord.st);
#elif defined(X3D_TEXTURE0_CUBE)
vec4 textureColor=textureCube(x3d_TextureCube[0],texCoord.stp);
#else
vec4 textureColor=vec4(0.0);
#endif
#if defined(X3D_PHYSICAL_MATERIAL)
textureColor=sRGBToLinear(textureColor);
#endif
return diffuseColor*textureColor;
#endif
}
#endif
#if defined(X3D_PROJECTIVE_TEXTURE_MAPPING)
uniform sampler2D x3d_ProjectiveTexture[X3D_NUM_TEXTURE_PROJECTORS];uniform mat4 x3d_ProjectiveTextureMatrix[X3D_NUM_TEXTURE_PROJECTORS];uniform vec3 x3d_ProjectiveTextureLocation[X3D_NUM_TEXTURE_PROJECTORS];vec4 getProjectiveTexture(const in int i,const in vec2 texCoord){vec4 color=vec4(0.0);
#if X3D_NUM_TEXTURE_PROJECTORS>0
if(i==0)color=texture2D(x3d_ProjectiveTexture[0],texCoord);
#endif
#if X3D_NUM_TEXTURE_PROJECTORS>1
else if(i==1)color=texture2D(x3d_ProjectiveTexture[1],texCoord);
#endif
return color;}vec4 getProjectiveTextureColor(in vec4 currentColor){vec3 N=gl_FrontFacing?normal:-normal;for(int i=0;i<X3D_NUM_TEXTURE_PROJECTORS;++i){vec4 texCoord=x3d_ProjectiveTextureMatrix[i]*vec4(vertex,1.0);texCoord.stp/=texCoord.q;if(texCoord.s<0.0||texCoord.s>1.0)continue;if(texCoord.t<0.0||texCoord.t>1.0)continue;if(texCoord.p<0.0||texCoord.p>1.0)continue;vec3 p=x3d_ProjectiveTextureLocation[i]-vertex;if(dot(N,p)<0.0)continue;currentColor*=getProjectiveTexture(i,texCoord.st);}return currentColor;}
#endif 
`
;

x_ite_Namespace .add ("Texture1.glsl", "assets/shaders/webgl1/common/Texture1.glsl", Texture1_glsl_default_);
/* harmony default export */ const Texture1_glsl = (Texture1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/common/Vertex1.glsl.js
const Vertex1_glsl_default_ = /* glsl */ `uniform mat4 x3d_ProjectionMatrix;uniform mat4 x3d_ModelViewMatrix;
#if defined(X3D_FOG)&&defined(X3D_FOG_COORDS)
attribute float x3d_FogDepth;
#endif
#if defined(X3D_COLOR_MATERIAL)
attribute vec4 x3d_Color;
#endif
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
#if X3D_NUM_TEXTURE_COORDINATES>0
attribute vec4 x3d_TexCoord0;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>1
attribute vec4 x3d_TexCoord1;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>2
attribute vec4 x3d_TexCoord2;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>3
attribute vec4 x3d_TexCoord3;
#endif
#endif
#endif
attribute vec4 x3d_Vertex;
#if defined(X3D_FOG)&&defined(X3D_FOG_COORDS)
varying float fogDepth;
#endif
#if defined(X3D_COLOR_MATERIAL)
varying vec4 color;
#endif
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
#if X3D_NUM_TEXTURE_COORDINATES>0
varying vec4 texCoord0;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>1
varying vec4 texCoord1;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>2
varying vec4 texCoord2;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>3
varying vec4 texCoord3;
#endif
#endif
#endif
#if defined(X3D_NORMALS)
uniform mat3 x3d_NormalMatrix;attribute vec3 x3d_Normal;varying vec3 normal;
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
varying vec3 localNormal;
#endif
#endif
varying vec3 vertex;
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
varying vec3 localVertex;
#endif
#if defined(X3D_LOGARITHMIC_DEPTH_BUFFER)
varying float depth;
#endif
#pragma X3D include "PointSize.glsl"
void vertex_main(){vec4 position=x3d_ModelViewMatrix*x3d_Vertex;vertex=position.xyz;
#if defined(X3D_GEOMETRY_0D)
#if defined(X3D_STYLE_PROPERTIES)
gl_PointSize=pointSize=getPointSize(vertex);
#else
gl_PointSize=1.0;
#endif
#endif
#if defined(X3D_FOG)&&defined(X3D_FOG_COORDS)
fogDepth=x3d_FogDepth;
#endif
#if defined(X3D_COLOR_MATERIAL)
color=x3d_Color;
#endif
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
#if X3D_NUM_TEXTURE_COORDINATES>0
texCoord0=x3d_TexCoord0;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>1
texCoord1=x3d_TexCoord1;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>2
texCoord2=x3d_TexCoord2;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>3
texCoord3=x3d_TexCoord3;
#endif
#endif
#endif
#if defined(X3D_NORMALS)
normal=x3d_NormalMatrix*x3d_Normal;
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
localNormal=x3d_Normal;
#endif
#endif
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
localVertex=x3d_Vertex.xyz;
#endif
gl_Position=x3d_ProjectionMatrix*position;
#if defined(X3D_LOGARITHMIC_DEPTH_BUFFER)
depth=1.0+gl_Position.w;
#endif
}
`
;

x_ite_Namespace .add ("Vertex1.glsl", "assets/shaders/webgl1/common/Vertex1.glsl", Vertex1_glsl_default_);
/* harmony default export */ const Vertex1_glsl = (Vertex1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/ClipPlanes2.glsl.js
const ClipPlanes2_glsl_default_ = /* glsl */ `#if defined(X3D_CLIP_PLANES)
uniform vec4 x3d_ClipPlane[X3D_NUM_CLIP_PLANES];void clip(){for(int i=0;i<X3D_NUM_CLIP_PLANES;++i){if(dot(vertex,x3d_ClipPlane[i].xyz)-x3d_ClipPlane[i].w<0.0)discard;}}
#endif
`
;

x_ite_Namespace .add ("ClipPlanes2.glsl", "assets/shaders/webgl2/common/ClipPlanes2.glsl", ClipPlanes2_glsl_default_);
/* harmony default export */ const ClipPlanes2_glsl = (ClipPlanes2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/Fog2.glsl.js
const Fog2_glsl_default_ = /* glsl */ `#if defined(X3D_FOG)
uniform x3d_FogParameters x3d_Fog;float getFogInterpolant(){
#if defined(X3D_FOG_COORDS)
return clamp(1.0-fogDepth,0.0,1.0);
#else
float visibilityRange=x3d_Fog.visibilityRange;float dV=length(x3d_Fog.matrix*vertex);
#if defined(X3D_FOG_LINEAR)
return max(0.0,visibilityRange-dV)/visibilityRange;
#elif defined(X3D_FOG_EXPONENTIAL)
return exp(-dV/max(0.001,visibilityRange-dV));
#endif
#endif
}vec3 getFogColor(const in vec3 color){return mix(x3d_Fog.color,color,getFogInterpolant());}
#endif
`
;

x_ite_Namespace .add ("Fog2.glsl", "assets/shaders/webgl2/common/Fog2.glsl", Fog2_glsl_default_);
/* harmony default export */ const Fog2_glsl = (Fog2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/Fragment2.glsl.js
const Fragment2_glsl_default_ = /* glsl */ `#if defined(X3D_ALPHA_MODE_MASK)
uniform float x3d_AlphaCutoff;
#endif
#if defined(X3D_FOG)&&defined(X3D_FOG_COORDS)
in float fogDepth;
#endif
#if defined(X3D_COLOR_MATERIAL)
in vec4 color;
#endif
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
#if X3D_NUM_TEXTURE_COORDINATES>0
in vec4 texCoord0;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>1
in vec4 texCoord1;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>2
in vec4 texCoord2;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>3
in vec4 texCoord3;
#endif
#endif
#else
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
#if X3D_NUM_TEXTURE_COORDINATES>0
vec4 texCoord0=vec4(0.0,0.0,0.0,1.0);
#endif
#if X3D_NUM_TEXTURE_COORDINATES>1
vec4 texCoord1=vec4(0.0,0.0,0.0,1.0);
#endif
#if X3D_NUM_TEXTURE_COORDINATES>2
vec4 texCoord2=vec4(0.0,0.0,0.0,1.0);
#endif
#if X3D_NUM_TEXTURE_COORDINATES>3
vec4 texCoord3=vec4(0.0,0.0,0.0,1.0);
#endif
#endif
#endif
#if defined(X3D_NORMALS)
in vec3 normal;
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
in vec3 localNormal;
#endif
#else
const vec3 normal=vec3(0.0,0.0,1.0);
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
const vec3 localNormal=vec3(0.0,0.0,1.0);
#endif
#endif
in vec3 vertex;
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
in vec3 localVertex;
#endif
#if defined(X3D_LOGARITHMIC_DEPTH_BUFFER)
uniform float x3d_LogarithmicFarFactor1_2;in float depth;
#endif
#if defined(X3D_ORDER_INDEPENDENT_TRANSPARENCY)
layout(location=0)out vec4 x3d_FragData0;layout(location=1)out vec4 x3d_FragData1;
#else
out vec4 x3d_FragColor;
#endif
#pragma X3D include "Texture.glsl"
#pragma X3D include "ClipPlanes.glsl"
#pragma X3D include "Point.glsl"
#pragma X3D include "Stipple.glsl"
#pragma X3D include "Hatch.glsl"
#pragma X3D include "Fog.glsl"
vec4 getMaterialColor();
#if defined(X3D_ORDER_INDEPENDENT_TRANSPARENCY)
float weight(const in float z,const in float a){return clamp(pow(min(1.0,a*10.0)+0.01,3.0)*1e8*pow(1.0-z*0.9,3.0),1e-2,3e3);}
#endif
void fragment_main(){
#if defined(X3D_CLIP_PLANES)
clip();
#endif
#if defined(X3D_GEOMETRY_1D)&&defined(X3D_STYLE_PROPERTIES)
stipple();
#endif
#if defined(X3D_GEOMETRY_0D)&&defined(X3D_STYLE_PROPERTIES)
setPointTexCoords();
#elif defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
setTexCoords();
#endif
vec4 finalColor=getMaterialColor();
#if defined(X3D_GEOMETRY_0D)&&defined(X3D_STYLE_PROPERTIES)
finalColor=getPointColor(finalColor);
#endif
#if(defined(X3D_GEOMETRY_2D)||defined(X3D_GEOMETRY_3D))&&defined(X3D_STYLE_PROPERTIES)
finalColor=getHatchColor(finalColor);
#endif
#if defined(X3D_FOG)
finalColor.rgb=getFogColor(finalColor.rgb);
#endif
#if defined(X3D_ALPHA_MODE_OPAQUE)
finalColor.a=1.0;
#endif
#if defined(X3D_ALPHA_MODE_MASK)
if(finalColor.a<x3d_AlphaCutoff)discard;finalColor.a=1.0;
#endif
#if defined(X3D_ORDER_INDEPENDENT_TRANSPARENCY)
float a=finalColor.a;float w=weight(gl_FragCoord.z,a);finalColor.rgb*=a;finalColor*=w;x3d_FragData0=vec4(finalColor.rgb,a);x3d_FragData1=vec4(finalColor.a);
#else
x3d_FragColor=finalColor;
#endif
#if defined(X3D_LOGARITHMIC_DEPTH_BUFFER)
gl_FragDepth=log2(depth)*x3d_LogarithmicFarFactor1_2;
#endif
}
`
;

x_ite_Namespace .add ("Fragment2.glsl", "assets/shaders/webgl2/common/Fragment2.glsl", Fragment2_glsl_default_);
/* harmony default export */ const Fragment2_glsl = (Fragment2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/Hatch2.glsl.js
const Hatch2_glsl_default_ = /* glsl */ `#if(defined(X3D_GEOMETRY_2D)||defined(X3D_GEOMETRY_3D))&&defined(X3D_STYLE_PROPERTIES)
uniform x3d_FillPropertiesParameters x3d_FillProperties;vec4 getHatchColor(vec4 color){vec4 finalColor=x3d_FillProperties.filled?color:vec4(0.0);
#if defined(X3D_STYLE_PROPERTIES_TEXTURE)
vec4 hatch=texture(x3d_FillProperties.texture,gl_FragCoord.xy/(32.0*x3d_FillProperties.scale));hatch.rgb*=x3d_FillProperties.hatchColor;finalColor=mix(finalColor,hatch,hatch.a);
#endif
return finalColor;}
#endif
`
;

x_ite_Namespace .add ("Hatch2.glsl", "assets/shaders/webgl2/common/Hatch2.glsl", Hatch2_glsl_default_);
/* harmony default export */ const Hatch2_glsl = (Hatch2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/Line22.glsl.js
const Line22_glsl_default_ = /* glsl */ `struct Line2{vec2 point;vec2 direction;};Line2 line2(const in vec2 point1,const in vec2 point2){return Line2(point1,normalize(point2-point1));}vec2 closest_point(const in Line2 line,const in vec2 point){vec2 r=point-line.point;float d=dot(r,line.direction);return line.direction*d+line.point;}
`
;

x_ite_Namespace .add ("Line22.glsl", "assets/shaders/webgl2/common/Line22.glsl", Line22_glsl_default_);
/* harmony default export */ const Line22_glsl = (Line22_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/Material2.glsl.js
const Material2_glsl_default_ = /* glsl */ `uniform x3d_MaterialParameters x3d_Material;
#if defined(X3D_LIGHTING)
#pragma X3D include "SpotFactor.glsl"
#pragma X3D include "Shadow.glsl"
uniform x3d_LightSourceParameters x3d_LightSource[X3D_NUM_LIGHTS];vec3 getMaterialColor(const in vec3 vertex,const in vec3 N,const in vec3 ambientColor,const in vec3 diffuseColor,const in vec3 specularColor,const in float shininess){vec3 V=normalize(-vertex);vec3 finalColor=vec3(0.0);for(int i=0;i<X3D_NUM_LIGHTS;++i){x3d_LightSourceParameters light=x3d_LightSource[i];vec3 vL=light.location-vertex;float dL=length(light.matrix*vL);if(dL<=light.radius||light.radius<0.0){bool di=light.type==x3d_DirectionalLight;vec3 d=light.direction;vec3 c=light.attenuation;vec3 L=di?-d:normalize(vL);vec3 H=normalize(L+V);float lightAngle=max(dot(N,L),0.0);vec3 diffuseTerm=diffuseColor*lightAngle;float specularFactor=shininess>0.0?pow(max(dot(N,H),0.0),shininess*128.0):1.0;vec3 specularTerm=specularColor*specularFactor;float attenuationFactor=di?1.0:1.0/max(dot(c,vec3(1.0,dL,dL*dL)),1.0);float spotFactor=light.type==x3d_SpotLight?getSpotFactor(light.cutOffAngle,light.beamWidth,L,d):1.0;float attenuationSpotFactor=attenuationFactor*spotFactor;vec3 ambientTerm=light.ambientIntensity*ambientColor;vec3 diffuseSpecularTerm=light.intensity*(diffuseTerm+specularTerm);
#if defined(X3D_FRAGMENT_SHADER)&&defined(X3D_SHADOWS)
if(lightAngle>0.0&&light.shadowIntensity>0.0)diffuseSpecularTerm=mix(diffuseSpecularTerm,light.shadowColor,getShadowIntensity(i,light));
#endif
finalColor+=attenuationSpotFactor*light.color*(ambientTerm+diffuseSpecularTerm);}}return finalColor;}
#endif
`
;

x_ite_Namespace .add ("Material2.glsl", "assets/shaders/webgl2/common/Material2.glsl", Material2_glsl_default_);
/* harmony default export */ const Material2_glsl = (Material2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/Normal2.glsl.js
const Normal2_glsl_default_ = /* glsl */ `#if defined(X3D_NORMAL_TEXTURE)
mat3 getTBNMatrix(const in vec2 texCoord){vec3 pos_dx=dFdx(vertex);vec3 pos_dy=dFdy(vertex);vec2 tex_dx=dFdx(texCoord);vec2 tex_dy=dFdy(texCoord);vec3 t=(tex_dy.t*pos_dx-tex_dx.t*pos_dy)/(tex_dx.s*tex_dy.t-tex_dy.s*tex_dx.t);vec3 N=normalize(normal);vec3 T=normalize(t-N*dot(N,t));vec3 B=normalize(cross(N,T));mat3 tbn=mat3(T,B,N);return tbn;}
#endif
#if defined(X3D_NORMAL_TEXTURE)
uniform x3d_NormalTextureParameters x3d_NormalTexture;
#endif
vec3 getNormalVector(const in float normalScale){float facing=gl_FrontFacing?1.0:-1.0;
#if defined(X3D_NORMAL_TEXTURE)
vec3 texCoord=getTexCoord(x3d_NormalTexture.textureTransformMapping,x3d_NormalTexture.textureCoordinateMapping);vec3 scale=vec3(vec2(normalScale),1.0);mat3 tbn=getTBNMatrix(texCoord.st);
#if defined(X3D_NORMAL_TEXTURE_2D)
vec3 n=texture(x3d_NormalTexture.texture2D,texCoord.st).rgb;
#elif defined(X3D_NORMAL_TEXTURE_3D)
vec3 n=texture(x3d_NormalTexture.texture3D,texCoord).rgb;
#elif defined(X3D_NORMAL_TEXTURE_CUBE)
vec3 n=texture(x3d_NormalTexture.textureCube,texCoord).rgb;
#endif
return normalize(tbn*((n*2.0-1.0)*scale))*facing;
#else
return normalize(normal)*facing;
#endif
}
`
;

x_ite_Namespace .add ("Normal2.glsl", "assets/shaders/webgl2/common/Normal2.glsl", Normal2_glsl_default_);
/* harmony default export */ const Normal2_glsl = (Normal2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/Particle2.glsl.js
const Particle2_glsl_default_ = /* glsl */ `#if defined(X3D_PARTICLE_SYSTEM)
#if defined(X3D_TEX_COORD_RAMP)
uniform sampler2D x3d_TexCoordRamp;in vec4 x3d_Particle;vec4 getParticleTexCoord(const in vec4 texCoord){const int map[6]=int[6](0,1,2,0,2,3);int index0=int(x3d_Particle[3]);return texelFetch(x3d_TexCoordRamp,index0+map[gl_VertexID % 6],0);}
#else
#define getParticleTexCoord(texCoord)(texCoord)
#endif
in mat4 x3d_ParticleMatrix;vec4 getParticleVertex(const in vec4 vertex){return x3d_ParticleMatrix*vertex;}
#else
#define getParticleVertex(vertex)(vertex)
#define getParticleTexCoord(texCoord)(texCoord)
#endif
`
;

x_ite_Namespace .add ("Particle2.glsl", "assets/shaders/webgl2/common/Particle2.glsl", Particle2_glsl_default_);
/* harmony default export */ const Particle2_glsl = (Particle2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/Perlin2.glsl.js
const Perlin2_glsl_default_ = /* glsl */ `float rand(const in vec2 co){return fract(sin(dot(co.xy,vec2(12.9898,78.233)))*43758.5453);}float rand(const in vec2 co,const in float l){return rand(vec2(rand(co),l));}float rand(const in vec2 co,const in float l,const in float t){return rand(vec2(rand(co,l),t));}float perlin(const in vec2 p,const in float dim,const in float time){const float M_PI=3.14159265358979323846;vec2 pos=floor(p*dim);vec2 posx=pos+vec2(1.0,0.0);vec2 posy=pos+vec2(0.0,1.0);vec2 posxy=pos+vec2(1.0);float c=rand(pos,dim,time);float cx=rand(posx,dim,time);float cy=rand(posy,dim,time);float cxy=rand(posxy,dim,time);vec2 d=fract(p*dim);d=-0.5*cos(d*M_PI)+0.5;float ccx=mix(c,cx,d.x);float cycxy=mix(cy,cxy,d.x);float center=mix(ccx,cycxy,d.y);return center*2.0-1.0;}vec3 perlin(const in vec3 p){return vec3(perlin(p.xy,1.0,0.0),perlin(p.yz,1.0,0.0),perlin(p.zx,1.0,0.0));}
`
;

x_ite_Namespace .add ("Perlin2.glsl", "assets/shaders/webgl2/common/Perlin2.glsl", Perlin2_glsl_default_);
/* harmony default export */ const Perlin2_glsl = (Perlin2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/Point2.glsl.js
const Point2_glsl_default_ = /* glsl */ `#if defined(X3D_GEOMETRY_0D)&&defined(X3D_STYLE_PROPERTIES)
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
void setPointTexCoords(){vec4 texCoord=vec4(gl_PointCoord.x,1.0-gl_PointCoord.y,0.0,1.0);
#if X3D_NUM_TEXTURE_COORDINATES>0
texCoords[0]=texCoord;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>1
texCoords[1]=texCoord;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>2
texCoords[2]=texCoord;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>3
texCoords[3]=texCoord;
#endif
}
#define getPointColor(color)(color)
#else
#define setPointTexCoords()
in float pointSize;vec4 getPointColor(in vec4 color){if(pointSize>1.0)color.a*=clamp(pointSize*(0.5-distance(vec2(0.5),gl_PointCoord)),0.0,1.0);else color.a*=pointSize;return color;}
#endif
#endif
`
;

x_ite_Namespace .add ("Point2.glsl", "assets/shaders/webgl2/common/Point2.glsl", Point2_glsl_default_);
/* harmony default export */ const Point2_glsl = (Point2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/PointSize2.glsl.js
const PointSize2_glsl_default_ = /* glsl */ `#if defined(X3D_GEOMETRY_0D)&&defined(X3D_STYLE_PROPERTIES)
uniform x3d_PointPropertiesParameters x3d_PointProperties;out float pointSize;float getPointSize(const in vec3 vertex){float pointSizeMinValue=x3d_PointProperties.pointSizeMinValue;float pointSizeMaxValue=x3d_PointProperties.pointSizeMaxValue;vec3 attenuation=x3d_PointProperties.attenuation;float dL=length(vertex);float pointSize=0.0;pointSize=x3d_PointProperties.pointSizeScaleFactor;pointSize/=dot(attenuation,vec3(1.0,dL,dL*dL));pointSize=clamp(pointSize,pointSizeMinValue,pointSizeMaxValue);
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURE)
return pointSize;
#else
return pointSize+1.0-step(pointSize,1.0);
#endif
}
#endif
`
;

x_ite_Namespace .add ("PointSize2.glsl", "assets/shaders/webgl2/common/PointSize2.glsl", PointSize2_glsl_default_);
/* harmony default export */ const PointSize2_glsl = (PointSize2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/Shadow2.glsl.js
const Shadow2_glsl_default_ = /* glsl */ `#if defined(X3D_FRAGMENT_SHADER)&&defined(X3D_SHADOWS)
uniform sampler2D x3d_ShadowMap[X3D_NUM_LIGHTS];float getShadowDepth(const in int index,const in vec2 shadowCoord){switch(index){
#if X3D_NUM_LIGHTS>0
case 0:{return texture(x3d_ShadowMap[0],shadowCoord).r;}
#endif
#if X3D_NUM_LIGHTS>1
case 1:{return texture(x3d_ShadowMap[1],shadowCoord).r;}
#endif
#if X3D_NUM_LIGHTS>2
case 2:{return texture(x3d_ShadowMap[2],shadowCoord).r;}
#endif
#if X3D_NUM_LIGHTS>3
case 3:{return texture(x3d_ShadowMap[3],shadowCoord).r;}
#endif
#if X3D_NUM_LIGHTS>4
case 4:{return texture(x3d_ShadowMap[4],shadowCoord).r;}
#endif
#if X3D_NUM_LIGHTS>5
case 5:{return texture(x3d_ShadowMap[5],shadowCoord).r;}
#endif
#if X3D_NUM_LIGHTS>6
case 6:{return texture(x3d_ShadowMap[6],shadowCoord).r;}
#endif
#if X3D_NUM_LIGHTS>7
case 7:{return texture(x3d_ShadowMap[7],shadowCoord).r;}
#endif
default:{return 0.0;}}}float texture2DCompare(const in int index,const in vec2 texCoord,const in float compare){float shadowDepth=getShadowDepth(index,texCoord);return(1.0-step(1.0,shadowDepth))*step(shadowDepth,compare);}float texture2DShadowLerp(const in int index,const in vec2 texelSize,const in float shadowMapSize,const in vec2 texCoord,const in float compare){const vec2 offset=vec2(0.0,1.0);vec2 centroidTexCoord=floor(texCoord*shadowMapSize+0.5)/shadowMapSize;float lb=texture2DCompare(index,centroidTexCoord+texelSize*offset.xx,compare);float lt=texture2DCompare(index,centroidTexCoord+texelSize*offset.xy,compare);float rb=texture2DCompare(index,centroidTexCoord+texelSize*offset.yx,compare);float rt=texture2DCompare(index,centroidTexCoord+texelSize*offset.yy,compare);vec2 f=fract(texCoord*shadowMapSize+0.5);float a=mix(lb,lt,f.y);float b=mix(rb,rt,f.y);float c=mix(a,b,f.x);return c;}vec2 cubeToUVCompact(in vec3 v,const float texelSizeY){vec3 absV=abs(v);float scaleToCube=1.0/max(absV.x,max(absV.y,absV.z));absV*=scaleToCube;v*=scaleToCube*(1.0-2.0*texelSizeY);vec2 planar=v.xy;float almostATexel=1.5*texelSizeY;float almostOne=1.0-almostATexel;if(absV.z>=almostOne){if(v.z>0.0)planar.x=4.0-v.x;}else if(absV.x>=almostOne){float signX=sign(v.x);planar.x=v.z*signX+2.0*signX;}else if(absV.y>=almostOne){float signY=sign(v.y);planar.x=(v.x+0.5+signY)*2.0;planar.y=v.z*signY-2.0;}return vec2(0.125,0.25)*planar+vec2(0.375,0.75);}mat4 getPointLightRotations(const in vec3 vector){mat4 rotations[6];rotations[0]=mat4(0,0,1,0,0,1,0,0,-1,0,0,0,0,0,0,1);rotations[1]=mat4(0,0,-1,0,0,1,0,0,1,0,0,0,0,0,0,1);rotations[2]=mat4(-1,0,0,0,0,1,0,0,0,0,-1,0,0,0,0,1);rotations[3]=mat4(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);rotations[4]=mat4(1,0,0,0,0,0,1,0,0,-1,0,0,0,0,0,1);rotations[5]=mat4(1,0,0,0,0,0,-1,0,0,1,0,0,0,0,0,1);vec3 a=abs(vector.xyz);if(a.x>a.y){if(a.x>a.z)return vector.x>0.0?rotations[1]:rotations[0];else return vector.z>0.0?rotations[2]:rotations[3];}else{if(a.y>a.z)return vector.y>0.0?rotations[5]:rotations[4];else return vector.z>0.0?rotations[2]:rotations[3];}return rotations[3];}float getShadowIntensity(const in int index,const in x3d_LightSourceParameters light){if(light.type==x3d_PointLight){const mat4 biasMatrix=mat4(0.5,0.0,0.0,0.0,0.0,0.5,0.0,0.0,0.0,0.0,0.5,0.0,0.5,0.5,0.5,1.0);const mat4 projectionMatrix=mat4(1.0,0.0,0.0,0.0,0.0,0.5,0.0,0.0,0.0,0.0,-1.000025000312504,-1.0,0,0.0,-0.25000312503906297,0.0);vec2 texelSize=vec2(1.0)/(float(light.shadowMapSize)*vec2(4.0,2.0));vec4 shadowCoord=light.shadowMatrix*vec4(vertex,1.0);vec3 lightToPosition=shadowCoord.xyz;shadowCoord=biasMatrix*(projectionMatrix*(getPointLightRotations(lightToPosition)*shadowCoord));shadowCoord.z-=light.shadowBias;shadowCoord.xyz/=shadowCoord.w;
#if defined(X3D_PCF_FILTERING)||defined(X3D_PCF_SOFT_FILTERING)
vec2 offset=vec2(-1,1)*(texelSize.y*42.0);float value=(texture2DCompare(index,cubeToUVCompact(lightToPosition+offset.xyy,texelSize.y),shadowCoord.z)+texture2DCompare(index,cubeToUVCompact(lightToPosition+offset.yyy,texelSize.y),shadowCoord.z)+texture2DCompare(index,cubeToUVCompact(lightToPosition+offset.xyx,texelSize.y),shadowCoord.z)+texture2DCompare(index,cubeToUVCompact(lightToPosition+offset.yyx,texelSize.y),shadowCoord.z)+texture2DCompare(index,cubeToUVCompact(lightToPosition,texelSize.y),shadowCoord.z)+texture2DCompare(index,cubeToUVCompact(lightToPosition+offset.xxy,texelSize.y),shadowCoord.z)+texture2DCompare(index,cubeToUVCompact(lightToPosition+offset.yxy,texelSize.y),shadowCoord.z)+texture2DCompare(index,cubeToUVCompact(lightToPosition+offset.xxx,texelSize.y),shadowCoord.z)+texture2DCompare(index,cubeToUVCompact(lightToPosition+offset.yxx,texelSize.y),shadowCoord.z))*(1.0/9.0);return light.shadowIntensity*value;
#else 
float value=texture2DCompare(index,cubeToUVCompact(lightToPosition,texelSize.y),shadowCoord.z);return light.shadowIntensity*value;
#endif
}else{
#if defined(X3D_PCF_FILTERING)
vec2 texelSize=vec2(1.0)/vec2(light.shadowMapSize);vec4 shadowCoord=light.shadowMatrix*vec4(vertex,1.0);shadowCoord.z-=light.shadowBias;shadowCoord.xyz/=shadowCoord.w;if(any(greaterThan(abs(shadowCoord.xy-0.5),vec2(0.5))))return 0.0;vec2 d0=-texelSize;vec2 d1=texelSize;float value=(texture2DCompare(index,shadowCoord.xy+d0,shadowCoord.z)+texture2DCompare(index,shadowCoord.xy+vec2(0.0,d0.y),shadowCoord.z)+texture2DCompare(index,shadowCoord.xy+vec2(d1.x,d0.y),shadowCoord.z)+texture2DCompare(index,shadowCoord.xy+vec2(d0.x,0.0),shadowCoord.z)+texture2DCompare(index,shadowCoord.xy,shadowCoord.z)+texture2DCompare(index,shadowCoord.xy+vec2(d1.x,0.0),shadowCoord.z)+texture2DCompare(index,shadowCoord.xy+vec2(d0.x,d1.y),shadowCoord.z)+texture2DCompare(index,shadowCoord.xy+vec2(0.0,d1.y),shadowCoord.z)+texture2DCompare(index,shadowCoord.xy+d1,shadowCoord.z))*(1.0/9.0);return light.shadowIntensity*value;
#elif defined(X3D_PCF_SOFT_FILTERING)
vec2 texelSize=vec2(1.0)/vec2(light.shadowMapSize);vec4 shadowCoord=light.shadowMatrix*vec4(vertex,1.0);shadowCoord.z-=light.shadowBias;shadowCoord.xyz/=shadowCoord.w;if(any(greaterThan(abs(shadowCoord.xy-0.5),vec2(0.5))))return 0.0;vec2 d0=-texelSize;vec2 d1=texelSize;float value=(texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy+d0,shadowCoord.z)+texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy+vec2(0.0,d0.y),shadowCoord.z)+texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy+vec2(d1.x,d0.y),shadowCoord.z)+texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy+vec2(d0.x,0.0),shadowCoord.z)+texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy,shadowCoord.z)+texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy+vec2(d1.x,0.0),shadowCoord.z)+texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy+vec2(d0.x,d1.y),shadowCoord.z)+texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy+vec2(0.0,d1.y),shadowCoord.z)+texture2DShadowLerp(index,texelSize,float(shadowMapSize),shadowCoord.xy+d1,shadowCoord.z))*(1.0/9.0);return light.shadowIntensity*value;
#else 
vec4 shadowCoord=light.shadowMatrix*vec4(vertex,1.0);shadowCoord.z-=light.shadowBias;shadowCoord.xyz/=shadowCoord.w;if(any(greaterThan(abs(shadowCoord.xy-0.5),vec2(0.5))))return 0.0;float value=texture2DCompare(index,shadowCoord.xy,shadowCoord.z);return light.shadowIntensity*value;
#endif
}return 0.0;}
#endif
`
;

x_ite_Namespace .add ("Shadow2.glsl", "assets/shaders/webgl2/common/Shadow2.glsl", Shadow2_glsl_default_);
/* harmony default export */ const Shadow2_glsl = (Shadow2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/Skin2.glsl.js
const Skin2_glsl_default_ = /* glsl */ `#if defined(X3D_SKINNING)
in float x3d_CoordIndex;uniform sampler2D x3d_JointsTexture;uniform sampler2D x3d_DisplacementsTexture;uniform sampler2D x3d_JointMatricesTexture;mat4 getJointMatrix(const in int joint){vec4 a=texelFetch(x3d_JointMatricesTexture,joint*8,0);vec4 b=texelFetch(x3d_JointMatricesTexture,joint*8+1,0);vec4 c=texelFetch(x3d_JointMatricesTexture,joint*8+2,0);vec4 d=texelFetch(x3d_JointMatricesTexture,joint*8+3,0);return mat4(a,b,c,d);}mat3 getDisplacementJointMatrix(const in int joint){mat4 m=getJointMatrix(joint);return mat3(m[0].xyz,m[1].xyz,m[2].xyz);}
#if defined(X3D_NORMALS)
vec3 skinNormal=vec3(0.0);mat3 getJointNormalMatrix(const in int joint){vec4 a=texelFetch(x3d_JointMatricesTexture,joint*8+4,0);vec4 b=texelFetch(x3d_JointMatricesTexture,joint*8+5,0);vec4 c=texelFetch(x3d_JointMatricesTexture,joint*8+6,0);return mat3(a.xyz,vec3(a.w,b.xy),vec3(b.zw,c.x));}
#define getSkinNormal(normal)(skinNormal)
#endif
vec4 getSkinVertex(const in vec4 vertex,const in vec3 normal){int coordIndex=int(x3d_CoordIndex);vec4 skin=vertex;
#if defined(X3D_NORMALS)
skinNormal=normal;
#endif
#if X3D_NUM_DISPLACEMENTS>0
{int coordIndexD=coordIndex*X3D_NUM_DISPLACEMENTS;int width=textureSize(x3d_DisplacementsTexture,0).x;int offset=(width*width)/2;for(int i=0;i<X3D_NUM_DISPLACEMENTS;++i){int index=coordIndexD+i;vec4 displacement=texelFetch(x3d_DisplacementsTexture,index,0);float weight=texelFetch(x3d_DisplacementsTexture,index+offset,0).x;skin.xyz+=getDisplacementJointMatrix(int(displacement.w))*displacement.xyz*weight;}}
#endif
int coordIndexJ=coordIndex*(X3D_NUM_JOINT_SETS*2);for(int i=0;i<X3D_NUM_JOINT_SETS;++i){int index=coordIndexJ+i;ivec4 joints=ivec4(texelFetch(x3d_JointsTexture,index,0));vec4 weights=texelFetch(x3d_JointsTexture,index+X3D_NUM_JOINT_SETS,0);for(int i=0;i<4;++i){int joint=joints[i];float weight=weights[i];skin+=(getJointMatrix(joint)*vertex-vertex)*weight;
#if defined(X3D_NORMALS)
skinNormal+=(getJointNormalMatrix(joint)*normal-normal)*weight;
#endif
}}return skin;}
#else
#define getSkinVertex(vertex,normal)(vertex)
#define getSkinNormal(normal)(normal)
#endif
`
;

x_ite_Namespace .add ("Skin2.glsl", "assets/shaders/webgl2/common/Skin2.glsl", Skin2_glsl_default_);
/* harmony default export */ const Skin2_glsl = (Skin2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/SpotFactor2.glsl.js
const SpotFactor2_glsl_default_ = /* glsl */ `float getSpotFactor(const in float cutOffAngle,const in float beamWidth,const in vec3 L,const in vec3 d){float spotAngle=acos(clamp(dot(-L,d),-1.0,1.0));if(spotAngle>=cutOffAngle)return 0.0;else if(spotAngle<=beamWidth)return 1.0;return(spotAngle-cutOffAngle)/(beamWidth-cutOffAngle);}
`
;

x_ite_Namespace .add ("SpotFactor2.glsl", "assets/shaders/webgl2/common/SpotFactor2.glsl", SpotFactor2_glsl_default_);
/* harmony default export */ const SpotFactor2_glsl = (SpotFactor2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/Stipple2.glsl.js
const Stipple2_glsl_default_ = /* glsl */ `#if defined(X3D_GEOMETRY_1D)&&defined(X3D_STYLE_PROPERTIES)
#pragma X3D include "Line2.glsl"
uniform x3d_LinePropertiesParameters x3d_LineProperties;flat in float lengthSoFar;flat in vec2 startPoint;in vec2 midPoint;void stipple(){vec2 point=closest_point(line2(startPoint,midPoint),gl_FragCoord.xy);float s=(lengthSoFar+length(point-startPoint))*x3d_LineProperties.lineStippleScale;
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
#if X3D_NUM_TEXTURE_COORDINATES>0
texCoord0=vec4(s,0.0,0.0,1.0);
#endif
#if X3D_NUM_TEXTURE_COORDINATES>1
texCoord1=vec4(s,0.0,0.0,1.0);
#endif
#endif
#if defined(X3D_STYLE_PROPERTIES_TEXTURE)
if(x3d_LineProperties.linetype==16)return;int linetype=x3d_LineProperties.linetype;int height=textureSize(x3d_LineProperties.texture,0).y;float t=1.0-float(linetype*2+1)/float(height*2);float alpha=texture(x3d_LineProperties.texture,vec2(s,t)).a;if(alpha!=1.0)discard;
#endif
}
#endif
`
;

x_ite_Namespace .add ("Stipple2.glsl", "assets/shaders/webgl2/common/Stipple2.glsl", Stipple2_glsl_default_);
/* harmony default export */ const Stipple2_glsl = (Stipple2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/Texture2.glsl.js
const Texture2_glsl_default_ = /* glsl */ `#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
#pragma X3D include "Perlin.glsl"
vec4 texCoords[X3D_NUM_TEXTURE_COORDINATES];void setTexCoords(){
#if X3D_NUM_TEXTURE_COORDINATES>0
texCoords[0]=texCoord0;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>1
texCoords[1]=texCoord1;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>2
texCoords[2]=texCoord2;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>3
texCoords[3]=texCoord3;
#endif
}uniform mat4 x3d_TextureMatrix[X3D_NUM_TEXTURE_TRANSFORMS];vec4 getTexCoord(const in x3d_TextureCoordinateGeneratorParameters textureCoordinateGenerator,const in int textureTransformMapping,const in int textureCoordinateMapping){int mode=textureCoordinateGenerator.mode;switch(mode){case x3d_None:{return x3d_TextureMatrix[textureTransformMapping]*texCoords[textureCoordinateMapping];}case x3d_Sphere:{vec2 N=normalize(gl_FrontFacing?normal:-normal).xy;return vec4(N*0.5+0.5,0.0,1.0);}case x3d_CameraSpaceNormal:{vec3 N=normalize(gl_FrontFacing?normal:-normal);return vec4(N,1.0);}case x3d_CameraSpacePosition:{return vec4(vertex,1.0);}case x3d_CameraSpaceReflectionVector:{vec3 N=normalize(gl_FrontFacing?normal:-normal);return vec4(reflect(normalize(vertex),-N),1.0);}case x3d_SphereLocal:{vec2 N=normalize(gl_FrontFacing?localNormal:-localNormal).xy;return vec4(N*0.5+0.5,0.0,1.0);}case x3d_Coord:{return vec4(localVertex,1.0);}case x3d_CoordEye:{return vec4(vertex,1.0);}case x3d_Noise:{vec3 scale=vec3(textureCoordinateGenerator.parameter[0],textureCoordinateGenerator.parameter[1],textureCoordinateGenerator.parameter[2]);vec3 translation=vec3(textureCoordinateGenerator.parameter[3],textureCoordinateGenerator.parameter[4],textureCoordinateGenerator.parameter[5]);return vec4(perlin(localVertex*scale+translation),1.0);}case x3d_NoiseEye:{vec3 scale=vec3(textureCoordinateGenerator.parameter[0],textureCoordinateGenerator.parameter[1],textureCoordinateGenerator.parameter[2]);vec3 translation=vec3(textureCoordinateGenerator.parameter[3],textureCoordinateGenerator.parameter[4],textureCoordinateGenerator.parameter[5]);return vec4(perlin(vertex*scale+translation),1.0);}case x3d_SphereReflect:{vec3 N=normalize(gl_FrontFacing?normal:-normal);float eta=textureCoordinateGenerator.parameter[0];return vec4(refract(normalize(vertex),-N,eta),1.0);}case x3d_SphereReflectLocal:{vec3 N=normalize(gl_FrontFacing?localNormal:-localNormal);float eta=textureCoordinateGenerator.parameter[0];vec3 eye=vec3(textureCoordinateGenerator.parameter[1],textureCoordinateGenerator.parameter[2],textureCoordinateGenerator.parameter[3]);return vec4(refract(normalize(localVertex-eye),-N,eta),1.0);}default:{return x3d_TextureMatrix[textureTransformMapping]*texCoords[textureCoordinateMapping];}}}uniform x3d_TextureCoordinateGeneratorParameters x3d_TextureCoordinateGenerator[X3D_NUM_TEXTURE_COORDINATES];vec3 getTexCoord(const in int textureTransformMapping,const in int textureCoordinateMapping){vec4 texCoord=getTexCoord(x3d_TextureCoordinateGenerator[textureCoordinateMapping],textureTransformMapping,textureCoordinateMapping);texCoord.stp/=texCoord.q;
#if defined(X3D_GEOMETRY_2D)
if(gl_FrontFacing==false)texCoord.s=1.0-texCoord.s;
#endif
return texCoord.stp;}
#endif 
#if defined(X3D_TEXTURE)
uniform int x3d_TextureType[X3D_NUM_TEXTURES];uniform sampler2D x3d_Texture2D[X3D_NUM_TEXTURES];uniform sampler3D x3d_Texture3D[X3D_NUM_TEXTURES];uniform samplerCube x3d_TextureCube[X3D_NUM_TEXTURES];
#if defined(X3D_MULTI_TEXTURING)
vec4 getTexture(const in int i,const in vec3 texCoord){switch(i){
#if X3D_NUM_TEXTURES>0
case 0:
#if defined(X3D_TEXTURE0_2D)
return texture(x3d_Texture2D[0],texCoord.st);
#elif defined(X3D_TEXTURE0_3D)
return texture(x3d_Texture3D[0],texCoord.stp);
#elif defined(X3D_TEXTURE0_CUBE)
return texture(x3d_TextureCube[0],texCoord.stp);
#endif
#endif
#if X3D_NUM_TEXTURES>1
case 1:
#if defined(X3D_TEXTURE0_2D)
return texture(x3d_Texture2D[1],texCoord.st);
#elif defined(X3D_TEXTURE0_3D)
return texture(x3d_Texture3D[1],texCoord.stp);
#elif defined(X3D_TEXTURE0_CUBE)
return texture(x3d_TextureCube[1],texCoord.stp);
#endif
#endif
}return vec4(0.0);}
#endif
#if defined(X3D_MULTI_TEXTURING)
uniform vec4 x3d_MultiTextureColor;uniform x3d_MultiTextureParameters x3d_MultiTexture[X3D_NUM_TEXTURES];
#endif
#if defined(X3D_PHYSICAL_MATERIAL)
vec4 sRGBToLinear(const in vec4 srgbIn);
#endif
vec4 getTextureColor(const in vec4 diffuseColor,const in vec4 specularColor){
#if defined(X3D_MULTI_TEXTURING)
vec4 currentColor=diffuseColor;for(int i=0;i<X3D_NUM_TEXTURES;++i){vec3 texCoord=getTexCoord(min(i,X3D_NUM_TEXTURE_TRANSFORMS-1),min(i,X3D_NUM_TEXTURE_COORDINATES-1));vec4 textureColor=getTexture(i,texCoord);
#if defined(X3D_PHYSICAL_MATERIAL)
textureColor=sRGBToLinear(textureColor);
#endif
x3d_MultiTextureParameters multiTexture=x3d_MultiTexture[i];vec4 arg1=textureColor;vec4 arg2=currentColor;int source=multiTexture.source;switch(source){case x3d_Diffuse:{arg1=diffuseColor;break;}case x3d_Specular:{arg1=specularColor;break;}case x3d_Factor:{arg1=x3d_MultiTextureColor;break;}}int function=multiTexture.function;switch(function){case x3d_Complement:{arg1=1.0-arg1;break;}case x3d_AlphaReplicate:{arg1.a=arg2.a;break;}}int mode=multiTexture.mode;int alphaMode=multiTexture.alphaMode;switch(mode){case x3d_Replace:{currentColor.rgb=arg1.rgb;break;}case x3d_Modulate:{currentColor.rgb=arg1.rgb*arg2.rgb;break;}case x3d_Modulate2X:{currentColor.rgb=(arg1.rgb*arg2.rgb)*2.0;break;}case x3d_Modulate4X:{currentColor.rgb=(arg1.rgb*arg2.rgb)*4.0;break;}case x3d_Add:{currentColor.rgb=arg1.rgb+arg2.rgb;break;}case x3d_AddSigned:{currentColor.rgb=arg1.rgb+arg2.rgb-0.5;break;}case x3d_AddSigned2X:{currentColor.rgb=(arg1.rgb+arg2.rgb-0.5)*2.0;break;}case x3d_AddSmooth:{currentColor.rgb=arg1.rgb+(1.0-arg1.rgb)*arg2.rgb;break;}case x3d_Subtract:{currentColor.rgb=arg1.rgb-arg2.rgb;break;}case x3d_BlendDiffuseAlpha:{currentColor.rgb=arg1.rgb*diffuseColor.a+arg2.rgb*(1.0-diffuseColor.a);break;}case x3d_BlendTextureAlpha:{currentColor.rgb=arg1.rgb*arg1.a+arg2.rgb*(1.0-arg1.a);break;}case x3d_BlendFactorAlpha:{currentColor.rgb=arg1.rgb*x3d_MultiTextureColor.a+arg2.rgb*(1.0-x3d_MultiTextureColor.a);break;}case x3d_BlendCurrentAlpha:{currentColor.rgb=arg1.rgb*arg2.a+arg2.rgb*(1.0-arg2.a);break;}case x3d_ModulateAlphaAddColor:{currentColor.rgb=arg1.rgb+arg1.a*arg2.rgb;break;}case x3d_ModulateInvAlphaAddColor:{currentColor.rgb=(1.0-arg1.a)*arg2.rgb+arg1.rgb;break;}case x3d_ModulateInvColorAddAlpha:{currentColor.rgb=(1.0-arg1.rgb)*arg2.rgb+arg1.a;break;}case x3d_DotProduct3:{currentColor.rgb=vec3(dot(arg1.rgb*2.0-1.0,arg2.rgb*2.0-1.0));break;}case x3d_SelectArg1:{currentColor.rgb=arg1.rgb;break;}case x3d_SelectArg2:{currentColor.rgb=arg2.rgb;break;}case x3d_Off:{break;}}switch(alphaMode){case x3d_Replace:{currentColor.a=arg1.a;break;}case x3d_Modulate:{currentColor.a=arg1.a*arg2.a;break;}case x3d_Modulate2X:{currentColor.a=(arg1.a*arg2.a)*2.0;break;}case x3d_Modulate4X:{currentColor.a=(arg1.a*arg2.a)*4.0;break;}case x3d_Add:{currentColor.a=arg1.a+arg2.a;break;}case x3d_AddSigned:{currentColor.a=arg1.a+arg2.a-0.5;break;}case x3d_AddSigned2X:{currentColor.a=(arg1.a+arg2.a-0.5)*2.0;break;}case x3d_AddSmooth:{currentColor.a=arg1.a+(1.0-arg1.a)*arg2.a;break;}case x3d_Subtract:{currentColor.a=arg1.a-arg2.a;break;}case x3d_BlendDiffuseAlpha:{currentColor.a=arg1.a*diffuseColor.a+arg2.a*(1.0-diffuseColor.a);break;}case x3d_BlendTextureAlpha:{currentColor.a=arg1.a*arg1.a+arg2.a*(1.0-arg1.a);break;}case x3d_BlendFactorAlpha:{currentColor.a=arg1.a*x3d_MultiTextureColor.a+arg2.a*(1.0-x3d_MultiTextureColor.a);break;}case x3d_BlendCurrentAlpha:{currentColor.a=arg1.a*arg2.a+arg2.a*(1.0-arg2.a);break;}case x3d_ModulateAlphaAddColor:{currentColor.a=arg1.a+arg1.a*arg2.a;break;}case x3d_ModulateInvAlphaAddColor:{currentColor.a=(1.0-arg1.a)*arg2.a+arg1.a;break;}case x3d_ModulateInvColorAddAlpha:{currentColor.a=(1.0-arg1.a)*arg2.a+arg1.a;break;}case x3d_DotProduct3:{currentColor.a=dot(arg1.rgb*2.0-1.0,arg2.rgb*2.0-1.0);break;}case x3d_SelectArg1:{currentColor.a=arg1.a;break;}case x3d_SelectArg2:{currentColor.a=arg2.a;break;}case x3d_Off:{break;}}}return currentColor;
#else
vec3 texCoord=getTexCoord(0,0);
#if defined(X3D_TEXTURE0_2D)
vec4 textureColor=texture(x3d_Texture2D[0],texCoord.st);
#elif defined(X3D_TEXTURE0_3D)
vec4 textureColor=texture(x3d_Texture3D[0],texCoord.stp);
#elif defined(X3D_TEXTURE0_CUBE)
vec4 textureColor=texture(x3d_TextureCube[0],texCoord.stp);
#endif
#if defined(X3D_PHYSICAL_MATERIAL)
textureColor=sRGBToLinear(textureColor);
#endif
return diffuseColor*textureColor;
#endif
}
#endif 
#if defined(X3D_PROJECTIVE_TEXTURE_MAPPING)
uniform sampler2D x3d_ProjectiveTexture[X3D_NUM_TEXTURE_PROJECTORS];uniform mat4 x3d_ProjectiveTextureMatrix[X3D_NUM_TEXTURE_PROJECTORS];uniform vec3 x3d_ProjectiveTextureLocation[X3D_NUM_TEXTURE_PROJECTORS];vec4 getProjectiveTexture(const in int i,const in vec2 texCoord){switch(i){
#if X3D_NUM_TEXTURE_PROJECTORS>0
case 0:return texture(x3d_ProjectiveTexture[0],texCoord);
#endif
#if X3D_NUM_TEXTURE_PROJECTORS>1
case 1:return texture(x3d_ProjectiveTexture[1],texCoord);
#endif
}return vec4(0.0);}vec4 getProjectiveTextureColor(in vec4 currentColor){vec3 N=gl_FrontFacing?normal:-normal;for(int i=0;i<X3D_NUM_TEXTURE_PROJECTORS;++i){vec4 texCoord=x3d_ProjectiveTextureMatrix[i]*vec4(vertex,1.0);texCoord.stp/=texCoord.q;if(texCoord.s<0.0||texCoord.s>1.0)continue;if(texCoord.t<0.0||texCoord.t>1.0)continue;if(texCoord.p<0.0||texCoord.p>1.0)continue;vec3 p=x3d_ProjectiveTextureLocation[i]-vertex;if(dot(N,p)<0.0)continue;currentColor*=getProjectiveTexture(i,texCoord.st);}return currentColor;}
#endif 
`
;

x_ite_Namespace .add ("Texture2.glsl", "assets/shaders/webgl2/common/Texture2.glsl", Texture2_glsl_default_);
/* harmony default export */ const Texture2_glsl = (Texture2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/Utils2.glsl.js
const Utils2_glsl_default_ = /* glsl */ `#if defined(X3D_SKINNING)||defined(X3D_PARTICLE_SYSTEM)
vec4 texelFetch(const in sampler2D _sampler,const in int index,const in int lod){int x=textureSize(_sampler,lod).x;ivec2 p=ivec2(index % x,index/x);vec4 t=texelFetch(_sampler,p,lod);return t;}
#endif
`
;

x_ite_Namespace .add ("Utils2.glsl", "assets/shaders/webgl2/common/Utils2.glsl", Utils2_glsl_default_);
/* harmony default export */ const Utils2_glsl = (Utils2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/common/Vertex2.glsl.js
const Vertex2_glsl_default_ = /* glsl */ `uniform mat4 x3d_ProjectionMatrix;uniform mat4 x3d_ModelViewMatrix;
#if defined(X3D_GEOMETRY_1D)&&defined(X3D_STYLE_PROPERTIES)
in vec3 x3d_LineStipple;
#endif
#if defined(X3D_FOG)&&defined(X3D_FOG_COORDS)
in float x3d_FogDepth;
#endif
#if defined(X3D_COLOR_MATERIAL)
in vec4 x3d_Color;
#endif
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
#if X3D_NUM_TEXTURE_COORDINATES>0
in vec4 x3d_TexCoord0;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>1
in vec4 x3d_TexCoord1;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>2
in vec4 x3d_TexCoord2;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>3
in vec4 x3d_TexCoord3;
#endif
#endif
#endif
in vec4 x3d_Vertex;
#if defined(X3D_FOG)&&defined(X3D_FOG_COORDS)
out float fogDepth;
#endif
#if defined(X3D_COLOR_MATERIAL)
out vec4 color;
#endif
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
#if X3D_NUM_TEXTURE_COORDINATES>0
out vec4 texCoord0;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>1
out vec4 texCoord1;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>2
out vec4 texCoord2;
#endif
#if X3D_NUM_TEXTURE_COORDINATES>3
out vec4 texCoord3;
#endif
#endif
#endif
#if defined(X3D_NORMALS)
uniform mat3 x3d_NormalMatrix;in vec3 x3d_Normal;out vec3 normal;
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
out vec3 localNormal;
#endif
#endif
#if defined(X3D_GEOMETRY_1D)&&defined(X3D_STYLE_PROPERTIES)
flat out float lengthSoFar;flat out vec2 startPoint;out vec2 midPoint;
#endif
out vec3 vertex;
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
out vec3 localVertex;
#endif
#if defined(X3D_LOGARITHMIC_DEPTH_BUFFER)
out float depth;
#endif
#pragma X3D include "Utils.glsl"
#pragma X3D include "Skin.glsl"
#pragma X3D include "Particle.glsl"
#pragma X3D include "PointSize.glsl"
void vertex_main(){
#if defined(X3D_NORMALS)
vec4 x3d_TransformedVertex=getParticleVertex(getSkinVertex(x3d_Vertex,x3d_Normal));vec3 x3d_TransformedNormal=getSkinNormal(x3d_Normal);
#else
vec4 x3d_TransformedVertex=getParticleVertex(getSkinVertex(x3d_Vertex,vec3(0.0)));
#endif
vec4 position=x3d_ModelViewMatrix*x3d_TransformedVertex;vertex=position.xyz;
#if defined(X3D_GEOMETRY_0D)
#if defined(X3D_STYLE_PROPERTIES)
gl_PointSize=pointSize=getPointSize(vertex);
#else
gl_PointSize=1.0;
#endif
#endif
#if defined(X3D_GEOMETRY_1D)&&defined(X3D_STYLE_PROPERTIES)
lengthSoFar=x3d_LineStipple.z;startPoint=x3d_LineStipple.xy;midPoint=x3d_LineStipple.xy;
#endif
#if defined(X3D_FOG)&&defined(X3D_FOG_COORDS)
fogDepth=x3d_FogDepth;
#endif
#if defined(X3D_COLOR_MATERIAL)
color=x3d_Color;
#endif
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
#if X3D_NUM_TEXTURE_COORDINATES>0
texCoord0=getParticleTexCoord(x3d_TexCoord0);
#endif
#if X3D_NUM_TEXTURE_COORDINATES>1
texCoord1=getParticleTexCoord(x3d_TexCoord1);
#endif
#if X3D_NUM_TEXTURE_COORDINATES>2
texCoord2=getParticleTexCoord(x3d_TexCoord2);
#endif
#if X3D_NUM_TEXTURE_COORDINATES>3
texCoord3=getParticleTexCoord(x3d_TexCoord3);
#endif
#endif
#endif
#if defined(X3D_NORMALS)
normal=x3d_NormalMatrix*x3d_TransformedNormal;
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
localNormal=x3d_TransformedNormal;
#endif
#endif
#if defined(X3D_TEXTURE)||defined(X3D_MATERIAL_TEXTURES)
localVertex=x3d_TransformedVertex.xyz;
#endif
gl_Position=x3d_ProjectionMatrix*position;
#if defined(X3D_LOGARITHMIC_DEPTH_BUFFER)
depth=1.0+gl_Position.w;
#endif
}
`
;

x_ite_Namespace .add ("Vertex2.glsl", "assets/shaders/webgl2/common/Vertex2.glsl", Vertex2_glsl_default_);
/* harmony default export */ const Vertex2_glsl = (Vertex2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/Default1.vs.js
const Default1_vs_default_ = /* glsl */ `precision highp float;precision highp int;precision highp sampler2D;precision highp samplerCube;
#pragma X3D include "common/Vertex.glsl"
void main(){vertex_main();}
`
;

x_ite_Namespace .add ("Default1.vs", "assets/shaders/webgl1/Default1.vs", Default1_vs_default_);
/* harmony default export */ const Default1_vs = (Default1_vs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/Depth1.fs.js
const Depth1_fs_default_ = /* glsl */ `precision highp float;precision highp int;precision highp sampler2D;varying vec3 vertex;
#pragma X3D include "common/ClipPlanes.glsl"
#pragma X3D include "common/Point.glsl"
void main(){
#if defined(X3D_CLIP_PLANES)
clip();
#endif
#if defined(X3D_GEOMETRY_0D)&&defined(X3D_STYLE_PROPERTIES)
if(getPointColor(vec4(1.0)).a<0.5)discard;
#endif
gl_FragColor=vec4(gl_FragCoord.z);}
`
;

x_ite_Namespace .add ("Depth1.fs", "assets/shaders/webgl1/Depth1.fs", Depth1_fs_default_);
/* harmony default export */ const Depth1_fs = (Depth1_fs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/Depth1.vs.js
const Depth1_vs_default_ = /* glsl */ `precision highp float;precision highp int;uniform mat4 x3d_ProjectionMatrix;uniform mat4 x3d_ModelViewMatrix;attribute vec4 x3d_Vertex;varying vec3 vertex;
#pragma X3D include "common/PointSize.glsl"
void main(){vec4 position=x3d_ModelViewMatrix*x3d_Vertex;vertex=position.xyz;
#if defined(X3D_GEOMETRY_0D)
#if defined(X3D_STYLE_PROPERTIES)
gl_PointSize=max(pointSize=getPointSize(vertex),2.0);
#else
gl_PointSize=2.0;
#endif
#endif
gl_Position=x3d_ProjectionMatrix*position;}
`
;

x_ite_Namespace .add ("Depth1.vs", "assets/shaders/webgl1/Depth1.vs", Depth1_vs_default_);
/* harmony default export */ const Depth1_vs = (Depth1_vs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/Gouraud1.fs.js
const Gouraud1_fs_default_ = /* glsl */ `precision highp float;precision highp int;precision highp sampler2D;precision highp samplerCube;
#pragma X3D include "common/Fragment.glsl"
varying vec4 frontColor;
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
varying vec4 backColor;
#endif
vec4 getMaterialColor(){
#if defined(X3D_GEOMETRY_0D)||defined(X3D_GEOMETRY_1D)
vec4 finalColor=frontColor;
#else
vec4 finalColor=gl_FrontFacing?frontColor:backColor;
#endif
#if defined(X3D_TEXTURE)
finalColor=getTextureColor(finalColor,vec4(1.0));
#endif
#if defined(X3D_PROJECTIVE_TEXTURE_MAPPING)
finalColor=getProjectiveTextureColor(finalColor);
#endif
return finalColor;}void main(){fragment_main();}
`
;

x_ite_Namespace .add ("Gouraud1.fs", "assets/shaders/webgl1/Gouraud1.fs", Gouraud1_fs_default_);
/* harmony default export */ const Gouraud1_fs = (Gouraud1_fs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/Gouraud1.vs.js
const Gouraud1_vs_default_ = /* glsl */ `precision highp float;precision highp int;precision highp sampler2D;precision highp samplerCube;
#pragma X3D include "common/Vertex.glsl"
#pragma X3D include "common/Material.glsl"
varying vec4 frontColor;
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
varying vec4 backColor;
#endif
vec4 getMaterialColor(const in vec3 N,const in vec3 vertex,const in x3d_MaterialParameters material){float alpha=1.0-x3d_Material.transparency;
#if defined(X3D_COLOR_MATERIAL)
vec4 diffuseParameter=vec4(color.rgb,color.a*alpha);
#else
vec4 diffuseParameter=vec4(x3d_Material.diffuseColor,alpha);
#endif
vec3 ambientColor=diffuseParameter.rgb*material.ambientIntensity;
#if defined(X3D_LIGHTING)
vec3 finalColor=getMaterialColor(vertex,N,ambientColor,diffuseParameter.rgb,material.specularColor,material.shininess);
#else
vec3 finalColor=vec3(0.0);
#endif
finalColor+=material.emissiveColor;return vec4(finalColor,diffuseParameter.a);}void main(){vertex_main();normal=normalize(normal);frontColor=getMaterialColor(normal,vertex,x3d_Material);
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
backColor=getMaterialColor(-normal,vertex,x3d_Material);
#endif
}
`
;

x_ite_Namespace .add ("Gouraud1.vs", "assets/shaders/webgl1/Gouraud1.vs", Gouraud1_vs_default_);
/* harmony default export */ const Gouraud1_vs = (Gouraud1_vs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/PBR1.fs.js
const PBR1_fs_default_ = /* glsl */ `precision highp float;precision highp int;precision highp sampler2D;precision highp samplerCube;
#pragma X3D include "common/Fragment.glsl"
#pragma X3D include "common/Normal.glsl"
#pragma X3D include "common/Shadow.glsl"
#if defined(X3D_LIGHTING)
uniform x3d_LightSourceParameters x3d_LightSource[X3D_NUM_LIGHTS];
#endif
uniform x3d_PhysicalMaterialParameters x3d_Material;
#pragma X3D include "pbr/BDRF.glsl"
#pragma X3D include "pbr/ToneMapping.glsl"
#pragma X3D include "pbr/MaterialInfo.glsl"
#pragma X3D include "pbr/Punctual.glsl"
vec4 getMaterialColor(){vec4 baseColor=getBaseColor();vec3 n=getNormalVector(x3d_Material.normalScale);vec3 v=normalize(-vertex);MaterialInfo materialInfo;materialInfo.baseColor=baseColor.rgb;materialInfo.ior=1.5;materialInfo.f0=vec3(0.04);materialInfo.specularWeight=1.0;
#if defined(X3D_MATERIAL_METALLIC_ROUGHNESS)
materialInfo=getMetallicRoughnessInfo(materialInfo);
#endif
materialInfo.perceptualRoughness=clamp(materialInfo.perceptualRoughness,0.0,1.0);materialInfo.metallic=clamp(materialInfo.metallic,0.0,1.0);materialInfo.alphaRoughness=materialInfo.perceptualRoughness*materialInfo.perceptualRoughness;float reflectance=max(max(materialInfo.f0.r,materialInfo.f0.g),materialInfo.f0.b);materialInfo.f90=vec3(1.0);vec3 f_specular=vec3(0.0);vec3 f_diffuse=vec3(0.0);vec3 f_emissive=vec3(0.0);vec3 f_clearcoat=vec3(0.0);vec3 f_sheen=vec3(0.0);vec3 f_transmission=vec3(0.0);float albedoSheenScaling=1.0;
#if defined(X3D_USE_IBL)
#endif
vec3 f_diffuse_ibl=f_diffuse;vec3 f_specular_ibl=f_specular;vec3 f_sheen_ibl=f_sheen;vec3 f_clearcoat_ibl=f_clearcoat;f_diffuse=vec3(0.0);f_specular=vec3(0.0);f_sheen=vec3(0.0);f_clearcoat=vec3(0.0);
#if defined(X3D_LIGHTING)
for(int i=0;i<X3D_NUM_LIGHTS;++i){x3d_LightSourceParameters light=x3d_LightSource[i];vec3 pointToLight;float distanceToLight;if(light.type!=x3d_DirectionalLight){pointToLight=light.location-vertex;distanceToLight=length(light.matrix*pointToLight);}else{pointToLight=-light.direction;distanceToLight=-1.0;}if(distanceToLight<=light.radius||light.radius<0.0){vec3 l=normalize(pointToLight);vec3 h=normalize(l+v);float NdotL=clamp(dot(n,l),0.0,1.0);float NdotV=clamp(dot(n,v),0.0,1.0);float NdotH=clamp(dot(n,h),0.0,1.0);float VdotH=clamp(dot(v,h),0.0,1.0);if(NdotL>0.0||NdotV>0.0){vec3 intensity=getLightIntensity(light,pointToLight,distanceToLight);
#if defined(X3D_SHADOWS)
if(light.shadowIntensity>0.0)intensity=mix(intensity,light.shadowColor,getShadowIntensity(i,light));
#endif
f_diffuse+=intensity*NdotL*BRDF_lambertian(materialInfo.f0,materialInfo.f90,materialInfo.c_diff,materialInfo.specularWeight,VdotH);f_specular+=intensity*NdotL*BRDF_specularGGX(materialInfo.f0,materialInfo.f90,materialInfo.alphaRoughness,materialInfo.specularWeight,VdotH,NdotL,NdotV,NdotH);}}}
#endif
f_emissive=getEmissiveColor();float clearcoatFactor=0.0;vec3 clearcoatFresnel=vec3(0.0);vec3 diffuse;vec3 specular;vec3 sheen;vec3 clearcoat;
#if defined(X3D_OCCLUSION_TEXTURE)
float ao=getOcclusionFactor();diffuse=f_diffuse+mix(f_diffuse_ibl,f_diffuse_ibl*ao,x3d_Material.occlusionStrength);specular=f_specular+mix(f_specular_ibl,f_specular_ibl*ao,x3d_Material.occlusionStrength);sheen=f_sheen+mix(f_sheen_ibl,f_sheen_ibl*ao,x3d_Material.occlusionStrength);clearcoat=f_clearcoat+mix(f_clearcoat_ibl,f_clearcoat_ibl*ao,x3d_Material.occlusionStrength);
#else
diffuse=f_diffuse_ibl+f_diffuse;specular=f_specular_ibl+f_specular;sheen=f_sheen_ibl+f_sheen;clearcoat=f_clearcoat_ibl+f_clearcoat;
#endif
vec3 color=vec3(0.0);
#if defined(X3D_MATERIAL_UNLIT)
color=baseColor.rgb;
#else
color=f_emissive+diffuse+specular;color=sheen+color*albedoSheenScaling;color=color*(1.0-clearcoatFactor*clearcoatFresnel)+clearcoat;
#endif
#if defined(X3D_LINEAR_OUTPUT)
return vec4(color.rgb,baseColor.a);
#else
return vec4(toneMap(color),baseColor.a);
#endif
}void main(){fragment_main();}
`
;

x_ite_Namespace .add ("PBR1.fs", "assets/shaders/webgl1/PBR1.fs", PBR1_fs_default_);
/* harmony default export */ const PBR1_fs = (PBR1_fs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/Phong1.fs.js
const Phong1_fs_default_ = /* glsl */ `precision highp float;precision highp int;precision highp sampler2D;precision highp samplerCube;
#pragma X3D include "common/Fragment.glsl"
#pragma X3D include "common/Material.glsl"
#pragma X3D include "common/Normal.glsl"
#if defined(X3D_AMBIENT_TEXTURE)
uniform x3d_AmbientTextureParameters x3d_AmbientTexture;
#endif
vec3 getAmbientColor(const in vec3 diffuseColor){vec3 ambientParameter=x3d_Material.ambientIntensity*diffuseColor;
#if defined(X3D_AMBIENT_TEXTURE)
vec3 texCoord=getTexCoord(x3d_AmbientTexture.textureTransformMapping,x3d_AmbientTexture.textureCoordinateMapping);
#if defined(X3D_AMBIENT_TEXTURE_2D)
return ambientParameter*texture2D(x3d_AmbientTexture.texture2D,texCoord.st).rgb;
#elif defined(X3D_AMBIENT_TEXTURE_CUBE)
return ambientParameter*textureCube(x3d_AmbientTexture.textureCube,texCoord).rgb;
#endif
#else
return ambientParameter;
#endif
}
#if defined(X3D_DIFFUSE_TEXTURE)
uniform x3d_DiffuseTextureParameters x3d_DiffuseTexture;
#endif
vec4 getDiffuseColor(){float alpha=1.0-x3d_Material.transparency;
#if defined(X3D_COLOR_MATERIAL)
vec4 diffuseParameter=vec4(color.rgb,color.a*alpha);
#else
vec4 diffuseParameter=vec4(x3d_Material.diffuseColor,alpha);
#endif
#if defined(X3D_DIFFUSE_TEXTURE)
vec3 texCoord=getTexCoord(x3d_DiffuseTexture.textureTransformMapping,x3d_DiffuseTexture.textureCoordinateMapping);
#if defined(X3D_DIFFUSE_TEXTURE_2D)
diffuseParameter*=texture2D(x3d_DiffuseTexture.texture2D,texCoord.st);
#elif defined(X3D_DIFFUSE_TEXTURE_CUBE)
diffuseParameter*=textureCube(x3d_DiffuseTexture.textureCube,texCoord);
#endif
#elif defined(X3D_TEXTURE)
diffuseParameter=getTextureColor(diffuseParameter,vec4(x3d_Material.specularColor,alpha));
#endif
return diffuseParameter;}
#if defined(X3D_SPECULAR_TEXTURE)
uniform x3d_SpecularTextureParameters x3d_SpecularTexture;
#endif
vec3 getSpecularColor(){vec3 specularParameter=x3d_Material.specularColor;
#if defined(X3D_SPECULAR_TEXTURE)
vec3 texCoord=getTexCoord(x3d_SpecularTexture.textureTransformMapping,x3d_SpecularTexture.textureCoordinateMapping);
#if defined(X3D_SPECULAR_TEXTURE_2D)
specularParameter*=texture2D(x3d_SpecularTexture.texture2D,texCoord.st).rgb;
#elif defined(X3D_SPECULAR_TEXTURE_CUBE)
specularParameter*=textureCube(x3d_SpecularTexture.textureCube,texCoord).rgb;
#endif
#endif
return specularParameter;}
#if defined(X3D_EMISSIVE_TEXTURE)
uniform x3d_EmissiveTextureParameters x3d_EmissiveTexture;
#endif
vec3 getEmissiveColor(){vec3 emissiveParameter=x3d_Material.emissiveColor;
#if defined(X3D_EMISSIVE_TEXTURE)
vec3 texCoord=getTexCoord(x3d_EmissiveTexture.textureTransformMapping,x3d_EmissiveTexture.textureCoordinateMapping);
#if defined(X3D_EMISSIVE_TEXTURE_2D)
emissiveParameter*=texture2D(x3d_EmissiveTexture.texture2D,texCoord.st).rgb;
#elif defined(X3D_EMISSIVE_TEXTURE_CUBE)
emissiveParameter*=textureCube(x3d_EmissiveTexture.textureCube,texCoord).rgb;
#endif
#endif
return emissiveParameter;}
#if defined(X3D_SHININESS_TEXTURE)
uniform x3d_ShininessTextureParameters x3d_ShininessTexture;
#endif
float getShininessFactor(){float shininess=x3d_Material.shininess;
#if defined(X3D_SHININESS_TEXTURE)
vec3 texCoord=getTexCoord(x3d_ShininessTexture.textureTransformMapping,x3d_ShininessTexture.textureCoordinateMapping);
#if defined(X3D_SHININESS_TEXTURE_2D)
shininess*=texture2D(x3d_ShininessTexture.texture2D,texCoord.st).a;
#elif defined(X3D_SHININESS_TEXTURE_CUBE)
shininess*=textureCube(x3d_ShininessTexture.textureCube,texCoord).a;
#endif
#endif
return shininess;}
#if defined(X3D_OCCLUSION_TEXTURE)
uniform x3d_OcclusionTextureParameters x3d_OcclusionTexture;
#endif
float getOcclusionFactor(){
#if defined(X3D_OCCLUSION_TEXTURE)
vec3 texCoord=getTexCoord(x3d_OcclusionTexture.textureTransformMapping,x3d_OcclusionTexture.textureCoordinateMapping);
#if defined(X3D_OCCLUSION_TEXTURE_2D)
return texture2D(x3d_OcclusionTexture.texture2D,texCoord.st).r;
#elif defined(X3D_OCCLUSION_TEXTURE_CUBE)
return textureCube(x3d_OcclusionTexture.textureCube,texCoord).r;
#endif
#else
return 1.0;
#endif
}vec4 getMaterialColor(){vec4 diffuseColorAlpha=getDiffuseColor();float alpha=diffuseColorAlpha.a;vec3 diffuseColor=diffuseColorAlpha.rgb;vec3 ambientColor=getAmbientColor(diffuseColor);vec3 specularColor=getSpecularColor();float shininess=getShininessFactor();float normalScale=x3d_Material.normalScale;
#if defined(X3D_PROJECTIVE_TEXTURE_MAPPING)
vec4 P=getProjectiveTextureColor(vec4(1.0));diffuseColor*=P.rgb;alpha*=P.a;
#endif
#if defined(X3D_LIGHTING)
vec3 finalColor=getMaterialColor(vertex,getNormalVector(normalScale),ambientColor,diffuseColor,specularColor,shininess);
#else
vec3 finalColor=vec3(0.0);
#endif
#if defined(X3D_OCCLUSION_TEXTURE)
finalColor=mix(finalColor,finalColor*getOcclusionFactor(),x3d_Material.occlusionStrength);
#endif
finalColor+=getEmissiveColor();return vec4(finalColor,alpha);}void main(){fragment_main();}
`
;

x_ite_Namespace .add ("Phong1.fs", "assets/shaders/webgl1/Phong1.fs", Phong1_fs_default_);
/* harmony default export */ const Phong1_fs = (Phong1_fs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/Pointing1.fs.js
const Pointing1_fs_default_ = /* glsl */ `#extension GL_EXT_draw_buffers:enable
precision highp float;precision highp int;precision highp sampler2D;varying vec3 vertex;varying vec3 normal;
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
varying vec4 texCoord0;
#else
vec4 texCoord0=vec4(0.0,0.0,0.0,1.0);
#endif
#pragma X3D include "common/ClipPlanes.glsl"
#pragma X3D include "common/Point.glsl"
uniform float x3d_Id;void main(){
#if defined(X3D_CLIP_PLANES)
clip();
#endif
#if defined(X3D_GEOMETRY_0D)&&defined(X3D_STYLE_PROPERTIES)
if(getPointColor(vec4(1.0)).a<0.5)discard;texCoord0=vec4(gl_PointCoord.x,1.0-gl_PointCoord.y,0.0,1.0);
#endif
gl_FragData[0]=vec4(vertex,x3d_Id);gl_FragData[1]=vec4(normal,0.0);gl_FragData[2]=texCoord0;}
`
;

x_ite_Namespace .add ("Pointing1.fs", "assets/shaders/webgl1/Pointing1.fs", Pointing1_fs_default_);
/* harmony default export */ const Pointing1_fs = (Pointing1_fs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/Pointing1.vs.js
const Pointing1_vs_default_ = /* glsl */ `precision highp float;precision highp int;uniform mat4 x3d_ProjectionMatrix;uniform mat4 x3d_ModelViewMatrix;attribute vec4 x3d_Vertex;attribute vec3 x3d_Normal;
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
attribute vec4 x3d_TexCoord0;
#endif
varying vec3 vertex;varying vec3 normal;
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
varying vec4 texCoord0;
#endif
#pragma X3D include "common/PointSize.glsl"
void main(){
#if defined(X3D_GEOMETRY_0D)
#if defined(X3D_STYLE_PROPERTIES)
gl_PointSize=max(pointSize=getPointSize(vertex),2.0);
#else
gl_PointSize=2.0;
#endif
#endif
vec4 position=x3d_ModelViewMatrix*x3d_Vertex;vertex=position.xyz;normal=x3d_Normal;
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
texCoord0=x3d_TexCoord0;
#endif
gl_Position=x3d_ProjectionMatrix*position;}
`
;

x_ite_Namespace .add ("Pointing1.vs", "assets/shaders/webgl1/Pointing1.vs", Pointing1_vs_default_);
/* harmony default export */ const Pointing1_vs = (Pointing1_vs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/Unlit1.fs.js
const Unlit1_fs_default_ = /* glsl */ `precision highp float;precision highp int;precision highp sampler2D;precision highp samplerCube;
#pragma X3D include "common/Fragment.glsl"
uniform x3d_UnlitMaterialParameters x3d_Material;
#if defined(X3D_EMISSIVE_TEXTURE)
uniform x3d_EmissiveTextureParameters x3d_EmissiveTexture;
#endif
vec4 getEmissiveColor(){float alpha=1.0-x3d_Material.transparency;
#if defined(X3D_COLOR_MATERIAL)
vec4 emissiveParameter=vec4(color.rgb,color.a*alpha);
#else
vec4 emissiveParameter=vec4(x3d_Material.emissiveColor,alpha);
#endif
#if defined(X3D_EMISSIVE_TEXTURE)
vec3 texCoord=getTexCoord(x3d_EmissiveTexture.textureTransformMapping,x3d_EmissiveTexture.textureCoordinateMapping);
#if defined(X3D_EMISSIVE_TEXTURE_2D)
emissiveParameter*=texture2D(x3d_EmissiveTexture.texture2D,texCoord.st);
#elif defined(X3D_EMISSIVE_TEXTURE_CUBE)
emissiveParameter*=textureCube(x3d_EmissiveTexture.textureCube,texCoord);
#endif
#elif defined(X3D_TEXTURE)
emissiveParameter=getTextureColor(emissiveParameter,vec4(vec3(1.0),alpha));
#endif
return emissiveParameter;}vec4 getMaterialColor(){return getEmissiveColor();}void main(){fragment_main();}
`
;

x_ite_Namespace .add ("Unlit1.fs", "assets/shaders/webgl1/Unlit1.fs", Unlit1_fs_default_);
/* harmony default export */ const Unlit1_fs = (Unlit1_fs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/Compose2.fs.js
const Compose2_fs_default_ = /* glsl */ `#version 300 es
precision highp float;precision highp int;precision highp sampler2D;uniform sampler2D x3d_AccumRevealageTexture;uniform sampler2D x3d_AlphaTexture;out vec4 x3d_FragColor;void main(){ivec2 fragCoord=ivec2(gl_FragCoord.xy);vec4 accum=texelFetch(x3d_AccumRevealageTexture,fragCoord,0);if(accum.a>=1.0)discard;float alpha=texelFetch(x3d_AlphaTexture,fragCoord,0).r;float revealage=1.0-accum.a;x3d_FragColor=vec4(revealage*accum.rgb/clamp(alpha,0.001,50000.0),revealage);}
`
;

x_ite_Namespace .add ("Compose2.fs", "assets/shaders/webgl2/Compose2.fs", Compose2_fs_default_);
/* harmony default export */ const Compose2_fs = (Compose2_fs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/Compose2.vs.js
const Compose2_vs_default_ = /* glsl */ `#version 300 es
precision highp float;precision highp int;precision highp sampler2D;layout(location=0)in vec4 x3d_Vertex;void main(){gl_Position=x3d_Vertex;}
`
;

x_ite_Namespace .add ("Compose2.vs", "assets/shaders/webgl2/Compose2.vs", Compose2_vs_default_);
/* harmony default export */ const Compose2_vs = (Compose2_vs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/Default2.vs.js
const Default2_vs_default_ = /* glsl */ `#version 300 es
precision highp float;precision highp int;precision highp sampler2D;precision highp sampler3D;precision highp samplerCube;
#pragma X3D include "common/Vertex.glsl"
void main(){vertex_main();}
`
;

x_ite_Namespace .add ("Default2.vs", "assets/shaders/webgl2/Default2.vs", Default2_vs_default_);
/* harmony default export */ const Default2_vs = (Default2_vs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/Depth2.fs.js
const Depth2_fs_default_ = /* glsl */ `#version 300 es
precision highp float;precision highp int;precision highp sampler2D;in vec3 vertex;out vec4 x3d_FragColor;
#pragma X3D include "common/ClipPlanes.glsl"
#pragma X3D include "common/Point.glsl"
void main(){
#if defined(X3D_CLIP_PLANES)
clip();
#endif
#if defined(X3D_GEOMETRY_0D)&&defined(X3D_STYLE_PROPERTIES)
if(getPointColor(vec4(1.0)).a<0.5)discard;
#endif
x3d_FragColor=vec4(gl_FragCoord.z);}
`
;

x_ite_Namespace .add ("Depth2.fs", "assets/shaders/webgl2/Depth2.fs", Depth2_fs_default_);
/* harmony default export */ const Depth2_fs = (Depth2_fs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/Depth2.vs.js
const Depth2_vs_default_ = /* glsl */ `#version 300 es
precision highp float;precision highp int;precision highp sampler2D;uniform mat4 x3d_ProjectionMatrix;uniform mat4 x3d_ModelViewMatrix;in vec4 x3d_Vertex;out vec3 vertex;
#pragma X3D include "common/Utils.glsl"
#pragma X3D include "common/Skin.glsl"
#pragma X3D include "common/Particle.glsl"
#pragma X3D include "common/PointSize.glsl"
void main(){vec4 x3d_TransformedVertex=getParticleVertex(getSkinVertex(x3d_Vertex,vec3(0.0)));vec4 position=x3d_ModelViewMatrix*x3d_TransformedVertex;vertex=position.xyz;
#if defined(X3D_GEOMETRY_0D)
#if defined(X3D_STYLE_PROPERTIES)
gl_PointSize=max(pointSize=getPointSize(vertex),2.0);
#else
gl_PointSize=2.0;
#endif
#endif
gl_Position=x3d_ProjectionMatrix*position;}
`
;

x_ite_Namespace .add ("Depth2.vs", "assets/shaders/webgl2/Depth2.vs", Depth2_vs_default_);
/* harmony default export */ const Depth2_vs = (Depth2_vs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/Gouraud2.fs.js
const Gouraud2_fs_default_ = /* glsl */ `#version 300 es
precision highp float;precision highp int;precision highp sampler2D;precision highp sampler3D;precision highp samplerCube;
#pragma X3D include "common/Fragment.glsl"
in vec4 frontColor;
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
in vec4 backColor;
#endif
vec4 getMaterialColor(){
#if defined(X3D_GEOMETRY_0D)||defined(X3D_GEOMETRY_1D)
vec4 finalColor=frontColor;
#else
vec4 finalColor=gl_FrontFacing?frontColor:backColor;
#endif
#if defined(X3D_TEXTURE)
finalColor=getTextureColor(finalColor,vec4(1.0));
#endif
#if defined(X3D_PROJECTIVE_TEXTURE_MAPPING)
finalColor=getProjectiveTextureColor(finalColor);
#endif
return finalColor;}void main(){fragment_main();}
`
;

x_ite_Namespace .add ("Gouraud2.fs", "assets/shaders/webgl2/Gouraud2.fs", Gouraud2_fs_default_);
/* harmony default export */ const Gouraud2_fs = (Gouraud2_fs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/Gouraud2.vs.js
const Gouraud2_vs_default_ = /* glsl */ `#version 300 es
precision highp float;precision highp int;precision highp sampler2D;precision highp sampler3D;precision highp samplerCube;
#pragma X3D include "common/Vertex.glsl"
#pragma X3D include "common/Material.glsl"
out vec4 frontColor;
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
out vec4 backColor;
#endif
vec4 getMaterialColor(const in vec3 N,const in vec3 vertex,const in x3d_MaterialParameters material){float alpha=1.0-x3d_Material.transparency;
#if defined(X3D_COLOR_MATERIAL)
vec4 diffuseParameter=vec4(color.rgb,color.a*alpha);
#else
vec4 diffuseParameter=vec4(x3d_Material.diffuseColor,alpha);
#endif
vec3 ambientColor=diffuseParameter.rgb*material.ambientIntensity;
#if defined(X3D_LIGHTING)
vec3 finalColor=getMaterialColor(vertex,N,ambientColor,diffuseParameter.rgb,material.specularColor,material.shininess);
#else
vec3 finalColor=vec3(0.0);
#endif
finalColor+=material.emissiveColor;return vec4(finalColor,diffuseParameter.a);}void main(){vertex_main();normal=normalize(normal);frontColor=getMaterialColor(normal,vertex,x3d_Material);
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
backColor=getMaterialColor(-normal,vertex,x3d_Material);
#endif
}
`
;

x_ite_Namespace .add ("Gouraud2.vs", "assets/shaders/webgl2/Gouraud2.vs", Gouraud2_vs_default_);
/* harmony default export */ const Gouraud2_vs = (Gouraud2_vs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/LineTransform2.fs.js
const LineTransform2_fs_default_ = /* glsl */ `#version 300 es
precision highp float;void main(){}
`
;

x_ite_Namespace .add ("LineTransform2.fs", "assets/shaders/webgl2/LineTransform2.fs", LineTransform2_fs_default_);
/* harmony default export */ const LineTransform2_fs = (LineTransform2_fs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/LineTransform2.vs.js
const LineTransform2_vs_default_ = /* glsl */ `#version 300 es
precision highp float;uniform vec4 viewport;uniform mat4 modelViewProjectionMatrix;uniform mat4 invModelViewProjectionMatrix;uniform float scale;in float x3d_CoordIndex0;in vec3 x3d_LineStipple0;in float x3d_FogDepth0;in vec4 x3d_Color0;in vec3 x3d_Normal0;in vec4 x3d_Vertex0;in float x3d_CoordIndex1;in vec3 x3d_LineStipple1;in float x3d_FogDepth1;in vec4 x3d_Color1;in vec3 x3d_Normal1;in vec4 x3d_Vertex1;out float coordIndex0;out vec3 lineStipple0;out float fogDepth0;out vec4 color0;out vec3 normal0;out vec4 vertex0;out float coordIndex1;out vec3 lineStipple1;out float fogDepth1;out vec4 color1;out vec3 normal1;out vec4 vertex1;out float coordIndex2;out vec3 lineStipple2;out float fogDepth2;out vec4 color2;out vec3 normal2;out vec4 vertex2;vec3 projectPoint(const in vec4 point,const in mat4 modelViewProjectionMatrix,const in vec4 viewport){vec4 vin=modelViewProjectionMatrix*point;vin.xyz=vin.xyz/(2.0*vin.w)+0.5;return vec3(vin.xy*viewport.zw+viewport.xy,vin.z);}vec4 unProjectPoint(const in vec3 win,const in mat4 invModelViewProjection,const in vec4 viewport){vec4 vin=vec4((win.xy-viewport.xy)/viewport.zw*2.0-1.0,2.0*win.z-1.0,1.0);vin=invModelViewProjection*vin;return vec4(vin.xyz/vin.w,1.0);}void main(){vec3 projected0=projectPoint(x3d_Vertex0,modelViewProjectionMatrix,viewport);vec3 projected1=projectPoint(x3d_Vertex1,modelViewProjectionMatrix,viewport);vec2 direction=normalize(projected1.xy-projected0.xy);vec2 offset=vec2(-direction.y,direction.x)*scale;if(gl_InstanceID==0){vec2 pq0=projected0.xy+offset;vec2 pq1=projected0.xy-offset;vec2 pq2=projected1.xy-offset;vec4 p0=unProjectPoint(vec3(pq0.xy,projected0.z),invModelViewProjectionMatrix,viewport);vec4 p1=unProjectPoint(vec3(pq1.xy,projected0.z),invModelViewProjectionMatrix,viewport);vec4 p2=unProjectPoint(vec3(pq2.xy,projected1.z),invModelViewProjectionMatrix,viewport);coordIndex0=x3d_CoordIndex0;lineStipple0=x3d_LineStipple0;fogDepth0=x3d_FogDepth0;color0=x3d_Color0;normal0=x3d_Normal0;vertex0=p0;coordIndex1=x3d_CoordIndex0;lineStipple1=x3d_LineStipple0;fogDepth1=x3d_FogDepth0;color1=x3d_Color0;normal1=x3d_Normal0;vertex1=p1;coordIndex2=x3d_CoordIndex1;lineStipple2=x3d_LineStipple1;fogDepth2=x3d_FogDepth1;color2=x3d_Color1;normal2=x3d_Normal1;vertex2=p2;}else{vec2 pq0=projected0.xy+offset;vec2 pq2=projected1.xy-offset;vec2 pq3=projected1.xy+offset;vec4 p0=unProjectPoint(vec3(pq0.xy,projected0.z),invModelViewProjectionMatrix,viewport);vec4 p2=unProjectPoint(vec3(pq2.xy,projected1.z),invModelViewProjectionMatrix,viewport);vec4 p3=unProjectPoint(vec3(pq3.xy,projected1.z),invModelViewProjectionMatrix,viewport);coordIndex0=x3d_CoordIndex0;lineStipple0=x3d_LineStipple0;fogDepth0=x3d_FogDepth0;color0=x3d_Color0;normal0=x3d_Normal0;vertex0=p0;coordIndex1=x3d_CoordIndex1;lineStipple1=x3d_LineStipple1;fogDepth1=x3d_FogDepth1;color1=x3d_Color1;normal1=x3d_Normal1;vertex1=p2;coordIndex2=x3d_CoordIndex1;lineStipple2=x3d_LineStipple1;fogDepth2=x3d_FogDepth1;color2=x3d_Color1;normal2=x3d_Normal1;vertex2=p3;}}
`
;

x_ite_Namespace .add ("LineTransform2.vs", "assets/shaders/webgl2/LineTransform2.vs", LineTransform2_vs_default_);
/* harmony default export */ const LineTransform2_vs = (LineTransform2_vs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/PBR2.fs.js
const PBR2_fs_default_ = /* glsl */ `#version 300 es
precision highp float;precision highp int;precision highp sampler2D;precision highp sampler3D;precision highp samplerCube;
#pragma X3D include "common/Fragment.glsl"
#pragma X3D include "common/Normal.glsl"
#pragma X3D include "common/Shadow.glsl"
#if defined(X3D_LIGHTING)
uniform x3d_LightSourceParameters x3d_LightSource[X3D_NUM_LIGHTS];
#endif
uniform x3d_PhysicalMaterialParameters x3d_Material;
#pragma X3D include "pbr/BDRF.glsl"
#pragma X3D include "pbr/ToneMapping.glsl"
#pragma X3D include "pbr/MaterialInfo.glsl"
#pragma X3D include "pbr/Punctual.glsl"
vec4 getMaterialColor(){vec4 baseColor=getBaseColor();vec3 n=getNormalVector(x3d_Material.normalScale);vec3 v=normalize(-vertex);MaterialInfo materialInfo;materialInfo.baseColor=baseColor.rgb;materialInfo.ior=1.5;materialInfo.f0=vec3(0.04);materialInfo.specularWeight=1.0;
#if defined(X3D_MATERIAL_METALLIC_ROUGHNESS)
materialInfo=getMetallicRoughnessInfo(materialInfo);
#endif
materialInfo.perceptualRoughness=clamp(materialInfo.perceptualRoughness,0.0,1.0);materialInfo.metallic=clamp(materialInfo.metallic,0.0,1.0);materialInfo.alphaRoughness=materialInfo.perceptualRoughness*materialInfo.perceptualRoughness;float reflectance=max(max(materialInfo.f0.r,materialInfo.f0.g),materialInfo.f0.b);materialInfo.f90=vec3(1.0);vec3 f_specular=vec3(0.0);vec3 f_diffuse=vec3(0.0);vec3 f_emissive=vec3(0.0);vec3 f_clearcoat=vec3(0.0);vec3 f_sheen=vec3(0.0);vec3 f_transmission=vec3(0.0);float albedoSheenScaling=1.0;
#if defined(X3D_USE_IBL)
#endif
vec3 f_diffuse_ibl=f_diffuse;vec3 f_specular_ibl=f_specular;vec3 f_sheen_ibl=f_sheen;vec3 f_clearcoat_ibl=f_clearcoat;f_diffuse=vec3(0.0);f_specular=vec3(0.0);f_sheen=vec3(0.0);f_clearcoat=vec3(0.0);
#if defined(X3D_LIGHTING)
for(int i=0;i<X3D_NUM_LIGHTS;++i){x3d_LightSourceParameters light=x3d_LightSource[i];vec3 pointToLight;float distanceToLight;if(light.type!=x3d_DirectionalLight){pointToLight=light.location-vertex;distanceToLight=length(light.matrix*pointToLight);}else{pointToLight=-light.direction;distanceToLight=-1.0;}if(distanceToLight<=light.radius||light.radius<0.0){vec3 l=normalize(pointToLight);vec3 h=normalize(l+v);float NdotL=clamp(dot(n,l),0.0,1.0);float NdotV=clamp(dot(n,v),0.0,1.0);float NdotH=clamp(dot(n,h),0.0,1.0);float VdotH=clamp(dot(v,h),0.0,1.0);if(NdotL>0.0||NdotV>0.0){vec3 intensity=getLightIntensity(light,pointToLight,distanceToLight);
#if defined(X3D_SHADOWS)
if(light.shadowIntensity>0.0)intensity=mix(intensity,light.shadowColor,getShadowIntensity(i,light));
#endif
f_diffuse+=intensity*NdotL*BRDF_lambertian(materialInfo.f0,materialInfo.f90,materialInfo.c_diff,materialInfo.specularWeight,VdotH);f_specular+=intensity*NdotL*BRDF_specularGGX(materialInfo.f0,materialInfo.f90,materialInfo.alphaRoughness,materialInfo.specularWeight,VdotH,NdotL,NdotV,NdotH);}}}
#endif
f_emissive=getEmissiveColor();float clearcoatFactor=0.0;vec3 clearcoatFresnel=vec3(0.0);vec3 diffuse;vec3 specular;vec3 sheen;vec3 clearcoat;
#if defined(X3D_OCCLUSION_TEXTURE)
float ao=getOcclusionFactor();diffuse=f_diffuse+mix(f_diffuse_ibl,f_diffuse_ibl*ao,x3d_Material.occlusionStrength);specular=f_specular+mix(f_specular_ibl,f_specular_ibl*ao,x3d_Material.occlusionStrength);sheen=f_sheen+mix(f_sheen_ibl,f_sheen_ibl*ao,x3d_Material.occlusionStrength);clearcoat=f_clearcoat+mix(f_clearcoat_ibl,f_clearcoat_ibl*ao,x3d_Material.occlusionStrength);
#else
diffuse=f_diffuse_ibl+f_diffuse;specular=f_specular_ibl+f_specular;sheen=f_sheen_ibl+f_sheen;clearcoat=f_clearcoat_ibl+f_clearcoat;
#endif
vec3 color=vec3(0.0);
#if defined(X3D_MATERIAL_UNLIT)
color=baseColor.rgb;
#else
color=f_emissive+diffuse+specular;color=sheen+color*albedoSheenScaling;color=color*(1.0-clearcoatFactor*clearcoatFresnel)+clearcoat;
#endif
#if defined(X3D_LINEAR_OUTPUT)
return vec4(color.rgb,baseColor.a);
#else
return vec4(toneMap(color),baseColor.a);
#endif
}void main(){fragment_main();}
`
;

x_ite_Namespace .add ("PBR2.fs", "assets/shaders/webgl2/PBR2.fs", PBR2_fs_default_);
/* harmony default export */ const PBR2_fs = (PBR2_fs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/Phong2.fs.js
const Phong2_fs_default_ = /* glsl */ `#version 300 es
precision highp float;precision highp int;precision highp sampler2D;precision highp sampler3D;precision highp samplerCube;
#pragma X3D include "common/Fragment.glsl"
#pragma X3D include "common/Material.glsl"
#pragma X3D include "common/Normal.glsl"
#if defined(X3D_AMBIENT_TEXTURE)
uniform x3d_AmbientTextureParameters x3d_AmbientTexture;
#endif
vec3 getAmbientColor(const in vec3 diffuseColor){vec3 ambientParameter=x3d_Material.ambientIntensity*diffuseColor;
#if defined(X3D_AMBIENT_TEXTURE)
vec3 texCoord=getTexCoord(x3d_AmbientTexture.textureTransformMapping,x3d_AmbientTexture.textureCoordinateMapping);
#if defined(X3D_AMBIENT_TEXTURE_2D)
ambientParameter*=texture(x3d_AmbientTexture.texture2D,texCoord.st).rgb;
#elif defined(X3D_AMBIENT_TEXTURE_3D)
ambientParameter*=texture(x3d_AmbientTexture.texture3D,texCoord).rgb;
#elif defined(X3D_AMBIENT_TEXTURE_CUBE)
ambientParameter*=texture(x3d_AmbientTexture.textureCube,texCoord).rgb;
#endif
#endif
return ambientParameter;}
#if defined(X3D_DIFFUSE_TEXTURE)
uniform x3d_DiffuseTextureParameters x3d_DiffuseTexture;
#endif
vec4 getDiffuseColor(){float alpha=1.0-x3d_Material.transparency;
#if defined(X3D_COLOR_MATERIAL)
vec4 diffuseParameter=vec4(color.rgb,color.a*alpha);
#else
vec4 diffuseParameter=vec4(x3d_Material.diffuseColor,alpha);
#endif
#if defined(X3D_DIFFUSE_TEXTURE)
vec3 texCoord=getTexCoord(x3d_DiffuseTexture.textureTransformMapping,x3d_DiffuseTexture.textureCoordinateMapping);
#if defined(X3D_DIFFUSE_TEXTURE_2D)
diffuseParameter*=texture(x3d_DiffuseTexture.texture2D,texCoord.st);
#elif defined(X3D_DIFFUSE_TEXTURE_3D)
diffuseParameter*=texture(x3d_DiffuseTexture.texture3D,texCoord);
#elif defined(X3D_DIFFUSE_TEXTURE_CUBE)
diffuseParameter*=texture(x3d_DiffuseTexture.textureCube,texCoord);
#endif
#elif defined(X3D_TEXTURE)
diffuseParameter=getTextureColor(diffuseParameter,vec4(x3d_Material.specularColor,alpha));
#endif
return diffuseParameter;}
#if defined(X3D_SPECULAR_TEXTURE)
uniform x3d_SpecularTextureParameters x3d_SpecularTexture;
#endif
vec3 getSpecularColor(){vec3 specularParameter=x3d_Material.specularColor;
#if defined(X3D_SPECULAR_TEXTURE)
vec3 texCoord=getTexCoord(x3d_SpecularTexture.textureTransformMapping,x3d_SpecularTexture.textureCoordinateMapping);
#if defined(X3D_SPECULAR_TEXTURE_2D)
specularParameter*=texture(x3d_SpecularTexture.texture2D,texCoord.st).rgb;
#elif defined(X3D_SPECULAR_TEXTURE_3D)
specularParameter*=texture(x3d_SpecularTexture.texture3D,texCoord).rgb;
#elif defined(X3D_SPECULAR_TEXTURE_CUBE)
specularParameter*=texture(x3d_SpecularTexture.textureCube,texCoord).rgb;
#endif
#endif
return specularParameter;}
#if defined(X3D_EMISSIVE_TEXTURE)
uniform x3d_EmissiveTextureParameters x3d_EmissiveTexture;
#endif
vec3 getEmissiveColor(){vec3 emissiveParameter=x3d_Material.emissiveColor;
#if defined(X3D_EMISSIVE_TEXTURE)
vec3 texCoord=getTexCoord(x3d_EmissiveTexture.textureTransformMapping,x3d_EmissiveTexture.textureCoordinateMapping);
#if defined(X3D_EMISSIVE_TEXTURE_2D)
emissiveParameter*=texture(x3d_EmissiveTexture.texture2D,texCoord.st).rgb;
#elif defined(X3D_EMISSIVE_TEXTURE_3D)
emissiveParameter*=texture(x3d_EmissiveTexture.texture3D,texCoord).rgb;
#elif defined(X3D_EMISSIVE_TEXTURE_CUBE)
emissiveParameter*=texture(x3d_EmissiveTexture.textureCube,texCoord).rgb;
#endif
#endif
return emissiveParameter;}
#if defined(X3D_SHININESS_TEXTURE)
uniform x3d_ShininessTextureParameters x3d_ShininessTexture;
#endif
float getShininessFactor(){float shininess=x3d_Material.shininess;
#if defined(X3D_SHININESS_TEXTURE)
vec3 texCoord=getTexCoord(x3d_ShininessTexture.textureTransformMapping,x3d_ShininessTexture.textureCoordinateMapping);
#if defined(X3D_SHININESS_TEXTURE_2D)
shininess*=texture(x3d_ShininessTexture.texture2D,texCoord.st).a;
#elif defined(X3D_SHININESS_TEXTURE_3D)
shininess*=texture(x3d_ShininessTexture.texture3D,texCoord).a;
#elif defined(X3D_SHININESS_TEXTURE_CUBE)
shininess*=texture(x3d_ShininessTexture.textureCube,texCoord).a;
#endif
#endif
return shininess;}
#if defined(X3D_OCCLUSION_TEXTURE)
uniform x3d_OcclusionTextureParameters x3d_OcclusionTexture;
#endif
float getOcclusionFactor(){
#if defined(X3D_OCCLUSION_TEXTURE)
vec3 texCoord=getTexCoord(x3d_OcclusionTexture.textureTransformMapping,x3d_OcclusionTexture.textureCoordinateMapping);
#if defined(X3D_OCCLUSION_TEXTURE_2D)
return texture(x3d_OcclusionTexture.texture2D,texCoord.st).r;
#elif defined(X3D_OCCLUSION_TEXTURE_3D)
return texture(x3d_OcclusionTexture.texture3D,texCoord).r;
#elif defined(X3D_OCCLUSION_TEXTURE_CUBE)
return texture(x3d_OcclusionTexture.textureCube,texCoord).r;
#endif
#else
return 1.0;
#endif
}vec4 getMaterialColor(){vec4 diffuseColorAlpha=getDiffuseColor();float alpha=diffuseColorAlpha.a;vec3 diffuseColor=diffuseColorAlpha.rgb;vec3 ambientColor=getAmbientColor(diffuseColor);vec3 specularColor=getSpecularColor();float shininess=getShininessFactor();float normalScale=x3d_Material.normalScale;
#if defined(X3D_PROJECTIVE_TEXTURE_MAPPING)
vec4 P=getProjectiveTextureColor(vec4(1.0));diffuseColor*=P.rgb;alpha*=P.a;
#endif
#if defined(X3D_LIGHTING)
vec3 finalColor=getMaterialColor(vertex,getNormalVector(normalScale),ambientColor,diffuseColor,specularColor,shininess);
#else
vec3 finalColor=vec3(0.0);
#endif
#if defined(X3D_OCCLUSION_TEXTURE)
finalColor=mix(finalColor,finalColor*getOcclusionFactor(),x3d_Material.occlusionStrength);
#endif
finalColor+=getEmissiveColor();return vec4(finalColor,alpha);}void main(){fragment_main();}
`
;

x_ite_Namespace .add ("Phong2.fs", "assets/shaders/webgl2/Phong2.fs", Phong2_fs_default_);
/* harmony default export */ const Phong2_fs = (Phong2_fs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/Pointing2.fs.js
const Pointing2_fs_default_ = /* glsl */ `#version 300 es
precision highp float;precision highp int;precision highp sampler2D;in vec3 vertex;in vec3 normal;in vec4 texCoord;
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
in vec4 texCoord0;
#else
vec4 texCoord0=vec4(0.0,0.0,0.0,1.0);
#endif
layout(location=0)out vec4 x3d_FragData0;layout(location=1)out vec4 x3d_FragData1;layout(location=2)out vec4 x3d_FragData2;
#pragma X3D include "common/ClipPlanes.glsl"
#pragma X3D include "common/Point.glsl"
#pragma X3D include "Stipple.glsl"
uniform float x3d_Id;void main(){
#if defined(X3D_CLIP_PLANES)
clip();
#endif
#if defined(X3D_GEOMETRY_0D)&&defined(X3D_STYLE_PROPERTIES)
if(getPointColor(vec4(1.0)).a<0.5)discard;texCoord0=vec4(gl_PointCoord.x,1.0-gl_PointCoord.y,0.0,1.0);
#endif
#if defined(X3D_GEOMETRY_1D)&&defined(X3D_STYLE_PROPERTIES)
stipple();
#endif
x3d_FragData0=vec4(vertex,x3d_Id);x3d_FragData1=vec4(normal,0.0);x3d_FragData2=texCoord0;}
`
;

x_ite_Namespace .add ("Pointing2.fs", "assets/shaders/webgl2/Pointing2.fs", Pointing2_fs_default_);
/* harmony default export */ const Pointing2_fs = (Pointing2_fs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/Pointing2.vs.js
const Pointing2_vs_default_ = /* glsl */ `#version 300 es
precision highp float;precision highp int;precision highp sampler2D;uniform mat4 x3d_ProjectionMatrix;uniform mat4 x3d_ModelViewMatrix;in vec4 x3d_Vertex;in vec3 x3d_Normal;
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
in vec4 x3d_TexCoord0;
#endif
#if defined(X3D_GEOMETRY_1D)&&defined(X3D_STYLE_PROPERTIES)
in vec3 x3d_LineStipple;
#endif
out vec3 vertex;out vec3 normal;
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
out vec4 texCoord0;
#endif
#if defined(X3D_GEOMETRY_1D)&&defined(X3D_STYLE_PROPERTIES)
flat out float lengthSoFar;flat out vec2 startPoint;out vec2 midPoint;
#endif
#pragma X3D include "common/Utils.glsl"
#pragma X3D include "common/Skin.glsl"
#pragma X3D include "common/Particle.glsl"
#pragma X3D include "common/PointSize.glsl"
void main(){
#if defined(X3D_GEOMETRY_1D)&&defined(X3D_STYLE_PROPERTIES)
lengthSoFar=x3d_LineStipple.z;startPoint=x3d_LineStipple.xy;midPoint=x3d_LineStipple.xy;
#endif
vec4 x3d_TransformedVertex=getParticleVertex(getSkinVertex(x3d_Vertex,vec3(0.0)));vec4 position=x3d_ModelViewMatrix*x3d_TransformedVertex;vertex=position.xyz;normal=x3d_Normal;
#if defined(X3D_GEOMETRY_0D)
#if defined(X3D_STYLE_PROPERTIES)
gl_PointSize=max(pointSize=getPointSize(vertex),2.0);
#else
gl_PointSize=2.0;
#endif
#endif
#if!defined(X3D_GEOMETRY_0D)&&!defined(X3D_GEOMETRY_1D)
texCoord0=x3d_TexCoord0;
#endif
gl_Position=x3d_ProjectionMatrix*position;}
`
;

x_ite_Namespace .add ("Pointing2.vs", "assets/shaders/webgl2/Pointing2.vs", Pointing2_vs_default_);
/* harmony default export */ const Pointing2_vs = (Pointing2_vs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/Unlit2.fs.js
const Unlit2_fs_default_ = /* glsl */ `#version 300 es
precision highp float;precision highp int;precision highp sampler2D;precision highp sampler3D;precision highp samplerCube;
#pragma X3D include "common/Fragment.glsl"
uniform x3d_UnlitMaterialParameters x3d_Material;
#if defined(X3D_EMISSIVE_TEXTURE)
uniform x3d_EmissiveTextureParameters x3d_EmissiveTexture;
#endif
vec4 getEmissiveColor(){float alpha=1.0-x3d_Material.transparency;
#if defined(X3D_COLOR_MATERIAL)
vec4 emissiveParameter=vec4(color.rgb,color.a*alpha);
#else
vec4 emissiveParameter=vec4(x3d_Material.emissiveColor,alpha);
#endif
#if defined(X3D_EMISSIVE_TEXTURE)
vec3 texCoord=getTexCoord(x3d_EmissiveTexture.textureTransformMapping,x3d_EmissiveTexture.textureCoordinateMapping);
#if defined(X3D_EMISSIVE_TEXTURE_2D)
emissiveParameter*=texture(x3d_EmissiveTexture.texture2D,texCoord.st);
#elif defined(X3D_EMISSIVE_TEXTURE_3D)
emissiveParameter*=texture(x3d_EmissiveTexture.texture3D,texCoord);
#elif defined(X3D_EMISSIVE_TEXTURE_CUBE)
emissiveParameter*=texture(x3d_EmissiveTexture.textureCube,texCoord);
#endif
#elif defined(X3D_TEXTURE)
emissiveParameter=getTextureColor(emissiveParameter,vec4(vec3(1.0),alpha));
#endif
return emissiveParameter;}vec4 getMaterialColor(){return getEmissiveColor();}void main(){fragment_main();}
`
;

x_ite_Namespace .add ("Unlit2.fs", "assets/shaders/webgl2/Unlit2.fs", Unlit2_fs_default_);
/* harmony default export */ const Unlit2_fs = (Unlit2_fs_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/pbr/BDRF1.glsl.js
const BDRF1_glsl_default_ = /* glsl */ `const float M_PI=3.14159265359;vec3 F_Schlick(vec3 f0,vec3 f90,float VdotH){return f0+(f90-f0)*pow(clamp(1.0-VdotH,0.0,1.0),5.0);}float V_GGX(float NdotL,float NdotV,float alphaRoughness){float alphaRoughnessSq=alphaRoughness*alphaRoughness;float GGXV=NdotL*sqrt(NdotV*NdotV*(1.0-alphaRoughnessSq)+alphaRoughnessSq);float GGXL=NdotV*sqrt(NdotL*NdotL*(1.0-alphaRoughnessSq)+alphaRoughnessSq);float GGX=GGXV+GGXL;if(GGX>0.0){return 0.5/GGX;}return 0.0;}float D_GGX(float NdotH,float alphaRoughness){float alphaRoughnessSq=alphaRoughness*alphaRoughness;float f=(NdotH*NdotH)*(alphaRoughnessSq-1.0)+1.0;return alphaRoughnessSq/(M_PI*f*f);}vec3 BRDF_lambertian(vec3 f0,vec3 f90,vec3 diffuseColor,float specularWeight,float VdotH){return(1.0-specularWeight*F_Schlick(f0,f90,VdotH))*(diffuseColor/M_PI);}vec3 BRDF_specularGGX(vec3 f0,vec3 f90,float alphaRoughness,float specularWeight,float VdotH,float NdotL,float NdotV,float NdotH){vec3 F=F_Schlick(f0,f90,VdotH);float Vis=V_GGX(NdotL,NdotV,alphaRoughness);float D=D_GGX(NdotH,alphaRoughness);return specularWeight*F*Vis*D;}
`
;

x_ite_Namespace .add ("BDRF1.glsl", "assets/shaders/webgl1/pbr/BDRF1.glsl", BDRF1_glsl_default_);
/* harmony default export */ const BDRF1_glsl = (BDRF1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/pbr/Punctual1.glsl.js
const Punctual1_glsl_default_ = /* glsl */ `#if defined(X3D_LIGHTING)
float getAttenuation(const in vec3 attenuation,const in float distanceToLight){return 1.0/max(dot(attenuation,vec3(1.0,distanceToLight,distanceToLight*distanceToLight)),1.0);}float getRangeAttenuation(const in float range,const in float _distance){if(range<=0.0){return 1.0/pow(_distance,2.0);}return max(min(1.0-pow(_distance/range,4.0),1.0),0.0)/pow(_distance,2.0);}float getSpotAttenuation(const in vec3 pointToLight,const in vec3 spotDirection,const in float outerConeCos,const in float innerConeCos){float actualCos=dot(normalize(spotDirection),normalize(-pointToLight));if(actualCos>outerConeCos){if(actualCos<innerConeCos){return smoothstep(outerConeCos,innerConeCos,actualCos);}return 1.0;}return 0.0;}vec3 getLightIntensity(const in x3d_LightSourceParameters light,const in vec3 pointToLight,const in float distanceToLight){float attenuation=1.0;float rangeAttenuation=1.0;float spotAttenuation=1.0;if(light.type!=x3d_DirectionalLight){attenuation=getAttenuation(light.attenuation,distanceToLight);rangeAttenuation=getRangeAttenuation(light.radius,length(pointToLight));}if(light.type==x3d_SpotLight){spotAttenuation=getSpotAttenuation(pointToLight,light.direction,cos(light.cutOffAngle),cos(light.beamWidth));}return attenuation*rangeAttenuation*spotAttenuation*light.intensity*light.color;}
#endif
`
;

x_ite_Namespace .add ("Punctual1.glsl", "assets/shaders/webgl1/pbr/Punctual1.glsl", Punctual1_glsl_default_);
/* harmony default export */ const Punctual1_glsl = (Punctual1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/pbr/MaterialInfo1.glsl.js
const MaterialInfo1_glsl_default_ = /* glsl */ `struct MaterialInfo{float ior;float perceptualRoughness;vec3 f0;float alphaRoughness;vec3 c_diff;vec3 f90;float metallic;vec3 baseColor;float sheenRoughnessFactor;vec3 sheenColorFactor;vec3 clearcoatF0;vec3 clearcoatF90;float clearcoatFactor;vec3 clearcoatNormal;float clearcoatRoughness;float specularWeight;float transmissionFactor;float thickness;vec3 attenuationColor;float attenuationDistance;float iridescenceFactor;float iridescenceIor;float iridescenceThickness;vec3 anisotropicT;vec3 anisotropicB;float anisotropyStrength;};
#if defined(X3D_MATERIAL_SPECULAR_GLOSSINESS)
#if defined(X3D_DIFFUSE_TEXTURE)
uniform x3d_DiffuseTextureParameters x3d_DiffuseTexture;
#endif
#elif defined(X3D_MATERIAL_METALLIC_ROUGHNESS)
#if defined(X3D_BASE_TEXTURE)
uniform x3d_BaseTextureParameters x3d_BaseTexture;
#endif
#endif
vec4 getBaseColor(){float alpha=1.0-x3d_Material.transparency;
#if defined(X3D_MATERIAL_SPECULAR_GLOSSINESS)
vec4 baseColor=vec4(x3d_Material.diffuseColor,alpha);
#elif defined(X3D_MATERIAL_METALLIC_ROUGHNESS)
vec4 baseColor=vec4(x3d_Material.baseColor,alpha);
#endif
#if defined(X3D_COLOR_MATERIAL)
baseColor*=color;
#endif
#if defined(X3D_MATERIAL_SPECULAR_GLOSSINESS)
#if defined(X3D_DIFFUSE_TEXTURE)
vec3 texCoord=getTexCoord(x3d_Diffuse.textureTransformMapping,x3d_Diffuse.textureCoordinateMapping);
#if defined(X3D_DIFFUSE_TEXTURE_2D)
baseColor*=sRGBToLinear(texture2D(x3d_Diffuse.texture2D,texCoord.st));
#elif defined(X3D_DIFFUSE_TEXTURE_CUBE)
baseColor*=sRGBToLinear(textureCube(x3d_Diffuse.textureCube,texCoord));
#endif
#elif defined(X3D_TEXTURE)
baseColor=getTextureColor(baseColor,vec4(vec3(1.0),alpha));
#endif
#elif defined(X3D_MATERIAL_METALLIC_ROUGHNESS)
#if defined(X3D_BASE_TEXTURE)
vec3 texCoord=getTexCoord(x3d_BaseTexture.textureTransformMapping,x3d_BaseTexture.textureCoordinateMapping);
#if defined(X3D_BASE_TEXTURE_2D)
baseColor*=sRGBToLinear(texture2D(x3d_BaseTexture.texture2D,texCoord.st));
#elif defined(X3D_BASE_TEXTURE_CUBE)
baseColor*=sRGBToLinear(textureCube(x3d_BaseTexture.textureCube,texCoord));
#endif
#elif defined(X3D_TEXTURE)
baseColor=getTextureColor(baseColor,vec4(vec3(1.0),alpha));
#endif
#endif
return baseColor;}
#if defined(X3D_MATERIAL_METALLIC_ROUGHNESS)
#if defined(X3D_METALLIC_ROUGHNESS_TEXTURE)
uniform x3d_MetallicRoughnessTextureParameters x3d_MetallicRoughnessTexture;
#endif
MaterialInfo getMetallicRoughnessInfo(MaterialInfo info){info.metallic=x3d_Material.metallic;info.perceptualRoughness=x3d_Material.roughness;
#if defined(X3D_METALLIC_ROUGHNESS_TEXTURE)
vec3 texCoord=getTexCoord(x3d_MetallicRoughnessTexture.textureTransformMapping,x3d_MetallicRoughnessTexture.textureCoordinateMapping);
#if defined(X3D_METALLIC_ROUGHNESS_TEXTURE_2D)
vec4 mrSample=texture2D(x3d_MetallicRoughnessTexture.texture2D,texCoord.st);
#elif defined(X3D_METALLIC_ROUGHNESS_TEXTURE_CUBE)
vec4 mrSample=textureCube(x3d_MetallicRoughnessTexture.textureCube,texCoord);
#endif
info.metallic*=mrSample.b;info.perceptualRoughness*=mrSample.g;
#endif
info.c_diff=mix(info.baseColor.rgb,vec3(0.0),info.metallic);info.f0=mix(info.f0,info.baseColor.rgb,info.metallic);return info;}
#endif
#if defined(X3D_EMISSIVE_TEXTURE)
uniform x3d_EmissiveTextureParameters x3d_EmissiveTexture;
#endif
vec3 getEmissiveColor(){vec3 emissiveParameter=x3d_Material.emissiveColor;
#if defined(X3D_EMISSIVE_TEXTURE)
vec3 texCoord=getTexCoord(x3d_EmissiveTexture.textureTransformMapping,x3d_EmissiveTexture.textureCoordinateMapping);
#if defined(X3D_EMISSIVE_TEXTURE_2D)
emissiveParameter*=sRGBToLinear(texture2D(x3d_EmissiveTexture.texture2D,texCoord.st)).rgb;
#elif defined(X3D_EMISSIVE_TEXTURE_CUBE)
emissiveParameter*=sRGBToLinear(textureCube(x3d_EmissiveTexture.textureCube,texCoord)).rgb;
#endif
#endif
return emissiveParameter.rgb;}
#if defined(X3D_OCCLUSION_TEXTURE)
uniform x3d_OcclusionTextureParameters x3d_OcclusionTexture;
#endif
float getOcclusionFactor(){
#if defined(X3D_OCCLUSION_TEXTURE)
vec3 texCoord=getTexCoord(x3d_OcclusionTexture.textureTransformMapping,x3d_OcclusionTexture.textureCoordinateMapping);
#if defined(X3D_OCCLUSION_TEXTURE_2D)
return texture2D(x3d_OcclusionTexture.texture2D,texCoord.st).r;
#elif defined(X3D_OCCLUSION_TEXTURE_CUBE)
return textureCube(x3d_OcclusionTexture.textureCube,texCoord).r;
#endif
#else
return 1.0;
#endif
}
`
;

x_ite_Namespace .add ("MaterialInfo1.glsl", "assets/shaders/webgl1/pbr/MaterialInfo1.glsl", MaterialInfo1_glsl_default_);
/* harmony default export */ const MaterialInfo1_glsl = (MaterialInfo1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl1/pbr/ToneMapping1.glsl.js
const ToneMapping1_glsl_default_ = /* glsl */ `const float exposure=1.0;const float GAMMA=2.2;const float INV_GAMMA=1.0/GAMMA;vec3 linearTosRGB(const in vec3 color){return pow(color,vec3(INV_GAMMA));}vec3 sRGBToLinear(const in vec3 srgbIn){return vec3(pow(srgbIn.xyz,vec3(GAMMA)));}vec4 sRGBToLinear(const in vec4 srgbIn){return vec4(sRGBToLinear(srgbIn.xyz),srgbIn.w);}
#if defined(X3D_TONEMAP_ACES_NARKOWICZ)
vec3 toneMapACES_Narkowicz(const in vec3 color){const float A=2.51;const float B=0.03;const float C=2.43;const float D=0.59;const float E=0.14;return clamp((color*(A*color+B))/(color*(C*color+D)+E),0.0,1.0);}
#endif
#if defined(X3D_TONEMAP_ACES_HILL)||defined(X3D_TONEMAP_ACES_HILL_EXPOSURE_BOOST)
const mat3 ACESInputMat=mat3(0.59719,0.07600,0.02840,0.35458,0.90834,0.13383,0.04823,0.01566,0.83777);const mat3 ACESOutputMat=mat3(1.60475,-0.10208,-0.00327,-0.53108,1.10813,-0.07276,-0.07367,-0.00605,1.07602);vec3 RRTAndODTFit(const in vec3 color){vec3 a=color*(color+0.0245786)-0.000090537;vec3 b=color*(0.983729*color+0.4329510)+0.238081;return a/b;}vec3 toneMapACES_Hill(in vec3 color){color=ACESInputMat*color;color=RRTAndODTFit(color);color=ACESOutputMat*color;color=clamp(color,0.0,1.0);return color;}
#endif
vec3 toneMap(in vec3 color){color*=exposure;
#if defined(X3D_TONEMAP_ACES_NARKOWICZ)
color=toneMapACES_Narkowicz(color);
#endif
#if defined(X3D_TONEMAP_ACES_HILL)
color=toneMapACES_Hill(color);
#endif
#if defined(X3D_TONEMAP_ACES_HILL_EXPOSURE_BOOST)
color/=0.6;color=toneMapACES_Hill(color);
#endif
return linearTosRGB(color);}
`
;

x_ite_Namespace .add ("ToneMapping1.glsl", "assets/shaders/webgl1/pbr/ToneMapping1.glsl", ToneMapping1_glsl_default_);
/* harmony default export */ const ToneMapping1_glsl = (ToneMapping1_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/pbr/BDRF2.glsl.js
const BDRF2_glsl_default_ = /* glsl */ `const float M_PI=3.14159265359;vec3 F_Schlick(vec3 f0,vec3 f90,float VdotH){return f0+(f90-f0)*pow(clamp(1.0-VdotH,0.0,1.0),5.0);}float V_GGX(float NdotL,float NdotV,float alphaRoughness){float alphaRoughnessSq=alphaRoughness*alphaRoughness;float GGXV=NdotL*sqrt(NdotV*NdotV*(1.0-alphaRoughnessSq)+alphaRoughnessSq);float GGXL=NdotV*sqrt(NdotL*NdotL*(1.0-alphaRoughnessSq)+alphaRoughnessSq);float GGX=GGXV+GGXL;if(GGX>0.0){return 0.5/GGX;}return 0.0;}float D_GGX(float NdotH,float alphaRoughness){float alphaRoughnessSq=alphaRoughness*alphaRoughness;float f=(NdotH*NdotH)*(alphaRoughnessSq-1.0)+1.0;return alphaRoughnessSq/(M_PI*f*f);}vec3 BRDF_lambertian(vec3 f0,vec3 f90,vec3 diffuseColor,float specularWeight,float VdotH){return(1.0-specularWeight*F_Schlick(f0,f90,VdotH))*(diffuseColor/M_PI);}vec3 BRDF_specularGGX(vec3 f0,vec3 f90,float alphaRoughness,float specularWeight,float VdotH,float NdotL,float NdotV,float NdotH){vec3 F=F_Schlick(f0,f90,VdotH);float Vis=V_GGX(NdotL,NdotV,alphaRoughness);float D=D_GGX(NdotH,alphaRoughness);return specularWeight*F*Vis*D;}
`
;

x_ite_Namespace .add ("BDRF2.glsl", "assets/shaders/webgl2/pbr/BDRF2.glsl", BDRF2_glsl_default_);
/* harmony default export */ const BDRF2_glsl = (BDRF2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/pbr/Punctual2.glsl.js
const Punctual2_glsl_default_ = /* glsl */ `#if defined(X3D_LIGHTING)
float getAttenuation(const in vec3 attenuation,const in float distanceToLight){return 1.0/max(dot(attenuation,vec3(1.0,distanceToLight,distanceToLight*distanceToLight)),1.0);}float getRangeAttenuation(const in float range,const in float _distance){if(range<=0.0){return 1.0/pow(_distance,2.0);}return max(min(1.0-pow(_distance/range,4.0),1.0),0.0)/pow(_distance,2.0);}float getSpotAttenuation(const in vec3 pointToLight,const in vec3 spotDirection,const in float outerConeCos,const in float innerConeCos){float actualCos=dot(normalize(spotDirection),normalize(-pointToLight));if(actualCos>outerConeCos){if(actualCos<innerConeCos){return smoothstep(outerConeCos,innerConeCos,actualCos);}return 1.0;}return 0.0;}vec3 getLightIntensity(const in x3d_LightSourceParameters light,const in vec3 pointToLight,const in float distanceToLight){float attenuation=1.0;float rangeAttenuation=1.0;float spotAttenuation=1.0;if(light.type!=x3d_DirectionalLight){attenuation=getAttenuation(light.attenuation,distanceToLight);rangeAttenuation=getRangeAttenuation(light.radius,length(pointToLight));}if(light.type==x3d_SpotLight){spotAttenuation=getSpotAttenuation(pointToLight,light.direction,cos(light.cutOffAngle),cos(light.beamWidth));}return attenuation*rangeAttenuation*spotAttenuation*light.intensity*light.color;}
#endif
`
;

x_ite_Namespace .add ("Punctual2.glsl", "assets/shaders/webgl2/pbr/Punctual2.glsl", Punctual2_glsl_default_);
/* harmony default export */ const Punctual2_glsl = (Punctual2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/pbr/MaterialInfo2.glsl.js
const MaterialInfo2_glsl_default_ = /* glsl */ `struct MaterialInfo{float ior;float perceptualRoughness;vec3 f0;float alphaRoughness;vec3 c_diff;vec3 f90;float metallic;vec3 baseColor;float sheenRoughnessFactor;vec3 sheenColorFactor;vec3 clearcoatF0;vec3 clearcoatF90;float clearcoatFactor;vec3 clearcoatNormal;float clearcoatRoughness;float specularWeight;float transmissionFactor;float thickness;vec3 attenuationColor;float attenuationDistance;float iridescenceFactor;float iridescenceIor;float iridescenceThickness;vec3 anisotropicT;vec3 anisotropicB;float anisotropyStrength;};
#if defined(X3D_MATERIAL_SPECULAR_GLOSSINESS)
#if defined(X3D_DIFFUSE_TEXTURE)
uniform x3d_DiffuseTextureParameters x3d_DiffuseTexture;
#endif
#elif defined(X3D_MATERIAL_METALLIC_ROUGHNESS)
#if defined(X3D_BASE_TEXTURE)
uniform x3d_BaseTextureParameters x3d_BaseTexture;
#endif
#endif
vec4 getBaseColor(){float alpha=1.0-x3d_Material.transparency;
#if defined(X3D_MATERIAL_SPECULAR_GLOSSINESS)
vec4 baseColor=vec4(x3d_Material.diffuseColor,alpha);
#elif defined(X3D_MATERIAL_METALLIC_ROUGHNESS)
vec4 baseColor=vec4(x3d_Material.baseColor,alpha);
#endif
#if defined(X3D_COLOR_MATERIAL)
baseColor*=color;
#endif
#if defined(X3D_MATERIAL_SPECULAR_GLOSSINESS)
#if defined(X3D_DIFFUSE_TEXTURE)
vec3 texCoord=getTexCoord(x3d_Diffuse.textureTransformMapping,x3d_Diffuse.textureCoordinateMapping);
#if defined(X3D_DIFFUSE_TEXTURE_2D)
baseColor*=sRGBToLinear(texture(x3d_Diffuse.texture2D,texCoord.st));
#elif defined(X3D_DIFFUSE_TEXTURE_3D)
baseColor*=sRGBToLinear(texture(x3d_Diffuse.texture3D,texCoord));
#elif defined(X3D_DIFFUSE_TEXTURE_CUBE)
baseColor*=sRGBToLinear(texture(x3d_Diffuse.textureCube,texCoord));
#endif
#elif defined(X3D_TEXTURE)
baseColor=getTextureColor(baseColor,vec4(vec3(1.0),alpha));
#endif
#elif defined(X3D_MATERIAL_METALLIC_ROUGHNESS)
#if defined(X3D_BASE_TEXTURE)
vec3 texCoord=getTexCoord(x3d_BaseTexture.textureTransformMapping,x3d_BaseTexture.textureCoordinateMapping);
#if defined(X3D_BASE_TEXTURE_2D)
baseColor*=sRGBToLinear(texture(x3d_BaseTexture.texture2D,texCoord.st));
#elif defined(X3D_BASE_TEXTURE_3D)
baseColor*=sRGBToLinear(texture(x3d_BaseTexture.texture3D,texCoord));
#elif defined(X3D_BASE_TEXTURE_CUBE)
baseColor*=sRGBToLinear(texture(x3d_BaseTexture.textureCube,texCoord));
#endif
#elif defined(X3D_TEXTURE)
baseColor=getTextureColor(baseColor,vec4(vec3(1.0),alpha));
#endif
#endif
return baseColor;}
#if defined(X3D_MATERIAL_METALLIC_ROUGHNESS)
#if defined(X3D_METALLIC_ROUGHNESS_TEXTURE)
uniform x3d_MetallicRoughnessTextureParameters x3d_MetallicRoughnessTexture;
#endif
MaterialInfo getMetallicRoughnessInfo(MaterialInfo info){info.metallic=x3d_Material.metallic;info.perceptualRoughness=x3d_Material.roughness;
#if defined(X3D_METALLIC_ROUGHNESS_TEXTURE)
vec3 texCoord=getTexCoord(x3d_MetallicRoughnessTexture.textureTransformMapping,x3d_MetallicRoughnessTexture.textureCoordinateMapping);
#if defined(X3D_METALLIC_ROUGHNESS_TEXTURE_2D)
vec4 mrSample=texture(x3d_MetallicRoughnessTexture.texture2D,texCoord.st);
#elif defined(X3D_METALLIC_ROUGHNESS_TEXTURE_3D)
vec4 mrSample=texture(x3d_MetallicRoughnessTexture.texture3D,texCoord);
#elif defined(X3D_METALLIC_ROUGHNESS_TEXTURE_CUBE)
vec4 mrSample=texture(x3d_MetallicRoughnessTexture.textureCube,texCoord);
#endif
info.metallic*=mrSample.b;info.perceptualRoughness*=mrSample.g;
#endif
info.c_diff=mix(info.baseColor.rgb,vec3(0.0),info.metallic);info.f0=mix(info.f0,info.baseColor.rgb,info.metallic);return info;}
#endif
#if defined(X3D_EMISSIVE_TEXTURE)
uniform x3d_EmissiveTextureParameters x3d_EmissiveTexture;
#endif
vec3 getEmissiveColor(){vec3 emissiveParameter=x3d_Material.emissiveColor;
#if defined(X3D_EMISSIVE_TEXTURE)
vec3 texCoord=getTexCoord(x3d_EmissiveTexture.textureTransformMapping,x3d_EmissiveTexture.textureCoordinateMapping);
#if defined(X3D_EMISSIVE_TEXTURE_2D)
emissiveParameter*=sRGBToLinear(texture(x3d_EmissiveTexture.texture2D,texCoord.st)).rgb;
#elif defined(X3D_EMISSIVE_TEXTURE_3D)
emissiveParameter*=sRGBToLinear(texture(x3d_EmissiveTexture.texture3D,texCoord)).rgb;
#elif defined(X3D_EMISSIVE_TEXTURE_CUBE)
emissiveParameter*=sRGBToLinear(texture(x3d_EmissiveTexture.textureCube,texCoord)).rgb;
#endif
#endif
return emissiveParameter.rgb;}
#if defined(X3D_OCCLUSION_TEXTURE)
uniform x3d_OcclusionTextureParameters x3d_OcclusionTexture;
#endif
float getOcclusionFactor(){
#if defined(X3D_OCCLUSION_TEXTURE)
vec3 texCoord=getTexCoord(x3d_OcclusionTexture.textureTransformMapping,x3d_OcclusionTexture.textureCoordinateMapping);
#if defined(X3D_OCCLUSION_TEXTURE_2D)
return texture(x3d_OcclusionTexture.texture2D,texCoord.st).r;
#elif defined(X3D_OCCLUSION_TEXTURE_3D)
return texture(x3d_OcclusionTexture.texture3D,texCoord).r;
#elif defined(X3D_OCCLUSION_TEXTURE_CUBE)
return texture(x3d_OcclusionTexture.textureCube,texCoord).r;
#endif
#else
return 1.0;
#endif
}
`
;

x_ite_Namespace .add ("MaterialInfo2.glsl", "assets/shaders/webgl2/pbr/MaterialInfo2.glsl", MaterialInfo2_glsl_default_);
/* harmony default export */ const MaterialInfo2_glsl = (MaterialInfo2_glsl_default_);
;// CONCATENATED MODULE: ./src/assets/shaders/webgl2/pbr/ToneMapping2.glsl.js
const ToneMapping2_glsl_default_ = /* glsl */ `const float exposure=1.0;const float GAMMA=2.2;const float INV_GAMMA=1.0/GAMMA;vec3 linearTosRGB(const in vec3 color){return pow(color,vec3(INV_GAMMA));}vec3 sRGBToLinear(const in vec3 srgbIn){return vec3(pow(srgbIn.xyz,vec3(GAMMA)));}vec4 sRGBToLinear(const in vec4 srgbIn){return vec4(sRGBToLinear(srgbIn.xyz),srgbIn.w);}
#if defined(X3D_TONEMAP_ACES_NARKOWICZ)
vec3 toneMapACES_Narkowicz(const in vec3 color){const float A=2.51;const float B=0.03;const float C=2.43;const float D=0.59;const float E=0.14;return clamp((color*(A*color+B))/(color*(C*color+D)+E),0.0,1.0);}
#endif
#if defined(X3D_TONEMAP_ACES_HILL)||defined(X3D_TONEMAP_ACES_HILL_EXPOSURE_BOOST)
const mat3 ACESInputMat=mat3(0.59719,0.07600,0.02840,0.35458,0.90834,0.13383,0.04823,0.01566,0.83777);const mat3 ACESOutputMat=mat3(1.60475,-0.10208,-0.00327,-0.53108,1.10813,-0.07276,-0.07367,-0.00605,1.07602);vec3 RRTAndODTFit(const in vec3 color){vec3 a=color*(color+0.0245786)-0.000090537;vec3 b=color*(0.983729*color+0.4329510)+0.238081;return a/b;}vec3 toneMapACES_Hill(in vec3 color){color=ACESInputMat*color;color=RRTAndODTFit(color);color=ACESOutputMat*color;color=clamp(color,0.0,1.0);return color;}
#endif
vec3 toneMap(in vec3 color){color*=exposure;
#if defined(X3D_TONEMAP_ACES_NARKOWICZ)
color=toneMapACES_Narkowicz(color);
#endif
#if defined(X3D_TONEMAP_ACES_HILL)
color=toneMapACES_Hill(color);
#endif
#if defined(X3D_TONEMAP_ACES_HILL_EXPOSURE_BOOST)
color/=0.6;color=toneMapACES_Hill(color);
#endif
return linearTosRGB(color);}
`
;

x_ite_Namespace .add ("ToneMapping2.glsl", "assets/shaders/webgl2/pbr/ToneMapping2.glsl", ToneMapping2_glsl_default_);
/* harmony default export */ const ToneMapping2_glsl = (ToneMapping2_glsl_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Shaders/ShaderRegistry.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

/* WebGL 1 */















/* WebGL 2 */



















/* WebGL 1 */











/* WebGL 2 */















/* PBR 1 */





/* PBR 2 */





const ShaderRegistry = {
   includes: {
      1: {
         ClipPlanes: ClipPlanes1_glsl,
         Colors: Colors1_glsl,
         Fog: Fog1_glsl,
         Fragment: Fragment1_glsl,
         Hatch: Hatch1_glsl,
         Material: Material1_glsl,
         Normal: Normal1_glsl,
         Perlin: Perlin1_glsl,
         Point: Point1_glsl,
         PointSize: PointSize1_glsl,
         Shadow: Shadow1_glsl,
         SpotFactor: SpotFactor1_glsl,
         Texture: Texture1_glsl,
         Vertex: Vertex1_glsl,
         // PBR
         BDRF: BDRF1_glsl,
         MaterialInfo: MaterialInfo1_glsl,
         Punctual: Punctual1_glsl,
         ToneMapping: ToneMapping1_glsl,
      },
      2: {
         ClipPlanes: ClipPlanes2_glsl,
         Fog: Fog2_glsl,
         Fragment: Fragment2_glsl,
         Hatch: Hatch2_glsl,
         Line2: Line22_glsl,
         Material: Material2_glsl,
         Normal: Normal2_glsl,
         Particle: Particle2_glsl,
         Perlin: Perlin2_glsl,
         Point: Point2_glsl,
         PointSize: PointSize2_glsl,
         Shadow: Shadow2_glsl,
         Skin: Skin2_glsl,
         SpotFactor: SpotFactor2_glsl,
         Stipple: Stipple2_glsl,
         Texture: Texture2_glsl,
         Utils: Utils2_glsl,
         Vertex: Vertex2_glsl,
         // PBR
         BDRF: BDRF2_glsl,
         MaterialInfo: MaterialInfo2_glsl,
         Punctual: Punctual2_glsl,
         ToneMapping: ToneMapping2_glsl,
      },
   },
   vertex: {
      1: {
         Default: Default1_vs,
         Depth: Depth1_vs,
         Gouraud: Gouraud1_vs,
         Pointing: Pointing1_vs,
      },
      2: {
         Compose: Compose2_vs,
         Default: Default2_vs,
         Depth: Depth2_vs,
         Gouraud: Gouraud2_vs,
         LineTransform: LineTransform2_vs,
         Pointing: Pointing2_vs,
      },
   },
   fragment: {
      1: {
         Depth: Depth1_fs,
         Gouraud: Gouraud1_fs,
         PBR: PBR1_fs,
         Phong: Phong1_fs,
         Pointing: Pointing1_fs,
         Unlit: Unlit1_fs,
      },
      2: {
         Compose: Compose2_fs,
         Depth: Depth2_fs,
         Gouraud: Gouraud2_fs,
         LineTransform: LineTransform2_fs,
         PBR: PBR2_fs,
         Phong: Phong2_fs,
         Pointing: Pointing2_fs,
         Unlit: Unlit2_fs,
      },
   },
};

const ShaderRegistry_default_ = ShaderRegistry;
;

x_ite_Namespace .add ("ShaderRegistry", "x_ite/Browser/Shaders/ShaderRegistry", ShaderRegistry_default_);
/* harmony default export */ const Shaders_ShaderRegistry = (ShaderRegistry_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Shaders/ShaderCompiler.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



const include = /^\s*#pragma\s+X3D\s+include\s+".*?([^\/]+)\.glsl"\s*$/;

function ShaderCompiler (gl)
{
   this .includes          = Shaders_ShaderRegistry .includes [gl .getVersion ()];
   this .sourceFileNumbers = { };

   for (const [i, name] of Object .getOwnPropertyNames (this .includes) .entries ())
      this .sourceFileNumbers [name] = i + 1;
}

Object .assign (ShaderCompiler .prototype,
{
   getSourceFileName (sourceFileNumber)
   {
      return Object .getOwnPropertyNames (this .includes) [sourceFileNumber - 1];
   },
   process (source, parent = 0)
   {
      const lines = source .split ("\n");

      source = "";

      for (let i = 0, length = lines .length; i < length; ++ i)
      {
         const
            line  = lines [i],
            match = line .match (include);

         if (match)
         {
            source += "#line 1 " + this .sourceFileNumbers [match [1]] + "\n";
            source += this .process (this .includes [match [1]], this .sourceFileNumbers [match [1]]);
            source += "\n";
            source += "#line " + (i + 2) + " " + parent + "\n";
         }
         else
         {
            source += line;
            source += "\n";
         }
      }

      return source;
   },
});

const ShaderCompiler_default_ = ShaderCompiler;
;

x_ite_Namespace .add ("ShaderCompiler", "x_ite/Browser/Shaders/ShaderCompiler", ShaderCompiler_default_);
/* harmony default export */ const Shaders_ShaderCompiler = (ShaderCompiler_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shaders/ShaderPart.js
/* provided dependency */ var ShaderPart_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/











const customOptions = [
   "X3D_GEOMETRY_0D",
   "X3D_GEOMETRY_1D",
   "X3D_GEOMETRY_2D",
   "X3D_GEOMETRY_3D",
   "X3D_FOG",
   "X3D_STYLE_PROPERTIES",
   "X3D_UNLIT_MATERIAL",
   "X3D_MATERIAL",
   "X3D_LIGHTING",
   "X3D_TEXTURE",
   "X3D_MULTI_TEXTURING",
];

function ShaderPart (executionContext)
{
   Core_X3DNode      .call (this, executionContext);
   Networking_X3DUrlObject .call (this, executionContext);

   this .addType (Base_X3DConstants .ShaderPart);

   this .options = [ ];
}

Object .assign (Object .setPrototypeOf (ShaderPart .prototype, Core_X3DNode .prototype),
   Networking_X3DUrlObject .prototype,
{
   initialize ()
   {
      Core_X3DNode      .prototype .initialize .call (this);
      Networking_X3DUrlObject .prototype .initialize .call (this);

      if (!this .isPrivate ())
         this .options = customOptions .slice ();

      this ._type .addInterest ("set_type__", this);

      this .requestImmediateLoad () .catch (Function .prototype);
   },
   set_type__ ()
   {
      this .setLoadState (Base_X3DConstants .NOT_STARTED_STATE);

      this .requestImmediateLoad () .catch (Function .prototype);
   },
   getSourceText ()
   {
      return this ._url;
   },
   getOptions ()
   {
      return this .options;
   },
   setOptions (value)
   {
      this .options = value;
   },
   getShader ()
   {
      return this .shader;
   },
   getShaderType: (() =>
   {
      const shaderTypes = new Map ([
         ["VERTEX",          "VERTEX_SHADER"],
         ["TESS_CONTROL",    "TESS_CONTROL_SHADER"],
         ["TESS_EVALUATION", "TESS_EVALUATION_SHADER"],
         ["GEOMETRY",        "GEOMETRY_SHADER"],
         ["FRAGMENT",        "FRAGMENT_SHADER"],
         ["COMPUTE",         "COMPUTE_SHADER"],
      ]);

      return function ()
      {
         return shaderTypes .get (this ._type .getValue ()) || "VERTEX_SHADER";
      };
   })(),
   unloadData ()
   {
      this .valid = false;
   },
   loadData ()
   {
      new InputOutput_FileLoader (this) .loadDocument (this ._url,
      function (data, url)
      {
         if (data === null)
         {
            // No URL could be loaded.
            this .setLoadState (Base_X3DConstants .FAILED_STATE);
         }
         else
         {
            const
               browser        = this .getBrowser (),
               gl             = browser .getContext (),
               type           = this .getShaderType (),
               options        = ["X3D_" + type] .concat (this .options),
               shaderCompiler = new Shaders_ShaderCompiler (gl),
               source         = Shaders_ShaderSource .getSource (gl, browser, shaderCompiler .process (ShaderPart_$.decodeText (data)), options),
               shader         = gl .createShader (gl [type]);

            gl .deleteShader (this .shader);

            this .shader = shader;

            gl .shaderSource (shader, source);
            gl .compileShader (shader);

            if (!gl .getShaderParameter (shader, gl .COMPILE_STATUS))
            {
               const
                  typeName = this .getTypeName (),
                  name     = this .getName (),
                  log      = gl .getShaderInfoLog (shader),
                  match    = log .match (/(\d+):(\d+)/);

               if (match)
               {
                  const fileName = shaderCompiler .getSourceFileName (match [1]) || url || this .getExecutionContext () .getWorldURL ();

                  throw new Error ("Error in " + typeName + " '" + name + "' in URL '" + fileName + "', line " + match [2] + ", " + log);
               }
               else
               {
                  const fileName = url || this .getExecutionContext () .getWorldURL ();

                  throw new Error ("Error in " + typeName + " '" + name + "' in URL '" + fileName + "', " + log);
               }
            }

            this .setLoadState (Base_X3DConstants .COMPLETE_STATE);
         }
      }
      .bind (this));
   },
   dispose ()
   {
      Networking_X3DUrlObject .prototype .dispose .call (this);
      Core_X3DNode      .prototype .dispose .call (this);
   },
});

Object .defineProperties (ShaderPart,
{
   typeName:
   {
      value: "ShaderPart",
      enumerable: true,
   },
   componentName:
   {
      value: "Shaders",
      enumerable: true,
   },
   containerField:
   {
      value: "parts",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "description",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "type",                 new x_ite_Fields .SFString ("VERTEX")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "load",                 new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "url",                  new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "autoRefresh",          new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "autoRefreshTimeLimit", new x_ite_Fields .SFTime (3600)),
      ]),
      enumerable: true,
   },
});

const ShaderPart_default_ = ShaderPart;
;

x_ite_Namespace .add ("ShaderPart", "x_ite/Components/Shaders/ShaderPart", ShaderPart_default_);
/* harmony default export */ const Shaders_ShaderPart = (ShaderPart_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shaders/ShaderProgram.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









function ShaderProgram (executionContext)
{
   Core_X3DNode                     .call (this, executionContext);
   Networking_X3DUrlObject                .call (this, executionContext);
   Shaders_X3DProgrammableShaderObject .call (this, executionContext);

   this .addType (Base_X3DConstants .ShaderProgram);
}

Object .assign (Object .setPrototypeOf (ShaderProgram .prototype, Core_X3DNode .prototype),
   Networking_X3DUrlObject .prototype,
   Shaders_X3DProgrammableShaderObject .prototype,
{
   getSourceText ()
   {
      return this ._url;
   },
   requestImmediateLoad (cache = true)
   { },
   initialize ()
   {
      Core_X3DNode                     .prototype .initialize .call (this);
      Networking_X3DUrlObject                .prototype .initialize .call (this);
      Shaders_X3DProgrammableShaderObject .prototype .initialize .call (this);
   },
   dispose ()
   {
      Shaders_X3DProgrammableShaderObject .prototype .dispose .call (this);
      Networking_X3DUrlObject                .prototype .dispose .call (this);
      Core_X3DNode                     .prototype .dispose .call (this);
   },
});

Object .defineProperties (ShaderProgram,
{
   typeName:
   {
      value: "ShaderProgram",
      enumerable: true,
   },
   componentName:
   {
      value: "Shaders",
      enumerable: true,
   },
   containerField:
   {
      value: "programs",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "description",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "type",                 new x_ite_Fields .SFString ("VERTEX")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "load",                 new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "url",                  new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "autoRefresh",          new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "autoRefreshTimeLimit", new x_ite_Fields .SFTime (3600)),
      ]),
      enumerable: true,
   },
});

const ShaderProgram_default_ = ShaderProgram;
;

x_ite_Namespace .add ("ShaderProgram", "x_ite/Components/Shaders/ShaderProgram", ShaderProgram_default_);
/* harmony default export */ const Shaders_ShaderProgram = (ShaderProgram_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shaders.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/













const Shaders_default_ = {
   name: "Shaders",
   concreteNodes:
   [
      Shaders_ComposedShader,
      Shaders_FloatVertexAttribute,
      Shaders_Matrix3VertexAttribute,
      Shaders_Matrix4VertexAttribute,
      Shaders_PackagedShader,
      Shaders_ProgramShader,
      Shaders_ShaderPart,
      Shaders_ShaderProgram,
   ],
   abstractNodes:
   [
      Shaders_X3DProgrammableShaderObject,
      Shaders_X3DShaderNode,
      Shaders_X3DVertexAttributeNode,
   ],
};
;

x_ite_Namespace .add ("Shaders", "x_ite/Components/Shaders", Shaders_default_);
/* harmony default export */ const Shaders = (Shaders_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shape/AcousticProperties.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function AcousticProperties (executionContext)
{
   Shape_X3DAppearanceChildNode .call (this, executionContext);

   this .addType (Base_X3DConstants .AcousticProperties);
}

Object .setPrototypeOf (AcousticProperties .prototype, Shape_X3DAppearanceChildNode .prototype);

Object .defineProperties (AcousticProperties,
{
   typeName:
   {
      value: "AcousticProperties",
      enumerable: true,
   },
   componentName:
   {
      value: "Shape",
      enumerable: true,
   },
   containerField:
   {
      value: "acousticProperties",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",   new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",    new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "absorption", new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "refraction", new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "diffuse",    new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "specular",   new x_ite_Fields .SFFloat ()),
      ]),
      enumerable: true,
   },
});

const AcousticProperties_default_ = AcousticProperties;
;

x_ite_Namespace .add ("AcousticProperties", "x_ite/Components/Shape/AcousticProperties", AcousticProperties_default_);
/* harmony default export */ const Shape_AcousticProperties = (AcousticProperties_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shape/X3DAppearanceNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function X3DAppearanceNode (executionContext)
{
   Core_X3DNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DAppearanceNode);

   this .addChildObjects (Base_X3DConstants .outputOnly, "transparent", new x_ite_Fields .SFBool ());
}

Object .assign (Object .setPrototypeOf (X3DAppearanceNode .prototype, Core_X3DNode .prototype),
{
   setTransparent (value)
   {
      if (value !== this ._transparent .getValue ())
         this ._transparent = value;
   },
   isTransparent ()
   {
      return this ._transparent .getValue ();
   },
});

Object .defineProperties (X3DAppearanceNode,
{
   typeName:
   {
      value: "X3DAppearanceNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Shape",
      enumerable: true,
   },
});

const X3DAppearanceNode_default_ = X3DAppearanceNode;
;

x_ite_Namespace .add ("X3DAppearanceNode", "x_ite/Components/Shape/X3DAppearanceNode", X3DAppearanceNode_default_);
/* harmony default export */ const Shape_X3DAppearanceNode = (X3DAppearanceNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shape/Appearance.js
/* provided dependency */ var Appearance_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










function Appearance (executionContext)
{
   Shape_X3DAppearanceNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Appearance);

   this .stylePropertiesNode     = [ ];
   this .textureTransformMapping = new Map ();
   this .textureBits             = new Utility_BitSet ();
   this .shaderNodes             = [ ];
}

Object .assign (Object .setPrototypeOf (Appearance .prototype, Shape_X3DAppearanceNode .prototype),
{
   initialize ()
   {
      Shape_X3DAppearanceNode .prototype .initialize .call (this);

      const browser = this .getBrowser ();

      browser .getRenderingProperties () ._ContentScale .addInterest ("set_contentScale__", this);

      this ._alphaMode  		.addInterest ("set_alphaMode__",        this);
      this ._alphaCutoff  		.addInterest ("set_alphaCutoff__",      this);
      this ._pointProperties  .addInterest ("set_pointProperties__",  this);
      this ._lineProperties   .addInterest ("set_lineProperties__",   this);
      this ._fillProperties   .addInterest ("set_fillProperties__",   this);
      this ._material         .addInterest ("set_material__",         this);
      this ._backMaterial     .addInterest ("set_backMaterial__",     this);
      this ._texture          .addInterest ("set_texture__",          this);
      this ._textureTransform .addInterest ("set_textureTransform__", this);
      this ._shaders          .addInterest ("set_shaders__",          this);
      this ._blendMode        .addInterest ("set_blendMode__",        this);

      this ._alphaMode      .addInterest ("set_transparent__", this);
      this ._fillProperties .addInterest ("set_transparent__", this);
      this ._material       .addInterest ("set_transparent__", this);
      this ._texture        .addInterest ("set_transparent__", this);
      this ._blendMode      .addInterest ("set_transparent__", this);

      this .set_alphaMode__ ();
      this .set_pointProperties__ ();
      this .set_lineProperties__ ();
      this .set_fillProperties__ ();
      this .set_material__ ();
      this .set_backMaterial__ ();
      this .set_texture__ ();
      this .set_textureTransform__ ();
      this .set_shaders__ ();
      this .set_blendMode__ ();
      this .set_transparent__ ();
   },
   getAlphaMode ()
   {
      return this .alphaMode;
   },
   getNormalizedAlphaMode (transparent)
   {
      return this .alphaMode || (transparent ? Shape_AlphaMode .BLEND : Shape_AlphaMode .OPAQUE);
   },
   getAlphaCutoff ()
   {
      return this .alphaCutoff;
   },
   getStyleProperties (geometryType)
   {
      return this .stylePropertiesNode [geometryType];
   },
   getPointProperties ()
   {
      return this .stylePropertiesNode [0];
   },
   getLineProperties ()
   {
      return this .stylePropertiesNode [1];
   },
   getFillProperties ()
   {
      return this .stylePropertiesNode [2];
   },
   getMaterial ()
   {
      return this .materialNode;
   },
   getBackMaterial ()
   {
      return this .backMaterialNode;
   },
   getTexture ()
   {
      return this .textureNode;
   },
   getTextureBits ()
   {
      return this .textureBits;
   },
   updateTextureBits ()
   {
      this .textureBits .clear ();
      this .textureNode .updateTextureBits (this .textureBits);
   },
   getTextureTransform ()
   {
      return this .textureTransformNode;
   },
   getTextureTransformMapping ()
   {
      return this .textureTransformMapping;
   },
   getShader (geometryContext, renderContext)
   {
      return this .materialNode .getShader (geometryContext, renderContext);
   },
   getBackShader (geometryContext, renderContext)
   {
      return this .backMaterialNode .getShader (geometryContext, renderContext);
   },
   getBlendMode ()
   {
      return this .blendModeNode;
   },
   set_contentScale__ ()
   {
      this .set_pointProperties__ ();
      this .set_applied__ ();
   },
   set_alphaMode__ ()
   {
      this .alphaMode = Appearance_$.enum (Shape_AlphaMode, this ._alphaMode .getValue (), Shape_AlphaMode .AUTO);

      this .set_alphaCutoff__ ();
   },
   set_alphaCutoff__ ()
   {
      this .alphaCutoff = this .alphaMode === Shape_AlphaMode .MASK ? this ._alphaCutoff .getValue () : 0;
   },
   set_pointProperties__ ()
   {
      this .stylePropertiesNode [0] = Base_X3DCast (Base_X3DConstants .PointProperties, this ._pointProperties);

      if (!this .stylePropertiesNode [0])
      {
         const browser = this .getBrowser ();

         if (browser .getRenderingProperty ("ContentScale") !== 1)
            this .stylePropertiesNode [0] = browser .getDefaultPointProperties ();
      }
   },
   set_lineProperties__ ()
   {
      if (this .linePropertiesNode)
         this .linePropertiesNode ._applied .removeInterest ("set_applied__", this);

      this .linePropertiesNode = Base_X3DCast (Base_X3DConstants .LineProperties, this ._lineProperties);

      if (this .linePropertiesNode)
         this .linePropertiesNode ._applied .addInterest ("set_applied__", this);

      this .set_applied__ ();
   },
   set_applied__ ()
   {
      if (this .linePropertiesNode && this .linePropertiesNode ._applied .getValue ())
      {
         this .stylePropertiesNode [1] = this .linePropertiesNode;
      }
      else
      {
         const browser = this .getBrowser ();

         if (browser .getRenderingProperty ("ContentScale") !== 1)
            this .stylePropertiesNode [1] = browser .getDefaultLineProperties ();
         else
            this .stylePropertiesNode [1] = null;
      }
   },
   set_fillProperties__ ()
   {
      if (this .stylePropertiesNode [2])
         this .stylePropertiesNode [2] ._transparent .removeInterest ("set_transparent__", this);

      this .stylePropertiesNode [2] = Base_X3DCast (Base_X3DConstants .FillProperties, this ._fillProperties);

      if (this .stylePropertiesNode [2])
         this .stylePropertiesNode [2] ._transparent .addInterest ("set_transparent__", this);

      this .stylePropertiesNode [3] = this .stylePropertiesNode [2];
   },
   set_material__ ()
   {
      if (this .materialNode)
         this .materialNode ._transparent .removeInterest ("set_transparent__", this);

      this .materialNode = Base_X3DCast (Base_X3DConstants .X3DMaterialNode, this ._material);

      if (!this .materialNode)
         this .materialNode = this .getBrowser () .getDefaultMaterial ();

      if (this .materialNode)
         this .materialNode ._transparent .addInterest ("set_transparent__", this);

      // Depreciated TwoSidedMaterial handling.

      if (Base_X3DCast (Base_X3DConstants .TwoSidedMaterial, this .materialNode))
         this .set_backMaterial__ ();
   },
   set_backMaterial__ ()
   {
      if (this .backMaterialNode)
         this .backMaterialNode ._transparent .removeInterest ("set_transparent__", this);

      this .backMaterialNode = Base_X3DCast (Base_X3DConstants .X3DOneSidedMaterialNode, this ._backMaterial);

      if (this .backMaterialNode)
         this .backMaterialNode ._transparent .addInterest ("set_transparent__", this);

      // Depreciated TwoSidedMaterial handling.

      if (!this .backMaterialNode && Base_X3DCast (Base_X3DConstants .TwoSidedMaterial, this .materialNode))
         this .backMaterialNode = this .materialNode;
   },
   set_texture__ ()
   {
      if (this .textureNode)
      {
         this .textureNode .removeInterest ("updateTextureBits", this);
         this .textureNode ._transparent .removeInterest ("set_transparent__", this);
      }

      this .textureNode = Base_X3DCast (Base_X3DConstants .X3DTextureNode, this ._texture);

      if (this .textureNode)
      {
         this .textureNode .addInterest ("updateTextureBits", this);
         this .textureNode ._transparent .addInterest ("set_transparent__", this);

         this .updateTextureBits ();
      }
      else
      {
         this .textureBits .clear ();
      }
   },
   set_textureTransform__ ()
   {
      if (this .textureTransformNode)
         this .textureTransformNode .removeInterest ("updateTextureTransformMapping", this);

      this .textureTransformNode = Base_X3DCast (Base_X3DConstants .X3DTextureTransformNode, this ._textureTransform);

      if (!this .textureTransformNode)
         this .textureTransformNode = this .getBrowser () .getDefaultTextureTransform ();

      this .textureTransformNode .addInterest ("updateTextureTransformMapping", this);

      this .updateTextureTransformMapping ();
   },
   updateTextureTransformMapping ()
   {
      this .textureTransformMapping .clear ();

      this .textureTransformNode .getTextureTransformMapping (this .textureTransformMapping);
   },
   set_shaders__ ()
   {
      const shaderNodes = this .shaderNodes;

      for (const shaderNode of shaderNodes)
         shaderNode ._isValid .removeInterest ("set_shader__", this);

      shaderNodes .length = 0;

      for (const node of this ._shaders)
      {
         const shaderNode = Base_X3DCast (Base_X3DConstants .X3DShaderNode, node);

         if (shaderNode)
            shaderNodes .push (shaderNode);
      }

      for (const shaderNode of shaderNodes)
         shaderNode ._isValid .addInterest ("set_shader__", this);

      this .set_shader__ ();
   },
   set_shader__: (() =>
   {
      function getShader ()
      {
         return this .shaderNode;
      }

      return function ()
      {
         const shaderNodes = this .shaderNodes;

         if (this .shaderNode)
            this .shaderNode .deselect ();

         this .shaderNode = null;

         for (const shaderNode of shaderNodes)
         {
            if (shaderNode ._isValid .getValue ())
            {
               this .shaderNode = shaderNode;
               break;
            }
         }

         if (this .shaderNode)
         {
            this .shaderNode .select ();

            this .getShader     = getShader;
            this .getBackShader = getShader;
         }
         else
         {
            delete this .getShader;
            delete this .getBackShader;
         }
      };
   })(),
   set_blendMode__ ()
   {
      this .blendModeNode = Base_X3DCast (Base_X3DConstants .BlendMode, this ._blendMode);
   },
   set_transparent__ ()
   {
      switch (this .alphaMode)
      {
         case Shape_AlphaMode .AUTO:
            this .setTransparent (!!(this .stylePropertiesNode [3] ?.isTransparent () ||
                                     this .materialNode ?.isTransparent () ||
                                     this .backMaterialNode ?.isTransparent () ||
                                     this .textureNode ?.isTransparent () ||
                                     this .blendModeNode));
            break;
         case Shape_AlphaMode .OPAQUE:
            this .setTransparent (false);
            break;
         case Shape_AlphaMode .MASK:
            // Alpha testing using alphaCutoff.
            this .setTransparent (false);
            break;
         case Shape_AlphaMode .BLEND:
            this .setTransparent (true);
            break;
      }
   },
   traverse (type, renderObject)
   {
      if (this .textureNode)
         this .textureNode .traverse (type, renderObject);
   },
});

Object .defineProperties (Appearance,
{
   typeName:
   {
      value: "Appearance",
      enumerable: true,
   },
   componentName:
   {
      value: "Shape",
      enumerable: true,
   },
   containerField:
   {
      value: "appearance",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "acousticProperties", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "alphaMode",          new x_ite_Fields .SFString ("AUTO")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "alphaCutoff",        new x_ite_Fields .SFFloat (0.5)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pointProperties",    new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "lineProperties",     new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "fillProperties",     new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "material",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "backMaterial",       new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "texture",            new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "textureTransform",   new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "shaders",            new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "blendMode",          new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const Appearance_default_ = Appearance;
;

x_ite_Namespace .add ("Appearance", "x_ite/Components/Shape/Appearance", Appearance_default_);
/* harmony default export */ const Shape_Appearance = (Appearance_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shape/FillProperties.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function FillProperties (executionContext)
{
   Shape_X3DAppearanceChildNode .call (this, executionContext);

   this .addType (Base_X3DConstants .FillProperties);

   this .addChildObjects (Base_X3DConstants .outputOnly, "transparent", new x_ite_Fields .SFBool ());

   this .hatchColor = new Float32Array (3);
}

Object .assign (Object .setPrototypeOf (FillProperties .prototype, Shape_X3DAppearanceChildNode .prototype),
{
   initialize ()
   {
      Shape_X3DAppearanceChildNode .prototype .initialize .call (this);

      this ._filled     .addInterest ("set_filled__",     this);
      this ._hatched    .addInterest ("set_hatched__",    this);
      this ._hatchColor .addInterest ("set_hatchColor__", this);
      this ._hatchStyle .addInterest ("set_hatchStyle__", this);

      this .set_filled__ ();
      this .set_hatched__ ();
      this .set_hatchColor__ ();
      this .set_hatchStyle__ ();

      // Preload texture.
      this .getBrowser () .getHatchStyleTexture (this .hatchStyle);
   },
   getStyleKey ()
   {
      return this .hatched ? 2 : 1;
   },
   set_filled__ ()
   {
      this .filled = this ._filled .getValue ();

      this .setTransparent (! this .filled);
   },
   set_hatched__ ()
   {
      this .hatched = this ._hatched .getValue ();
   },
   set_hatchColor__ ()
   {
      this .hatchColor [0] = this ._hatchColor [0];
      this .hatchColor [1] = this ._hatchColor [1];
      this .hatchColor [2] = this ._hatchColor [2];
   },
   set_hatchStyle__ ()
   {
      let hatchStyle = this ._hatchStyle .getValue ();

      if (hatchStyle < 1 || hatchStyle > 19)
         hatchStyle = 1;

      this .hatchStyle = hatchStyle;
   },
   setTransparent (value)
   {
      if (value !== this ._transparent .getValue ())
         this ._transparent = value;
   },
   isTransparent ()
   {
      return this ._transparent .getValue ();
   },
   setShaderUniforms (gl, shaderObject)
   {
      const hatched = this .hatched;

      gl .uniform1i (shaderObject .x3d_FillPropertiesFilled,  this .filled);
      gl .uniform1i (shaderObject .x3d_FillPropertiesHatched, hatched);

      if (hatched)
      {
         const
            browser     = this .getBrowser (),
            texture     = browser .getHatchStyleTexture (this .hatchStyle),
            textureUnit = browser .getTexture2DUnit ();

         gl .uniform3fv (shaderObject .x3d_FillPropertiesHatchColor, this .hatchColor);
         gl .uniform1f  (shaderObject .x3d_FillPropertiesScale,      browser .getRenderingProperty ("ContentScale"));

         gl .activeTexture (gl .TEXTURE0 + textureUnit);
         gl .bindTexture (gl .TEXTURE_2D, texture .getTexture ());
         gl .uniform1i (shaderObject .x3d_FillPropertiesTexture, textureUnit);
      }
   },
});

Object .defineProperties (FillProperties,
{
   typeName:
   {
      value: "FillProperties",
      enumerable: true,
   },
   componentName:
   {
      value: "Shape",
      enumerable: true,
   },
   containerField:
   {
      value: "fillProperties",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",   new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "filled",     new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "hatched",    new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "hatchStyle", new x_ite_Fields .SFInt32 (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "hatchColor", new x_ite_Fields .SFColor (1, 1, 1)),
      ]),
      enumerable: true,
   },
});

const FillProperties_default_ = FillProperties;
;

x_ite_Namespace .add ("FillProperties", "x_ite/Components/Shape/FillProperties", FillProperties_default_);
/* harmony default export */ const Shape_FillProperties = (FillProperties_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shape/LineProperties.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function LineProperties (executionContext)
{
   Shape_X3DAppearanceChildNode .call (this, executionContext);

   this .addType (Base_X3DConstants .LineProperties);
}

Object .assign (Object .setPrototypeOf (LineProperties .prototype, Shape_X3DAppearanceChildNode .prototype),
{
   initialize ()
   {
      Shape_X3DAppearanceChildNode .prototype .initialize .call (this);

      const browser = this .getBrowser ();

      browser .getRenderingProperties () ._ContentScale .addInterest ("set_linewidthScaleFactor__", this);

      this ._applied              .addInterest ("set_applied__",              this);
      this ._linetype             .addInterest ("set_linetype__",             this);
      this ._linewidthScaleFactor .addInterest ("set_linewidthScaleFactor__", this);

      this .set_applied__ ();
      this .set_linetype__ ();
      this .set_linewidthScaleFactor__ ();

      // Preload texture.
      this .getBrowser () .getLinetypeTexture ();
   },
   getStyleKey ()
   {
      return this .applied ? 2 : 1;
   },
   getApplied ()
   {
      return this .applied;
   },
   getLinetype ()
   {
      return this .linetype;
   },
   getLinewidthScaleFactor ()
   {
      return this .linewidthScaleFactor;
   },
   getTransformLines ()
   {
      return this .transformLines;
   },
   set_applied__ ()
   {
      this .applied = this ._applied .getValue ();
   },
   set_linetype__ ()
   {
      let linetype = this ._linetype .getValue ();

      if (linetype < 1 || linetype > 16)
         linetype = 1;

      this .linetype = linetype;
   },
   set_linewidthScaleFactor__ ()
   {
      const
         browser      = this .getBrowser (),
         gl           = browser .getContext (),
         contentScale = browser .getRenderingProperty ("ContentScale");

      this .linewidthScaleFactor = Math .max (1, this ._linewidthScaleFactor .getValue ()) * contentScale;
      this .transformLines       = gl .HAS_FEATURE_TRANSFORMED_LINES && this .linewidthScaleFactor > 1;
   },
   setShaderUniforms (gl, shaderObject)
   {
      const browser = this .getBrowser ();

      if (this .applied)
      {
         const textureUnit = browser .getTexture2DUnit ();

         gl .lineWidth (this .linewidthScaleFactor);
         gl .uniform1i (shaderObject .x3d_LinePropertiesLinetype, this .linetype);
         gl .uniform1f (shaderObject .x3d_LineStippleScale,       browser .getLineStippleScale ());

         gl .activeTexture (gl .TEXTURE0 + textureUnit);
         gl .bindTexture (gl .TEXTURE_2D, browser .getLinetypeTexture () .getTexture ());
         gl .uniform1i (shaderObject .x3d_LinePropertiesTexture, textureUnit);
      }
      else
      {
         gl .lineWidth (browser .getRenderingProperty ("ContentScale"));
         gl .uniform1i (shaderObject .x3d_LinePropertiesLinetype, 16);
         gl .uniform1f (shaderObject .x3d_LineStippleScale,       1);
      }
   },
});

Object .defineProperties (LineProperties,
{
   typeName:
   {
      value: "LineProperties",
      enumerable: true,
   },
   componentName:
   {
      value: "Shape",
      enumerable: true,
   },
   containerField:
   {
      value: "lineProperties",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "applied",              new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "linetype",             new x_ite_Fields .SFInt32 (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "linewidthScaleFactor", new x_ite_Fields .SFFloat ()),
      ]),
      enumerable: true,
   },
});

const LineProperties_default_ = LineProperties;
;

x_ite_Namespace .add ("LineProperties", "x_ite/Components/Shape/LineProperties", LineProperties_default_);
/* harmony default export */ const Shape_LineProperties = (LineProperties_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shape/X3DMaterialNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function X3DMaterialNode (executionContext)
{
   Shape_X3DAppearanceChildNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DMaterialNode);

   this .addChildObjects (Base_X3DConstants .outputOnly, "transparent", new x_ite_Fields .SFBool ());

   this .textureBits = new Utility_BitSet ();
   this .shaderNodes = this .getBrowser () .getShaders ();
}

Object .assign (Object .setPrototypeOf (X3DMaterialNode .prototype, Shape_X3DAppearanceChildNode .prototype),
{
   setTransparent (value)
   {
      if (value !== this ._transparent .getValue ())
         this ._transparent = value;
   },
   isTransparent ()
   {
      return this ._transparent .getValue ();
   },
   getBaseTexture ()
   {
      return null;
   },
   setTexture (index, textureNode)
   {
      const textureType = textureNode ? textureNode .getTextureType () - 1 : 0;

      this .textureBits .set (index * 2 + 0, textureType & 0b01);
      this .textureBits .set (index * 2 + 1, textureType & 0b10);
   },
   getTextureBits ()
   {
      return this .textureBits;
   },
   getShader (geometryContext, renderContext)
   {
      let key = "";

      key += this .textureBits .toString (4);
      key += ".";
      key += geometryContext .geometryKey;

      if (renderContext)
      {
         const { renderObject, transparent, shadows, fogNode, shapeNode, appearanceNode, textureNode, humanoidNode, objectsCount } = renderContext;

         key += appearanceNode .getNormalizedAlphaMode (transparent);
         key += this .getMaterialKey (shadows);
         key += renderObject .getLogarithmicDepthBuffer () ? 1 : 0;
         key += shadows ? 1 : 0;
         key += fogNode ?.getFogType () ?? 0;
         key += shapeNode .getShapeKey ();
         key += appearanceNode .getStyleProperties (geometryContext .geometryType) ?.getStyleKey () ?? 0;
         key += appearanceNode .getTextureTransformMapping () .size || 1;
         key += geometryContext .textureCoordinateMapping .size || 1;
         key += ".";
         key += humanoidNode ?.getHumanoidKey () ?? "";
         key += ".";
         key += objectsCount [0]; // Clip planes
         key += ".";
         key += objectsCount [1]; // Lights
         key += ".";
         key += objectsCount [2]; // Texture projectors
         key += ".";
         key += textureNode ? 1 : appearanceNode .getTextureBits () .toString (4);
      }
      else
      {
         // Rubberband, X3DBackgroundNode

         const { textureNode, objectsCount } = geometryContext;

         key += geometryContext .alphaMode;
         key += this .getMaterialKey (false);
         key += "0000011.0.";
         key += objectsCount [0]; // Clip planes
         key += ".";
         key += objectsCount [1]; // Lights
         key += ".";
         key += objectsCount [2]; // Texture projectors
         key += ".";
         key += textureNode ? 1 : 0;
      }

      return this .shaderNodes .get (key) ?? this .createShader (key, geometryContext, renderContext);
   },
   getShaderOptions (geometryContext, renderContext)
   {
      const
         browser = this .getBrowser (),
         options = [ ];

      options .push (`X3D_GEOMETRY_${geometryContext .geometryType}D`);

      if (geometryContext .hasFogCoords)
         options .push ("X3D_FOG_COORDS");

      if (geometryContext .colorMaterial)
         options .push ("X3D_COLOR_MATERIAL");

      if (geometryContext .hasNormals)
         options .push ("X3D_NORMALS");

      if (renderContext)
      {
         const { renderObject, fogNode, shapeNode, appearanceNode, humanoidNode, objectsCount } = renderContext;

         if (renderObject .getLogarithmicDepthBuffer ())
            options .push ("X3D_LOGARITHMIC_DEPTH_BUFFER");

         switch (appearanceNode .getNormalizedAlphaMode (renderContext .transparent))
         {
            case Shape_AlphaMode .OPAQUE:
            {
               options .push ("X3D_ALPHA_MODE_OPAQUE");
               break;
            }
            case Shape_AlphaMode .MASK:
            {
               options .push ("X3D_ALPHA_MODE_MASK");
               break;
            }
            case Shape_AlphaMode .BLEND:
            {
               options .push ("X3D_ALPHA_MODE_BLEND");

               if (browser .getBrowserOption ("OrderIndependentTransparency"))
                  options .push ("X3D_ORDER_INDEPENDENT_TRANSPARENCY");

               break;
            }
         }

         if (renderContext .shadows)
            options .push ("X3D_SHADOWS", "X3D_PCF_FILTERING");

         switch (fogNode ?.getFogType ())
         {
            case 1:
               options .push ("X3D_FOG", "X3D_FOG_LINEAR");
               break;
            case 2:
               options .push ("X3D_FOG", "X3D_FOG_EXPONENTIAL");
               break;
         }

         if (humanoidNode)
         {
            options .push ("X3D_SKINNING");
            options .push (`X3D_NUM_JOINT_SETS ${humanoidNode .getNumJoints () / 4}`);
            options .push (`X3D_NUM_DISPLACEMENTS ${humanoidNode .getNumDisplacements ()}`);
         }

         if (objectsCount [0])
         {
            options .push ("X3D_CLIP_PLANES")
            options .push (`X3D_NUM_CLIP_PLANES ${Math .min (objectsCount [0], browser .getMaxClipPlanes ())}`);
         }

         if (objectsCount [1])
         {
            options .push ("X3D_LIGHTING")
            options .push (`X3D_NUM_LIGHTS ${Math .min (objectsCount [1], browser .getMaxLights ())}`);
         }

         if (objectsCount [2])
         {
            options .push ("X3D_PROJECTIVE_TEXTURE_MAPPING")
            options .push (`X3D_NUM_TEXTURE_PROJECTORS ${Math .min (objectsCount [2], browser .getMaxTextures ())}`);
         }

         if (appearanceNode .getStyleProperties (geometryContext .geometryType))
         {
            options .push ("X3D_STYLE_PROPERTIES");

            if (appearanceNode .getStyleProperties (geometryContext .geometryType) .getStyleKey () > 1)
               options .push ("X3D_STYLE_PROPERTIES_TEXTURE");
         }

         if (+this .textureBits)
            options .push ("X3D_MATERIAL_TEXTURES");

         if (renderContext .textureNode)
         {
            // ScreenText

            options .push ("X3D_TEXTURE",
                           "X3D_NUM_TEXTURES 1",
                           "X3D_NUM_TEXTURE_TRANSFORMS 1",
                           "X3D_NUM_TEXTURE_COORDINATES 1",
                           "X3D_TEXTURE0_2D");
         }
         else
         {
            if (+appearanceNode .getTextureBits () && !this .getBaseTexture ())
            {
               const textureNode = appearanceNode .getTexture ();

               options .push ("X3D_TEXTURE");
               options .push (`X3D_NUM_TEXTURES ${textureNode .getCount ()}`);

               if (textureNode .getType () .includes (Base_X3DConstants .MultiTexture))
                  options .push ("X3D_MULTI_TEXTURING");

               textureNode .getShaderOptions (options);
            }

            options .push (`X3D_NUM_TEXTURE_TRANSFORMS ${appearanceNode .getTextureTransformMapping () .size || 1}`);
            options .push (`X3D_NUM_TEXTURE_COORDINATES ${geometryContext .textureCoordinateMapping .size || 1}`);
         }

         switch (shapeNode .getShapeKey ())
         {
            case 1:
               options .push ("X3D_PARTICLE_SYSTEM");
               break;
            case 2:
               options .push ("X3D_PARTICLE_SYSTEM", "X3D_TEX_COORD_RAMP");
               break;
         }
      }
      else
      {
         const { alphaMode, textureNode, objectsCount } = geometryContext;

         switch (alphaMode)
         {
            case Shape_AlphaMode .OPAQUE:
            {
               options .push ("X3D_ALPHA_MODE_OPAQUE");
               break;
            }
            case Shape_AlphaMode .MASK:
            {
               options .push ("X3D_ALPHA_MODE_MASK");
               break;
            }
            case Shape_AlphaMode .BLEND:
            {
               options .push ("X3D_ALPHA_MODE_BLEND");

               if (browser .getBrowserOption ("OrderIndependentTransparency"))
                  options .push ("X3D_ORDER_INDEPENDENT_TRANSPARENCY");

               break;
            }
         }

         if (objectsCount [0])
         {
            options .push ("X3D_CLIP_PLANES")
            options .push (`X3D_NUM_CLIP_PLANES ${Math .min (objectsCount [0], browser .getMaxClipPlanes ())}`);
         }

         if (objectsCount [1])
         {
            options .push ("X3D_LIGHTING")
            options .push (`X3D_NUM_LIGHTS ${Math .min (objectsCount [1], browser .getMaxLights ())}`);
         }

         if (objectsCount [2])
         {
            options .push ("X3D_PROJECTIVE_TEXTURE_MAPPING")
            options .push (`X3D_NUM_TEXTURE_PROJECTORS ${Math .min (objectsCount [2], browser .getMaxTextures ())}`);
         }

         if (textureNode)
         {
            // X3DBackgroundNode textures

            options .push ("X3D_TEXTURE",
                           "X3D_NUM_TEXTURES 1",
                           "X3D_NUM_TEXTURE_TRANSFORMS 1",
                           "X3D_NUM_TEXTURE_COORDINATES 1",
                           "X3D_TEXTURE0_2D");
         }
      }

      return options;
   },
});

Object .defineProperties (X3DMaterialNode,
{
   typeName:
   {
      value: "X3DMaterialNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Shape",
      enumerable: true,
   },
});

const X3DMaterialNode_default_ = X3DMaterialNode;
;

x_ite_Namespace .add ("X3DMaterialNode", "x_ite/Components/Shape/X3DMaterialNode", X3DMaterialNode_default_);
/* harmony default export */ const Shape_X3DMaterialNode = (X3DMaterialNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shape/X3DOneSidedMaterialNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function X3DOneSidedMaterialNode (executionContext)
{
   Shape_X3DMaterialNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DOneSidedMaterialNode);

   this .emissiveColor = new Float32Array (3);
}

Object .assign (Object .setPrototypeOf (X3DOneSidedMaterialNode .prototype, Shape_X3DMaterialNode .prototype),
{
   initialize ()
   {
      Shape_X3DMaterialNode .prototype .initialize .call (this);

      this ._emissiveColor    .addInterest ("set_emissiveColor__",   this);
      this ._emissiveTexture  .addInterest ("set_emissiveTexture__", this);
      this ._normalTexture    .addInterest ("set_normalTexture__",   this);
      this ._transparency     .addInterest ("set_transparency__",    this);
      this ._transparency     .addInterest ("set_transparent__",     this);

      this .set_emissiveColor__ ();
      this .set_emissiveTexture__ ();
      this .set_normalTexture__ ();
      this .set_transparency__ ();
   },
   set_emissiveColor__ ()
   {
      //We cannot use this in Windows Edge:
      //this .emissiveColor .set (this ._emissiveColor .getValue ());

      const
         emissiveColor   = this .emissiveColor,
         emissiveColor_  = this ._emissiveColor .getValue ();

      emissiveColor [0] = emissiveColor_ .r;
      emissiveColor [1] = emissiveColor_ .g;
      emissiveColor [2] = emissiveColor_ .b;
   },
   set_emissiveTexture__ ()
   {
      this .emissiveTextureNode = Base_X3DCast (Base_X3DConstants .X3DSingleTextureNode, this ._emissiveTexture);

      this .setTexture (this .getTextureIndices () .EMISSIVE_TEXTURE, this .emissiveTextureNode);
   },
   set_normalTexture__ ()
   {
      this .normalTextureNode = Base_X3DCast (Base_X3DConstants .X3DSingleTextureNode, this ._normalTexture);

      this .setTexture (this .getTextureIndices () .NORMAL_TEXTURE, this .normalTextureNode);
   },
   set_transparency__ ()
   {
      this .transparency = Math_Algorithm .clamp (this ._transparency .getValue (), 0, 1);
   },
   set_transparent__ ()
   {
      this .setTransparent (!! this .transparency);
   },
   getBaseTexture ()
   {
      return this .getEmissiveTexture ();
   },
   getEmissiveTexture ()
   {
      return this .emissiveTextureNode;
   },
   getNormalTexture ()
   {
      return this .normalTextureNode;
   },
   getTransparency ()
   {
      return this .transparency;
   },
   getTextureIndices: (() =>
   {
      let i = 0;

      const textureIndices = {
         EMISSIVE_TEXTURE: i ++,
         NORMAL_TEXTURE: i ++,
      };

      return function ()
      {
         return textureIndices;
      };
   })(),
   getShaderOptions (geometryContext, renderContext)
   {
      const options = Shape_X3DMaterialNode .prototype .getShaderOptions .call (this, geometryContext, renderContext);

      if (+this .getTextureBits ())
      {
         if (this .getEmissiveTexture ())
            options .push ("X3D_EMISSIVE_TEXTURE", `X3D_EMISSIVE_TEXTURE_${this .getEmissiveTexture () .getTextureTypeString ()}`);

         if (this .getNormalTexture ())
            options .push ("X3D_NORMAL_TEXTURE", `X3D_NORMAL_TEXTURE_${this .getNormalTexture () .getTextureTypeString ()}`);
      }

      return options;
   },
   setShaderUniforms (gl, shaderObject, renderObject, textureTransformMapping, textureCoordinateMapping)
   {
      gl .uniform3fv (shaderObject .x3d_EmissiveColor, this .emissiveColor);
      gl .uniform1f  (shaderObject .x3d_Transparency,  this .transparency);

      if (+this .getTextureBits ())
      {
         // Emissive parameters

         if (this .emissiveTextureNode)
         {
            const
               emissiveTextureMapping = this ._emissiveTextureMapping .getValue (),
               emissiveTexture        = shaderObject .x3d_EmissiveTexture;

            this .emissiveTextureNode .setShaderUniforms (gl, shaderObject, renderObject, emissiveTexture);

            gl .uniform1i (emissiveTexture .textureTransformMapping,  textureTransformMapping  .get (emissiveTextureMapping) ?? 0);
            gl .uniform1i (emissiveTexture .textureCoordinateMapping, textureCoordinateMapping .get (emissiveTextureMapping) ?? 0);
         }

         // Normal parameters

         if (this .normalTextureNode)
         {
            const
               normalTextureMapping = this ._normalTextureMapping .getValue (),
               normalTexture        = shaderObject .x3d_NormalTexture;

            gl .uniform1f (shaderObject .x3d_NormalScale, Math .max (this ._normalScale .getValue (), 0));

            this .normalTextureNode .setShaderUniforms (gl, shaderObject, renderObject, normalTexture);

            gl .uniform1i (normalTexture .textureTransformMapping,  textureTransformMapping  .get (normalTextureMapping) ?? 0);
            gl .uniform1i (normalTexture .textureCoordinateMapping, textureCoordinateMapping .get (normalTextureMapping) ?? 0);
         }
      }
   },
});

Object .defineProperties (X3DOneSidedMaterialNode,
{
   typeName:
   {
      value: "X3DOneSidedMaterialNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Shape",
      enumerable: true,
   },
});

const X3DOneSidedMaterialNode_default_ = X3DOneSidedMaterialNode;
;

x_ite_Namespace .add ("X3DOneSidedMaterialNode", "x_ite/Components/Shape/X3DOneSidedMaterialNode", X3DOneSidedMaterialNode_default_);
/* harmony default export */ const Shape_X3DOneSidedMaterialNode = (X3DOneSidedMaterialNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shape/Material.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










function Material (executionContext)
{
   Shape_X3DOneSidedMaterialNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Material);

   if (executionContext .getSpecificationVersion () <= 3.3)
      this .getMaterialKey = getMaterialKey;

   this .diffuseColor  = new Float32Array (3);
   this .specularColor = new Float32Array (3);
}

Object .assign (Object .setPrototypeOf (Material .prototype, Shape_X3DOneSidedMaterialNode .prototype),
{
   initialize ()
   {
      Shape_X3DOneSidedMaterialNode .prototype .initialize .call (this);

      this ._ambientIntensity  .addInterest ("set_ambientIntensity__",  this);
      this ._ambientTexture    .addInterest ("set_ambientTexture__",    this);
      this ._diffuseColor      .addInterest ("set_diffuseColor__",      this);
      this ._diffuseTexture    .addInterest ("set_diffuseTexture__",    this);
      this ._specularColor     .addInterest ("set_specularColor__",     this);
      this ._specularTexture   .addInterest ("set_specularTexture__",   this);
      this ._shininess         .addInterest ("set_shininess__",         this);
      this ._shininessTexture  .addInterest ("set_shininessTexture__",  this);
      this ._occlusionStrength .addInterest ("set_occlusionStrength__", this);
      this ._occlusionTexture  .addInterest ("set_occlusionTexture__",  this);

      this .set_ambientIntensity__ ();
      this .set_ambientTexture__ ();
      this .set_diffuseColor__ ();
      this .set_diffuseTexture__ ();
      this .set_specularColor__ ();
      this .set_specularTexture__ ();
      this .set_shininess__ ();
      this .set_shininessTexture__ ();
      this .set_occlusionStrength__ ();
      this .set_occlusionTexture__ ();
      this .set_transparent__ ();
   },
   set_ambientIntensity__ ()
   {
      this .ambientIntensity = Math_Algorithm .clamp (this ._ambientIntensity .getValue (), 0, 1);
   },
   set_ambientTexture__ ()
   {
      this .ambientTextureNode = Base_X3DCast (Base_X3DConstants .X3DSingleTextureNode, this ._ambientTexture);

      this .setTexture (this .getTextureIndices () .AMBIENT_TEXTURE, this .ambientTextureNode);
   },
   set_diffuseColor__ ()
   {
      //We cannot use this in Windows Edge:
      //this .diffuseColor .set (this ._diffuseColor .getValue ());

      const
         diffuseColor  = this .diffuseColor,
         diffuseColor_ = this ._diffuseColor .getValue ();

      diffuseColor [0] = diffuseColor_ .r;
      diffuseColor [1] = diffuseColor_ .g;
      diffuseColor [2] = diffuseColor_ .b;
   },
   set_diffuseTexture__ ()
   {
      if (this .diffuseTextureNode)
         this .diffuseTextureNode ._transparent .removeInterest ("set_transparent__", this);

      this .diffuseTextureNode = Base_X3DCast (Base_X3DConstants .X3DSingleTextureNode, this ._diffuseTexture);

      if (this .diffuseTextureNode)
         this .diffuseTextureNode ._transparent .addInterest ("set_transparent__", this);

      this .setTexture (this .getTextureIndices () .DIFFUSE_TEXTURE, this .diffuseTextureNode);
   },
   set_specularColor__ ()
   {
      //We cannot use this in Windows Edge:
      //this .specularColor .set (this ._specularColor .getValue ());

      const
         specularColor  = this .specularColor,
         specularColor_ = this ._specularColor .getValue ();

      specularColor [0] = specularColor_ .r;
      specularColor [1] = specularColor_ .g;
      specularColor [2] = specularColor_ .b;
   },
   set_specularTexture__ ()
   {
      this .specularTextureNode = Base_X3DCast (Base_X3DConstants .X3DSingleTextureNode, this ._specularTexture);

      this .setTexture (this .getTextureIndices () .SPECULAR_TEXTURE, this .specularTextureNode);
   },
   set_shininess__ ()
   {
      this .shininess = Math_Algorithm .clamp (this ._shininess .getValue (), 0, 1);
   },
   set_shininessTexture__ ()
   {
      this .shininessTextureNode = Base_X3DCast (Base_X3DConstants .X3DSingleTextureNode, this ._shininessTexture);

      this .setTexture (this .getTextureIndices () .SHININESS_TEXTURE, this .shininessTextureNode);
   },
   set_occlusionStrength__ ()
   {
      this .occlusionStrength = Math_Algorithm .clamp (this ._occlusionStrength .getValue (), 0, 1);
   },
   set_occlusionTexture__ ()
   {
      this .occlusionTextureNode = Base_X3DCast (Base_X3DConstants .X3DSingleTextureNode, this ._occlusionTexture);

      this .setTexture (this .getTextureIndices () .OCCLUSION_TEXTURE, this .occlusionTextureNode);
   },
   set_transparent__ ()
   {
      this .setTransparent (!!(this .getTransparency () || this .diffuseTextureNode ?.isTransparent ()));
   },
   getBaseTexture ()
   {
      return this .diffuseTexture;
   },
   getTextureIndices: (() =>
   {
      let i = 0;

      const textureIndices = {
         EMISSIVE_TEXTURE: i ++,
         NORMAL_TEXTURE: i ++,
         AMBIENT_TEXTURE: i ++,
         DIFFUSE_TEXTURE: i ++,
         SPECULAR_TEXTURE: i ++,
         SHININESS_TEXTURE: i ++,
         OCCLUSION_TEXTURE: i ++,
      };

      return function ()
      {
         return textureIndices;
      };
   })(),
   getMaterialKey ()
   {
      return "2";
   },
   createShader (key, geometryContext, renderContext)
   {
      const
         browser = this .getBrowser (),
         options = this .getShaderOptions (geometryContext, renderContext);

      if (geometryContext .hasNormals)
      {
         options .push ("X3D_MATERIAL");

         if (+this .getTextureBits ())
         {
            if (this .ambientTextureNode)
               options .push ("X3D_AMBIENT_TEXTURE", `X3D_AMBIENT_TEXTURE_${this .ambientTextureNode .getTextureTypeString ()}`);

            if (this .diffuseTextureNode)
               options .push ("X3D_DIFFUSE_TEXTURE", `X3D_DIFFUSE_TEXTURE_${this .diffuseTextureNode .getTextureTypeString ()}`);

            if (this .specularTextureNode)
               options .push ("X3D_SPECULAR_TEXTURE", `X3D_SPECULAR_TEXTURE_${this .specularTextureNode .getTextureTypeString ()}`);

            if (this .shininessTextureNode)
               options .push ("X3D_SHININESS_TEXTURE", `X3D_SHININESS_TEXTURE_${this .shininessTextureNode .getTextureTypeString ()}`);

            if (this .occlusionTextureNode)
               options .push ("X3D_OCCLUSION_TEXTURE", `X3D_OCCLUSION_TEXTURE_${this .occlusionTextureNode .getTextureTypeString ()}`);
         }

         switch (this .getMaterialKey (renderContext && renderContext .shadows))
         {
            case "1":
               var shaderNode = browser .createShader ("GouraudShader", "Gouraud", "Gouraud", options);
               break;
            case "2":
               var shaderNode = browser .createShader ("PhongShader", "Default", "Phong", options);
               break;
         }
      }
      else
      {
         options .push ("X3D_UNLIT_MATERIAL");

         var shaderNode = browser .createShader ("UnlitShader", "Default", "Unlit", options);

         browser .getShaders () .set (key .replace (/^(\d{1,2})\d*/, "$1") .replace (/\d$/, "0"), shaderNode);
      }

      browser .getShaders () .set (key, shaderNode);

      return shaderNode;
   },
   setShaderUniforms (gl, shaderObject, renderObject, textureTransformMapping, textureCoordinateMapping)
   {
      Shape_X3DOneSidedMaterialNode .prototype .setShaderUniforms .call (this, gl, shaderObject, renderObject, textureTransformMapping, textureCoordinateMapping);

      gl .uniform1f  (shaderObject .x3d_AmbientIntensity, this .ambientIntensity);
      gl .uniform3fv (shaderObject .x3d_DiffuseColor,     this .diffuseColor);
      gl .uniform3fv (shaderObject .x3d_SpecularColor,    this .specularColor);
      gl .uniform1f  (shaderObject .x3d_Shininess,        this .shininess);

      if (+this .getTextureBits ())
      {
         // Ambient parameters

         if (this .ambientTextureNode)
         {
            const
               ambientTextureMapping = this ._ambientTextureMapping .getValue (),
               ambientTexture        = shaderObject .x3d_AmbientTexture;

            this .ambientTextureNode .setShaderUniforms (gl, shaderObject, renderObject, ambientTexture);

            gl .uniform1i (ambientTexture .textureTransformMapping,  textureTransformMapping  .get (ambientTextureMapping) ?? 0);
            gl .uniform1i (ambientTexture .textureCoordinateMapping, textureCoordinateMapping .get (ambientTextureMapping) ?? 0);
         }

         // Diffuse parameters

         if (this .diffuseTextureNode)
         {
            const
               diffuseTextureMapping = this ._diffuseTextureMapping .getValue (),
               diffuseTexture        = shaderObject .x3d_DiffuseTexture;

            this .diffuseTextureNode .setShaderUniforms (gl, shaderObject, renderObject, diffuseTexture);

            gl .uniform1i (diffuseTexture .textureTransformMapping,  textureTransformMapping  .get (diffuseTextureMapping) ?? 0);
            gl .uniform1i (diffuseTexture .textureCoordinateMapping, textureCoordinateMapping .get (diffuseTextureMapping) ?? 0);
         }

         // Specular parameters

         if (this .specularTextureNode)
         {
            const
               specularTextureMapping = this ._specularTextureMapping .getValue (),
               specularTexture        = shaderObject .x3d_SpecularTexture;

            this .specularTextureNode .setShaderUniforms (gl, shaderObject, renderObject, specularTexture);

            gl .uniform1i (specularTexture .textureTransformMapping,  textureTransformMapping  .get (specularTextureMapping) ?? 0);
            gl .uniform1i (specularTexture .textureCoordinateMapping, textureCoordinateMapping .get (specularTextureMapping) ?? 0);
         }

         // Shininess parameters

         if (this .shininessTextureNode)
         {
            const
               shininessTextureMapping = this ._shininessTextureMapping .getValue (),
               shininessTexture        = shaderObject .x3d_ShininessTexture;

            this .shininessTextureNode .setShaderUniforms (gl, shaderObject, renderObject, shininessTexture);

            gl .uniform1i (shininessTexture .textureTransformMapping,  textureTransformMapping  .get (shininessTextureMapping) ?? 0);
            gl .uniform1i (shininessTexture .textureCoordinateMapping, textureCoordinateMapping .get (shininessTextureMapping) ?? 0);
         }

         // Occlusion parameters

         if (this .occlusionTextureNode)
         {
            const
               occlusionTextureMapping = this ._occlusionTextureMapping .getValue (),
               occlusionTexture        = shaderObject .x3d_OcclusionTexture;

            gl .uniform1f (shaderObject .x3d_OcclusionStrength, this .occlusionStrength);

            this .occlusionTextureNode .setShaderUniforms (gl, shaderObject, renderObject, occlusionTexture);

            gl .uniform1i (occlusionTexture .textureTransformMapping,  textureTransformMapping  .get (occlusionTextureMapping) ?? 0);
            gl .uniform1i (occlusionTexture .textureCoordinateMapping, textureCoordinateMapping .get (occlusionTextureMapping) ?? 0);
         }
      }
   },
});

function getMaterialKey (shadows)
{
   if (shadows || +this .getTextureBits ())
   {
      return "2";
   }
   else
   {
      switch (this .getBrowser () .getBrowserOptions () .getShading ())
      {
         default:
            return "1";
         case Core_Shading .PHONG:
            return "2";
      }
   }
}

Object .defineProperties (Material,
{
   typeName:
   {
      value: "Material",
      enumerable: true,
   },
   componentName:
   {
      value: "Shape",
      enumerable: true,
   },
   containerField:
   {
      value: "material",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",                 new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "ambientIntensity",         new x_ite_Fields .SFFloat (0.2)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "ambientTextureMapping",    new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "ambientTexture",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "diffuseColor",             new x_ite_Fields .SFColor (0.8, 0.8, 0.8)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "diffuseTextureMapping",    new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "diffuseTexture",           new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "specularColor",            new x_ite_Fields .SFColor ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "specularTextureMapping",   new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "specularTexture",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "emissiveColor",            new x_ite_Fields .SFColor ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "emissiveTextureMapping",   new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "emissiveTexture",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "shininess",                new x_ite_Fields .SFFloat (0.2)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "shininessTextureMapping",  new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "shininessTexture",         new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "occlusionStrength",        new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "occlusionTextureMapping",  new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "occlusionTexture",         new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "normalScale",              new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "normalTextureMapping",     new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "normalTexture",            new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "transparency",             new x_ite_Fields .SFFloat ()),
      ]),
      enumerable: true,
   },
});

const Material_default_ = Material;
;

x_ite_Namespace .add ("Material", "x_ite/Components/Shape/Material", Material_default_);
/* harmony default export */ const Shape_Material = (Material_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shape/PhysicalMaterial.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









function PhysicalMaterial (executionContext)
{
   Shape_X3DOneSidedMaterialNode .call (this, executionContext);

   this .addType (Base_X3DConstants .PhysicalMaterial);

   this .baseColor = new Float32Array (3);
}

Object .assign (Object .setPrototypeOf (PhysicalMaterial .prototype, Shape_X3DOneSidedMaterialNode .prototype),
{
   initialize ()
   {
      Shape_X3DOneSidedMaterialNode .prototype .initialize .call (this);

      this ._baseColor                .addInterest ("set_baseColor__",                this);
      this ._baseTexture              .addInterest ("set_baseTexture__",              this);
      this ._metallic                 .addInterest ("set_metallic__",                 this);
      this ._roughness                .addInterest ("set_roughness__",                this);
      this ._metallicRoughnessTexture .addInterest ("set_metallicRoughnessTexture__", this);
      this ._occlusionStrength        .addInterest ("set_occlusionStrength__",        this);
      this ._occlusionTexture         .addInterest ("set_occlusionTexture__",         this);

      this .set_baseColor__ ();
      this .set_baseTexture__ ();
      this .set_metallic__ ();
      this .set_roughness__ ();
      this .set_metallicRoughnessTexture__ ();
      this .set_occlusionStrength__ ();
      this .set_occlusionTexture__ ();
      this .set_transparent__ ();
   },
   set_baseColor__ ()
   {
      //We cannot use this in Windows Edge:
      //this .baseColor .set (this ._baseColor .getValue ());

      const
         baseColor  = this .baseColor,
         baseColor_ = this ._baseColor .getValue ();

      baseColor [0] = baseColor_ .r;
      baseColor [1] = baseColor_ .g;
      baseColor [2] = baseColor_ .b;
   },
   set_baseTexture__ ()
   {
      if (this .baseTextureNode)
         this .baseTextureNode ._transparent .removeInterest ("set_transparent__", this);

      this .baseTextureNode = Base_X3DCast (Base_X3DConstants .X3DSingleTextureNode, this ._baseTexture);

      this .setTexture (this .getTextureIndices () .BASE_TEXTURE, this .baseTextureNode);

      if (this .baseTextureNode)
         this .baseTextureNode ._transparent .addInterest ("set_transparent__", this);
   },
   set_metallic__ ()
   {
      this .metallic = Math_Algorithm .clamp (this ._metallic .getValue (), 0, 1);
   },
   set_roughness__ ()
   {
      this .roughness = Math_Algorithm .clamp (this ._roughness .getValue (), 0, 1);
   },
   set_metallicRoughnessTexture__ ()
   {
      this .metallicRoughnessTextureNode = Base_X3DCast (Base_X3DConstants .X3DSingleTextureNode, this ._metallicRoughnessTexture);

      this .setTexture (this .getTextureIndices () .METALLIC_ROUGHNESS_TEXTURE, this .metallicRoughnessTextureNode);
   },
   set_occlusionStrength__ ()
   {
      this .occlusionStrength = Math_Algorithm .clamp (this ._occlusionStrength .getValue (), 0, 1);
   },
   set_occlusionTexture__ ()
   {
      this .occlusionTextureNode = Base_X3DCast (Base_X3DConstants .X3DSingleTextureNode, this ._occlusionTexture);

      this .setTexture (this .getTextureIndices () .OCCLUSION_TEXTURE, this .occlusionTextureNode);
   },
   set_transparent__ ()
   {
      this .setTransparent (!!(this .getTransparency () || this .baseTextureNode ?.isTransparent ()));
   },
   getBaseTexture ()
   {
      return this .baseTextureNode;
   },
   getTextureIndices: (() =>
   {
      let i = 0;

      const textureIndices = {
         EMISSIVE_TEXTURE: i ++,
         NORMAL_TEXTURE:  i ++,
         BASE_TEXTURE: i ++,
         METALLIC_ROUGHNESS_TEXTURE: i ++,
         OCCLUSION_TEXTURE:  i ++,
      };

      return function ()
      {
         return textureIndices;
      };
   })(),
   getMaterialKey ()
   {
      return "3";
   },
   createShader (key, geometryContext, renderContext)
   {
      const
         browser = this .getBrowser (),
         options = this .getShaderOptions (geometryContext, renderContext);

      if (geometryContext .hasNormals)
      {
         options .push ("X3D_PHYSICAL_MATERIAL", "X3D_MATERIAL_METALLIC_ROUGHNESS");

         if (+this .getTextureBits ())
         {
            if (this .baseTextureNode)
               options .push ("X3D_BASE_TEXTURE", `X3D_BASE_TEXTURE_${this .baseTextureNode .getTextureTypeString ()}`);

            if (this .metallicRoughnessTextureNode)
               options .push ("X3D_METALLIC_ROUGHNESS_TEXTURE", `X3D_METALLIC_ROUGHNESS_TEXTURE_${this .metallicRoughnessTextureNode .getTextureTypeString ()}`);

            if (this .occlusionTextureNode)
               options .push ("X3D_OCCLUSION_TEXTURE", `X3D_OCCLUSION_TEXTURE_${this .occlusionTextureNode .getTextureTypeString ()}`);
         }

         var shaderNode = browser .createShader ("PBRShader", "Default", "PBR", options);
      }
      else
      {
         options .push ("X3D_UNLIT_MATERIAL");

         var shaderNode = browser .createShader ("UnlitShader", "Default", "Unlit", options);

         browser .getShaders () .set (key .replace (/^(\d{1,2})\d*/, "$1") .replace (/\d$/, "0"), shaderNode);
      }

      browser .getShaders () .set (key, shaderNode);

      return shaderNode;
   },
   setShaderUniforms (gl, shaderObject, renderObject, textureTransformMapping, textureCoordinateMapping)
   {
      Shape_X3DOneSidedMaterialNode .prototype .setShaderUniforms .call (this, gl, shaderObject, renderObject, textureTransformMapping, textureCoordinateMapping);

      gl .uniform3fv (shaderObject .x3d_BaseColor, this .baseColor);
      gl .uniform1f  (shaderObject .x3d_Metallic,  this .metallic);
      gl .uniform1f  (shaderObject .x3d_Roughness, this .roughness);

      if (+this .getTextureBits ())
      {
         // Base parameters

         if (this .baseTextureNode)
         {
            const
               baseTextureMapping = this ._baseTextureMapping .getValue (),
               baseTexture        = shaderObject .x3d_BaseTexture;

            this .baseTextureNode .setShaderUniforms (gl, shaderObject, renderObject, baseTexture);

            gl .uniform1i (baseTexture .textureTransformMapping,  textureTransformMapping  .get (baseTextureMapping) ?? 0);
            gl .uniform1i (baseTexture .textureCoordinateMapping, textureCoordinateMapping .get (baseTextureMapping) ?? 0);
         }

         // Metallic roughness parameters

         if (this .metallicRoughnessTextureNode)
         {
            const
               metallicRoughnessTextureMapping = this ._metallicRoughnessTextureMapping .getValue (),
               metallicRoughnessTexture        = shaderObject .x3d_MetallicRoughnessTexture;

            this .metallicRoughnessTextureNode .setShaderUniforms (gl, shaderObject, renderObject, metallicRoughnessTexture);

            gl .uniform1i (metallicRoughnessTexture .textureTransformMapping,  textureTransformMapping  .get (metallicRoughnessTextureMapping) ?? 0);
            gl .uniform1i (metallicRoughnessTexture .textureCoordinateMapping, textureCoordinateMapping .get (metallicRoughnessTextureMapping) ?? 0);
         }

         // Occlusion parameters

         if (this .occlusionTextureNode)
         {
            const
               occlusionTextureMapping = this ._occlusionTextureMapping .getValue (),
               occlusionTexture        = shaderObject .x3d_OcclusionTexture;

            gl .uniform1f (shaderObject .x3d_OcclusionStrength, this .occlusionStrength);

            this .occlusionTextureNode .setShaderUniforms (gl, shaderObject, renderObject, occlusionTexture);

            gl .uniform1i (occlusionTexture .textureTransformMapping,  textureTransformMapping  .get (occlusionTextureMapping) ?? 0);
            gl .uniform1i (occlusionTexture .textureCoordinateMapping, textureCoordinateMapping .get (occlusionTextureMapping) ?? 0);
         }
      }
   },
});

Object .defineProperties (PhysicalMaterial,
{
   typeName:
   {
      value: "PhysicalMaterial",
      enumerable: true,
   },
   componentName:
   {
      value: "Shape",
      enumerable: true,
   },
   containerField:
   {
      value: "material",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",                        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "baseColor",                       new x_ite_Fields .SFColor (1, 1, 1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "baseTextureMapping",              new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "baseTexture",                     new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "emissiveColor",                   new x_ite_Fields .SFColor ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "emissiveTextureMapping",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "emissiveTexture",                 new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metallic",                        new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "roughness",                       new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metallicRoughnessTextureMapping", new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metallicRoughnessTexture",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "occlusionStrength",               new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "occlusionTextureMapping",         new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "occlusionTexture",                new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "normalScale",                     new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "normalTextureMapping",            new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "normalTexture",                   new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "transparency",                    new x_ite_Fields .SFFloat ()),
      ]),
      enumerable: true,
   },
});

const PhysicalMaterial_default_ = PhysicalMaterial;
;

x_ite_Namespace .add ("PhysicalMaterial", "x_ite/Components/Shape/PhysicalMaterial", PhysicalMaterial_default_);
/* harmony default export */ const Shape_PhysicalMaterial = (PhysicalMaterial_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shape/PointProperties.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









function PointProperties (executionContext)
{
   Shape_X3DAppearanceChildNode .call (this, executionContext);

   this .addType (Base_X3DConstants .PointProperties);

   this .attenuation = new Float32Array (3);
}

Object .assign (Object .setPrototypeOf (PointProperties .prototype, Shape_X3DAppearanceChildNode .prototype),
{
   initialize ()
   {
      Shape_X3DAppearanceChildNode .prototype .initialize .call (this);

      const
         browser = this .getBrowser (),
         gl      = browser .getContext ();

      this .pointSizeRange = gl .getParameter (gl .ALIASED_POINT_SIZE_RANGE);

      browser .getRenderingProperties () ._ContentScale .addInterest ("set_contentScale__", this);

      this ._pointSizeScaleFactor .addInterest ("set_pointSizeScaleFactor__", this);
      this ._pointSizeMinValue    .addInterest ("set_pointSizeMinValue__",    this);
      this ._pointSizeMaxValue    .addInterest ("set_pointSizeMaxValue__",    this);
      this ._attenuation          .addInterest ("set_attenuation__",          this);

      this .set_pointSizeScaleFactor__ ();
      this .set_pointSizeMinValue__ ();
      this .set_pointSizeMaxValue__ ();
      this .set_attenuation__ ();
   },
   getStyleKey ()
   {
      return 1;
   },
   set_contentScale__ ()
   {
      this .set_pointSizeScaleFactor__ ();
      this .set_pointSizeMinValue__ ();
      this .set_pointSizeMaxValue__ ();
   },
   set_pointSizeScaleFactor__ ()
   {
      const contentScale = this .getBrowser () .getRenderingProperty ("ContentScale");

      this .pointSizeScaleFactor = Math .max (this ._pointSizeScaleFactor .getValue (), 0) * contentScale;
   },
   set_pointSizeMinValue__ ()
   {
      const contentScale = this .getBrowser () .getRenderingProperty ("ContentScale");

      this .pointSizeMinValue = Math_Algorithm .clamp (this ._pointSizeMinValue .getValue (), 0, this .pointSizeRange [1]) * contentScale;
   },
   set_pointSizeMaxValue__ ()
   {
      const contentScale = this .getBrowser () .getRenderingProperty ("ContentScale");

      this .pointSizeMaxValue = Math_Algorithm .clamp (this ._pointSizeMaxValue .getValue (), 0, this .pointSizeRange [1]) * contentScale;
   },
   set_attenuation__ ()
   {
      const length = this ._attenuation .length;

      this .attenuation [0] = length > 0 ? Math .max (0, this ._attenuation [0]) : 1;
      this .attenuation [1] = length > 1 ? Math .max (0, this ._attenuation [1]) : 0;
      this .attenuation [2] = length > 2 ? Math .max (0, this ._attenuation [2]) : 0;
   },
   setShaderUniforms (gl, shaderObject)
   {
      gl .uniform1f  (shaderObject .x3d_PointPropertiesPointSizeScaleFactor, this .pointSizeScaleFactor);
      gl .uniform1f  (shaderObject .x3d_PointPropertiesPointSizeMinValue,    this .pointSizeMinValue);
      gl .uniform1f  (shaderObject .x3d_PointPropertiesPointSizeMaxValue,    this .pointSizeMaxValue);
      gl .uniform3fv (shaderObject .x3d_PointPropertiesAttenuation,          this .attenuation);
   },
});

Object .defineProperties (PointProperties,
{
   typeName:
   {
      value: "PointProperties",
      enumerable: true,
   },
   componentName:
   {
      value: "Shape",
      enumerable: true,
   },
   containerField:
   {
      value: "pointProperties",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pointSizeScaleFactor", new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pointSizeMinValue",    new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pointSizeMaxValue",    new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "attenuation",          new x_ite_Fields .MFFloat (1, 0, 0)),
      ]),
      enumerable: true,
   },
});

const PointProperties_default_ = PointProperties;
;

x_ite_Namespace .add ("PointProperties", "x_ite/Components/Shape/PointProperties", PointProperties_default_);
/* harmony default export */ const Shape_PointProperties = (PointProperties_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shape/X3DShapeNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









function X3DShapeNode (executionContext)
{
   Core_X3DChildNode     .call (this, executionContext);
   Grouping_X3DBoundedObject .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DShapeNode);

   this .bbox       = new Geometry_Box3 ();
   this .bboxSize   = new Numbers_Vector3 (0, 0, 0);
   this .bboxCenter = new Numbers_Vector3 (0, 0, 0);
}

Object .assign (Object .setPrototypeOf (X3DShapeNode .prototype, Core_X3DChildNode .prototype),
   Grouping_X3DBoundedObject .prototype,
{
   initialize ()
   {
      Core_X3DChildNode     .prototype .initialize .call (this);
      Grouping_X3DBoundedObject .prototype .initialize .call (this);

      this ._bboxSize   .addInterest ("set_bbox__",       this);
      this ._bboxCenter .addInterest ("set_bbox__",       this);
      this ._appearance .addInterest ("set_appearance__", this);
      this ._geometry   .addInterest ("set_geometry__",   this);

      this ._appearance .addInterest ("set_transparent__", this);
      this ._geometry   .addInterest ("set_transparent__", this);

      this .set_appearance__ ();
      this .set_geometry__ ();
      this .set_transparent__ ();
   },
   getBBox (bbox, shadows)
   {
      if (shadows)
      {
         if (this ._castShadow .getValue ())
            return bbox .assign (this .bbox);
         else
            return bbox .set ();
      }
      else
      {
         return bbox .assign (this .bbox);
      }
   },
   getBBoxSize ()
   {
      return this .bboxSize;
   },
   getBBoxCenter ()
   {
      return this .bboxCenter;
   },
   setTransparent (value)
   {
      this .transparent = value;
   },
   isTransparent ()
   {
      return this .transparent;
   },
   getAppearance ()
   {
      return this .appearanceNode;
   },
   getGeometry ()
   {
      return this .geometryNode;
   },
   set_bbox__ ()
   {
      if (this ._bboxSize .getValue () .equals (this .getDefaultBBoxSize ()))
      {
         if (this .getGeometry ())
            this .bbox .assign (this .getGeometry () .getBBox ());

         else
            this .bbox .set ();
      }
      else
      {
         this .bbox .set (this ._bboxSize .getValue (), this ._bboxCenter .getValue ());
      }

      this .bboxSize   .assign (this .bbox .size);
      this .bboxCenter .assign (this .bbox .center);
   },
   set_appearance__ ()
   {
      if (this .appearanceNode)
         this .appearanceNode ._transparent .removeInterest ("set_transparent__", this);

      this .appearanceNode = Base_X3DCast (Base_X3DConstants .X3DAppearanceNode, this ._appearance);

      if (this .appearanceNode)
      {
         this .appearanceNode ._alphaMode   .addInterest ("set_transparent__", this);
         this .appearanceNode ._transparent .addInterest ("set_transparent__", this);
      }
      else
      {
         this .appearanceNode = this .getBrowser () .getDefaultAppearance ();
      }
   },
   set_geometry__ ()
   {
      if (this .geometryNode)
      {
         this .geometryNode ._transparent  .addInterest ("set_transparent__", this);
         this .geometryNode ._bbox_changed .addInterest ("set_bbox__",        this);
      }

      this .geometryNode = Base_X3DCast (Base_X3DConstants .X3DGeometryNode, this ._geometry);

      if (this .geometryNode)
      {
         this .geometryNode ._transparent  .addInterest ("set_transparent__", this);
         this .geometryNode ._bbox_changed .addInterest ("set_bbox__",        this);
      }

      this .set_bbox__ ();
   },
   set_transparent__ ()
   {
      if (this .appearanceNode .getAlphaMode () === Shape_AlphaMode .AUTO)
      {
         this .transparent = !!(this .appearanceNode .isTransparent () || this .geometryNode ?.isTransparent ());
      }
      else
      {
         this .transparent = this .appearanceNode .isTransparent ();
      }
   },
   dispose ()
   {
      Grouping_X3DBoundedObject .prototype .dispose .call (this);
      Core_X3DChildNode     .prototype .dispose .call (this);
   },
});

Object .defineProperties (X3DShapeNode,
{
   typeName:
   {
      value: "X3DShapeNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Shape",
      enumerable: true,
   },
});

const X3DShapeNode_default_ = X3DShapeNode;
;

x_ite_Namespace .add ("X3DShapeNode", "x_ite/Components/Shape/X3DShapeNode", X3DShapeNode_default_);
/* harmony default export */ const Shape_X3DShapeNode = (X3DShapeNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shape/Shape.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function Shape (executionContext)
{
   Shape_X3DShapeNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Shape);
}

Object .assign (Object .setPrototypeOf (Shape .prototype, Shape_X3DShapeNode .prototype),
{
   initialize ()
   {
      Shape_X3DShapeNode .prototype .initialize .call (this);

      this ._transformSensors_changed .addInterest ("set_transformSensors__", this);

      this .set_transformSensors__ ();
   },
   getShapeKey ()
   {
      return 0;
   },
   getGeometryContext: Shape_X3DShapeNode .prototype .getGeometry,
   set_geometry__ ()
   {
      Shape_X3DShapeNode .prototype .set_geometry__ .call (this);

      if (this .getGeometry ())
         delete this .traverse;
      else
         this .traverse = Function .prototype;
   },
   set_transformSensors__ ()
   {
      this .setPickableObject (this .getTransformSensors () .size);
   },
   intersectsBox (box, clipPlanes, modelViewMatrix)
   {
      return this .getGeometry () .intersectsBox (box, clipPlanes, modelViewMatrix);
   },
   traverse (type, renderObject)
   {
      // Always look at ParticleSystem if you do modify something here and there.

      switch (type)
      {
         case Rendering_TraverseType .POINTER:
         {
            renderObject .addPointingShape (this);
            break;
         }
         case Rendering_TraverseType .PICKING:
         {
            this .picking (renderObject);
            break;
         }
         case Rendering_TraverseType .COLLISION:
         {
            renderObject .addCollisionShape (this);
            break;
         }
         case Rendering_TraverseType .SHADOW:
         {
            if (this ._castShadow .getValue ())
               renderObject .addShadowShape (this);

            break;
         }
         case Rendering_TraverseType .DISPLAY:
         {
            if (renderObject .addDisplayShape (this))
               this .getAppearance () .traverse (type, renderObject); // Currently used for GeneratedCubeMapTexture.

            break;
         }
      }

      this .getGeometry () .traverse (type, renderObject); // Currently used for ScreenText.
   },
   picking (renderObject)
   {
      const modelMatrix = renderObject .getModelViewMatrix () .get ();

      if (this .getTransformSensors () .size)
      {
         for (const transformSensorNode of this .getTransformSensors ())
            transformSensorNode .collect (modelMatrix);
      }

      const
         browser          = this .getBrowser (),
         pickSensorStack  = browser .getPickSensors (),
         pickingHierarchy = browser .getPickingHierarchy ();

      pickingHierarchy .push (this);

      for (const pickSensor of pickSensorStack .at (-1))
      {
         pickSensor .collect (this .getGeometry (), modelMatrix, pickingHierarchy);
      }

      pickingHierarchy .pop ();
   },
   displaySimple (gl, renderContext, shaderNode)
   {
      this .getGeometry () .displaySimple (gl, renderContext, shaderNode);
   },
   display (gl, renderContext)
   {
      this .getGeometry () .display (gl, renderContext);
   },
});

Object .defineProperties (Shape,
{
   typeName:
   {
      value: "Shape",
      enumerable: true,
   },
   componentName:
   {
      value: "Shape",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",    new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "visible",     new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "castShadow",  new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "bboxDisplay", new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxSize",    new x_ite_Fields .SFVec3f (-1, -1, -1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "bboxCenter",  new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "appearance",  new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "geometry",    new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const Shape_default_ = Shape;
;

x_ite_Namespace .add ("Shape", "x_ite/Components/Shape/Shape", Shape_default_);
/* harmony default export */ const Shape_Shape = (Shape_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shape/TwoSidedMaterial.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









function TwoSidedMaterial (executionContext)
{
   console .warn ("TwoSidedMaterial is depreciated, please use Appearance backMaterial field.");

   Shape_X3DMaterialNode .call (this, executionContext);

   this .addType (Base_X3DConstants .TwoSidedMaterial);

   this .diffuseColor  = new Float32Array (3);
   this .specularColor = new Float32Array (3);
   this .emissiveColor = new Float32Array (3);

   this .backDiffuseColor  = new Float32Array (3);
   this .backSpecularColor = new Float32Array (3);
   this .backEmissiveColor = new Float32Array (3);
}

Object .assign (Object .setPrototypeOf (TwoSidedMaterial .prototype, Shape_X3DMaterialNode .prototype),
{
   initialize ()
   {
      Shape_X3DMaterialNode . prototype .initialize .call (this);

      this ._ambientIntensity .addInterest ("set_ambientIntensity__", this);
      this ._diffuseColor     .addInterest ("set_diffuseColor__",     this);
      this ._specularColor    .addInterest ("set_specularColor__",    this);
      this ._emissiveColor    .addInterest ("set_emissiveColor__",    this);
      this ._shininess        .addInterest ("set_shininess__",        this);
      this ._transparency     .addInterest ("set_transparency__",     this);

      this ._backAmbientIntensity .addInterest ("set_backAmbientIntensity__", this);
      this ._backDiffuseColor     .addInterest ("set_backDiffuseColor__",     this);
      this ._backSpecularColor    .addInterest ("set_backSpecularColor__",    this);
      this ._backEmissiveColor    .addInterest ("set_backEmissiveColor__",    this);
      this ._backShininess        .addInterest ("set_backShininess__",        this);
      this ._backTransparency     .addInterest ("set_backTransparency__",     this);

      this ._separateBackColor .addInterest ("set_transparent__", this);
      this ._transparency      .addInterest ("set_transparent__", this);
      this ._backTransparency  .addInterest ("set_transparent__", this);

      this .set_ambientIntensity__ ();
      this .set_diffuseColor__ ();
      this .set_specularColor__ ();
      this .set_emissiveColor__ ();
      this .set_shininess__ ();
      this .set_transparency__ ();

      this .set_backAmbientIntensity__ ();
      this .set_backDiffuseColor__ ();
      this .set_backSpecularColor__ ();
      this .set_backEmissiveColor__ ();
      this .set_backShininess__ ();
      this .set_backTransparency__ ();

      this .set_transparent__ ();
   },
   set_ambientIntensity__ ()
   {
      this .ambientIntensity = Math .max (this ._ambientIntensity .getValue (), 0);
   },
   set_diffuseColor__ ()
   {
      //We cannot use this in Windows Edge:
      //this .diffuseColor .set (this ._diffuseColor .getValue ());

      const
         diffuseColor  = this .diffuseColor,
         diffuseColor_ = this ._diffuseColor .getValue ();

      diffuseColor [0] = diffuseColor_ .r;
      diffuseColor [1] = diffuseColor_ .g;
      diffuseColor [2] = diffuseColor_ .b;
   },
   set_specularColor__ ()
   {
      //We cannot use this in Windows Edge:
      //this .specularColor .set (this ._specularColor .getValue ());

      const
         specularColor  = this .specularColor,
         specularColor_ = this ._specularColor .getValue ();

      specularColor [0] = specularColor_ .r;
      specularColor [1] = specularColor_ .g;
      specularColor [2] = specularColor_ .b;
   },
   set_emissiveColor__ ()
   {
      //We cannot use this in Windows Edge:
      //this .emissiveColor .set (this ._emissiveColor .getValue ());

      const
         emissiveColor  = this .emissiveColor,
         emissiveColor_ = this ._emissiveColor .getValue ();

      emissiveColor [0] = emissiveColor_ .r;
      emissiveColor [1] = emissiveColor_ .g;
      emissiveColor [2] = emissiveColor_ .b;
   },
   set_shininess__ ()
   {
      this .shininess = Math_Algorithm .clamp (this ._shininess .getValue (), 0, 1);
   },
   set_transparency__ ()
   {
      this .transparency = Math_Algorithm .clamp (this ._transparency .getValue (), 0, 1);
   },
   /*
    * Back Material
    */
   set_backAmbientIntensity__ ()
   {
      this .backAmbientIntensity = Math .max (this ._backAmbientIntensity .getValue (), 0);
   },
   set_backDiffuseColor__ ()
   {
      //We cannot use this in Windows Edge:
      //this .backDiffuseColor .set (this ._backDiffuseColor .getValue ());

      const
         backDiffuseColor  = this .backDiffuseColor,
         backDiffuseColor_ = this ._backDiffuseColor .getValue ();

      backDiffuseColor [0] = backDiffuseColor_ .r;
      backDiffuseColor [1] = backDiffuseColor_ .g;
      backDiffuseColor [2] = backDiffuseColor_ .b;
   },
   set_backSpecularColor__ ()
   {
      //We cannot use this in Windows Edge:
      //this .backSpecularColor .set (this ._backSpecularColor .getValue ());

      const
         backSpecularColor  = this .backSpecularColor,
         backSpecularColor_ = this ._backSpecularColor .getValue ();

      backSpecularColor [0] = backSpecularColor_ .r;
      backSpecularColor [1] = backSpecularColor_ .g;
      backSpecularColor [2] = backSpecularColor_ .b;
   },
   set_backEmissiveColor__ ()
   {
      //We cannot use this in Windows Edge:
      //this .backEmissiveColor .set (this ._backEmissiveColor .getValue ());

      const
         backEmissiveColor  = this .backEmissiveColor,
         backEmissiveColor_ = this ._backEmissiveColor .getValue ();

      backEmissiveColor [0] = backEmissiveColor_ .r;
      backEmissiveColor [1] = backEmissiveColor_ .g;
      backEmissiveColor [2] = backEmissiveColor_ .b;
   },
   set_backShininess__ ()
   {
      this .backShininess = Math_Algorithm .clamp (this ._backShininess .getValue (), 0, 1);
   },
   set_backTransparency__ ()
   {
      this .backTransparency = Math_Algorithm .clamp (this ._backTransparency .getValue (), 0, 1);
   },
   set_transparent__ ()
   {
      this .setTransparent (!!(this ._transparency .getValue () || (this ._separateBackColor .getValue () && this ._backTransparency .getValue ())));
   },
   getBaseTexture: Shape_Material .prototype .getBaseTexture,
   getMaterialKey: Shape_Material .prototype .getMaterialKey,
   createShader: Shape_Material .prototype .createShader,
   setShaderUniforms (gl, shaderObject, renderObject, textureTransformMapping, textureCoordinateMapping, front)
   {
      if (! front && this ._separateBackColor .getValue ())
      {
         gl .uniform1f  (shaderObject .x3d_AmbientIntensity, this .backAmbientIntensity);
         gl .uniform3fv (shaderObject .x3d_DiffuseColor,     this .backDiffuseColor);
         gl .uniform3fv (shaderObject .x3d_SpecularColor,    this .backSpecularColor);
         gl .uniform3fv (shaderObject .x3d_EmissiveColor,    this .backEmissiveColor);
         gl .uniform1f  (shaderObject .x3d_Shininess,        this .backShininess);
         gl .uniform1f  (shaderObject .x3d_Transparency,     this .backTransparency);
      }
      else
      {
         gl .uniform1f  (shaderObject .x3d_AmbientIntensity, this .ambientIntensity);
         gl .uniform3fv (shaderObject .x3d_DiffuseColor,     this .diffuseColor);
         gl .uniform3fv (shaderObject .x3d_SpecularColor,    this .specularColor);
         gl .uniform3fv (shaderObject .x3d_EmissiveColor,    this .emissiveColor);
         gl .uniform1f  (shaderObject .x3d_Shininess,        this .shininess);
         gl .uniform1f  (shaderObject .x3d_Transparency,     this .transparency);
      }
   },
});

Object .defineProperties (TwoSidedMaterial,
{
   typeName:
   {
      value: "TwoSidedMaterial",
      enumerable: true,
   },
   componentName:
   {
      value: "Shape",
      enumerable: true,
   },
   containerField:
   {
      value: "material",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.2", "4.0"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "separateBackColor",    new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "ambientIntensity",     new x_ite_Fields .SFFloat (0.2)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "diffuseColor",         new x_ite_Fields .SFColor (0.8, 0.8, 0.8)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "specularColor",        new x_ite_Fields .SFColor ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "emissiveColor",        new x_ite_Fields .SFColor ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "shininess",            new x_ite_Fields .SFFloat (0.2)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "transparency",         new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "backAmbientIntensity", new x_ite_Fields .SFFloat (0.2)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "backDiffuseColor",     new x_ite_Fields .SFColor (0.8, 0.8, 0.8)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "backSpecularColor",    new x_ite_Fields .SFColor ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "backEmissiveColor",    new x_ite_Fields .SFColor ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "backShininess",        new x_ite_Fields .SFFloat (0.2)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "backTransparency",     new x_ite_Fields .SFFloat ()),
      ]),
      enumerable: true,
   },
});

const TwoSidedMaterial_default_ = TwoSidedMaterial;
;

x_ite_Namespace .add ("TwoSidedMaterial", "x_ite/Components/Shape/TwoSidedMaterial", TwoSidedMaterial_default_);
/* harmony default export */ const Shape_TwoSidedMaterial = (TwoSidedMaterial_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shape/UnlitMaterial.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function UnlitMaterial (executionContext)
{
   Shape_X3DOneSidedMaterialNode .call (this, executionContext);

   this .addType (Base_X3DConstants .UnlitMaterial);
}

Object .assign (Object .setPrototypeOf (UnlitMaterial .prototype, Shape_X3DOneSidedMaterialNode .prototype),
{
   initialize ()
   {
      Shape_X3DOneSidedMaterialNode .prototype .initialize .call (this);

      this .set_transparent__ ();
   },
   set_emissiveTexture__ ()
   {
      if (this .getEmissiveTexture ())
         this .getEmissiveTexture () ._transparent .removeInterest ("set_transparent__", this);

      Shape_X3DOneSidedMaterialNode .prototype .set_emissiveTexture__ .call (this);

      if (this .getEmissiveTexture ())
         this .getEmissiveTexture () ._transparent .addInterest ("set_transparent__", this);
   },
   set_transparent__ ()
   {
      this .setTransparent (!!(this .getTransparency () ||
                               this .getEmissiveTexture () ?.isTransparent ()));
   },
   getMaterialKey ()
   {
      return "0";
   },
   createShader (key, geometryContext, renderContext)
   {
      const
         browser = this .getBrowser (),
         options = this .getShaderOptions (geometryContext, renderContext);

      options .push ("X3D_UNLIT_MATERIAL");

      const shaderNode = browser .createShader ("UnlitShader", "Default", "Unlit", options);

      browser .getShaders () .set (key, shaderNode);

      return shaderNode;
   },
});

Object .defineProperties (UnlitMaterial,
{
   typeName:
   {
      value: "UnlitMaterial",
      enumerable: true,
   },
   componentName:
   {
      value: "Shape",
      enumerable: true,
   },
   containerField:
   {
      value: "material",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",               new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "emissiveColor",          new x_ite_Fields .SFColor (1, 1, 1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "emissiveTextureMapping", new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "emissiveTexture",        new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "normalScale",            new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "normalTextureMapping",   new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "normalTexture",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "transparency",           new x_ite_Fields .SFFloat ()),
      ]),
      enumerable: true,
   },
});

const UnlitMaterial_default_ = UnlitMaterial;
;

x_ite_Namespace .add ("UnlitMaterial", "x_ite/Components/Shape/UnlitMaterial", UnlitMaterial_default_);
/* harmony default export */ const Shape_UnlitMaterial = (UnlitMaterial_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Shape.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

















const Components_Shape_default_ = {
   name: "Shape",
   concreteNodes:
   [
      Shape_AcousticProperties,
      Shape_Appearance,
      Shape_FillProperties,
      Shape_LineProperties,
      Shape_Material,
      Shape_PhysicalMaterial,
      Shape_PointProperties,
      Shape_Shape,
      Shape_TwoSidedMaterial,
      Shape_UnlitMaterial,
   ],
   abstractNodes:
   [
      Shape_X3DAppearanceChildNode,
      Shape_X3DAppearanceNode,
      Shape_X3DMaterialNode,
      Shape_X3DOneSidedMaterialNode,
      Shape_X3DShapeNode,
   ],
};
;

x_ite_Namespace .add ("Shape", "x_ite/Components/Shape", Components_Shape_default_);
/* harmony default export */ const Components_Shape = (Components_Shape_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/X3DSoundProcessingNode.js
/* provided dependency */ var X3DSoundProcessingNode_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function X3DSoundProcessingNode (executionContext)
{
   Core_X3DChildNode         .call (this, executionContext);
   Time_X3DTimeDependentNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DSoundProcessingNode);

   this .addChildObjects (Base_X3DConstants .inputOutput, "loop",   new x_ite_Fields .SFBool (true),
                          Base_X3DConstants .inputOutput, "active", new x_ite_Fields .SFBool ());

   const audioContext = this .getBrowser () .getAudioContext ();

   this .childNodes = [ ];
   this .gainNode   = new GainNode (audioContext);
}

Object .assign (Object .setPrototypeOf (X3DSoundProcessingNode .prototype, Core_X3DChildNode .prototype),
   Time_X3DTimeDependentNode .prototype,
{
   initialize ()
   {
      Core_X3DChildNode         .prototype .initialize .call (this);
      Time_X3DTimeDependentNode .prototype .initialize .call (this);

      this ._active                .addInterest ("set_gain__",                  this);
      this ._gain                  .addInterest ("set_gain__",                  this);
      this ._channelCount          .addInterest ("set_channelCount__",          this);
      this ._channelCountMode      .addInterest ("set_channelCountMode__",      this);
      this ._channelInterpretation .addInterest ("set_channelInterpretation__", this);
      this ._children              .addInterest ("set_children__",              this);
      this ._active                .addInterest ("set_active__",                this);

      this .set_gain__ ();
      this .set_channelCount__ ();
      this .set_channelCountMode__ ();
      this .set_channelInterpretation__ ();
      this .set_children__ ();
   },
   getAudioSource ()
   {
      return this .gainNode;
   },
   getSoundProcessor ()
   {
      return this .gainNode;
   },
   set_gain__ ()
   {
      this .gainNode .gain .value = this ._active .getValue () ? this ._gain .getValue () : 1;
   },
   set_channelCount__ ()
   {
      this .getSoundProcessor () .channelCount = Math .max (this ._channelCount .getValue (), 1);
   },
   set_channelCountMode__: (function ()
   {
      const channelCountModes = new Set (["max", "clamped-max", "explicit"]);

      return function ()
      {
         const channelCountMode = this ._channelCountMode .getValue () .toLowerCase () .replaceAll ("_", "-");

         this .getSoundProcessor () .channelCountMode = channelCountModes .has (channelCountMode) ? channelCountMode : "max";
      };
   })(),
   set_channelInterpretation__: (function ()
   {
      const channelInterpretations = new Set (["speakers", "discrete"]);

      return function ()
      {
         const channelInterpretation = this ._channelInterpretation .getValue () .toLowerCase ();

         this .getSoundProcessor () .channelInterpretation = channelInterpretations .has (channelInterpretation) ? channelInterpretation : "speakers";
      };
   })(),
   set_children__ ()
   {
      this .set_disconnect__ ();

      this .childNodes .length = 0;

      for (const child of this ._children)
      {
         const childNode = Base_X3DCast (Base_X3DConstants .X3DChildNode, child);

         if (!childNode)
            continue;

         const type = childNode .getType ();

         for (let t = type .length - 1; t >= 0; -- t)
         {
            switch (type [t])
            {
               case Base_X3DConstants .X3DSoundChannelNode:
               case Base_X3DConstants .X3DSoundProcessingNode:
               case Base_X3DConstants .X3DSoundSourceNode:
                  this .childNodes .push (childNode);
                  break;
               default:
                  continue;
            }

            break;
         }
      }

      this .set_active__ ();
   },
   set_disconnect__ ()
   {
      for (const childNode of this .childNodes)
         X3DSoundProcessingNode_$.try (() => childNode .getAudioSource () .disconnect (this .gainNode));

      for (const childNode of this .childNodes)
         X3DSoundProcessingNode_$.try (() => childNode .getAudioSource () .disconnect (this .getSoundProcessor ()));
   },
   set_active__ ()
   {
      this .set_disconnect__ ();

      if (this ._active .getValue ())
      {
         for (const childNode of this .childNodes)
            X3DSoundProcessingNode_$.try (() => childNode .getAudioSource () .connect (this .getSoundProcessor ()), true);
      }
      else
      {
         for (const childNode of this .childNodes)
            X3DSoundProcessingNode_$.try (() => childNode .getAudioSource () .connect (this .gainNode), true);
      }
   },
   set_start ()
   {
      if (!this ._active .getValue ())
         this ._active = true;
   },
   set_pause ()
   {
      if (this ._active .getValue ())
         this ._active = false;
   },
   set_resume ()
   {
      if (!this ._active .getValue ())
         this ._active = true;
   },
   set_stop ()
   {
      if (this ._active .getValue ())
         this ._active = false;
   },
   set_time ()
   {
      this ._elapsedTime = this .getElapsedTime ();
   },
   dispose ()
   {
      Time_X3DTimeDependentNode .prototype .dispose .call (this);
      Core_X3DChildNode         .prototype .dispose .call (this);
   },
});

Object .defineProperties (X3DSoundProcessingNode,
{
   typeName:
   {
      value: "X3DSoundProcessingNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
});

const X3DSoundProcessingNode_default_ = X3DSoundProcessingNode;
;

x_ite_Namespace .add ("X3DSoundProcessingNode", "x_ite/Components/Sound/X3DSoundProcessingNode", X3DSoundProcessingNode_default_);
/* harmony default export */ const Sound_X3DSoundProcessingNode = (X3DSoundProcessingNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/Analyser.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function Analyser (executionContext)
{
   Sound_X3DSoundProcessingNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Analyser);

   const audioContext = this .getBrowser () .getAudioContext ();

   this .analyzerNode       = new AnalyserNode (audioContext);
   this .byteFrequencyData  = new Uint8Array (this .analyzerNode .frequencyBinCount);
   this .byteTimeDomainData = new Uint8Array (this .analyzerNode .frequencyBinCount);

   this .analyzerNode .connect (this .getAudioSource ());
}

Object .assign (Object .setPrototypeOf (Analyser .prototype, Sound_X3DSoundProcessingNode .prototype),
{
   initialize ()
   {
      Sound_X3DSoundProcessingNode .prototype .initialize .call (this);

      this ._fftSize               .addInterest ("set_fftSize__",               this);
      this ._minDecibels           .addInterest ("set_decibels__",              this);
      this ._maxDecibels           .addInterest ("set_decibels__",              this);
      this ._smoothingTimeConstant .addInterest ("set_smoothingTimeConstant__", this);

      this .set_fftSize__ ();
      this .set_decibels__ ();
      this .set_smoothingTimeConstant__ ();
   },
   getSoundProcessor ()
   {
      return this .analyzerNode;
   },
   set_fftSize__ ()
   {
      this .analyzerNode .fftSize = Math_Algorithm .clamp (Math_Algorithm .nextPowerOfTwo (this ._fftSize .getValue ()), 32, 32768);

      this ._frequencyBinCount = this .analyzerNode .frequencyBinCount;
   },
   set_decibels__ ()
   {
      const
         minDecibels = Math .min (this ._minDecibels .getValue (), 0),
         maxDecibels = Math .min (this ._maxDecibels .getValue (), 0);

      this .analyzerNode .minDecibels = Math .min (minDecibels, maxDecibels);
      this .analyzerNode .maxDecibels = Math .max (minDecibels, maxDecibels);
   },
   set_smoothingTimeConstant__ ()
   {
      this .analyzerNode .smoothingTimeConstant = Math_Algorithm .clamp (this ._smoothingTimeConstant .getValue (), 0, 1);
   },
   set_time ()
   {
      Sound_X3DSoundProcessingNode .prototype .set_time .call (this);

      const
         analyzerNode      = this .analyzerNode,
         frequencyBinCount = analyzerNode .frequencyBinCount;

      if (this .byteFrequencyData .length !== frequencyBinCount)
      {
         this .byteFrequencyData  = new Uint8Array (frequencyBinCount);
         this .byteTimeDomainData = new Uint8Array (frequencyBinCount);
      }

      this ._byteFrequencyData   .length = frequencyBinCount;
      this ._byteTimeDomainData  .length = frequencyBinCount;
      this ._floatFrequencyData  .length = frequencyBinCount;
      this ._floatTimeDomainData .length = frequencyBinCount;

      analyzerNode .getByteFrequencyData  (this .byteFrequencyData);
      analyzerNode .getByteTimeDomainData (this .byteTimeDomainData);

      this ._byteFrequencyData  .getValue () .set (this .byteFrequencyData);
      this ._byteTimeDomainData .getValue () .set (this .byteTimeDomainData);

      analyzerNode .getFloatFrequencyData  (this ._floatFrequencyData  .shrinkToFit ());
      analyzerNode .getFloatTimeDomainData (this ._floatTimeDomainData .shrinkToFit ());

      this ._byteFrequencyData   .addEvent ();
      this ._byteTimeDomainData  .addEvent ();
      this ._floatFrequencyData  .addEvent ();
      this ._floatTimeDomainData .addEvent ();
   },
});

Object .defineProperties (Analyser,
{
   typeName:
   {
      value: "Analyser",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",              new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",                  new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "fftSize",               new x_ite_Fields .SFInt32 (2048)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "minDecibels",           new x_ite_Fields .SFFloat (-100)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "maxDecibels",           new x_ite_Fields .SFFloat (-30)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "smoothingTimeConstant", new x_ite_Fields .SFFloat (0.8)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "tailTime",              new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "frequencyBinCount",     new x_ite_Fields .SFInt32 ()), // skip test
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "byteFrequencyData",     new x_ite_Fields .MFInt32 ()), // experimental
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "byteTimeDomainData",    new x_ite_Fields .MFInt32 ()), // experimental
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "floatFrequencyData",    new x_ite_Fields .MFFloat ()), // experimental
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "floatTimeDomainData",   new x_ite_Fields .MFFloat ()), // experimental

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCount",          new x_ite_Fields .SFInt32 ()), // skip test
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCountMode",      new x_ite_Fields .SFString ("MAX")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelInterpretation", new x_ite_Fields .SFString ("SPEAKERS")),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "startTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "resumeTime",            new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pauseTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "stopTime",              new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isPaused",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "elapsedTime",           new x_ite_Fields .SFTime ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "children",              new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const Analyser_default_ = Analyser;
;

x_ite_Namespace .add ("Analyser", "x_ite/Components/Sound/Analyser", Analyser_default_);
/* harmony default export */ const Sound_Analyser = (Analyser_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/X3DSoundSourceNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function X3DSoundSourceNode (executionContext)
{
   Core_X3DChildNode         .call (this, executionContext);
   Time_X3DTimeDependentNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DSoundSourceNode);

   const audioContext = this .getBrowser () .getAudioContext ();

   this .gainNode = new GainNode (audioContext);
   this .mediaElement    = null;
}

Object .assign (Object .setPrototypeOf (X3DSoundSourceNode .prototype, Core_X3DChildNode .prototype),
   Time_X3DTimeDependentNode .prototype,
{
   initialize ()
   {
      Core_X3DChildNode         .prototype .initialize .call (this);
      Time_X3DTimeDependentNode .prototype .initialize .call (this);

      this ._gain .addInterest ("set_gain__", this);

      this .set_gain__ ();
   },
   getAudioSource ()
   {
      return this .gainNode;
   },
   setMediaElement (value)
   {
      this .mediaElement ?.pause ();

      this .mediaElement = value;

      if (value)
      {
         // Init mediaElement.

         this .set_loop ();

         // Handle events.

         this ._duration_changed = this .mediaElement .duration;

         this .resetElapsedTime ();

         if (this ._isActive .getValue ())
         {
            if (this ._isPaused .getValue ())
            {
               this .set_pause ();
            }
            else
            {
               if (this .getLiveState ())
                  this .set_start ();
               else
                  this .set_pause ();
            }
         }
         else
         {
            this .set_stop ();
         }
      }
   },
   set_gain__ ()
   {
      this .gainNode .gain .value = this ._gain .getValue ();
   },
   set_pitch ()
   { },
   set_loop ()
   {
      if (this .mediaElement)
         this .mediaElement .loop = this ._loop .getValue ();
   },
   set_start ()
   {
      if (this .mediaElement)
      {
         this .mediaElement .currentTime = 0;
         this .mediaElement .play () .catch (() => this .getBrowser () .startAudioElement (this .mediaElement));
      }
   },
   set_pause ()
   {
      this .mediaElement ?.pause ();
   },
   set_resume ()
   {
      this .mediaElement ?.play () .catch (Function .prototype);
   },
   set_stop ()
   {
      this .mediaElement ?.pause ();
   },
   set_end ()
   {
      if (this ._loop .getValue ())
         return;

      this .stop ();
   },
   set_time ()
   {
      this ._elapsedTime = this .getElapsedTime ();

      if (!this .mediaElement)
         return;

      if (this .mediaElement .currentTime < this .mediaElement .duration)
         return;

      this .set_end ();
   },
   dispose ()
   {
      Time_X3DTimeDependentNode .prototype .dispose .call (this);
      Core_X3DChildNode         .prototype .dispose .call (this);
   },
});

Object .defineProperties (X3DSoundSourceNode,
{
   typeName:
   {
      value: "X3DSoundSourceNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
});

const X3DSoundSourceNode_default_ = X3DSoundSourceNode;
;

x_ite_Namespace .add ("X3DSoundSourceNode", "x_ite/Components/Sound/X3DSoundSourceNode", X3DSoundSourceNode_default_);
/* harmony default export */ const Sound_X3DSoundSourceNode = (X3DSoundSourceNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/AudioClip.js
/* provided dependency */ var AudioClip_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









function AudioClip (executionContext)
{
   Sound_X3DSoundSourceNode .call (this, executionContext);
   Networking_X3DUrlObject       .call (this, executionContext);

   this .addType (Base_X3DConstants .AudioClip);

   const audioContext = this .getBrowser () .getAudioContext ();

   this .urlStack   = new x_ite_Fields .MFString ();
   this .audio      = AudioClip_$("<audio></audio>");
   this .sourceNode = audioContext .createMediaElementSource (this .audio [0]);

   this .sourceNode .connect (this .getAudioSource ());
}

Object .assign (Object .setPrototypeOf (AudioClip .prototype, Sound_X3DSoundSourceNode .prototype),
   Networking_X3DUrlObject .prototype,
{
   initialize ()
   {
      Sound_X3DSoundSourceNode .prototype .initialize .call (this);
      Networking_X3DUrlObject       .prototype .initialize .call (this);

      this .audio
         .on ("abort error", this .setError .bind (this))
         .on ("suspend stalled", this .setTimeout .bind (this))
         .prop ("crossOrigin", "Anonymous")
         .prop ("preload", "auto");

      this .requestImmediateLoad () .catch (Function .prototype);
   },
   set_live__ ()
   {
      Sound_X3DSoundSourceNode .prototype .set_live__ .call (this);
      Networking_X3DUrlObject       .prototype .set_live__ .call (this);
   },
   unloadData ()
   {
      this .setMediaElement (null);
   },
   loadData ()
   {
      this .setMediaElement (null);
      this .urlStack .setValue (this ._url);
      this .audio .on ("canplaythrough", this .setAudio .bind (this));
      this .loadNext ();
   },
   loadNext ()
   {
      if (this .urlStack .length === 0)
      {
         this .audio .off ("canplaythrough");
         this ._duration_changed = -1;
         this .setLoadState (Base_X3DConstants .FAILED_STATE);
         return;
      }

      // Get URL.

      this .URL = new URL (this .urlStack .shift (), this .getExecutionContext () .getBaseURL ());

      if (this .URL .protocol !== "data:")
      {
         if (!this .getCache ())
            this .URL .searchParams .set ("_", Date .now ());
      }

      this .audio .attr ("src", this .URL .href);
      this .audio .get (0) .load ();
   },
   setTimeout (event)
   {
      setTimeout (() =>
      {
         if (this .checkLoadState () === Base_X3DConstants .IN_PROGRESS_STATE)
            this .setError (event);
      },
      3000);
   },
   setError (event)
   {
      if (this .URL .protocol !== "data:")
         console .warn (`Error loading audio '${decodeURI (this .URL .href)}'`, event .type);

      this .loadNext ();
   },
   setAudio ()
   {
      try
      {
         if (DEVELOPMENT)
         {
            if (this .URL .protocol !== "data:")
               console .info (`Done loading audio '${decodeURI (this .URL .href)}'`);
         }

         this .audio .unbind ("canplaythrough");
         this .setMediaElement (this .audio [0]);
         this .setLoadState (Base_X3DConstants .COMPLETE_STATE);
      }
      catch (error)
      {
         this .setError ({ type: error .message });
      }
   },
   dispose ()
   {
      Networking_X3DUrlObject       .prototype .dispose .call (this);
      Sound_X3DSoundSourceNode .prototype .dispose .call (this);
   },
});

Object .defineProperties (AudioClip,
{
   typeName:
   {
      value: "AudioClip",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "source",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",              new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "load",                 new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "url",                  new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "autoRefresh",          new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "autoRefreshTimeLimit", new x_ite_Fields .SFTime (3600)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",                 new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pitch",                new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "loop",                 new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "startTime",            new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "resumeTime",           new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pauseTime",            new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "stopTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isPaused",             new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",             new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "elapsedTime",          new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "duration_changed",     new x_ite_Fields .SFTime (-1)),
      ]),
      enumerable: true,
   },
});

const AudioClip_default_ = AudioClip;
;

x_ite_Namespace .add ("AudioClip", "x_ite/Components/Sound/AudioClip", AudioClip_default_);
/* harmony default export */ const Sound_AudioClip = (AudioClip_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/X3DSoundNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function X3DSoundNode (executionContext)
{
   Core_X3DChildNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DSoundNode);
}

Object .setPrototypeOf (X3DSoundNode .prototype, Core_X3DChildNode .prototype);

Object .defineProperties (X3DSoundNode,
{
   typeName:
   {
      value: "X3DSoundNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
});

const X3DSoundNode_default_ = X3DSoundNode;
;

x_ite_Namespace .add ("X3DSoundNode", "x_ite/Components/Sound/X3DSoundNode", X3DSoundNode_default_);
/* harmony default export */ const Sound_X3DSoundNode = (X3DSoundNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/X3DSoundDestinationNode.js
/* provided dependency */ var X3DSoundDestinationNode_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function X3DSoundDestinationNode (executionContext)
{
   Sound_X3DSoundNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DSoundDestinationNode);

   const audioContext = this .getBrowser () .getAudioContext ();

   this .childNodes = [ ];
   this .gainNode   = new GainNode (audioContext);
}

Object .assign (Object .setPrototypeOf (X3DSoundDestinationNode .prototype, Sound_X3DSoundNode .prototype),
{
   initialize ()
   {
      Sound_X3DSoundNode .prototype .initialize .call (this);

      this .getLive () .addInterest ("set_enabled__", this);

      this ._enabled  .addInterest ("set_enabled__",  this);
      this ._gain     .addInterest ("set_gain__",     this);
      this ._children .addInterest ("set_children__", this);

      this .set_enabled__ ();
      this .set_gain__ ();
      this .set_children__ ();
   },
   getAudioSource ()
   {
      return this .gainNode;
   },
   set_enabled__ ()
   {
      if (this ._enabled .getValue () && this .getLive () .getValue ())
      {
         this ._channelCount          .addInterest ("set_channelCount__",          this);
         this ._channelCountMode      .addInterest ("set_channelCountMode__",      this);
         this ._channelInterpretation .addInterest ("set_channelInterpretation__", this);

         this .gainNode .connect (this .getSoundDestination ());

         this .set_channelCount__ ();
         this .set_channelCountMode__ ();
         this .set_channelInterpretation__ ();
      }
      else
      {
         this ._channelCount          .removeInterest ("set_channelCount__",          this);
         this ._channelCountMode      .removeInterest ("set_channelCountMode__",      this);
         this ._channelInterpretation .removeInterest ("set_channelInterpretation__", this);

         this .gainNode .disconnect ();
      }

      this ._isActive = this ._enabled;
   },
   set_gain__ ()
   {
      this .gainNode .gain .value = this ._gain .getValue ();
   },
   set_channelCount__ ()
   {
      this .getSoundDestination () .channelCount = Math .max (this ._channelCount .getValue (), 1);
   },
   set_channelCountMode__: (function ()
   {
      const channelCountModes = new Set (["max", "clamped-max", "explicit"]);

      return function ()
      {
         const channelCountMode = this ._channelCountMode .getValue () .toLowerCase () .replaceAll ("_", "-");

         this .getSoundDestination () .channelCountMode = channelCountModes .has (channelCountMode) ? channelCountMode : "max";
      };
   })(),
   set_channelInterpretation__: (function ()
   {
      const channelInterpretations = new Set (["speakers", "discrete"]);

      return function ()
      {
         const channelInterpretation = this ._channelInterpretation .getValue () .toLowerCase ();

         this .getSoundDestination () .channelInterpretation = channelInterpretations .has (channelInterpretation) ? channelInterpretation : "speakers";
      };
   })(),
   set_children__ ()
   {
      for (const childNode of this .childNodes)
         X3DSoundDestinationNode_$.try (() => childNode .getAudioSource () .disconnect (this .gainNode));

      this .childNodes .length = 0;

      for (const child of this ._children)
      {
         const childNode = Base_X3DCast (Base_X3DConstants .X3DChildNode, child);

         if (!childNode)
            continue;

         const type = childNode .getType ();

         for (let t = type .length - 1; t >= 0; -- t)
         {
            switch (type [t])
            {
               case Base_X3DConstants .X3DSoundChannelNode:
               case Base_X3DConstants .X3DSoundProcessingNode:
               case Base_X3DConstants .X3DSoundSourceNode:
                  this .childNodes .push (childNode);
                  break;
               default:
                  continue;
            }

            break;
         }
      }

      for (const childNode of this .childNodes)
         X3DSoundDestinationNode_$.try (() => childNode .getAudioSource () .connect (this .gainNode), true);
   },
});

Object .defineProperties (X3DSoundDestinationNode,
{
   typeName:
   {
      value: "X3DSoundDestinationNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
});

const X3DSoundDestinationNode_default_ = X3DSoundDestinationNode;
;

x_ite_Namespace .add ("X3DSoundDestinationNode", "x_ite/Components/Sound/X3DSoundDestinationNode", X3DSoundDestinationNode_default_);
/* harmony default export */ const Sound_X3DSoundDestinationNode = (X3DSoundDestinationNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/AudioDestination.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function AudioDestination (executionContext)
{
   Sound_X3DSoundDestinationNode .call (this, executionContext);

   this .addType (Base_X3DConstants .AudioDestination);

   this .audioElement = new Audio ();
}

Object .assign (Object .setPrototypeOf (AudioDestination .prototype, Sound_X3DSoundDestinationNode .prototype),
{
   initialize ()
   {
      Sound_X3DSoundDestinationNode .prototype .initialize .call (this);

      const audioContext = this .getBrowser () .getAudioContext ();

      this ._mediaDeviceID .addInterest ("set_mediaDeviceID__", this);

      this ._maxChannelCount = audioContext .destination .maxChannelCount;

      this .set_mediaDeviceID__ ();
   },
   getSoundDestination ()
   {
      return this .mediaStreamDestination;
   },
   set_enabled__ ()
   {
      const active = this ._enabled .getValue () && this .getLive () .getValue ();

      if (!!this .mediaStreamDestination === active)
         return;

      if (active)
      {
         const audioContext = this .getBrowser () .getAudioContext ();

         this .mediaStreamDestination  = audioContext .createMediaStreamDestination ();
         this .audioElement .srcObject = this .mediaStreamDestination .stream;

         this .audioElement .play () .catch (() => this .getBrowser () .startAudioElement (this .audioElement));
      }
      else
      {
         this .audioElement .pause ();

         for (const track of this .mediaStreamDestination .stream .getAudioTracks ())
            track .stop ();

         for (const track of this .mediaStreamDestination .stream .getVideoTracks ())
            track .stop ();

         this .mediaStreamDestination = null;
      }

      Sound_X3DSoundDestinationNode .prototype .set_enabled__ .call (this);
   },
   set_mediaDeviceID__ ()
   {
      // Safari has no support yet, as of Aug 2023.
      if (!this .audioElement .setSinkId)
         return;

      this .audioElement .setSinkId (this ._mediaDeviceID .getValue ()) .catch (error =>
      {
         console .error (error .message);

         this .audioElement .setSinkId ("default") .catch (Function .prototype);
      });
   },
});

Object .defineProperties (AudioDestination,
{
   typeName:
   {
      value: "AudioDestination",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",              new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",           new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",               new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",                  new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "mediaDeviceID",         new x_ite_Fields .SFString ()), // skip test

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCount",          new x_ite_Fields .SFInt32 ()), // skip test
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCountMode",      new x_ite_Fields .SFString ("MAX")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelInterpretation", new x_ite_Fields .SFString ("SPEAKERS")),

         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "maxChannelCount",       new x_ite_Fields .SFInt32 ()), // skip test
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "children",              new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const AudioDestination_default_ = AudioDestination;
;

x_ite_Namespace .add ("AudioDestination", "x_ite/Components/Sound/AudioDestination", AudioDestination_default_);
/* harmony default export */ const Sound_AudioDestination = (AudioDestination_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/BiquadFilter.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function BiquadFilter (executionContext)
{
   Sound_X3DSoundProcessingNode .call (this, executionContext);

   this .addType (Base_X3DConstants .BiquadFilter);
}

Object .setPrototypeOf (BiquadFilter .prototype, Sound_X3DSoundProcessingNode .prototype);

Object .defineProperties (BiquadFilter,
{
   typeName:
   {
      value: "BiquadFilter",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",              new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",                  new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "frequency",             new x_ite_Fields .SFFloat (350)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "detune",                new x_ite_Fields .SFFloat (0)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "type",                  new x_ite_Fields .SFString ("LOWPASS")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "qualityFactor",         new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "tailTime",              new x_ite_Fields .SFTime ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCount",          new x_ite_Fields .SFInt32 ()), // skip test
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCountMode",      new x_ite_Fields .SFString ("MAX")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelInterpretation", new x_ite_Fields .SFString ("SPEAKERS")),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "startTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "resumeTime",            new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pauseTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "stopTime",              new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isPaused",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "elapsedTime",           new x_ite_Fields .SFTime ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "children",              new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const BiquadFilter_default_ = BiquadFilter;
;

x_ite_Namespace .add ("BiquadFilter", "x_ite/Components/Sound/BiquadFilter", BiquadFilter_default_);
/* harmony default export */ const Sound_BiquadFilter = (BiquadFilter_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/BufferAudioSource.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function BufferAudioSource (executionContext)
{
   Sound_X3DSoundSourceNode .call (this, executionContext);
   Networking_X3DUrlObject       .call (this, executionContext);

   this .addType (Base_X3DConstants .BufferAudioSource);
}

Object .assign (Object .setPrototypeOf (BufferAudioSource .prototype, Sound_X3DSoundSourceNode .prototype),
   Networking_X3DUrlObject .prototype,
{
   initialize ()
   {
      Sound_X3DSoundSourceNode .prototype .initialize .call (this);
      Networking_X3DUrlObject       .prototype .initialize .call (this);
   },
   dispose ()
   {
      Networking_X3DUrlObject       .prototype .dispose .call (this);
      Sound_X3DSoundSourceNode .prototype .dispose .call (this);
   },
});

Object .defineProperties (BufferAudioSource,
{
   typeName:
   {
      value: "BufferAudioSource",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",              new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",           new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",               new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "load",                  new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "url",                   new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "autoRefresh",           new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "autoRefreshTimeLimit",  new x_ite_Fields .SFTime (3600)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",                  new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "detune",                new x_ite_Fields .SFFloat (0)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "buffer",                new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "bufferDuration",        new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "bufferLength",          new x_ite_Fields .SFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "numberOfChannels",      new x_ite_Fields .SFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "sampleRate",            new x_ite_Fields .SFFloat (0)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "playbackRate",          new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "loopStart",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "loopEnd",               new x_ite_Fields .SFTime ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCount",          new x_ite_Fields .SFInt32 ()), // skip test
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCountMode",      new x_ite_Fields .SFString ("MAX")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelInterpretation", new x_ite_Fields .SFString ("SPEAKERS")),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "loop",                  new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "startTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "resumeTime",            new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pauseTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "stopTime",              new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isPaused",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "elapsedTime",           new x_ite_Fields .SFTime ()),
      ]),
      enumerable: true,
   },
});

const BufferAudioSource_default_ = BufferAudioSource;
;

x_ite_Namespace .add ("BufferAudioSource", "x_ite/Components/Sound/BufferAudioSource", BufferAudioSource_default_);
/* harmony default export */ const Sound_BufferAudioSource = (BufferAudioSource_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/X3DSoundChannelNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function X3DSoundChannelNode (executionContext)
{
   Sound_X3DSoundNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DSoundChannelNode);
}

Object .setPrototypeOf (X3DSoundChannelNode .prototype, Sound_X3DSoundNode .prototype);

Object .defineProperties (X3DSoundChannelNode,
{
   typeName:
   {
      value: "X3DSoundChannelNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
});

const X3DSoundChannelNode_default_ = X3DSoundChannelNode;
;

x_ite_Namespace .add ("X3DSoundChannelNode", "x_ite/Components/Sound/X3DSoundChannelNode", X3DSoundChannelNode_default_);
/* harmony default export */ const Sound_X3DSoundChannelNode = (X3DSoundChannelNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/ChannelMerger.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function ChannelMerger (executionContext)
{
   Sound_X3DSoundChannelNode .call (this, executionContext);

   this .addType (Base_X3DConstants .ChannelMerger);
}

Object .setPrototypeOf (ChannelMerger .prototype, Sound_X3DSoundChannelNode .prototype);

Object .defineProperties (ChannelMerger,
{
   typeName:
   {
      value: "ChannelMerger",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",              new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",                  new x_ite_Fields .SFFloat (1)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCount",          new x_ite_Fields .SFInt32 ()), // skip test
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCountMode",      new x_ite_Fields .SFString ("MAX")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelInterpretation", new x_ite_Fields .SFString ("SPEAKERS")),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "children",              new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const ChannelMerger_default_ = ChannelMerger;
;

x_ite_Namespace .add ("ChannelMerger", "x_ite/Components/Sound/ChannelMerger", ChannelMerger_default_);
/* harmony default export */ const Sound_ChannelMerger = (ChannelMerger_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/ChannelSelector.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function ChannelSelector (executionContext)
{
   Sound_X3DSoundChannelNode .call (this, executionContext);

   this .addType (Base_X3DConstants .ChannelSelector);
}

Object .setPrototypeOf (ChannelSelector .prototype, Sound_X3DSoundChannelNode .prototype);

Object .defineProperties (ChannelSelector,
{
   typeName:
   {
      value: "ChannelSelector",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",              new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",                  new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelSelection",      new x_ite_Fields .SFInt32 (0)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCount",          new x_ite_Fields .SFInt32 ()), // skip test
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCountMode",      new x_ite_Fields .SFString ("MAX")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelInterpretation", new x_ite_Fields .SFString ("SPEAKERS")),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "children",              new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const ChannelSelector_default_ = ChannelSelector;
;

x_ite_Namespace .add ("ChannelSelector", "x_ite/Components/Sound/ChannelSelector", ChannelSelector_default_);
/* harmony default export */ const Sound_ChannelSelector = (ChannelSelector_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/ChannelSplitter.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function ChannelSplitter (executionContext)
{
   Sound_X3DSoundChannelNode .call (this, executionContext);

   this .addType (Base_X3DConstants .ChannelSplitter);
}

Object .setPrototypeOf (ChannelSplitter .prototype, Sound_X3DSoundChannelNode .prototype);

Object .defineProperties (ChannelSplitter,
{
   typeName:
   {
      value: "ChannelSplitter",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",              new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",                  new x_ite_Fields .SFFloat (1)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCount",          new x_ite_Fields .SFInt32 ()), // skip test
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCountMode",      new x_ite_Fields .SFString ("MAX")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelInterpretation", new x_ite_Fields .SFString ("SPEAKERS")),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "children",              new x_ite_Fields .MFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "outputs",               new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const ChannelSplitter_default_ = ChannelSplitter;
;

x_ite_Namespace .add ("ChannelSplitter", "x_ite/Components/Sound/ChannelSplitter", ChannelSplitter_default_);
/* harmony default export */ const Sound_ChannelSplitter = (ChannelSplitter_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/Convolver.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function Convolver (executionContext)
{
   Sound_X3DSoundProcessingNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Convolver);
}

Object .setPrototypeOf (Convolver .prototype, Sound_X3DSoundProcessingNode .prototype);

Object .defineProperties (Convolver,
{
   typeName:
   {
      value: "Convolver",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",              new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",                  new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "buffer",                new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "normalize",             new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "tailTime",              new x_ite_Fields .SFTime ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCount",          new x_ite_Fields .SFInt32 ()), // skip test
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCountMode",      new x_ite_Fields .SFString ("MAX")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelInterpretation", new x_ite_Fields .SFString ("SPEAKERS")),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "startTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "resumeTime",            new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pauseTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "stopTime",              new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isPaused",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "elapsedTime",           new x_ite_Fields .SFTime ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "children",              new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const Convolver_default_ = Convolver;
;

x_ite_Namespace .add ("Convolver", "x_ite/Components/Sound/Convolver", Convolver_default_);
/* harmony default export */ const Sound_Convolver = (Convolver_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/Delay.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function Delay (executionContext)
{
   Sound_X3DSoundProcessingNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Delay);
}

Object .setPrototypeOf (Delay .prototype, Sound_X3DSoundProcessingNode .prototype);

Object .defineProperties (Delay,
{
   typeName:
   {
      value: "Delay",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",              new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",                  new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "delayTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "maxDelayTime",          new x_ite_Fields .SFTime (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "tailTime",              new x_ite_Fields .SFTime ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCount",          new x_ite_Fields .SFInt32 ()), // skip test
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCountMode",      new x_ite_Fields .SFString ("MAX")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelInterpretation", new x_ite_Fields .SFString ("SPEAKERS")),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "startTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "resumeTime",            new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pauseTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "stopTime",              new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isPaused",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "elapsedTime",           new x_ite_Fields .SFTime ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "children",              new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const Delay_default_ = Delay;
;

x_ite_Namespace .add ("Delay", "x_ite/Components/Sound/Delay", Delay_default_);
/* harmony default export */ const Sound_Delay = (Delay_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/DynamicsCompressor.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function DynamicsCompressor (executionContext)
{
   Sound_X3DSoundProcessingNode .call (this, executionContext);

   this .addType (Base_X3DConstants .DynamicsCompressor);
}

Object .setPrototypeOf (DynamicsCompressor .prototype, Sound_X3DSoundProcessingNode .prototype);

Object .defineProperties (DynamicsCompressor,
{
   typeName:
   {
      value: "DynamicsCompressor",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",              new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",           new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",               new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",                  new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "attack",                new x_ite_Fields .SFFloat (0.003)), // TODO: SFTime
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "knee",                  new x_ite_Fields .SFFloat (30)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "ratio",                 new x_ite_Fields .SFFloat (12)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "reduction",             new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "release",               new x_ite_Fields .SFTime (0.25)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "threshold",             new x_ite_Fields .SFFloat (-24)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "tailTime",              new x_ite_Fields .SFTime ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCount",          new x_ite_Fields .SFInt32 ()), // skip test
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCountMode",      new x_ite_Fields .SFString ("MAX")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelInterpretation", new x_ite_Fields .SFString ("SPEAKERS")),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "startTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "resumeTime",            new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pauseTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "stopTime",              new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isPaused",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "elapsedTime",           new x_ite_Fields .SFTime ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "children",              new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const DynamicsCompressor_default_ = DynamicsCompressor;
;

x_ite_Namespace .add ("DynamicsCompressor", "x_ite/Components/Sound/DynamicsCompressor", DynamicsCompressor_default_);
/* harmony default export */ const Sound_DynamicsCompressor = (DynamicsCompressor_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/Gain.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function Gain (executionContext)
{
   Sound_X3DSoundProcessingNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Gain);
}

Object .setPrototypeOf (Gain .prototype, Sound_X3DSoundProcessingNode .prototype);

Object .defineProperties (Gain,
{
   typeName:
   {
      value: "Gain",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",              new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",           new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",               new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",                  new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "tailTime",              new x_ite_Fields .SFTime ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCount",          new x_ite_Fields .SFInt32 ()), // skip test
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCountMode",      new x_ite_Fields .SFString ("MAX")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelInterpretation", new x_ite_Fields .SFString ("SPEAKERS")),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "startTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "resumeTime",            new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pauseTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "stopTime",              new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isPaused",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "elapsedTime",           new x_ite_Fields .SFTime ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "children",              new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const Gain_default_ = Gain;
;

x_ite_Namespace .add ("Gain", "x_ite/Components/Sound/Gain", Gain_default_);
/* harmony default export */ const Sound_Gain = (Gain_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/ListenerPointSource.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function ListenerPointSource (executionContext)
{
   Sound_X3DSoundSourceNode .call (this, executionContext);

   this .addType (Base_X3DConstants .ListenerPointSource);

   this .addChildObjects (Base_X3DConstants .inputOutput, "loop", new x_ite_Fields .SFBool ());

   this ._position .setUnit ("length");
}

Object .setPrototypeOf (ListenerPointSource .prototype, Sound_X3DSoundSourceNode .prototype);

Object .defineProperties (ListenerPointSource,
{
   typeName:
   {
      value: "ListenerPointSource",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",              new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "position",             new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "orientation",          new x_ite_Fields .SFRotation ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",                 new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "dopplerEnabled",       new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "interauralDistance",   new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "trackCurrentView",     new x_ite_Fields .SFBool ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "startTime",            new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "resumeTime",           new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pauseTime",            new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "stopTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isPaused",             new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",             new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "elapsedTime",          new x_ite_Fields .SFTime ()),
      ]),
      enumerable: true,
   },
});

const ListenerPointSource_default_ = ListenerPointSource;
;

x_ite_Namespace .add ("ListenerPointSource", "x_ite/Components/Sound/ListenerPointSource", ListenerPointSource_default_);
/* harmony default export */ const Sound_ListenerPointSource = (ListenerPointSource_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/MicrophoneSource.js
/* provided dependency */ var MicrophoneSource_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function MicrophoneSource (executionContext)
{
   Sound_X3DSoundSourceNode .call (this, executionContext);

   this .addType (Base_X3DConstants .MicrophoneSource);

   this .addChildObjects (Base_X3DConstants .inputOutput, "loop", new x_ite_Fields .SFBool (true));
}

Object .assign (Object .setPrototypeOf (MicrophoneSource .prototype, Sound_X3DSoundSourceNode .prototype),
{
   initialize ()
   {
      Sound_X3DSoundSourceNode .prototype .initialize .call (this);

      this ._mediaDeviceID .addInterest ("set_mediaDeviceID__", this);
   },
   set_mediaDeviceID__ ()
   {
      this .set_stop ();

      if (this ._isActive .getValue ())
         this .set_start ();
   },
   set_start ()
   {
      if (!navigator .mediaDevices)
         return;

      this .restore = false;

      navigator .mediaDevices .getUserMedia ({
         audio:
         {
            deviceId: this ._mediaDeviceID .getValue (),
         },
      })
      .then (stream =>
      {
         const audioContext = this .getBrowser () .getAudioContext ();

         this .mediaStreamSource = audioContext .createMediaStreamSource (stream);

         if (this ._isActive .getValue ())
         {
            if (this ._isPaused .getValue () || !this .getLive () .getValue ())
               this .set_pause ();
            else
               this .set_resume ();
         }
         else
         {
            this .set_stop ();
         }
      })
      .catch (error =>
      {
         console .error (error .message);
      });
   },
   set_pause ()
   {
      if (!this .mediaStreamSource)
         return;

      if (this .getLive () .getValue ())
      {
         MicrophoneSource_$.try (() => this .mediaStreamSource .disconnect (this .getAudioSource ()));

         for (const track of this .mediaStreamSource .mediaStream .getAudioTracks ())
            track .enabled = false;

         for (const track of this .mediaStreamSource .mediaStream .getVideoTracks ())
            track .enabled = false;
      }
      else
      {
         this .set_stop (true);
      }
   },
   set_resume ()
   {
      if (this .restore)
         return this .set_start ();

      if (!this .mediaStreamSource)
         return;

      this .mediaStreamSource .connect (this .getAudioSource ());

      for (const track of this .mediaStreamSource .mediaStream .getAudioTracks ())
         track .enabled = true;

      for (const track of this .mediaStreamSource .mediaStream .getVideoTracks ())
         track .enabled = true;
   },
   set_stop (restore = false)
   {
      if (!this .mediaStreamSource)
         return;

      MicrophoneSource_$.try (() => this .mediaStreamSource .disconnect (this .getAudioSource ()));

      for (const track of this .mediaStreamSource .mediaStream .getAudioTracks ())
         track .stop ();

      for (const track of this .mediaStreamSource .mediaStream .getVideoTracks ())
         track .stop ();

      this .mediaStreamSource = null;
      this .restore           = restore;
   },
});

Object .defineProperties (MicrophoneSource,
{
   typeName:
   {
      value: "MicrophoneSource",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",      new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",   new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",       new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",          new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "mediaDeviceID", new x_ite_Fields .SFString ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "startTime",     new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "resumeTime",    new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pauseTime",     new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "stopTime",      new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isPaused",      new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",      new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "elapsedTime",   new x_ite_Fields .SFTime ()),
      ]),
      enumerable: true,
   },
});

const MicrophoneSource_default_ = MicrophoneSource;
;

x_ite_Namespace .add ("MicrophoneSource", "x_ite/Components/Sound/MicrophoneSource", MicrophoneSource_default_);
/* harmony default export */ const Sound_MicrophoneSource = (MicrophoneSource_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/OscillatorSource.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function OscillatorSource (executionContext)
{
   Sound_X3DSoundSourceNode .call (this, executionContext);

   this .addType (Base_X3DConstants .OscillatorSource);

   this .addChildObjects (Base_X3DConstants .inputOutput, "loop", new x_ite_Fields .SFBool ());

   const audioContext = this .getBrowser () .getAudioContext ();

   this .oscillatorNode = new OscillatorNode (audioContext);
   this .mergerNode     = new ChannelMergerNode (audioContext, { numberOfInputs: 2 });
}

Object .assign (Object .setPrototypeOf (OscillatorSource .prototype, Sound_X3DSoundSourceNode .prototype),
{
   initialize ()
   {
      Sound_X3DSoundSourceNode .prototype .initialize .call (this);

      this ._detune       .addInterest ("set_detune__",       this);
      this ._frequency    .addInterest ("set_frequency__",    this);
      this ._periodicWave .addInterest ("set_periodicWave__", this);

      this .set_periodicWave__ ();
   },
   set_type__: (function ()
   {
      const types = new Set ([
         "sine",
         "square",
         "sawtooth",
         "triangle",
      ]);

      return function ()
      {
         this .periodicWaveNode ._optionsReal .removeInterest ("set_periodicWaveOptions__", this);
         this .periodicWaveNode ._optionsImag .removeInterest ("set_periodicWaveOptions__", this);

         const type = this .periodicWaveNode ._type .getValue () .toLowerCase ();

         if (type === "custom")
         {
            this .periodicWaveNode ._optionsReal .addInterest ("set_periodicWaveOptions__", this);
            this .periodicWaveNode ._optionsImag .addInterest ("set_periodicWaveOptions__", this);

            this .set_periodicWaveOptions__ ();
         }
         else
         {
            this .oscillatorNode .type = types .has (type) ? type : "square";
         }
      };
   })(),
   set_frequency__ ()
   {
      this .oscillatorNode .frequency .value = this ._frequency .getValue ();
   },
   set_detune__ ()
   {
      this .oscillatorNode .detune .value = this ._detune .getValue ();
   },
   set_periodicWave__ ()
   {
      this .periodicWaveNode ?._type .removeInterest ("set_type__", this);

      this .periodicWaveNode = Base_X3DCast (Base_X3DConstants .PeriodicWave, this ._periodicWave)
         ?? this .getBrowser () .getDefaultPeriodicWave ();

      this .periodicWaveNode ._type .addInterest ("set_type__", this);

      this .set_type__ ();
   },
   set_periodicWaveOptions__ ()
   {
      this .oscillatorNode .setPeriodicWave (this .periodicWaveNode .createPeriodicWave ());
   },
   set_start ()
   {
      const audioContext = this .getBrowser () .getAudioContext ();

      this .oscillatorNode = new OscillatorNode (audioContext);

      this .set_type__ ();
      this .set_frequency__ ();
      this .set_detune__ ();

      this .oscillatorNode .connect (this .mergerNode, 0, 0);
      this .oscillatorNode .connect (this .mergerNode, 0, 1);
      this .mergerNode     .connect (this .getAudioSource ());

      this .oscillatorNode .start ();
   },
   set_pause ()
   {
      this .mergerNode .disconnect ();
   },
   set_resume ()
   {
      this .mergerNode .connect (this .getAudioSource ());
   },
   set_stop ()
   {
      this .oscillatorNode .stop ();
      this .oscillatorNode .disconnect ();
   },
});

Object .defineProperties (OscillatorSource,
{
   typeName:
   {
      value: "OscillatorSource",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",     new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",  new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",      new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",         new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "frequency",    new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "detune",       new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "periodicWave", new x_ite_Fields .SFNode ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "startTime",    new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "resumeTime",   new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pauseTime",    new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "stopTime",     new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isPaused",     new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",     new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "elapsedTime",  new x_ite_Fields .SFTime ()),
      ]),
      enumerable: true,
   },
});

const OscillatorSource_default_ = OscillatorSource;
;

x_ite_Namespace .add ("OscillatorSource", "x_ite/Components/Sound/OscillatorSource", OscillatorSource_default_);
/* harmony default export */ const Sound_OscillatorSource = (OscillatorSource_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/PeriodicWave.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function PeriodicWave (executionContext)
{
   Sound_X3DSoundNode .call (this, executionContext);

   this .addType (Base_X3DConstants .PeriodicWave);

   this .real = new Float32Array (2);
   this .imag = new Float32Array (2);
}

Object .assign (Object .setPrototypeOf (PeriodicWave .prototype, Sound_X3DSoundNode .prototype),
{
   createPeriodicWave ()
   {
      const
         audioContext = this .getBrowser () .getAudioContext (),
         optionsReal  = this ._optionsReal .shrinkToFit (),
         optionsImag  = this ._optionsImag .shrinkToFit (),
         length       = Math .max (optionsReal .length, optionsImag .length, 2);

      if (this .real .length !== length)
      {
         this .real = new Float32Array (length);
         this .imag = new Float32Array (length);
      }

      this .real .set (optionsReal);
      this .imag .set (optionsImag);

      return audioContext .createPeriodicWave (this .real, this .imag);
   },
});

Object .defineProperties (PeriodicWave,
{
   typeName:
   {
      value: "PeriodicWave",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "periodicWave",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",      new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",   new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",       new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "type",          new x_ite_Fields .SFString ("SQUARE")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "optionsReal",   new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "optionsImag",   new x_ite_Fields .MFFloat ()),
      ]),
      enumerable: true,
   },
});

const PeriodicWave_default_ = PeriodicWave;
;

x_ite_Namespace .add ("PeriodicWave", "x_ite/Components/Sound/PeriodicWave", PeriodicWave_default_);
/* harmony default export */ const Sound_PeriodicWave = (PeriodicWave_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/Sound.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/















function Sound (executionContext)
{
   Sound_X3DSoundNode .call (this, executionContext);

   this .addType (Base_X3DConstants .Sound);

   this .addChildObjects (Base_X3DConstants .outputOnly, "traversed", new x_ite_Fields .SFBool (true));

   this ._location .setUnit ("length");
   this ._minBack  .setUnit ("length");
   this ._minFront .setUnit ("length");
   this ._maxBack  .setUnit ("length");
   this ._maxFront .setUnit ("length");

   this .childNodes       = [ ];
   this .currentTraversed = true;
}

Object .assign (Object .setPrototypeOf (Sound .prototype, Sound_X3DSoundNode .prototype),
{
   initialize ()
   {
      Sound_X3DSoundNode .prototype .initialize .call (this);

      const
         audioContext  = this .getBrowser () .getAudioContext (),
         splitterNode  = new ChannelSplitterNode (audioContext, { numberOfOutputs: 2 }),
         mergerNode    = new ChannelMergerNode (audioContext, { numberOfInputs: 2 }),
         gainLeftNode  = new GainNode (audioContext, { gain: 0 }),
         gainRightNode = new GainNode (audioContext, { gain: 0 });

      splitterNode  .connect (gainLeftNode, 0);
      splitterNode  .connect (gainRightNode, 1);
      gainLeftNode  .connect (mergerNode, 0, 0);
      gainRightNode .connect (mergerNode, 0, 1);
      mergerNode    .connect (audioContext .destination);

      this .splitterNode  = splitterNode;
      this .gainLeftNode  = gainLeftNode;
      this .gainRightNode = gainRightNode;

      this .getLive ()  .addInterest ("set_live__", this);
      this ._traversed .addInterest ("set_live__", this);

      this ._source   .addInterest ("set_children__", this);
      this ._children .addInterest ("set_children__", this);

      this .set_live__ ();
      this .set_children__ ();
   },
   setTraversed (value)
   {
      if (value)
      {
         if (this ._traversed .getValue () === false)
            this ._traversed = true;
      }
      else
      {
         if (this .currentTraversed !== this ._traversed .getValue ())
            this ._traversed = this .currentTraversed;
      }

      this .currentTraversed = value;
   },
   getTraversed ()
   {
      return this .currentTraversed;
   },
   setVolume (volume, pan = 0.5)
   {
      this .gainLeftNode  .gain .value = volume * (1 - pan ** 2);
      this .gainRightNode .gain .value = volume * (1 - (1 - pan) ** 2);
   },
   set_live__ ()
   {
      if (this .getLive () .getValue () && this ._traversed .getValue ())
      {
         this .getBrowser () .sensorEvents () .addInterest ("update", this);
      }
      else
      {
         this .getBrowser () .sensorEvents () .removeInterest ("update", this);
         this .setVolume (0);
      }
   },
   set_children__ ()
   {
      for (const childNode of this .childNodes)
         childNode .getAudioSource () .disconnect (this .splitterNode);

      this .childNodes .length = 0;

      const sourceNode = Base_X3DCast (Base_X3DConstants .X3DSoundSourceNode, this ._source);

      if (sourceNode)
         this .childNodes .push (sourceNode);

      for (const child of this ._children)
      {
         const childNode = Base_X3DCast (Base_X3DConstants .X3DChildNode, child);

         if (!childNode)
            continue;

         const type = childNode .getType ();

         for (let t = type .length - 1; t >= 0; -- t)
         {
            switch (type [t])
            {
               case Base_X3DConstants .X3DSoundChannelNode:
               case Base_X3DConstants .X3DSoundProcessingNode:
               case Base_X3DConstants .X3DSoundSourceNode:
                  this .childNodes .push (childNode);
                  break;
               default:
                  continue;
            }

            break;
         }
      }

      for (const childNode of this .childNodes)
         childNode .getAudioSource () .connect (this .splitterNode);
   },
   update ()
   {
      if (!this .getTraversed ())
         this .setVolume (0);

      this .setTraversed (false);
   },
   traverse: (() =>
   {
      const
         min = { distance: 0, intersection: new Numbers_Vector3 (0, 0, 0) },
         max = { distance: 0, intersection: new Numbers_Vector3 (0, 0, 0) };

      return function (type, renderObject)
      {
         if (type !== Rendering_TraverseType .DISPLAY)
            return;

         if (!this .childNodes .length)
            return;

         // if (!this .sourceNode ._isActive .getValue () || this .sourceNode ._isPaused .getValue ())
         //    return;

         this .setTraversed (true);

         const modelViewMatrix = renderObject .getModelViewMatrix () .get ();

         this .getEllipsoidParameter (modelViewMatrix,
                                      Math .max (this ._maxBack  .getValue (), 0),
                                      Math .max (this ._maxFront .getValue (), 0),
                                      max);

         if (max .distance < 1) // Radius of normalized sphere is 1.
         {
            this .getEllipsoidParameter (modelViewMatrix,
                                         Math .max (this ._minBack  .getValue (), 0),
                                         Math .max (this ._minFront .getValue (), 0),
                                         min);

            const pan = this .getPan (modelViewMatrix);

            if (min .distance < 1) // Radius of normalized sphere is 1.
            {
               this .setVolume (Math_Algorithm .clamp (this ._intensity .getValue (), 0, 1), pan);
            }
            else
            {
               const
                  d1        = max .intersection .magnitude (), // Viewer is here at (0, 0, 0)
                  d2        = max .intersection .distance (min .intersection),
                  d         = Math .min (d1 / d2, 1),
                  intensity = Math_Algorithm .clamp (this ._intensity .getValue (), 0, 1),
                  volume    = intensity * d;

               this .setVolume (volume, pan);
            }
         }
         else
         {
            this .setVolume (0);
         }
      };
   })(),
   getEllipsoidParameter: (() =>
   {
      const
         location        = new Numbers_Vector3 (0, 0, 0),
         sphereMatrix    = new Numbers_Matrix4 (),
         invSphereMatrix = new Numbers_Matrix4 (),
         rotation        = new Numbers_Rotation4 (),
         scale           = new Numbers_Vector3 (1, 1, 1),
         sphere          = new Geometry_Sphere3 (1, Numbers_Vector3 .Zero),
         normal          = new Numbers_Vector3 (0, 0, 0),
         line            = new Geometry_Line3 (Numbers_Vector3 .Zero, Numbers_Vector3 .zAxis),
         enterPoint      = new Numbers_Vector3 (0, 0, 0),
         exitPoint       = new Numbers_Vector3 (0, 0, 0);

      return function (modelViewMatrix, back, front, value)
      {
         /*
          * https://de.wikipedia.org/wiki/Ellipse
          *
          * The ellipsoid is transformed to a sphere for easier calculation and then the viewer position is
          * transformed into this coordinate system. The radius and distance can then be obtained.
          *
          * throws Error
          */

         if (back == 0 || front == 0)
         {
            sphereMatrix .multVecMatrix (value .intersection .assign (this ._location .getValue ()));
            value .distance = 1;
            return;
         }

         const
            a = (back + front) / 2,
            e = a - back,
            b = Math .sqrt (a * a - e * e);

         location .set (0, 0, e);
         scale    .set (b, b, a);
         rotation .setFromToVec (Numbers_Vector3 .zAxis, this ._direction .getValue ());

         sphereMatrix
            .assign (modelViewMatrix)
            .translate (this ._location .getValue ())
            .rotate (rotation)
            .translate (location)
            .scale (scale);

         invSphereMatrix .assign (sphereMatrix) .inverse ();

         const viewer = invSphereMatrix .origin;
         location .negate () .divVec (scale);

         normal .assign (location) .subtract (viewer) .normalize ();
         line .set (viewer, normal);
         sphere .intersectsLine (line, enterPoint, exitPoint);

         value .intersection .assign (sphereMatrix .multVecMatrix (enterPoint));
         value .distance = viewer .magnitude ();
      };
   })(),
   getPan: (function ()
   {
      const location = new Numbers_Vector3 (0, 0, 0);

      return function (modelViewMatrix)
      {
         if (!this ._spatialize .getValue ())
            return 0.5;

         const
            direction = modelViewMatrix .multVecMatrix (location .assign (this ._location .getValue ())) .normalize (),
            pan       = Math .acos (Math_Algorithm .clamp (-direction .dot (Numbers_Vector3 .xAxis), -1, 1)) / Math .PI;

         return pan;
      };
   })(),
});

Object .defineProperties (Sound,
{
   typeName:
   {
      value: "Sound",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",    new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "description", new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "enabled",     new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "spatialize",  new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "intensity",   new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "location",    new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "direction",   new x_ite_Fields .SFVec3f (0, 0, 1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "minBack",     new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "minFront",    new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "maxBack",     new x_ite_Fields .SFFloat (10)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "maxFront",    new x_ite_Fields .SFFloat (10)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "priority",    new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "source",      new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "children",    new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const Sound_default_ = Sound;
;

x_ite_Namespace .add ("Sound", "x_ite/Components/Sound/Sound", Sound_default_);
/* harmony default export */ const Sound_Sound = (Sound_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/SpatialSound.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function SpatialSound (executionContext)
{
   Sound_X3DSoundNode .call (this, executionContext);

   this .addType (Base_X3DConstants .SpatialSound);

   this ._location .setUnit ("length");
}

Object .setPrototypeOf (SpatialSound .prototype, Sound_X3DSoundNode .prototype);

Object .defineProperties (SpatialSound,
{
   typeName:
   {
      value: "SpatialSound",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",    new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "description", new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "enabled",     new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "spatialize",        new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "coneInnerAngle",    new x_ite_Fields .SFFloat (6.2832)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "coneOuterAngle",    new x_ite_Fields .SFFloat (6.2832)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "coneOuterGain",     new x_ite_Fields .SFFloat (0)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "direction",         new x_ite_Fields .SFVec3f (0, 0, 1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "distanceModel",     new x_ite_Fields .SFString ("INVERSE")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "dopplerEnabled",    new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "enableHRTF",        new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "gain",              new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "intensity",         new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "location",          new x_ite_Fields .SFVec3f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "maxDistance",       new x_ite_Fields .SFFloat (10000)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "priority",          new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "referenceDistance", new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "rolloffFactor",     new x_ite_Fields .SFFloat (1)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "children",    new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const SpatialSound_default_ = SpatialSound;
;

x_ite_Namespace .add ("SpatialSound", "x_ite/Components/Sound/SpatialSound", SpatialSound_default_);
/* harmony default export */ const Sound_SpatialSound = (SpatialSound_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/StreamAudioDestination.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function StreamAudioDestination (executionContext)
{
   Sound_X3DSoundDestinationNode .call (this, executionContext);

   this .addType (Base_X3DConstants .StreamAudioDestination);

   const audioContext = this .getBrowser () .getAudioContext ();

   this .mediaStreamDestination = audioContext .createMediaStreamDestination ();
}

Object .assign (Object .setPrototypeOf (StreamAudioDestination .prototype, Sound_X3DSoundDestinationNode .prototype),
{
   initialize ()
   {
      Sound_X3DSoundDestinationNode .prototype .initialize .call (this);

      this ._streamIdentifier [0] = this .mediaStreamDestination .stream .id;
   },
   getSoundDestination ()
   {
      return this .mediaStreamDestination;
   },
});

Object .defineProperties (StreamAudioDestination,
{
   typeName:
   {
      value: "StreamAudioDestination",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",              new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",           new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",               new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",                  new x_ite_Fields .SFFloat (1)),
         // new X3DFieldDefinition (X3DConstants .inputOutput, "mediaDeviceID",         new Fields .SFString ()), // skip test

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCount",          new x_ite_Fields .SFInt32 ()), // skip test
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCountMode",      new x_ite_Fields .SFString ("MAX")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelInterpretation", new x_ite_Fields .SFString ("SPEAKERS")),

         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "streamIdentifier",      new x_ite_Fields .MFString ()), // skip test
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "children",              new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const StreamAudioDestination_default_ = StreamAudioDestination;
;

x_ite_Namespace .add ("StreamAudioDestination", "x_ite/Components/Sound/StreamAudioDestination", StreamAudioDestination_default_);
/* harmony default export */ const Sound_StreamAudioDestination = (StreamAudioDestination_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/StreamAudioSource.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function StreamAudioSource (executionContext)
{
   Sound_X3DSoundSourceNode .call (this, executionContext);

   this .addType (Base_X3DConstants .StreamAudioSource);

   this .addChildObjects (Base_X3DConstants .inputOutput, "loop", new x_ite_Fields .SFBool ());
}

Object .setPrototypeOf (StreamAudioSource .prototype, Sound_X3DSoundSourceNode .prototype);

Object .defineProperties (StreamAudioSource,
{
   typeName:
   {
      value: "StreamAudioSource",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",         new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",      new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",          new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",             new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "streamIdentifier", new x_ite_Fields .MFString ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "startTime",        new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "resumeTime",       new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pauseTime",        new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "stopTime",         new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isPaused",         new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",         new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "elapsedTime",      new x_ite_Fields .SFTime ()),
      ]),
      enumerable: true,
   },
});

const StreamAudioSource_default_ = StreamAudioSource;
;

x_ite_Namespace .add ("StreamAudioSource", "x_ite/Components/Sound/StreamAudioSource", StreamAudioSource_default_);
/* harmony default export */ const Sound_StreamAudioSource = (StreamAudioSource_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound/WaveShaper.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function WaveShaper (executionContext)
{
   Sound_X3DSoundProcessingNode .call (this, executionContext);

   this .addType (Base_X3DConstants .WaveShaper);
}

Object .setPrototypeOf (WaveShaper .prototype, Sound_X3DSoundProcessingNode .prototype);

Object .defineProperties (WaveShaper,
{
   typeName:
   {
      value: "WaveShaper",
      enumerable: true,
   },
   componentName:
   {
      value: "Sound",
      enumerable: true,
   },
   containerField:
   {
      value: "children",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["4.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "enabled",              new x_ite_Fields .SFBool (true)),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "gain",                  new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "curve",                 new x_ite_Fields .MFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "oversample",            new x_ite_Fields .SFString ("NONE")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "tailTime",              new x_ite_Fields .SFTime ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCount",          new x_ite_Fields .SFInt32 ()), // skip test
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelCountMode",      new x_ite_Fields .SFString ("MAX")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "channelInterpretation", new x_ite_Fields .SFString ("SPEAKERS")),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "startTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "resumeTime",            new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "pauseTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "stopTime",              new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isPaused",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "isActive",              new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,  "elapsedTime",           new x_ite_Fields .SFTime ()),

         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "children",              new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const WaveShaper_default_ = WaveShaper;
;

x_ite_Namespace .add ("WaveShaper", "x_ite/Components/Sound/WaveShaper", WaveShaper_default_);
/* harmony default export */ const Sound_WaveShaper = (WaveShaper_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Sound.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




























const Components_Sound_default_ = {
   name: "Sound",
   concreteNodes:
   [
      Sound_Analyser,
      Sound_AudioClip,
      Sound_AudioDestination,
      Sound_BiquadFilter,
      Sound_BufferAudioSource,
      Sound_ChannelMerger,
      Sound_ChannelSelector,
      Sound_ChannelSplitter,
      Sound_Convolver,
      Sound_Delay,
      Sound_DynamicsCompressor,
      Sound_Gain,
      Sound_ListenerPointSource,
      Sound_MicrophoneSource,
      Sound_OscillatorSource,
      Sound_PeriodicWave,
      Sound_Sound,
      Sound_SpatialSound,
      Sound_StreamAudioDestination,
      Sound_StreamAudioSource,
      Sound_WaveShaper,
   ],
   abstractNodes:
   [
      Sound_X3DSoundChannelNode,
      Sound_X3DSoundDestinationNode,
      Sound_X3DSoundNode,
      Sound_X3DSoundProcessingNode,
      Sound_X3DSoundSourceNode,
   ],
};
;

x_ite_Namespace .add ("Sound", "x_ite/Components/Sound", Components_Sound_default_);
/* harmony default export */ const Components_Sound = (Components_Sound_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Texturing/GifMedia.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

function GifMedia (gif, movieTexture)
{
   let
      playbackRate = 1,
      cycle        = 0,
      loop         = false;

   Object .defineProperties (gif,
   {
      currentTime:
      {
         get ()
         {
            if (!loop && cycle < this .cycle)
               return this .duration;

            return (movieTexture ._elapsedTime * playbackRate) % this .duration;
         },
         set: Function .prototype,
      },
      duration:
      {
         get ()
         {
            return this .get_duration_ms () / 1000;
         },
      },
      loop:
      {
         get ()
         {
            return loop;
         },
         set (value)
         {
            cycle = this .cycle;
            loop  = value;
         },
      },
      cycle:
      {
         get ()
         {
            return Math .floor (movieTexture ._elapsedTime / this .duration);
         },
      },
      currentFrame:
      {
         get ()
         {
            const length = this .get_length ();

            return this .get_frames () [Math .max (Math .ceil (this .currentTime / this .duration * length) - 1, 0)];
         },
      },
      play:
      {
         value ()
         {
            cycle = this .cycle;
            return Promise .resolve ();
         },
      },
      playbackRate:
      {
         get ()
         {
            return playbackRate;
         },
         set (value)
         {
            playbackRate = value;
         },
      },
   });
}

const GifMedia_default_ = GifMedia;
;

x_ite_Namespace .add ("GifMedia", "x_ite/Browser/Texturing/GifMedia", GifMedia_default_);
/* harmony default export */ const Texturing_GifMedia = (GifMedia_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing/MovieTexture.js
/* provided dependency */ var MovieTexture_$ = __webpack_require__(659);
/* provided dependency */ var SuperGif = __webpack_require__(357);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/












function MovieTexture (executionContext)
{
   Texturing_X3DTexture2DNode   .call (this, executionContext);
   Sound_X3DSoundSourceNode .call (this, executionContext);
   Networking_X3DUrlObject       .call (this, executionContext);

   this .addType (Base_X3DConstants .MovieTexture);

   const audioContext = this .getBrowser () .getAudioContext ();

   this .urlStack   = new x_ite_Fields .MFString ();
   this .video      = MovieTexture_$("<video></video>");
   this .sourceNode = audioContext .createMediaElementSource (this .video [0]);

   this .sourceNode .connect (this .getAudioSource ());
}

Object .assign (Object .setPrototypeOf (MovieTexture .prototype, Texturing_X3DTexture2DNode .prototype),
   Sound_X3DSoundSourceNode .prototype,
   Networking_X3DUrlObject .prototype,
{
   initialize ()
   {
      Texturing_X3DTexture2DNode   .prototype .initialize .call (this);
      Sound_X3DSoundSourceNode .prototype .initialize .call (this);
      Networking_X3DUrlObject       .prototype .initialize .call (this);

      this ._speed .addInterest ("set_speed__", this);

      this .video
         .on ("abort error", this .setError .bind (this))
         .on ("suspend stalled", this .setTimeout .bind (this))
         .prop ("crossOrigin", "Anonymous")
         .prop ("preload", "auto");

      this .requestImmediateLoad () .catch (Function .prototype);
   },
   set_live__ ()
   {
      Sound_X3DSoundSourceNode .prototype .set_live__ .call (this);
      Networking_X3DUrlObject       .prototype .set_live__ .call (this);
   },
   unloadData ()
   {
      this .clearTexture ();
   },
   loadData ()
   {
      delete this .gif;
      this .setMediaElement (null);
      this .urlStack .setValue (this ._url);
      this .video .on ("canplaythrough", this .setVideo .bind (this));
      this .loadNext ();
   },
   loadNext ()
   {
      if (this .urlStack .length === 0)
      {
         this .video .off ("canplaythrough");
         this ._duration_changed = -1;
         this .clearTexture ();
         this .setLoadState (Base_X3DConstants .FAILED_STATE);
         return;
      }

      // Get URL.

      this .URL = new URL (this .urlStack .shift (), this .getExecutionContext () .getBaseURL ());

      if (this .URL .protocol !== "data:")
      {
         if (!this .getCache ())
            this .URL .searchParams .set ("_", Date .now ());
      }

      if (this .URL .pathname .endsWith (".gif"))
      {
         const
            img = MovieTexture_$("<img></img>") .appendTo (MovieTexture_$("<div></div>")),
            gif = new SuperGif ({ gif: img [0], on_error: type => this .setError ({ type: type }) });

         gif .load_url (this .URL, this .setGif .bind (this, gif));

         this .setTimeout ({ type: "timeout" });
      }
      else
      {
         this .video .attr ("src", this .URL .href);
         this .video .get (0) .load ();
      }
   },
   setTimeout (event)
   {
      setTimeout (() =>
      {
         if (this .checkLoadState () === Base_X3DConstants .IN_PROGRESS_STATE)
            this .setError (event);
      },
      3000);
   },
   setError (event)
   {
      if (this .URL .protocol !== "data:")
         console .warn (`Error loading movie '${decodeURI (this .URL .href)}'`, event .type);

      this .loadNext ();
   },
   setVideo ()
   {
      try
      {
         if (DEVELOPMENT)
         {
            if (this .URL .protocol !== "data:")
               console .info (`Done loading movie '${decodeURI (this .URL .href)}'`);
         }

         this .video .unbind ("canplaythrough");

         const
            video  = this .video [0],
            width  = video .videoWidth,
            height = video .videoHeight;

         if (!Math_Algorithm .isPowerOfTwo (width) || !Math_Algorithm .isPowerOfTwo (height))
            throw new Error ("The movie texture is a non power-of-two texture.");

         this .setMediaElement (this .video [0]);
         this .setTexture (width, height, false, video, true);
         this .setLoadState (Base_X3DConstants .COMPLETE_STATE);

         this .set_speed__ ();
      }
      catch (error)
      {
         // Catch security error from cross origin requests.
         this .setError ({ type: error .message });
      }
   },
   setGif (gif)
   {
      try
      {
         this .gif = gif;

         Texturing_GifMedia (gif, this);

         gif .pause ();

         this .setMediaElement (gif);
         this .setTexture (gif .get_canvas () .width, gif .get_canvas () .height, false, gif .get_frames () [0] .data, true);
         this .setLoadState (Base_X3DConstants .COMPLETE_STATE);

         this .set_speed__ ();
      }
      catch (error)
      {
         // Catch security error from cross origin requests.
         this .setError ({ type: error .message });
      }
   },
   set_speed__ ()
   {
      if (this .gif)
         this .gif .playbackRate = this ._speed .getValue ();

      this .video [0] .playbackRate = this ._speed .getValue ();
   },
   set_time ()
   {
      Sound_X3DSoundSourceNode .prototype .set_time .call (this);

      if (this .checkLoadState () !== Base_X3DConstants .COMPLETE_STATE)
         return;

      this .updateTexture (this .gif ?.currentFrame .data ?? this .video [0], true);
   },
   traverse: Texturing_X3DTexture2DNode .prototype .traverse,
   dispose ()
   {
      Networking_X3DUrlObject       .prototype .dispose .call (this);
      Sound_X3DSoundSourceNode .prototype .dispose .call (this);
      Texturing_X3DTexture2DNode   .prototype .dispose .call (this);
   },
});

Object .defineProperties (MovieTexture,
{
   typeName:
   {
      value: "MovieTexture",
      enumerable: true,
   },
   componentName:
   {
      value: "Texturing",
      enumerable: true,
   },
   containerField:
   {
      value: "texture",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",             new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "description",          new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "enabled",              new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "load",                 new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "url",                  new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "autoRefresh",          new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "autoRefreshTimeLimit", new x_ite_Fields .SFTime (3600)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "gain",                 new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "speed",                new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "pitch",                new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "loop",                 new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "startTime",            new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "resumeTime",           new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "pauseTime",            new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "stopTime",             new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isPaused",             new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "isActive",             new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "elapsedTime",          new x_ite_Fields .SFTime ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly,     "duration_changed",     new x_ite_Fields .SFTime (-1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "repeatS",              new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "repeatT",              new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "textureProperties",    new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const MovieTexture_default_ = MovieTexture;
;

x_ite_Namespace .add ("MovieTexture", "x_ite/Components/Texturing/MovieTexture", MovieTexture_default_);
/* harmony default export */ const Texturing_MovieTexture = (MovieTexture_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing/MultiTexture.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/











function MultiTexture (executionContext)
{
   Texturing_X3DTextureNode .call (this, executionContext);

   this .addType (Base_X3DConstants .MultiTexture);

   this .addChildObjects (Base_X3DConstants .outputOnly, "loadState", new x_ite_Fields .SFInt32 (Base_X3DConstants .NOT_STARTED_STATE));

   const browser = this .getBrowser ();

   this .maxTextures  = browser .getMaxTextures ()
   this .color        = new Float32Array (4);
   this .modes        = [ ];
   this .alphaModes   = [ ];
   this .sources      = [ ];
   this .functions    = [ ];
   this .textureNodes = [ ];
}

Object .assign (Object .setPrototypeOf (MultiTexture .prototype, Texturing_X3DTextureNode .prototype),
{
   initialize ()
   {
      Texturing_X3DTextureNode .prototype .initialize .call (this);

      this ._color    .addInterest ("set_color__",    this);
      this ._alpha    .addInterest ("set_alpha__",    this);
      this ._mode     .addInterest ("set_mode__",     this);
      this ._source   .addInterest ("set_source__",   this);
      this ._function .addInterest ("set_function__", this);
      this ._texture  .addInterest ("set_texture__",  this);

      this .set_color__ ();
      this .set_alpha__ ();
      this .set_mode__ ();
      this .set_source__ ();
      this .set_function__ ();
      this .set_texture__ ();

      this ._loadState = Base_X3DConstants .COMPLETE_STATE;
   },
   getCount ()
   {
      return Math .min (this .maxTextures, this .textureNodes .length);
   },
   getMode (index)
   {
      if (index < this .modes .length)
         return this .modes [index];

      return Texturing_ModeType .MODULATE;
   },
   getAlphaMode (index)
   {
      if (index < this .alphaModes .length)
         return this .alphaModes [index];

      return Texturing_ModeType .MODULATE;
   },
   getSource (index)
   {
      if (index < this .sources .length)
         return this .sources [index];

      return Texturing_SourceType .DEFAULT;
   },
   getFunction (index)
   {
      if (index < this .functions .length)
         return this .functions [index];

      return Texturing_FunctionType .DEFAULT;
   },
   set_color__ ()
   {
      this .color [0] = this ._color .r;
      this .color [1] = this ._color .g;
      this .color [2] = this ._color .b;
   },
   set_alpha__ ()
   {
      this .color [3] = this ._alpha;
   },
   set_mode__: (() =>
   {
      const modeTypes = new Map ([
         ["REPLACE",                   Texturing_ModeType .REPLACE],
         ["MODULATE",                  Texturing_ModeType .MODULATE],
         ["MODULATE2X",                Texturing_ModeType .MODULATE2X],
         ["MODULATE4X",                Texturing_ModeType .MODULATE4X],
         ["ADD",                       Texturing_ModeType .ADD],
         ["ADDSIGNED",                 Texturing_ModeType .ADDSIGNED],
         ["ADDSIGNED2X",               Texturing_ModeType .ADDSIGNED2X],
         ["ADDSMOOTH",                 Texturing_ModeType .ADDSMOOTH],
         ["SUBTRACT",                  Texturing_ModeType .SUBTRACT],
         ["BLENDDIFFUSEALPHA",         Texturing_ModeType .BLENDDIFFUSEALPHA],
         ["BLENDTEXTUREALPHA",         Texturing_ModeType .BLENDTEXTUREALPHA],
         ["BLENDFACTORALPHA",          Texturing_ModeType .BLENDFACTORALPHA],
         ["BLENDCURRENTALPHA",         Texturing_ModeType .BLENDCURRENTALPHA],
         ["MODULATEALPHA_ADDCOLOR",    Texturing_ModeType .MODULATEALPHA_ADDCOLOR],
         ["MODULATEINVALPHA_ADDCOLOR", Texturing_ModeType .MODULATEINVALPHA_ADDCOLOR],
         ["MODULATEINVCOLOR_ADDALPHA", Texturing_ModeType .MODULATEINVCOLOR_ADDALPHA],
         ["DOTPRODUCT3",               Texturing_ModeType .DOTPRODUCT3],
         ["SELECTARG1",                Texturing_ModeType .SELECTARG1],
         ["SELECTARG2",                Texturing_ModeType .SELECTARG2],
         ["OFF",                       Texturing_ModeType .OFF],
      ]);

      return function ()
      {
         this .modes      .length = 0;
         this .alphaModes .length = 0;

         for (const modes of this ._mode)
         {
            const mode = modes .split (",");

            for (let m = 0, l = mode .length; m < l; ++ m)
               mode [m] = mode [m] .trim ();

            if (mode .length === 0)
               mode .push ("MODULATE");

            if (mode .length < 2)
               mode .push (mode [0]);

            // RGB

            const modeType = modeTypes .get (mode [0]);

            if (modeType !== undefined)
               this .modes .push (modeType);
            else
               this .modes .push (Texturing_ModeType .MODULATE);

            // Alpha

            const alphaModeType = modeTypes .get (mode [1]);

            if (alphaModeType !== undefined)
               this .alphaModes .push (alphaModeType);
            else
               this .alphaModes .push (Texturing_ModeType .MODULATE);
         }
      };
   })(),
   set_source__: (() =>
   {
      const sourceTypes = new Map ([
         ["DIFFUSE",  Texturing_SourceType .DIFFUSE],
         ["SPECULAR", Texturing_SourceType .SPECULAR],
         ["FACTOR",   Texturing_SourceType .FACTOR],
      ]);

      return function ()
      {
         this .sources .length = 0;

         for (const source of this ._source)
         {
            const sourceType = sourceTypes .get (source);

            if (sourceType !== undefined)
               this .sources .push (sourceType);
            else
               this .sources .push (Texturing_SourceType .DEFAULT);
         }
      };
   })(),
   set_function__: (() =>
   {
      const functionsTypes = new Map ([
         ["COMPLEMENT",     Texturing_FunctionType .COMPLEMENT],
         ["ALPHAREPLICATE", Texturing_FunctionType .ALPHAREPLICATE],
      ]);

      return function ()
      {
         this .functions .length = 0;

         for (const func of this ._function)
         {
            const functionsType = functionsTypes .get (func);

            if (functionsType !== undefined)
               this .functions .push (functionsType);
            else
               this .functions .push (Texturing_FunctionType .DEFAULT);
         }
      };
   })(),
   set_texture__ ()
   {
      this .textureNodes .length = 0;

      for (const node of this ._texture)
      {
         const textureNode = Base_X3DCast (Base_X3DConstants .X3DSingleTextureNode, node);

         if (textureNode)
            this .textureNodes .push (textureNode);
      }
   },
   updateTextureBits (textureBits)
   {
      const
         maxTextures  = this .maxTextures,
         textureNodes = this .textureNodes,
         channels     = Math .min (maxTextures, textureNodes .length);

      for (let i = 0; i < channels; ++ i)
         textureNodes [i] .updateTextureBits (textureBits, i);

      textureBits .set (maxTextures * 2, 1);
   },
   getShaderOptions (options)
   {
      const
         textureNodes = this .textureNodes,
         channels     = Math .min (this .maxTextures, textureNodes .length);

      for (let i = 0; i < channels; ++ i)
         textureNodes [i] .getShaderOptions (options, i);
   },
   traverse (type, renderObject)
   {
      for (const textureNode of this .textureNodes)
         textureNode .traverse (type, renderObject);
   },
   setShaderUniforms (gl, shaderObject, renderObject)
   {
      const
         textureNodes = this .textureNodes,
         channels     = Math .min (this .maxTextures, textureNodes .length);

      gl .uniform4fv (shaderObject .x3d_MultiTextureColor, this .color);

      for (let i = 0; i < channels; ++ i)
      {
         textureNodes [i] .setShaderUniforms (gl, shaderObject, renderObject, shaderObject .x3d_Texture [i]);

         gl .uniform1i  (shaderObject .x3d_MultiTextureMode [i],      this .getMode (i));
         gl .uniform1i  (shaderObject .x3d_MultiTextureAlphaMode [i], this .getAlphaMode (i));
         gl .uniform1i  (shaderObject .x3d_MultiTextureSource [i],    this .getSource (i));
         gl .uniform1i  (shaderObject .x3d_MultiTextureFunction [i],  this .getFunction (i));
      }
   },
});

Object .defineProperties (MultiTexture,
{
   typeName:
   {
      value: "MultiTexture",
      enumerable: true,
   },
   componentName:
   {
      value: "Texturing",
      enumerable: true,
   },
   containerField:
   {
      value: "texture",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",    new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "description", new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "color",       new x_ite_Fields .SFColor (1, 1, 1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "alpha",       new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "mode",        new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "source",      new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "function",    new x_ite_Fields .MFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "texture",     new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const MultiTexture_default_ = MultiTexture;
;

x_ite_Namespace .add ("MultiTexture", "x_ite/Components/Texturing/MultiTexture", MultiTexture_default_);
/* harmony default export */ const Texturing_MultiTexture = (MultiTexture_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing/X3DTextureCoordinateNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function X3DTextureCoordinateNode (executionContext)
{
   Rendering_X3DGeometricPropertyNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DTextureCoordinateNode);
}

Object .setPrototypeOf (X3DTextureCoordinateNode .prototype, Rendering_X3DGeometricPropertyNode .prototype);

Object .defineProperties (X3DTextureCoordinateNode,
{
   typeName:
   {
      value: "X3DTextureCoordinateNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Texturing",
      enumerable: true,
   },
});

const X3DTextureCoordinateNode_default_ = X3DTextureCoordinateNode;
;

x_ite_Namespace .add ("X3DTextureCoordinateNode", "x_ite/Components/Texturing/X3DTextureCoordinateNode", X3DTextureCoordinateNode_default_);
/* harmony default export */ const Texturing_X3DTextureCoordinateNode = (X3DTextureCoordinateNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing/MultiTextureCoordinate.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function MultiTextureCoordinate (executionContext)
{
   Texturing_X3DTextureCoordinateNode .call (this, executionContext);

   this .addType (Base_X3DConstants .MultiTextureCoordinate);

   const browser = this .getBrowser ();

   this .maxTexCoords           = browser .getMaxTexCoords ();
   this .textureCoordinateNodes = [ ];
}

Object .assign (Object .setPrototypeOf (MultiTextureCoordinate .prototype, Texturing_X3DTextureCoordinateNode .prototype),
{
   initialize ()
   {
      Texturing_X3DTextureCoordinateNode .prototype .initialize .call (this);

      this ._texCoord .addInterest ("set_texCoord__", this);

      this .set_texCoord__ ();
   },
   set_texCoord__ ()
   {
      const textureCoordinateNodes = this .textureCoordinateNodes;

      for (const textureCoordinateNode of textureCoordinateNodes)
         textureCoordinateNode .removeInterest ("addNodeEvent", this);

      textureCoordinateNodes .length = 0;

      for (const node of this ._texCoord)
      {
         const textureCoordinateNode = Base_X3DCast (Base_X3DConstants .X3DSingleTextureCoordinateNode, node);

         if (textureCoordinateNode)
            textureCoordinateNodes .push (textureCoordinateNode);
      }

      for (const textureCoordinateNode of textureCoordinateNodes)
         textureCoordinateNode .addInterest ("addNodeEvent", this);
   },
   getCount ()
   {
      return Math .min (this .maxTexCoords, this .textureCoordinateNodes .length);
   },
   isEmpty ()
   {
      return true;
   },
   getSize ()
   {
      return 0;
   },
   init (multiArray)
   {
      const
         textureCoordinateNodes = this .textureCoordinateNodes,
         length                 = Math .min (this .maxTexCoords, textureCoordinateNodes .length);

      for (let i = 0; i < length; ++ i)
         textureCoordinateNodes [i] .init (multiArray);
   },
   addPoint (index, multiArray)
   {
      const
         textureCoordinateNodes = this .textureCoordinateNodes,
         length                 = Math .min (this .maxTexCoords, textureCoordinateNodes .length);

      for (let i = 0; i < length; ++ i)
         textureCoordinateNodes [i] .addPointToChannel (index, multiArray [i]);
   },
   addPoints (array)
   {
      for (const textureCoordinateNode of this .textureCoordinateNodes)
         return textureCoordinateNode .addPoints (array);

      return array;
   },
   getTextureCoordinateMapping (textureCoordinateMapping)
   {
      const
         textureCoordinateNodes = this .textureCoordinateNodes,
         length                 = Math .min (this .maxTexCoords, textureCoordinateNodes .length);

      for (let i = 0; i < length; ++ i)
         textureCoordinateNodes [i] .getTextureCoordinateMapping (textureCoordinateMapping, i);
   },
   setShaderUniforms (gl, shaderObject)
   {
      const
         textureCoordinateNodes = this .textureCoordinateNodes,
         length                 = Math .min (this .maxTexCoords, textureCoordinateNodes .length);

      if (length)
      {
         for (let i = 0; i < length; ++ i)
            textureCoordinateNodes [i] .setShaderUniforms (gl, shaderObject, i);
      }
      else
      {
         this .getBrowser () .getDefaultTextureCoordinate () .setShaderUniforms (gl, shaderObject, 0);
      }
   },
});

Object .defineProperties (MultiTextureCoordinate,
{
   typeName:
   {
      value: "MultiTextureCoordinate",
      enumerable: true,
   },
   componentName:
   {
      value: "Texturing",
      enumerable: true,
   },
   containerField:
   {
      value: "texCoord",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "texCoord", new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const MultiTextureCoordinate_default_ = MultiTextureCoordinate;
;

x_ite_Namespace .add ("MultiTextureCoordinate", "x_ite/Components/Texturing/MultiTextureCoordinate", MultiTextureCoordinate_default_);
/* harmony default export */ const Texturing_MultiTextureCoordinate = (MultiTextureCoordinate_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing/X3DTextureTransformNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function X3DTextureTransformNode (executionContext)
{
   Shape_X3DAppearanceChildNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DTextureTransformNode);
}

Object .setPrototypeOf (X3DTextureTransformNode .prototype, Shape_X3DAppearanceChildNode .prototype);

Object .defineProperties (X3DTextureTransformNode,
{
   typeName:
   {
      value: "X3DTextureTransformNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Texturing",
      enumerable: true,
   },
});

const X3DTextureTransformNode_default_ = X3DTextureTransformNode;
;

x_ite_Namespace .add ("X3DTextureTransformNode", "x_ite/Components/Texturing/X3DTextureTransformNode", X3DTextureTransformNode_default_);
/* harmony default export */ const Texturing_X3DTextureTransformNode = (X3DTextureTransformNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing/MultiTextureTransform.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function MultiTextureTransform (executionContext)
{
   Texturing_X3DTextureTransformNode .call (this, executionContext);

   this .addType (Base_X3DConstants .MultiTextureTransform);

   const browser = this .getBrowser ();

   this .maxTextureTransforms  = browser .getMaxTextureTransforms ();
   this .textureTransformNodes = [ ];
}

Object .assign (Object .setPrototypeOf (MultiTextureTransform .prototype, Texturing_X3DTextureTransformNode .prototype),
{
   initialize ()
   {
      Texturing_X3DTextureTransformNode .prototype .initialize .call (this);

      this ._textureTransform .addInterest ("set_textureTransform__", this);

      this .set_textureTransform__ ();
   },
   set_textureTransform__ ()
   {
      const textureTransformNodes = this .textureTransformNodes;

      textureTransformNodes .length = 0;

      for (const node of this ._textureTransform)
      {
         const textureTransformNode = Base_X3DCast (Base_X3DConstants .X3DSingleTextureTransformNode, node);

         if (textureTransformNode)
            textureTransformNodes .push (textureTransformNode);
      }

      if (!textureTransformNodes .length)
         textureTransformNodes .push (this .getBrowser () .getDefaultTextureTransform ());
   },
   getCount ()
   {
      return Math .min (this .maxTextureTransforms, this .textureTransformNodes .length);
   },
   getTextureTransformMapping (textureTransformMapping)
   {
      const
         textureTransformNodes = this .textureTransformNodes,
         length                = Math .min (this .maxTextureTransforms, textureTransformNodes .length);

      for (let i = 0; i < length; ++ i)
         textureTransformNodes [i] .getTextureTransformMapping (textureTransformMapping, i);
   },
   setShaderUniforms (gl, shaderObject)
   {
      const
         textureTransformNodes = this .textureTransformNodes,
         length                = Math .min (this .maxTextureTransforms, textureTransformNodes .length);

      for (let i = 0; i < length; ++ i)
         textureTransformNodes [i] .setShaderUniforms (gl, shaderObject, i);
   },
   transformPoint (texCoord)
   {
      return this .textureTransformNodes [0] .transformPoint (texCoord);
   },
});

Object .defineProperties (MultiTextureTransform,
{
   typeName:
   {
      value: "MultiTextureTransform",
      enumerable: true,
   },
   componentName:
   {
      value: "Texturing",
      enumerable: true,
   },
   containerField:
   {
      value: "textureTransform",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",         new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "textureTransform", new x_ite_Fields .MFNode ()),
      ]),
      enumerable: true,
   },
});

const MultiTextureTransform_default_ = MultiTextureTransform;
;

x_ite_Namespace .add ("MultiTextureTransform", "x_ite/Components/Texturing/MultiTextureTransform", MultiTextureTransform_default_);
/* harmony default export */ const Texturing_MultiTextureTransform = (MultiTextureTransform_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing/PixelTexture.js
/* provided dependency */ var PixelTexture_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










function PixelTexture (executionContext)
{
   Texturing_X3DTexture2DNode .call (this, executionContext);

   this .addType (Base_X3DConstants .PixelTexture);

   this .addChildObjects (Base_X3DConstants .outputOnly, "loadState", new x_ite_Fields .SFInt32 (Base_X3DConstants .NOT_STARTED_STATE));
}

Object .assign (Object .setPrototypeOf (PixelTexture .prototype, Texturing_X3DTexture2DNode .prototype),
{
   initialize ()
   {
      Texturing_X3DTexture2DNode .prototype .initialize .call (this);

      this ._image .addInterest ("set_image__", this);

      this .canvas1 = PixelTexture_$("<canvas></canvas>");
      this .canvas2 = PixelTexture_$("<canvas></canvas>");

      this .set_image__ ();
   },
   checkLoadState ()
   {
      return this ._loadState .getValue ();
   },
   convert (data, comp, array, length)
   {
      switch (comp)
      {
         case 1:
         {
            for (let i = 0, index = 0; i < length; ++ i, index += 4)
            {
               const pixel = array [i];

               data [index]     =
               data [index + 1] =
               data [index + 2] = pixel & 255;
               data [index + 3] = 255;
            }

            break;
         }
         case 2:
         {
            for (let i = 0, index = 0; i < length; ++ i, index += 4)
            {
               const pixel = array [i];

               data [index]     =
               data [index + 1] =
               data [index + 2] = (pixel >>> 8) & 255;
               data [index + 3] = pixel & 255;
            }

            break;
         }
         case 3:
         {
            for (let i = 0, index = 0; i < length; ++ i, index += 4)
            {
               const pixel = array [i];

               data [index]     = (pixel >>> 16) & 255;
               data [index + 1] = (pixel >>>  8) & 255;
               data [index + 2] = pixel & 255;
               data [index + 3] = 255;
            }

            break;
         }
         case 4:
         {
            for (let i = 0, index = 0; i < length; ++ i, index += 4)
            {
               const pixel = array [i];

               data [index]     = (pixel >>> 24);
               data [index + 1] = (pixel >>> 16) & 255;
               data [index + 2] = (pixel >>>  8) & 255;
               data [index + 3] = pixel & 255;
            }

            break;
         }
      }
   },
   resize (input, inputWidth, inputHeight, outputWidth, outputHeight)
   {
      // Nearest neighbor scaling algorithm for very small images.

      const
         output = new Uint8Array (outputWidth * outputHeight * 4),
         scaleX = outputWidth / inputWidth,
         scaleY = outputHeight / inputHeight;

      for (let y = 0; y < outputHeight; ++ y)
      {
         const
            inputW  = Math .floor (y / scaleY) * inputWidth,
            outputW = y * outputWidth;

         for (let x = 0; x < outputWidth; ++ x)
         {
            const
               index       = (inputW + Math.floor (x / scaleX)) * 4,
               indexScaled = (outputW + x) * 4;

            output [indexScaled]     = input [index];
            output [indexScaled + 1] = input [index + 1];
            output [indexScaled + 2] = input [index + 2];
            output [indexScaled + 3] = input [index + 3];
         }
      }

      return output;
   },
   set_image__ ()
   {
      const
         gl          = this .getBrowser () .getContext (),
         comp        = this ._image .comp,
         array       = this ._image .array,
         transparent = !(comp % 2);

      let
         width  = this ._image .width,
         height = this ._image .height,
         data   = null;

      if (width > 0 && height > 0 && comp > 0 && comp < 5)
      {
         if (gl .getVersion () >= 2 || (Math_Algorithm .isPowerOfTwo (width) && Math_Algorithm .isPowerOfTwo (height)))
         {
            data = new Uint8Array (width * height * 4);

            this .convert (data, comp, array .getValue (), array .length);
         }
         else if (Math .max (width, height) < this .getBrowser () .getMinTextureSize () && ! this ._textureProperties .getValue ())
         {
            data = new Uint8Array (width * height * 4);

            this .convert (data, comp, array .getValue (), array .length);

            const
               inputWidth  = width,
               inputHeight = height;

            width  = Math_Algorithm .nextPowerOfTwo (inputWidth)  * 8;
            height = Math_Algorithm .nextPowerOfTwo (inputHeight) * 8;
            data   = this .resize (data, inputWidth, inputHeight, width, height);
         }
         else
         {
            const
               canvas1   = this .canvas1 [0],
               canvas2   = this .canvas2 [0],
               cx1       = canvas1 .getContext ("2d", { willReadFrequently: true }),
               cx2       = canvas2 .getContext ("2d", { willReadFrequently: true }),
               imageData = cx1 .createImageData (width, height);

            canvas1 .width  = width;
            canvas1 .height = height;

            this .convert (imageData .data, comp, array, array .length);
            cx1 .putImageData (imageData, 0, 0);

            width  = Math_Algorithm .nextPowerOfTwo (width);
            height = Math_Algorithm .nextPowerOfTwo (height);

            canvas2 .width  = width;
            canvas2 .height = height;

            cx2 .clearRect (0, 0, width, height);
            cx2 .drawImage (canvas1, 0, 0, canvas1 .width, canvas1 .height, 0, 0, width, height);

            data = cx2 .getImageData (0, 0, width, height) .data;
         }

         this .setTexture (width, height, transparent, new Uint8Array (data .buffer), false);
         this ._loadState = Base_X3DConstants .COMPLETE_STATE;
      }
      else
      {
         this .clearTexture ();
         this ._loadState = Base_X3DConstants .FAILED_STATE;
      }
   },
});

Object .defineProperties (PixelTexture,
{
   typeName:
   {
      value: "PixelTexture",
      enumerable: true,
   },
   componentName:
   {
      value: "Texturing",
      enumerable: true,
   },
   containerField:
   {
      value: "texture",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",          new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "description",       new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "image",             new x_ite_Fields .SFImage ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "repeatS",           new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "repeatT",           new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "textureProperties", new x_ite_Fields .SFNode ()),
      ]),
      enumerable: true,
   },
});

const PixelTexture_default_ = PixelTexture;
;

x_ite_Namespace .add ("PixelTexture", "x_ite/Components/Texturing/PixelTexture", PixelTexture_default_);
/* harmony default export */ const Texturing_PixelTexture = (PixelTexture_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing/X3DSingleTextureCoordinateNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function X3DSingleTextureCoordinateNode (executionContext)
{
   Texturing_X3DTextureCoordinateNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DSingleTextureCoordinateNode);

   this .texCoordArray = new x_ite_Fields .MFFloat ();
}

Object .assign (Object .setPrototypeOf (X3DSingleTextureCoordinateNode .prototype, Texturing_X3DTextureCoordinateNode .prototype),
{
   getCount ()
   {
      return 1;
   },
   init (multiArray)
   {
      this .texCoordArray .length = 0;

      multiArray .push (this .texCoordArray);
   },
   addPoint (index, multiArray)
   {
      this .addPointToChannel (index, multiArray [0]);
   },
   getTextureCoordinateMapping (textureCoordinateMapping, channel = 0)
   {
      textureCoordinateMapping .set (this ._mapping .getValue () || channel, channel);
   },
   setShaderUniforms (gl, shaderObject, channel = 0)
   {
      gl .uniform1i (shaderObject .x3d_TextureCoordinateGeneratorMode [channel], 0);
   },
});

Object .defineProperties (X3DSingleTextureCoordinateNode,
{
   typeName:
   {
      value: "X3DSingleTextureCoordinateNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Texturing",
      enumerable: true,
   },
});

const X3DSingleTextureCoordinateNode_default_ = X3DSingleTextureCoordinateNode;
;

x_ite_Namespace .add ("X3DSingleTextureCoordinateNode", "x_ite/Components/Texturing/X3DSingleTextureCoordinateNode", X3DSingleTextureCoordinateNode_default_);
/* harmony default export */ const Texturing_X3DSingleTextureCoordinateNode = (X3DSingleTextureCoordinateNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing/TextureCoordinate.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function TextureCoordinate (executionContext)
{
   Texturing_X3DSingleTextureCoordinateNode .call (this, executionContext);

   this .addType (Base_X3DConstants .TextureCoordinate);
}

Object .assign (Object .setPrototypeOf (TextureCoordinate .prototype, Texturing_X3DSingleTextureCoordinateNode .prototype),
{
   initialize ()
   {
      Texturing_X3DSingleTextureCoordinateNode .prototype .initialize .call (this);

      this ._point .addInterest ("set_point__", this);

      this .set_point__ ();
   },
   set_point__ ()
   {
      this .point  = this ._point .getValue ();
      this .length = this ._point .length;
   },
   isEmpty ()
   {
      return this .length === 0;
   },
   getSize ()
   {
      return this .length;
   },
   addPointToChannel (index, array)
   {
      if (index >= 0 && this .length)
      {
         const
            point = this .point,
            i      = (index % this .length) * 2;

         array .push (point [i], point [i + 1], 0, 1);
      }
      else
      {
         array .push (0, 0, 0, 1);
      }
   },
   addPoints (array)
   {
      const
         point  = this .point,
         length = this .length;

      for (let i = 0, p = 0; i < length; ++ i, p += 2)
         array .push (point [p], point [p + 1], 0, 1);

      return array;
   },
});

Object .defineProperties (TextureCoordinate,
{
   typeName:
   {
      value: "TextureCoordinate",
      enumerable: true,
   },
   componentName:
   {
      value: "Texturing",
      enumerable: true,
   },
   containerField:
   {
      value: "texCoord",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata", new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "mapping",  new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "point",    new x_ite_Fields .MFVec2f ()),
      ]),
      enumerable: true,
   },
});

const TextureCoordinate_default_ = TextureCoordinate;
;

x_ite_Namespace .add ("TextureCoordinate", "x_ite/Components/Texturing/TextureCoordinate", TextureCoordinate_default_);
/* harmony default export */ const Texturing_TextureCoordinate = (TextureCoordinate_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing/TextureCoordinateGenerator.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function TextureCoordinateGenerator (executionContext)
{
   Texturing_X3DSingleTextureCoordinateNode .call (this, executionContext);

   this .addType (Base_X3DConstants .TextureCoordinateGenerator);

   this .mode      = TextureCoordinateGeneratorModeType .SPHERE;
   this .parameter = new Float32Array (6);
}

Object .assign (Object .setPrototypeOf (TextureCoordinateGenerator .prototype, Texturing_X3DSingleTextureCoordinateNode .prototype),
{
   initialize ()
   {
      Texturing_X3DSingleTextureCoordinateNode .prototype .initialize .call (this);

      this ._mode      .addInterest ("set_mode__",      this);
      this ._parameter .addInterest ("set_parameter__", this);

      this .set_mode__ ();
      this .set_parameter__ ();
   },
   set_mode__: (() =>
   {
      const modes = new Map ([
         ["SPHERE",                      TextureCoordinateGeneratorModeType .SPHERE],
         ["CAMERASPACENORMAL",           TextureCoordinateGeneratorModeType .CAMERASPACENORMAL],
         ["CAMERASPACEPOSITION",         TextureCoordinateGeneratorModeType .CAMERASPACEPOSITION],
         ["CAMERASPACEREFLECTIONVECTOR", TextureCoordinateGeneratorModeType .CAMERASPACEREFLECTIONVECTOR],
         ["SPHERE-LOCAL",                TextureCoordinateGeneratorModeType .SPHERE_LOCAL],
         ["COORD",                       TextureCoordinateGeneratorModeType .COORD],
         ["COORD-EYE",                   TextureCoordinateGeneratorModeType .COORD_EYE],
         ["NOISE",                       TextureCoordinateGeneratorModeType .NOISE],
         ["NOISE-EYE",                   TextureCoordinateGeneratorModeType .NOISE_EYE],
         ["SPHERE-REFLECT",              TextureCoordinateGeneratorModeType .SPHERE_REFLECT],
         ["SPHERE-REFLECT-LOCAL",        TextureCoordinateGeneratorModeType .SPHERE_REFLECT_LOCAL],
      ]);

      return function ()
      {
         this .mode = modes .get (this ._mode .getValue ());

         if (this .mode === undefined)
            this .mode = TextureCoordinateGeneratorModeType .SPHERE;
      };
   })(),
   set_parameter__ ()
   {
      const length = Math .min (this .parameter .length, this ._parameter .length)

      for (let i = 0; i < length; ++ i)
         this .parameter [i] = this ._parameter [i];

      this .parameter .fill (0, length);
   },
   addPointToChannel (index, array)
   {
      array .push (0, 0, 0, 1);
   },
   addPoints (array)
   {
      return array;
   },
   setShaderUniforms (gl, shaderObject, channel = 0)
   {
      gl .uniform1i  (shaderObject .x3d_TextureCoordinateGeneratorMode [channel],      this .mode);
      gl .uniform1fv (shaderObject .x3d_TextureCoordinateGeneratorParameter [channel], this .parameter);
   },
});

Object .defineProperties (TextureCoordinateGenerator,
{
   typeName:
   {
      value: "TextureCoordinateGenerator",
      enumerable: true,
   },
   componentName:
   {
      value: "Texturing",
      enumerable: true,
   },
   containerField:
   {
      value: "texCoord",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",  new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "mapping",   new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "mode",      new x_ite_Fields .SFString ("SPHERE")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "parameter", new x_ite_Fields .MFFloat ()),
      ]),
      enumerable: true,
   },
});

const TextureCoordinateGenerator_default_ = TextureCoordinateGenerator;
;

x_ite_Namespace .add ("TextureCoordinateGenerator", "x_ite/Components/Texturing/TextureCoordinateGenerator", TextureCoordinateGenerator_default_);
/* harmony default export */ const Texturing_TextureCoordinateGenerator = (TextureCoordinateGenerator_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing/TextureProperties.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








function TextureProperties (executionContext)
{
   Core_X3DNode .call (this, executionContext);

   this .addType (Base_X3DConstants .TextureProperties);

   if (executionContext .getSpecificationVersion () <= 3.3)
   {
      this ._minificationFilter  = "DEFAULT";
      this ._magnificationFilter = "DEFAULT";
      this ._textureCompression  = "DEFAULT";
   }
}

Object .assign (Object .setPrototypeOf (TextureProperties .prototype, Core_X3DNode .prototype),
{
   getBorderWidth ()
   {
      // https://stackoverflow.com/questions/27760277/webgl-border-color-shader?lq=1
      return Math_Algorithm .clamp (this ._borderWidth .getValue (), 0, 1);
   },
   getBoundaryMode: (() =>
   {
      const boundaryModes = new Map ([
         ["CLAMP",             "CLAMP_TO_EDGE"], // "CLAMP"
         ["CLAMP_TO_EDGE",     "CLAMP_TO_EDGE"],
         ["CLAMP_TO_BOUNDARY", "CLAMP_TO_EDGE"], // "CLAMP_TO_BORDER"
         ["MIRRORED_REPEAT",   "MIRRORED_REPEAT"],
         ["REPEAT",            "REPEAT"],
      ]);

      return function (string)
      {
         const boundaryMode = boundaryModes .get (string);

         if (boundaryMode !== undefined)
            return boundaryMode;

         return "REPEAT";
      };
   })(),
   getBoundaryModeS ()
   {
      return this .getBoundaryMode (this ._boundaryModeS .getValue ());
   },
   getBoundaryModeT ()
   {
      return this .getBoundaryMode (this ._boundaryModeT .getValue ());
   },
   getBoundaryModeR ()
   {
      return this .getBoundaryMode (this ._boundaryModeR .getValue ());
   },
   getMinificationFilter: (() =>
   {
      const minificationFilters = new Map ([
         ["AVG_PIXEL_AVG_MIPMAP",         "LINEAR_MIPMAP_LINEAR"],
         ["AVG_PIXEL",                    "LINEAR"],
         ["AVG_PIXEL_NEAREST_MIPMAP",     "LINEAR_MIPMAP_NEAREST"],
         ["NEAREST_PIXEL_AVG_MIPMAP",     "NEAREST_MIPMAP_LINEAR"],
         ["NEAREST_PIXEL_NEAREST_MIPMAP", "NEAREST_MIPMAP_NEAREST"],
         ["NEAREST_PIXEL",                "NEAREST"],
         ["NICEST",                       "LINEAR_MIPMAP_LINEAR"],
         ["FASTEST",                      "NEAREST"],
      ]);

      return function ()
      {
         if (this ._generateMipMaps .getValue ())
         {
            const minificationFilter = minificationFilters .get (this ._minificationFilter .getValue ());

            if (minificationFilter !== undefined)
               return minificationFilter;

            return this .getBrowser () .getDefaultTextureProperties () .getMinificationFilter ();
         }

         return "LINEAR";
      };
   })(),
   getMagnificationFilter: (() =>
   {
      const magnificationFilters = new Map ([
         ["AVG_PIXEL",     "LINEAR"],
         ["NEAREST_PIXEL", "NEAREST"],
         ["NICEST",        "LINEAR"],
         ["FASTEST",       "NEAREST"],
      ]);

      return function ()
      {
         const magnificationFilter = magnificationFilters .get (this ._magnificationFilter .getValue ());

         if (magnificationFilter !== undefined)
            return magnificationFilter;

         // DEFAULT
         return this .getBrowser () .getDefaultTextureProperties () .getMagnificationFilter ();
      };
   })(),
   getTextureCompression: (() =>
   {
      const textureCompressions = new Map ([
         ["DEFAULT", "RGBA"],
         ["NICEST",  "RGBA"],
         ["FASTEST", "RGBA"],
         ["LOW",     "RGBA"],
         ["MEDIUM",  "RGBA"],
         ["HIGH",    "RGBA"],
      ]);

      return function ()
      {
         const
            browser            = this .getBrowser (),
            gl                 = browser .getContext (),
            compressedTexture  = gl .getExtension ("WEBGL_compressed_texture_etc"), // TODO: find suitable compression.
            textureCompression = compressedTexture ? compressedTexture [textureCompressions .get (this ._textureCompression .getValue ())] : undefined;

         if (textureCompression !== undefined)
            return textureCompression;

         // DEFAULT
         return gl .RGBA;
      };
   })(),
});

Object .defineProperties (TextureProperties,
{
   typeName:
   {
      value: "TextureProperties",
      enumerable: true,
   },
   componentName:
   {
      value: "Texturing",
      enumerable: true,
   },
   containerField:
   {
      value: "textureProperties",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["3.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "metadata",            new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "borderColor",         new x_ite_Fields .SFColorRGBA ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "borderWidth",         new x_ite_Fields .SFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "anisotropicDegree",   new x_ite_Fields .SFFloat (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "generateMipMaps",     new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "minificationFilter",  new x_ite_Fields .SFString ("FASTEST")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "magnificationFilter", new x_ite_Fields .SFString ("FASTEST")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "boundaryModeS",       new x_ite_Fields .SFString ("REPEAT")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "boundaryModeT",       new x_ite_Fields .SFString ("REPEAT")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "boundaryModeR",       new x_ite_Fields .SFString ("REPEAT")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "textureCompression",  new x_ite_Fields .SFString ("FASTEST")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput,    "texturePriority",     new x_ite_Fields .SFFloat ()),
      ]),
      enumerable: true,
   },
});

const TextureProperties_default_ = TextureProperties;
;

x_ite_Namespace .add ("TextureProperties", "x_ite/Components/Texturing/TextureProperties", TextureProperties_default_);
/* harmony default export */ const Texturing_TextureProperties = (TextureProperties_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing/X3DSingleTextureTransformNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function X3DSingleTextureTransformNode (executionContext)
{
   Texturing_X3DTextureTransformNode .call (this, executionContext);

   this .addType (Base_X3DConstants .X3DSingleTextureTransformNode);

   this .matrixArray = new Float32Array (Numbers_Matrix4 .Identity);
}

Object .assign (Object .setPrototypeOf (X3DSingleTextureTransformNode .prototype, Texturing_X3DTextureTransformNode .prototype),
{
   getCount ()
   {
      return 1;
   },
   setMatrix (value)
   {
      this .matrixArray .set (value);
   },
   getTextureTransformMapping (textureTransformMapping, channel = 0)
   {
      textureTransformMapping .set (this ._mapping .getValue () || channel, channel);
   },
   setShaderUniforms (gl, shaderObject, channel = 0)
   {
      gl .uniformMatrix4fv (shaderObject .x3d_TextureMatrix [channel], false, this .matrixArray);
   },
   transformPoint (texCoord)
   {
      return Numbers_Matrix4 .prototype .multVecMatrix .call (this .matrixArray, texCoord);
   },
});

Object .defineProperties (X3DSingleTextureTransformNode,
{
   typeName:
   {
      value: "X3DSingleTextureTransformNode",
      enumerable: true,
   },
   componentName:
   {
      value: "Texturing",
      enumerable: true,
   },
});

const X3DSingleTextureTransformNode_default_ = X3DSingleTextureTransformNode;
;

x_ite_Namespace .add ("X3DSingleTextureTransformNode", "x_ite/Components/Texturing/X3DSingleTextureTransformNode", X3DSingleTextureTransformNode_default_);
/* harmony default export */ const Texturing_X3DSingleTextureTransformNode = (X3DSingleTextureTransformNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing/TextureTransform.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










function TextureTransform (executionContext)
{
   Texturing_X3DSingleTextureTransformNode .call (this, executionContext);

   this .addType (Base_X3DConstants .TextureTransform);

   this ._rotation .setUnit ("angle");

   this .matrix = new Numbers_Matrix4 ();
}

Object .assign (Object .setPrototypeOf (TextureTransform .prototype, Texturing_X3DSingleTextureTransformNode .prototype),
{
   initialize ()
   {
      Texturing_X3DSingleTextureTransformNode .prototype .initialize .call (this);

      this .addInterest ("eventsProcessed", this);

      this .eventsProcessed ();
   },
   getMatrix ()
   {
      return this .matrix;
   },
   eventsProcessed: (() =>
   {
      const
         vector  = new Numbers_Vector2 (0, 0),
         matrix3 = new Numbers_Matrix3 ();

      return function ()
      {
         const
            translation = this ._translation .getValue (),
            rotation    = this ._rotation .getValue (),
            scale       = this ._scale .getValue (),
            center      = this ._center .getValue (),
            matrix4     = this .matrix;

         matrix3 .identity ();

         if (! center .equals (Numbers_Vector2 .Zero))
            matrix3 .translate (vector .assign (center) .negate ());

         if (! scale .equals (Numbers_Vector2 .One))
            matrix3 .scale (scale);

         if (rotation !== 0)
            matrix3 .rotate (rotation);

         if (! center .equals (Numbers_Vector2 .Zero))
            matrix3 .translate (center);

         if (! translation .equals (Numbers_Vector2 .Zero))
            matrix3 .translate (translation);

         matrix4 [ 0] = matrix3 [0];
         matrix4 [ 1] = matrix3 [1];
         matrix4 [ 4] = matrix3 [3];
         matrix4 [ 5] = matrix3 [4];
         matrix4 [12] = matrix3 [6];
         matrix4 [13] = matrix3 [7];

         this .setMatrix (matrix4);
      };
   })(),
});

Object .defineProperties (TextureTransform,
{
   typeName:
   {
      value: "TextureTransform",
      enumerable: true,
   },
   componentName:
   {
      value: "Texturing",
      enumerable: true,
   },
   containerField:
   {
      value: "textureTransform",
      enumerable: true,
   },
   specificationRange:
   {
      value: Object .freeze (["2.0", "Infinity"]),
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "metadata",    new x_ite_Fields .SFNode ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "mapping",     new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "translation", new x_ite_Fields .SFVec2f ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "rotation",    new x_ite_Fields .SFFloat ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "scale",       new x_ite_Fields .SFVec2f (1, 1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "center",      new x_ite_Fields .SFVec2f ()),
      ]),
      enumerable: true,
   },
});

const TextureTransform_default_ = TextureTransform;
;

x_ite_Namespace .add ("TextureTransform", "x_ite/Components/Texturing/TextureTransform", TextureTransform_default_);
/* harmony default export */ const Texturing_TextureTransform = (TextureTransform_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Texturing.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



















const Texturing_default_ = {
   name: "Texturing",
   concreteNodes:
   [
      Texturing_ImageTexture,
      Texturing_MovieTexture,
      Texturing_MultiTexture,
      Texturing_MultiTextureCoordinate,
      Texturing_MultiTextureTransform,
      Texturing_PixelTexture,
      Texturing_TextureCoordinate,
      Texturing_TextureCoordinateGenerator,
      Texturing_TextureProperties,
      Texturing_TextureTransform,
   ],
   abstractNodes:
   [
      Texturing_X3DSingleTextureCoordinateNode,
      Texturing_X3DSingleTextureNode,
      Texturing_X3DSingleTextureTransformNode,
      Texturing_X3DTexture2DNode,
      Texturing_X3DTextureCoordinateNode,
      Texturing_X3DTextureNode,
      Texturing_X3DTextureTransformNode,
   ],
};
;

x_ite_Namespace .add ("Texturing", "x_ite/Components/Texturing", Texturing_default_);
/* harmony default export */ const Texturing = (Texturing_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components/Time.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




const Time_default_ = {
   name: "Time",
   concreteNodes:
   [
      Time_TimeSensor,
   ],
   abstractNodes:
   [
      Time_X3DTimeDependentNode,
   ],
};
;

x_ite_Namespace .add ("Time", "x_ite/Components/Time", Time_default_);
/* harmony default export */ const Time = (Time_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Core/Context.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



const extensions = [
   "ANGLE_instanced_arrays",
   "EXT_blend_minmax",
   "EXT_frag_depth",
   "EXT_shader_texture_lod",
   "EXT_texture_filter_anisotropic",
   "OES_element_index_uint",
   "OES_standard_derivatives",
   "OES_texture_float",
   "OES_texture_float_linear",
   "OES_texture_half_float",
   "OES_texture_half_float_linear",
   "OES_vertex_array_object",
   "WEBGL_compressed_texture_s3tc",
   //"WEBGL_debug_renderer_info",
   "WEBGL_debug_shaders",
   "WEBGL_depth_texture",
   "WEBGL_draw_buffers",
   "WEBGL_lose_context",

   "EXT_color_buffer_float",
   "EXT_color_buffer_half_float",
   "EXT_disjoint_timer_query",
   "EXT_disjoint_timer_query_webgl2",
   "EXT_sRGB",
   "WEBGL_color_buffer_float",
   "WEBGL_compressed_texture_astc",
   "WEBGL_compressed_texture_atc",
   "WEBGL_compressed_texture_etc",
   "WEBGL_compressed_texture_etc1",
   "WEBGL_compressed_texture_pvrtc",
   "WEBGL_compressed_texture_s3tc",
   "WEBGL_compressed_texture_s3tc_srgb",

   "EXT_float_blend",
   "OES_fbo_render_mipmap",
   "WEBGL_get_buffer_sub_data_async",
   "WEBGL_multiview",
   "WEBGL_security_sensitive_resources",
   "WEBGL_shared_resources",

   "EXT_clip_cull_distance",
   "WEBGL_debug",
   "WEBGL_dynamic_texture",
   "WEBGL_subarray_uploads",
   "WEBGL_texture_multisample",
   "WEBGL_texture_source_iframe",
   "WEBGL_video_texture",

   "EXT_texture_storage",
   "OES_depth24",
   "WEBGL_debug_shader_precision",
   "WEBGL_draw_elements_no_range_check",
   "WEBGL_subscribe_uniform",
   "WEBGL_texture_from_depth_video",
];

const Context =
{
   create (canvas, version, preserveDrawingBuffer, mobile)
   {
      const options = { preserveDrawingBuffer: preserveDrawingBuffer };

      let gl = null;

      if (version >= 2 && !gl)
      {
         gl = canvas .getContext ("webgl2", { ... options, antialias: false });

         if (gl)
            gl .getVersion = () => 2;
      }

      if (version >= 1 && !gl)
      {
         gl = canvas .getContext ("webgl",              options) ||
              canvas .getContext ("experimental-webgl", options);

         if (gl)
         {
            gl .getVersion = () => 1;

            {
               const ext = gl .getExtension ("OES_vertex_array_object");

               gl .bindVertexArray   =  ext .bindVertexArrayOES   .bind (ext);
               gl .createVertexArray =  ext .createVertexArrayOES .bind (ext);
               gl .deleteVertexArray =  ext .deleteVertexArrayOES .bind (ext);
               gl .isVertexArray     =  ext .isVertexArrayOES     .bind (ext);
            }
         }
      }

      if (!gl)
         throw new Error ("Couldn't create WebGL context.");

      // Load extensions.

      for (const extension of extensions)
         gl .getExtension (extension);

      // Feature detection:

      // If the aliased lineWidth ranges are both 1, gl .lineWidth is probably not possible,
      // thus we disable it completely to prevent webgl errors.

      const aliasedLineWidthRange = gl .getParameter (gl .ALIASED_LINE_WIDTH_RANGE);

      if (aliasedLineWidthRange [0] === 1 && aliasedLineWidthRange [1] === 1)
      {
         gl .lineWidth                     = Function .prototype;
         gl .HAS_FEATURE_TRANSFORMED_LINES = gl .getVersion () >= 2;

         if (DEVELOPMENT)
            console .info ("Lines are transformed if necessary to obtain thick lines.");
      }
      else
      {
         gl .HAS_FEATURE_TRANSFORMED_LINES = false;
      }

      gl .HAS_FEATURE_DEPTH_TEXTURE = gl .getVersion () >= 2 || !! gl .getExtension ("WEBGL_depth_texture");
      gl .HAS_FEATURE_FRAG_DEPTH    = gl .getVersion () >= 2 || !! gl .getExtension ("EXT_frag_depth");

      if (gl .getVersion () === 1)
      {
         const
            color_buffer_float = gl .getExtension ("WEBGL_color_buffer_float"),
            draw_buffers       = gl .getExtension ("WEBGL_draw_buffers");

         gl .RGBA32F               = color_buffer_float .RGBA32F_EXT;
         gl .MAX_COLOR_ATTACHMENTS = draw_buffers .MAX_COLOR_ATTACHMENTS_WEBGL;
         gl .drawBuffers           = draw_buffers .drawBuffersWEBGL .bind (draw_buffers);

         for (let i = 0, length = gl .getParameter(gl .MAX_COLOR_ATTACHMENTS); i < length; ++ i)
         {
            const COLOR_ATTACHMENTi = draw_buffers .COLOR_ATTACHMENT0_WEBGL + i;

            if (gl [`COLOR_ATTACHMENT${i}`] === undefined)
               gl [`COLOR_ATTACHMENT${i}`] = COLOR_ATTACHMENTi;
         }
      }

      if (mobile)
      {
         const color_buffer_half_float = gl .getExtension ("EXT_color_buffer_half_float");

         Object .defineProperty (gl, "RGBA32F",
         {
            value: gl .getVersion () === 1 ? color_buffer_half_float .RGBA16F_EXT : gl .RGBA16F,
         });
      }

      // Async functions

      Object .assign (gl, gl .getVersion () === 1
      ?
      {
         readPixelsAsync: gl .readPixels,
      }
      :
      {
         clientWaitAsync (sync, flags, timeout)
         {
            return new Promise ((resolve, reject) =>
            {
               const check = () =>
               {
                  const result = this .clientWaitSync (sync, flags, 0);

                  switch (result)
                  {
                     case this .WAIT_FAILED:
                     {
                        reject (new Error ("clientWaitSync: WAIT_FAILED"));
                        return;
                     }
                     case this .TIMEOUT_EXPIRED:
                     {
                        setTimeout (check, timeout);
                        return;
                     }
                     default:
                     {
                        resolve ();
                        return;
                     }
                  }
               };

               setTimeout (check);
            });
         },
         getBufferSubDataAsync: async function (target, buffer, srcByteOffset, dstBuffer, /* optional */ dstOffset, /* optional */ length)
         {
            const sync = this .fenceSync (this .SYNC_GPU_COMMANDS_COMPLETE, 0);

            this .flush ();

            await this .clientWaitAsync (sync, 0, 10);

            this .deleteSync (sync);

            this .bindBuffer (target, buffer);
            this .getBufferSubData (target, srcByteOffset, dstBuffer, dstOffset, length);
            this .bindBuffer (target, null);
         },
         readPixelsAsync: async function (x, y, w, h, format, type, dest, dstOffset)
         {
            const buffer = this .createBuffer ();

            this .bindBuffer (this .PIXEL_PACK_BUFFER, buffer);
            this .bufferData (this .PIXEL_PACK_BUFFER, dest .byteLength, this .STREAM_READ);
            this .readPixels (x, y, w, h, format, type, 0);
            this .bindBuffer (this .PIXEL_PACK_BUFFER, null);

            await this .getBufferSubDataAsync (this .PIXEL_PACK_BUFFER, buffer, 0, dest, dstOffset);

            this .deleteBuffer (buffer);
         },
      });

      // Return context.

      return gl;
   },
}

const Context_default_ = Context;
;

x_ite_Namespace .add ("Context", "x_ite/Browser/Core/Context", Context_default_);
/* harmony default export */ const Core_Context = (Context_default_);
;// CONCATENATED MODULE: ./src/locale/de.po.js
const de_po_default_ = `msgid ""
msgstr ""
"Project-Id-Version: X_ITE\n"
"POT-Creation-Date: 2015-12-23 04:56+0100\n"
"PO-Revision-Date: 2015-12-23 04:57+0100\n"
"Last-Translator: Holger Seelig <holger.seelig@yahoo.de>\n"
"Language-Team: \n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.4\n"
"X-Poedit-Basepath: ../x_ite\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-SearchPath-0: .\n"

msgid "Less Properties"
msgstr "Weniger Eigenschaften"

msgid "More Properties"
msgstr "Mehr Eigenschaften"

msgid "Frame rate"
msgstr "Bildrate"

msgid "fps"
msgstr "BpS"

msgid "Speed"
msgstr "Geschwindigkeit"

msgid "m/s"
msgstr ""

msgid "km/h"
msgstr ""

msgid "Browser"
msgstr ""

msgid "ms"
msgstr ""

msgid "X3D total"
msgstr "X3D gesamt"

msgid "Event Processing"
msgstr "Ereignisverarbeitung"

msgid "Pointer"
msgstr "Zeigegerät"

msgid "Camera"
msgstr "Kamera"

msgid "Collision Detection"
msgstr "Kollisionserkennung"

msgid "Rendering"
msgstr "Rendering"

msgid "Number of Shapes"
msgstr "Anzahl der Formen"

msgid "Number of Sensors"
msgstr "Anzahl der Sensoren"

msgid "Browser Timings"
msgstr "Zeitberechnung"

msgid "X_ITE Browser"
msgstr ""

msgid "Viewpoints"
msgstr "Ansichtspunkte"

msgid "Available Viewers"
msgstr "Verfügbare Betrachter"

msgid "Straighten Horizon"
msgstr "Horizont gerade richten"

msgid "Primitive Quality"
msgstr "Qualität der Grundobjekte"

msgid "High"
msgstr "Hoch"

msgid "high"
msgstr "hoch"

msgid "Medium"
msgstr "Mittel"

msgid "medium"
msgstr "mittel"

msgid "Low"
msgstr "Niedrig"

msgid "low"
msgstr "niedrig"

msgid "Texture Quality"
msgstr "Textur Qualität"

msgid "Display Rubberband"
msgstr "Gummiband anzeigen"

msgid "Rubberband"
msgstr "Gummiband"

msgid "on"
msgstr "an"

msgid "off"
msgstr "aus"

msgid "Mute Browser"
msgstr "Browser stumm schalten"

msgid "Browser muted"
msgstr "Browser stumm geschalten"

msgid "Browser unmuted"
msgstr "Browser Ton an"

msgid "Leave Fullscreen"
msgstr "Vollbild verlassen"

msgid "Fullscreen"
msgstr "Vollbild"

msgid "About X_ITE"
msgstr "Über X_ITE"

msgid "Examine Viewer"
msgstr "Untersuchen"

msgid "Walk Viewer"
msgstr "Laufen"

msgid "Fly Viewer"
msgstr "Fliegen"

msgid "Plane Viewer"
msgstr "Ebenen Betrachter"

msgid "Look At Viewer"
msgstr "Auf Objekte zielen"

msgid "None Viewer"
msgstr "Kein Betrachter"

msgid "Points"
msgstr "Punkte"

msgid "Flat"
msgstr "Flach"

msgid "Wireframe"
msgstr "Drahtgittermodel"

msgid "Loading %1 file"
msgstr "Lade %1 Datei"

msgid "Loading %1 files"
msgstr "Lade %1 Dateien"

msgid "Loading done"
msgstr "Fertig mit Laden"

msgid "Failed loading world."
msgstr "Laden der Dateien fehlgeschlagen."

msgid "Show World Info"
msgstr "World Info anzeigen"

msgid "Viewpoint is copied to clipboard."
msgstr "Ansichtspunkt wurde in die Zwischenablage kopiert."
`;
;

x_ite_Namespace .add ("de.po", "locale/de.po", de_po_default_);
/* harmony default export */ const de_po = (de_po_default_);
;// CONCATENATED MODULE: ./src/locale/fr.po.js
const fr_po_default_ = `msgid ""
msgstr ""
"Project-Id-Version: X_ITE\n"
"POT-Creation-Date: 2015-12-23 04:58+0100\n"
"PO-Revision-Date: 2015-12-23 05:07+0100\n"
"Last-Translator: Holger Seelig <holger.seelig@yahoo.de>\n"
"Language-Team: \n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.4\n"
"X-Poedit-Basepath: ../x_ite\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-SearchPath-0: .\n"

msgid "Less Properties"
msgstr "Moins de Propriétés"

msgid "More Properties"
msgstr "Plus de Propriétés"

msgid "Frame rate"
msgstr "Fréquence d'Images"

msgid "fps"
msgstr "fps"

msgid "Speed"
msgstr "Vélocité"

msgid "m/s"
msgstr ""

msgid "km/h"
msgstr ""

msgid "Browser"
msgstr "X_ITE Navigateur"

msgid "ms"
msgstr ""

msgid "X3D total"
msgstr "X3D total"

msgid "Event Processing"
msgstr "Traitement des Événements"

msgid "Pointer"
msgstr "Pointeur"

msgid "Camera"
msgstr "Caméra"

msgid "Collision Detection"
msgstr "Détection des Collisions"

msgid "Rendering"
msgstr "Rendement"

msgid "Number of Shapes"
msgstr "Nombre de Formes"

msgid "Number of Sensors"
msgstr "Nombre de Senseurs"

msgid "Browser Timings"
msgstr "Calcul du Temps"

msgid "X_ITE Browser"
msgstr "X_ITE Navigateur"

msgid "Viewpoints"
msgstr "Points de Vue"

msgid "Available Viewers"
msgstr "Visionneurs disponibles"

msgid "Straighten Horizon"
msgstr "Redresser l'Horizon"

msgid "Primitive Quality"
msgstr "Qualité des Objets simples"

msgid "High"
msgstr "Haut"

msgid "high"
msgstr "haut"

msgid "Medium"
msgstr "Moyenne"

msgid "medium"
msgstr "moyenne"

msgid "Low"
msgstr "Faible"

msgid "low"
msgstr "faible"

msgid "Texture Quality"
msgstr "Qualité des Textures"

msgid "Display Rubberband"
msgstr "Présenter le Bande élastique"

msgid "Rubberband"
msgstr "Bande élastique"

msgid "on"
msgstr "marche"

msgid "off"
msgstr "arrêt"

msgid "Mute Browser"
msgstr "Rendre Navigateur muet"

msgid "Browser muted"
msgstr "Navigateur muet"

msgid "Browser unmuted"
msgstr "Son de Navigateur réactivé"

msgid "Leave Fullscreen"
msgstr "Laisser le plein Écran"

msgid "Fullscreen"
msgstr "Plein Écran"

msgid "About X_ITE"
msgstr "À propos de X_ITE"

msgid "Examine Viewer"
msgstr "Examiner"

msgid "Walk Viewer"
msgstr "Aller"

msgid "Fly Viewer"
msgstr "Voler"

msgid "Plane Viewer"
msgstr "Visionneur de la Plaine"

msgid "Look At Viewer"
msgstr "Regarder un Objet de près"

msgid "None Viewer"
msgstr "Pas de Visionneur"

msgid "Flat"
msgstr "Plat"

msgid "Wireframe"
msgstr "Image filaire"

msgid "Loading %1 file"
msgstr "Télécharger %1 Fichier"

msgid "Loading %1 files"
msgstr "Télécharger %1 Fichiers"

msgid "Loading done"
msgstr "Téléchargement fini"

msgid "Failed loading world."
msgstr "Le chargement des Fichiers a échoué."

msgid "Show World Info"
msgstr "Afficher World Info"

msgid "Viewpoint is copied to clipboard."
msgstr "Le point de Vue est copié dans le Presse-Papiers."
`;
;

x_ite_Namespace .add ("fr.po", "locale/fr.po", fr_po_default_);
/* harmony default export */ const fr_po = (fr_po_default_);
;// CONCATENATED MODULE: ./src/locale/gettext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function execAll (regex, string)
{
   const matches = [ ];

   let match = null;

   while (match = regex .exec (string))
      matches .push (match);

   return matches;
}

function getLanguage ()
{
   for (const value of navigator .languages)
   {
      const language = value .split ("-") [0];

      if (locales [language])
         return language;
   }

   return (navigator .language || navigator .userLanguage) .split ("-") [0];
}

function setLocale (language)
{
   if (locales [language])
   {
      const
         matches = execAll (msg, locales [language]),
         locale  = locales [language] = { };

      for (var i = 0, length = matches .length; i < length; ++ i)
      {
         if (matches [i] [2] .length)
            locale [matches [i] [1]] = matches [i] [2];
      }
   }
}

const locales =
{
   en: "C",
   de: de_po,
   fr: fr_po,
};

const
   msg      = /msgid\s+"(.*?)"\nmsgstr\s+"(.*?)"\n/g,
   language = getLanguage ();

setLocale (language);

function gettext (string)
{
   const locale = locales [language];

   if (locale === undefined)
      return string;

   const translation = locale [string];

   if (translation === undefined)
      return string;

   return translation;
}

const gettext_default_ = gettext;
;

x_ite_Namespace .add ("gettext", "locale/gettext", gettext_default_);
/* harmony default export */ const locale_gettext = (gettext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Core/BrowserTimings.js
/* provided dependency */ var BrowserTimings_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function BrowserTimings (executionContext)
{
   Base_X3DBaseNode .call (this, executionContext);

   this .localStorage  = this .getBrowser () .getLocalStorage () .addNameSpace ("BrowserTimings.");
   this .fps           = new Time_StopWatch ();
}

Object .assign (Object .setPrototypeOf (BrowserTimings .prototype, Base_X3DBaseNode .prototype),
{
   initialize ()
   {
      Base_X3DBaseNode .prototype .initialize .call (this);

      this .getBrowser () .getBrowserOptions () ._Timings .addInterest ("set_enabled__", this);

      this .localStorage .setDefaultValues ({ type: "LESS" });

      this .element = BrowserTimings_$("<div></div>")
         .hide ()
         .addClass ("x_ite-private-browser-timings")
         .appendTo (this .getBrowser () .getSurface ());

      this .table = BrowserTimings_$("<table></table>")
         .appendTo (this .element);

      this .header = BrowserTimings_$("<thead></thead>")
         .append (BrowserTimings_$("<tr></tr>")
         .append (BrowserTimings_$("<th colspan='2'></th>")
         .text (locale_gettext("Browser Timings"))))
         .appendTo (this .table);

      this .body = BrowserTimings_$("<tbody></tbody>")
         .appendTo (this .table);

      this .footer = BrowserTimings_$("<tfoot></tfoot>")
         .append (BrowserTimings_$("<tr></tr>")
         .append (BrowserTimings_$("<td colspan='2'></td>")))
         .appendTo (this .table);

      this .button = BrowserTimings_$("<button></button>")
         .attr ("type", "button")
         .appendTo (this .footer .find ("td"));

      this .frameRate       = BrowserTimings_$("<td></td>");
      this .speed           = BrowserTimings_$("<td></td>");
      this .frameRate       = BrowserTimings_$("<td></td>");
      this .speed           = BrowserTimings_$("<td></td>");
      this .browserTime     = BrowserTimings_$("<td></td>");
      this .x3dTotal        = BrowserTimings_$("<td></td>");
      this .eventProcessing = BrowserTimings_$("<td></td>");
      this .pointerTime     = BrowserTimings_$("<td></td>");
      this .cameraTime      = BrowserTimings_$("<td></td>");
      this .pickingTime     = BrowserTimings_$("<td></td>");
      this .collisionTime   = BrowserTimings_$("<td></td>");
      this .renderTime      = BrowserTimings_$("<td></td>");
      this .numShapes       = BrowserTimings_$("<td></td>");
      this .sensors         = BrowserTimings_$("<td></td>");

      this .body .append (BrowserTimings_$("<tr></tr>")
         .append (BrowserTimings_$("<td></td>") .text (locale_gettext("Frame rate") + ":"))
         .append (this .frameRate));

      this .body .append (BrowserTimings_$("<tr></tr>")
         .append (BrowserTimings_$("<td></td>") .text (locale_gettext("Speed") + ":"))
         .append (this .speed)
         .addClass ("x_ite-private-more"));

      this .body .append (BrowserTimings_$("<tr></tr>")
         .append (BrowserTimings_$("<td></td>") .text (locale_gettext("Browser") + ":"))
         .append (this .browserTime));

      this .body .append (BrowserTimings_$("<tr></tr>")
         .append (BrowserTimings_$("<td></td>") .text (locale_gettext("X3D total") + ":"))
         .append (this .x3dTotal));

      this .body .append (BrowserTimings_$("<tr></tr>")
         .append (BrowserTimings_$("<td></td>") .text (locale_gettext("Event Processing") + ":"))
         .append (this .eventProcessing));

      this .body .append (BrowserTimings_$("<tr></tr>")
         .append (BrowserTimings_$("<td></td>") .text (locale_gettext("Pointer") + ":"))
         .append (this .pointerTime));

      this .body .append (BrowserTimings_$("<tr></tr>")
         .append (BrowserTimings_$("<td></td>") .text (locale_gettext("Camera") + ":"))
         .append (this .cameraTime));

      this .body .append (BrowserTimings_$("<tr></tr>")
         .append (BrowserTimings_$("<td></td>") .text (locale_gettext("Picking") + ":"))
         .append (this .pickingTime));

      this .body .append (BrowserTimings_$("<tr></tr>")
         .append (BrowserTimings_$("<td></td>") .text (locale_gettext("Collision Detection") + ":"))
         .append (this .collisionTime));

      this .body .append (BrowserTimings_$("<tr></tr>")
         .append (BrowserTimings_$("<td></td>") .text (locale_gettext("Rendering") + ":"))
         .append (this .renderTime));

      this .body .append (BrowserTimings_$("<tr></tr>")
         .append (BrowserTimings_$("<td></td>") .text (locale_gettext("Number of Shapes") + ":"))
         .append (this .numShapes));

      this .body .append (BrowserTimings_$("<tr></tr>")
         .append (BrowserTimings_$("<td></td>") .text (locale_gettext("Number of Sensors") + ":"))
         .append (this .sensors));

      this .button .on ("click touchend", this .set_type__ .bind (this));

      this .localStorage .type = this .localStorage .type === "MORE" ? "LESS" : "MORE";

      this .set_type__ ();
   },
   set_enabled__ ()
   {
      if (this .getBrowser () .getBrowserOption ("Timings"))
      {
         this .element .stop (true, true) .fadeIn ();
         this .fps .reset ();
         this .getBrowser () .prepareEvents () .addInterest ("update", this);
         this .update ();
         this .build ();
      }
      else
      {
         this .element .stop (true, true) .fadeOut ();
         this .getBrowser () .prepareEvents () .removeInterest ("update", this);
      }
   },
   set_type__ ()
   {
      if (this .localStorage .type === "MORE")
      {
         this .localStorage .type = "LESS";
         this .table .addClass ("less");
         this .table .removeClass ("more");
      }
      else
      {
         this .localStorage .type = "MORE";
         this .table .addClass ("more");
         this .table .removeClass ("less");
      }

      this .set_button__ ();
      this .build ();
   },
   set_button__ ()
   {
      if (this .localStorage .type === "MORE")
         this .button .text (locale_gettext("Less Properties"));
      else
         this .button .text (locale_gettext("More Properties"));
   },
   update ()
   {
      this .fps .stop ()

      if (this .fps .elapsedTime > 1000)
      {
         this .build ();
         this .fps .reset ();
      }

      this .fps .start ();
   },
   build ()
   {
      const browser = this .getBrowser ();

      this .frameRate .text (`${f2 (1000 / this .fps .averageTime)} ${locale_gettext("fps")}`);
      this .speed .text (`${f2 (this .getSpeed (browser .currentSpeed))} ${this .getSpeedUnit (browser .currentSpeed)}`);

      if (this .localStorage .type !== "MORE" || !browser .getWorld ())
         return;

      const
         layers            = browser .getWorld () .getLayerSet () .getLayers (),
         activeLayer       = browser .getActiveLayer (),
         navigationTime    = activeLayer && browser .getCollisionCount () ? activeLayer .getCollisionTime () .averageTime : 0,
         collisionTime     = browser .getCollisionTime () .averageTime + navigationTime,
         routingTime       = Math .max (0, browser .getBrowserTime () .averageTime - (browser .getCameraTime () .averageTime + browser .getCollisionTime () .averageTime + browser .getDisplayTime () .averageTime)),
         prepareEvents     = browser .prepareEvents () .getInterests () .size - 1,
         sensors           = browser .sensorEvents () .getInterests () .size,
         opaqueShapes      = layers .reduce ((n, layer) => n + layer .getNumOpaqueShapes (), 0),
         transparentShapes = layers .reduce ((n, layer) => n + layer .getNumTransparentShapes (), 0);

      this .browserTime     .text (`${f2 (browser .getSystemTime () .averageTime)} ${locale_gettext("ms")}`);
      this .x3dTotal        .text (`${f2 (browser .getBrowserTime () .averageTime)} ${locale_gettext("ms")}`);
      this .eventProcessing .text (`${f2 (routingTime)} ${locale_gettext("ms")}`);
      this .pointerTime     .text (`${f2 (browser .getPointingTime () .averageTime)} ${locale_gettext("ms")}`);
      this .cameraTime      .text (`${f2 (browser .getCameraTime () .averageTime)} ${locale_gettext("ms")}`);
      this .pickingTime     .text (`${f2 (browser .getPickingTime () .averageTime)} ${locale_gettext("ms")}`);
      this .collisionTime   .text (`${f2 (collisionTime)} ${locale_gettext("ms")}`);
      this .renderTime      .text (`${f2 (browser .getDisplayTime () .averageTime)} ${locale_gettext("ms")}`);
      this .numShapes       .text (`${opaqueShapes} + ${transparentShapes}`);
      this .sensors         .text (prepareEvents + sensors);

      browser .getSystemTime ()    .reset ();
      browser .getBrowserTime ()   .reset ();
      browser .getPointingTime ()  .reset ();
      browser .getCameraTime ()    .reset ();
      browser .getPickingTime ()   .reset ();
      browser .getCollisionTime () .reset ();
      browser .getDisplayTime ()   .reset ();

      activeLayer ?.getCollisionTime () .reset ();
   },
   getSpeed (speed)
   {
      if (speed < 15)
         return speed;

      return speed * 3.6;
   },
   getSpeedUnit (speed)
   {
      if (speed < 15)
         return locale_gettext("m/s");

      return locale_gettext("km/h");
   },
});

Object .defineProperties (BrowserTimings,
{
   typeName:
   {
      value: "BrowserTimings",
      enumerable: true,
   },
});

const f2 = (() =>
{
   const format = new Intl .NumberFormat (navigator .language || navigator .userLanguage, {
      notation: "standard",
      minimumFractionDigits: 2,
      maximumFractionDigits: 2,
   }) .format;

   return function (value)
   {
      return format (Number .isFinite (value) ? value : 0);
   };
})();

const BrowserTimings_default_ = BrowserTimings;
;

x_ite_Namespace .add ("BrowserTimings", "x_ite/Browser/Core/BrowserTimings", BrowserTimings_default_);
/* harmony default export */ const Core_BrowserTimings = (BrowserTimings_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Core/PrimitiveQuality.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

let PrimitiveQuality_i = 0;

const PrimitiveQuality =
{
   LOW:    PrimitiveQuality_i ++,
   MEDIUM: PrimitiveQuality_i ++,
   HIGH:   PrimitiveQuality_i ++,
};

const PrimitiveQuality_default_ = PrimitiveQuality;
;

x_ite_Namespace .add ("PrimitiveQuality", "x_ite/Browser/Core/PrimitiveQuality", PrimitiveQuality_default_);
/* harmony default export */ const Core_PrimitiveQuality = (PrimitiveQuality_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Core/TextureQuality.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

let TextureQuality_i = 0;

const TextureQuality =
{
   LOW:    TextureQuality_i ++,
   MEDIUM: TextureQuality_i ++,
   HIGH:   TextureQuality_i ++,
};

const TextureQuality_default_ = TextureQuality;
;

x_ite_Namespace .add ("TextureQuality", "x_ite/Browser/Core/TextureQuality", TextureQuality_default_);
/* harmony default export */ const Core_TextureQuality = (TextureQuality_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Core/BrowserOptions.js
/* provided dependency */ var BrowserOptions_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/











function BrowserOptions (executionContext)
{
   Base_X3DBaseNode .call (this, executionContext);

   this .addAlias ("AntiAliased", this ._Antialiased);

   const browser = this .getBrowser ();

   this .localStorage     = browser .getLocalStorage () .addNameSpace ("BrowserOptions.");
   this .textureQuality   = Core_TextureQuality .MEDIUM
   this .primitiveQuality = Core_PrimitiveQuality .MEDIUM;
   this .shading          = Core_Shading .GOURAUD;
}

Object .assign (Object .setPrototypeOf (BrowserOptions .prototype, Base_X3DBaseNode .prototype),
{
   initialize ()
   {
      Base_X3DBaseNode .prototype .initialize .call (this);

      this .localStorage .setDefaultValues ({
         Rubberband:        this ._Rubberband        .getValue (),
         PrimitiveQuality:  this ._PrimitiveQuality  .getValue (),
         TextureQuality:    this ._TextureQuality    .getValue (),
         StraightenHorizon: this ._StraightenHorizon .getValue (),
         Timings:           this ._Timings           .getValue (),
      });

      this ._Rubberband                   .addInterest ("set_rubberband__",                   this);
      this ._Antialiased                  .addInterest ("set_antialiased__",                  this);
      this ._PrimitiveQuality             .addInterest ("set_primitiveQuality__",             this);
      this ._TextureQuality               .addInterest ("set_textureQuality__",               this);
      this ._Shading                      .addInterest ("set_shading__",                      this);
      this ._StraightenHorizon            .addInterest ("set_straightenHorizon__",            this);
      this ._AutoUpdate                   .addInterest ("set_autoUpdate__",                   this);
      this ._ContentScale                 .addInterest ("set_contentScale__",                 this);
      this ._LogarithmicDepthBuffer       .addInterest ("set_logarithmicDepthBuffer__",       this);
      this ._Multisampling                .addInterest ("set_multisampling__",                this);
      this ._OrderIndependentTransparency .addInterest ("set_orderIndependentTransparency__", this);
      this ._Timings                      .addInterest ("set_timings__",                      this);

      this .set_antialiased__                  (this ._Antialiased);
      this .set_shading__                      (this ._Shading);
      this .set_contentScale__                 (this ._ContentScale);
      this .set_logarithmicDepthBuffer__       (this ._LogarithmicDepthBuffer);
      this .set_multisampling__                (this ._Multisampling);
      this .set_orderIndependentTransparency__ (this ._OrderIndependentTransparency);

      this .reset ();
   },
   reset: (() =>
   {
      const attributes = new Set ([
         "Antialiased",
         "AutoUpdate",
         "Cache",
         "ContentScale",
         "ContextMenu",
         "Debug",
         "Multisampling",
         "Notifications",
         "OrderIndependentTransparency",
         "SplashScreen",
      ]);

      const mappings = new Map ([
         ["AutoUpdate", "Update"],
      ]);

      const restorable = new Set ([
         "PrimitiveQuality",
         "Rubberband",
         "StraightenHorizon",
         "TextureQuality",
         "Timings",
      ]);

      return function ()
      {
         const
            browser      = this .getBrowser (),
            localStorage = this .localStorage;

         for (const { name, value } of this .getFieldDefinitions ())
         {
            if (attributes .has (name))
            {
               const
                  attribute = BrowserOptions_$.toLowerCaseFirst (mappings .get (name) ?? name),
                  value     = browser .getElement () .attr (attribute);

               if (value !== undefined)
               {
                  browser .attributeChangedCallback (attribute, null, value);
                  continue;
               }
            }

            if (restorable .has (name))
            {
               const
                  value = localStorage [name],
                  field = this .getField (name);

               if (value !== field .getValue ())
                  field .setValue (value);

               continue;
            }

            const field = this .getField (name);

            if (field .equals (value))
               continue;

            field .assign (value);
         }
      };
   })(),
   getPrimitiveQuality ()
   {
      return this .primitiveQuality;
   },
   getShading ()
   {
      return this .shading;
   },
   getTextureQuality ()
   {
      return this .textureQuality;
   },
   set_rubberband__ (rubberband)
   {
      this .localStorage .Rubberband = rubberband .getValue ();
   },
   set_antialiased__ ()
   {
      this .set_multisampling__ (this ._Multisampling);
   },
   set_primitiveQuality__ (value)
   {
      const
         browser          = this .getBrowser (),
         primitiveQuality = value .getValue () .toUpperCase ();

      this .localStorage .PrimitiveQuality = primitiveQuality;
      this .primitiveQuality               = BrowserOptions_$.enum (Core_PrimitiveQuality, primitiveQuality, Core_PrimitiveQuality .MEDIUM);

      if (typeof browser .setPrimitiveQuality2D === "function")
         browser .setPrimitiveQuality2D (this .primitiveQuality);

      if (typeof browser .setPrimitiveQuality3D === "function")
         browser .setPrimitiveQuality3D (this .primitiveQuality);
   },
   set_textureQuality__ (value)
   {
      const
         browser        = this .getBrowser (),
         textureQuality = value .getValue () .toUpperCase ();

      this .localStorage .TextureQuality = textureQuality;
      this .textureQuality               = BrowserOptions_$.enum (Core_TextureQuality, textureQuality, Core_TextureQuality .MEDIUM);

      if (typeof browser .setTextureQuality === "function")
         browser .setTextureQuality (this .textureQuality);
   },
   set_shading__: (() =>
   {
      const strings = {
         [Core_Shading .POINT]:     "POINT",
         [Core_Shading .WIREFRAME]: "WIREFRAME",
         [Core_Shading .FLAT]:      "FLAT",
         [Core_Shading .GOURAUD]:   "GOURAUD",
         [Core_Shading .PHONG]:     "PHONG",
      };

      return function (value)
      {
         const
            browser = this .getBrowser (),
            shading = value .getValue () .toUpperCase () .replace ("POINTSET", "POINT");

         this .shading = BrowserOptions_$.enum (Core_Shading, shading, Core_Shading .GOURAUD);

         browser .getRenderingProperties () ._Shading = strings [this .shading];
         browser .setShading (this .shading);
      };
   })(),
   set_straightenHorizon__ (straightenHorizon)
   {
      this .localStorage .StraightenHorizon = straightenHorizon .getValue ();

      if (straightenHorizon .getValue ())
         this .getBrowser () .getActiveLayer () ?.straightenView ();
   },
   set_autoUpdate__ (autoUpdate)
   {
      const events = ["resize", "scroll", "load"]
         .map (event => `${event}.${this .getTypeName ()}${this .getId ()}`)
         .join (" ");

      if (autoUpdate .getValue ())
      {
         const
            browser = this .getBrowser (),
            element = browser .getElement ();

         const checkUpdate = () =>
         {
            if (element .isInViewport ())
            {
               if (!browser .isLive ())
                  browser .beginUpdate ();
            }
            else
            {
               if (browser .isLive ())
                  browser .endUpdate ();
            }
         };

         BrowserOptions_$(window) .on (events, checkUpdate);
         checkUpdate ();
      }
      else
      {
         BrowserOptions_$(window) .off (events);
      }
   },
   set_contentScale__ (contentScale)
   {
      const browser = this .getBrowser ();

      if (this .removeUpdateContentScale)
         this .removeUpdateContentScale ();

      if (contentScale .getValue () === -1)
         this .updateContentScale ();
      else
         browser .getRenderingProperties () ._ContentScale = Math .max (contentScale .getValue (), 0) || 1;

      browser .reshape ();
   },
   updateContentScale ()
   {
      const
         browser = this .getBrowser (),
         media   = window .matchMedia (`(resolution: ${window .devicePixelRatio}dppx)`),
         update  = this .updateContentScale .bind (this);

      if (this .removeUpdateContentScale)
         this .removeUpdateContentScale ();

      this .removeUpdateContentScale = function () { media .removeEventListener ("change", update) };

      media .addEventListener ("change", update);

      browser .getRenderingProperties () ._ContentScale = window .devicePixelRatio;

      browser .reshape ();
   },
   set_logarithmicDepthBuffer__ (logarithmicDepthBuffer)
   {
      const
         browser = this .getBrowser (),
         gl      = browser .getContext ();

      browser .getRenderingProperties () ._LogarithmicDepthBuffer = logarithmicDepthBuffer .getValue () && gl .HAS_FEATURE_FRAG_DEPTH;
   },
   set_multisampling__ (multisampling)
   {
      const
         browser = this .getBrowser (),
         samples = Math_Algorithm .clamp (multisampling .getValue (), 0, browser .getMaxSamples ());

      browser .getRenderingProperties () ._Multisampling = this ._Antialiased .getValue () ? samples : 0;
      browser .getRenderingProperties () ._Antialiased   = samples > 0;

      browser .reshape ();
   },
   set_orderIndependentTransparency__ ()
   {
      const browser = this .getBrowser ();

      browser .getShaders () .clear ();
      browser .reshape ();
   },
   set_timings__ (timings)
   {
      this .localStorage .Timings = timings .getValue ();
   },
});

Object .defineProperties (BrowserOptions,
{
   typeName:
   {
      value: "BrowserOptions",
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "SplashScreen",                 new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "Dashboard",                    new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "Rubberband",                   new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "EnableInlineViewpoints",       new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "Antialiased",                  new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "TextureQuality",               new x_ite_Fields .SFString ("MEDIUM")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "PrimitiveQuality",             new x_ite_Fields .SFString ("MEDIUM")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "QualityWhenMoving",            new x_ite_Fields .SFString ("SAME")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "Shading",                      new x_ite_Fields .SFString ("GOURAUD")),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "MotionBlur",                   new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "AutoUpdate",                   new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "Cache",                        new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "ContentScale",                 new x_ite_Fields .SFDouble (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "ContextMenu",                  new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "Debug",                        new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "Gravity",                      new x_ite_Fields .SFDouble (9.80665)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "LoadUrlObjects",               new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "LogarithmicDepthBuffer",       new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "Notifications",                new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "Multisampling",                new x_ite_Fields .SFInt32 (4)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "OrderIndependentTransparency", new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "StraightenHorizon",            new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .inputOutput, "Timings",                      new x_ite_Fields .SFBool ()),
      ]),
      enumerable: true,
   },
});

const BrowserOptions_default_ = BrowserOptions;
;

x_ite_Namespace .add ("BrowserOptions", "x_ite/Browser/Core/BrowserOptions", BrowserOptions_default_);
/* harmony default export */ const Core_BrowserOptions = (BrowserOptions_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Core/BrowserProperties.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function BrowserProperties (executionContext)
{
   Base_X3DBaseNode .call (this, executionContext);
}

Object .setPrototypeOf (BrowserProperties .prototype, Base_X3DBaseNode .prototype);

Object .defineProperties (BrowserProperties,
{
   typeName:
   {
      value: "BrowserProperties",
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "ABSTRACT_NODES",        new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "CONCRETE_NODES",        new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "EXTERNAL_INTERACTIONS", new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "PROTOTYPE_CREATE",      new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "DOM_IMPORT",            new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "XML_ENCODING",          new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "CLASSIC_VRML_ENCODING", new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .initializeOnly, "BINARY_ENCODING",       new x_ite_Fields .SFBool ()),
      ]),
      enumerable: true,
   },
});

const BrowserProperties_default_ = BrowserProperties;
;

x_ite_Namespace .add ("BrowserProperties", "x_ite/Browser/Core/BrowserProperties", BrowserProperties_default_);
/* harmony default export */ const Core_BrowserProperties = (BrowserProperties_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Core/RenderingProperties.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function RenderingProperties (executionContext)
{
   Base_X3DBaseNode .call (this, executionContext);

   this .addAlias ("AntiAliased", this ._Antialiased);
}

Object .assign (Object .setPrototypeOf (RenderingProperties .prototype, Base_X3DBaseNode .prototype),
{
   initialize ()
   {
      Base_X3DBaseNode .prototype .initialize .call (this);

      const browser = this .getBrowser ();

      this ._MaxTextureSize = browser .getMaxTextureSize ();
      this ._TextureUnits   = browser .getMaxCombinedTextureUnits ();
      this ._MaxLights      = browser .getMaxLights ();
      this ._ColorDepth     = browser .getColorDepth ();
      this ._TextureMemory  = browser .getTextureMemory ();
      this ._MaxSamples     = browser .getMaxSamples ();
   },
});

Object .defineProperties (RenderingProperties,
{
   typeName:
   {
      value: "RenderingProperties",
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly, "Shading",                new x_ite_Fields .SFString ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly, "MaxTextureSize",         new x_ite_Fields .SFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly, "TextureUnits",           new x_ite_Fields .SFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly, "MaxLights",              new x_ite_Fields .SFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly, "Antialiased",            new x_ite_Fields .SFBool (true)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly, "ColorDepth",             new x_ite_Fields .SFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly, "TextureMemory",          new x_ite_Fields .SFDouble ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly, "ContentScale",           new x_ite_Fields .SFDouble (1)),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly, "LogarithmicDepthBuffer", new x_ite_Fields .SFBool ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly, "MaxSamples",             new x_ite_Fields .SFInt32 ()),
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly, "Multisampling",          new x_ite_Fields .SFInt32 (4)),
      ]),
      enumerable: true,
   }
});

const RenderingProperties_default_ = RenderingProperties;
;

x_ite_Namespace .add ("RenderingProperties", "x_ite/Browser/Core/RenderingProperties", RenderingProperties_default_);
/* harmony default export */ const Core_RenderingProperties = (RenderingProperties_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Core/Notification.js
/* provided dependency */ var Notification_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





Notification_$.fn.textWidth = function (string)
{
   const
      children = Notification_$(this) .children (),
      html     = Notification_$(this) .html (),
      span     = '<span>' + html + '</span>';
   Notification_$(this) .html (span);
   const width = Notification_$(this) .find ('span:first') .width ();
   Notification_$(this) .empty ();
   Notification_$(this) .append (children);
   return width;
};

function Notification (executionContext)
{
   Base_X3DBaseNode .call (this, executionContext);

   this .addChildObjects (Base_X3DConstants .inputOutput, "string", new Fields_SFString ());
}

Object .assign (Object .setPrototypeOf (Notification .prototype, Base_X3DBaseNode .prototype),
{
   initialize ()
   {
      Base_X3DBaseNode .prototype .initialize .call (this);

      this .element = Notification_$("<div></div>")
         .hide ()
         .addClass ("x_ite-private-notification")
         .appendTo (this .getBrowser () .getSurface ())
         .animate ({ width: 0 });

      Notification_$("<span></span>") .appendTo (this .element);

      this ._string .addInterest ("set_string__", this);
   },
   set_string__ ()
   {
      if (! this .getBrowser () .getBrowserOption ("Notifications"))
         return;

      if (this ._string .length === 0)
         return;

      this .element .children () .text (this ._string .getValue ());

      this .element
         .stop (true, true)
         .fadeIn (0)
         .animate ({ width: this .element .textWidth () })
         .animate ({ "delay": 1 }, 5000)
         .animate ({ width: 0 })
         .fadeOut (0);
   },
});

Object .defineProperties (Notification,
{
   typeName:
   {
      value: "Notification",
      enumerable: true,
   },
});

const Notification_default_ = Notification;
;

x_ite_Namespace .add ("Notification", "x_ite/Browser/Core/Notification", Notification_default_);
/* harmony default export */ const Core_Notification = (Notification_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Core/ContextMenu.js
/* provided dependency */ var jquery_fullscreen = __webpack_require__(196);
/* provided dependency */ var ContextMenu_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




typeof jquery_fullscreen; // import plugin

const _userMenu = Symbol ();

function ContextMenu (executionContext)
{
   Base_X3DBaseNode .call (this, executionContext);

   this [_userMenu] = null;
}

Object .assign (Object .setPrototypeOf (ContextMenu .prototype, Base_X3DBaseNode .prototype),
{
   initialize ()
   {
      Base_X3DBaseNode .prototype .initialize .call (this);

      const browser = this .getBrowser ();

      this .init ({
         element: browser .getElement (),
         appendTo: browser .getShadow (),
         build: this .build .bind (this),
         animation: {duration: 500, show: "fadeIn", hide: "fadeOut"},
      });
   },
   getUserMenu ()
   {
      return this [_userMenu];
   },
   setUserMenu (userMenu)
   {
      this [_userMenu] = userMenu;
   },
   createUserMenu ()
   {
      const userMenu = { };

      if (typeof this [_userMenu] === "function")
      {
         const menu = this [_userMenu] ();

         if (ContextMenu_$.isPlainObject (menu))
         {
            for (const key in menu)
               userMenu ["user-" + key] = menu [key];
         }
      }

      return userMenu;
   },
   build (event)
   {
      const
         browser    = this .getBrowser (),
         fullscreen = browser .getElement () .fullScreen ();

      if (! browser .getBrowserOption ("ContextMenu"))
         return;

      const menu = {
         className: "x_ite-private-menu",
         items: {
            "title": {
               name: browser .getName () + " Browser v" + browser .getVersion (),
               className: "context-menu-title context-menu-not-selectable",
            },
            "separator0": "--------",
            "viewpoints": {
               name: locale_gettext("Viewpoints"),
               className: "context-menu-icon x_ite-private-icon-viewpoint",
               items: this .getViewpoints (),
            },
            "available-viewers": {
               name: locale_gettext("Available Viewers"),
               items: this .getAvailableViewers (),
            },
            "straighten-horizon": {
               name: locale_gettext("Straighten Horizon"),
               type: "checkbox",
               selected: browser .getBrowserOption ("StraightenHorizon"),
               events: {
                  click: (event) =>
                  {
                     const straightenHorizon = ContextMenu_$(event .target) .is (":checked");

                     browser .setBrowserOption ("StraightenHorizon", straightenHorizon);

                     if (straightenHorizon)
                        browser .getNotification () ._string = locale_gettext("Straighten Horizon") + ": " + locale_gettext("on");
                     else
                        browser .getNotification () ._string = locale_gettext("Straighten Horizon") + ": " + locale_gettext("off");
                  },
               },
            },
            "display-rubberband": {
               name: locale_gettext("Display Rubberband"),
               type: "checkbox",
               selected: browser .getBrowserOption ("Rubberband"),
               events: {
                  click: (event) =>
                  {
                     const rubberband = ContextMenu_$(event .target) .is (":checked");

                     browser .setBrowserOption ("Rubberband", rubberband);

                     if (rubberband)
                        browser .getNotification () ._string = locale_gettext("Rubberband") + ": " + locale_gettext("on");
                     else
                        browser .getNotification () ._string = locale_gettext("Rubberband") + ": " + locale_gettext("off");
                  },
               },
            },
            "separator1": "--------",
            "primitive-quality": {
               name: locale_gettext("Primitive Quality"),
               className: "context-menu-icon x_ite-private-icon-primitive-quality",
               items: {
                  "high": {
                     name: locale_gettext("High"),
                     type: "radio",
                     radio: "primitive-quality",
                     selected: browser .getBrowserOption ("PrimitiveQuality") === "HIGH",
                     events: {
                        click: () =>
                        {
                           browser .setBrowserOption ("PrimitiveQuality", "HIGH");
                           browser .getNotification () ._string = locale_gettext("Primitive Quality") + ": " + locale_gettext("high");
                        },
                     },
                  },
                  "medium": {
                     name: locale_gettext("Medium"),
                     type: "radio",
                     radio: "primitive-quality",
                     selected: browser .getBrowserOption ("PrimitiveQuality") === "MEDIUM",
                     events: {
                        click: () =>
                        {
                           browser .setBrowserOption ("PrimitiveQuality", "MEDIUM");
                           browser .getNotification () ._string = locale_gettext("Primitive Quality") + ": " + locale_gettext("medium");
                        },
                     },
                  },
                  "low": {
                     name: locale_gettext("Low"),
                     type: "radio",
                     radio: "primitive-quality",
                     selected: browser .getBrowserOption ("PrimitiveQuality") === "LOW",
                     events: {
                        click: () =>
                        {
                           browser .setBrowserOption ("PrimitiveQuality", "LOW");
                           browser .getNotification () ._string = locale_gettext("Primitive Quality") + ": " + locale_gettext("low");
                        },
                     },
                  },
               },
            },
            "texture-quality": {
               name: locale_gettext("Texture Quality"),
               className: "context-menu-icon x_ite-private-icon-texture-quality",
               items: {
                  "high": {
                     name: locale_gettext("High"),
                     type: "radio",
                     radio: "texture-quality",
                     selected: browser .getBrowserOption ("TextureQuality") === "HIGH",
                     events: {
                        click: () =>
                        {
                           browser .setBrowserOption ("TextureQuality", "HIGH");
                           browser .getNotification () ._string = locale_gettext("Texture Quality") + ": " + locale_gettext("high");
                        },
                     },
                  },
                  "medium": {
                     name: locale_gettext("Medium"),
                     type: "radio",
                     radio: "texture-quality",
                     selected: browser .getBrowserOption ("TextureQuality") === "MEDIUM",
                     events: {
                        click: () =>
                        {
                           browser .setBrowserOption ("TextureQuality", "MEDIUM");
                           browser .getNotification () ._string = locale_gettext("Texture Quality") + ": " + locale_gettext("medium");
                        },
                     },
                  },
                  "low": {
                     name: locale_gettext("Low"),
                     type: "radio",
                     radio: "texture-quality",
                     selected: browser .getBrowserOption ("TextureQuality") === "LOW",
                     events: {
                        click: () =>
                        {
                           browser .setBrowserOption ("TextureQuality", "LOW");
                           browser .getNotification () ._string = locale_gettext("Texture Quality") + ": " + locale_gettext("low");
                        },
                     },
                  },
               },
            },
            "shading": {
               name: locale_gettext("Shading"),
               className: "context-menu-icon x_ite-private-icon-shading",
               items: {
                  "point": {
                     name: locale_gettext("Points"),
                     type: "radio",
                     radio: "shading",
                     selected: browser .getBrowserOption ("Shading") === "POINT",
                     events: {
                        click: () =>
                        {
                           browser .setBrowserOption ("Shading", "POINT");
                           browser .getNotification () ._string = locale_gettext("Shading") + ": " + locale_gettext("Points");
                        },
                     },
                  },
                  "wireframe": {
                     name: locale_gettext("Wireframe"),
                     type: "radio",
                     radio: "shading",
                     selected: browser .getBrowserOption ("Shading") === "WIREFRAME",
                     events: {
                        click: () =>
                        {
                           browser .setBrowserOption ("Shading", "WIREFRAME");
                           browser .getNotification () ._string = locale_gettext("Shading") + ": " + locale_gettext("Wireframe");
                        },
                     },
                  },
                  "flat": {
                     name: locale_gettext("Flat"),
                     type: "radio",
                     radio: "shading",
                     selected: browser .getBrowserOption ("Shading") === "FLAT",
                     events: {
                        click: () =>
                        {
                           browser .setBrowserOption ("Shading", "FLAT");
                           browser .getNotification () ._string = locale_gettext("Shading") + ": " + locale_gettext("Flat");
                        },
                     },
                  },
                  "gouraud": {
                     name: locale_gettext("Gouraud"),
                     type: "radio",
                     radio: "shading",
                     selected: browser .getBrowserOption ("Shading") === "GOURAUD",
                     events: {
                        click: () =>
                        {
                           browser .setBrowserOption ("Shading", "GOURAUD");
                           browser .getNotification () ._string = locale_gettext("Shading") + ": " + locale_gettext("Gouraud");
                        },
                     },
                  },
                  "phong": {
                     name: locale_gettext("Phong"),
                     type: "radio",
                     radio: "shading",
                     selected: browser .getBrowserOption ("Shading") === "PHONG",
                     events: {
                        click: () =>
                        {
                           browser .setBrowserOption ("Shading", "PHONG");
                           browser .getNotification () ._string = locale_gettext("Shading") + ": " + locale_gettext("Phong");
                        },
                     },
                  },
               },
            },
            "separator2": "--------",
            "browser-timings": {
               name: locale_gettext("Browser Timings"),
               type: "checkbox",
               selected: browser .getBrowserOption ("Timings"),
               events: {
                  click: (event) =>
                  {
                     browser .setBrowserOption ("Timings", ContextMenu_$(event .target) .is (":checked"));
                     browser .getSurface () .focus ();
                  },
               },
            },
            "fullscreen": {
               name: fullscreen ? locale_gettext("Leave Fullscreen") : locale_gettext("Fullscreen"),
               className: "context-menu-icon " + (fullscreen
                  ? "x_ite-private-icon-leave-fullscreen"
                  : "x_ite-private-icon-enter-fullscreen"),
               callback: () =>
               {
                  browser .getElement () .toggleFullScreen ();
               },
            },
            "separator3": "--------",
         },
      };

      Object .assign (menu .items, this .createUserMenu ());

      Object .assign (menu .items, {
         "separator4": "--------",
         "world-info": {
            name: locale_gettext("Show World Info"),
            className: "context-menu-icon x_ite-private-icon-world-info",
            callback ()
            {
               browser .getShadow () .find (".x_ite-private-world-info") .remove ();

               const
                  priv      = browser .getShadow () .find (".x_ite-private-browser"),
                  overlay   = ContextMenu_$("<div></div>") .addClass ("x_ite-private-world-info-overlay") .appendTo (priv),
                  div       = ContextMenu_$("<div></div>") .addClass ("x_ite-private-world-info") .appendTo (overlay),
                  worldInfo = browser .getExecutionContext () .getWorldInfos () [0],
                  title     = worldInfo .title,
                  info      = worldInfo .info;

               ContextMenu_$("<div></div>") .addClass ("x_ite-private-world-info-top") .text ("World Info") .appendTo (div);

               if (title .length)
               {
                  ContextMenu_$("<div></div>") .addClass ("x_ite-private-world-info-title") .text (title) .appendTo (div);
               }

               for (const line of info)
               {
                  ContextMenu_$("<div></div>") .addClass ("x_ite-private-world-info-info") .text (line) .appendTo (div);
               }

               overlay .on ("click", function () { overlay .remove (); });
            },
         },
         "about": {
            name: locale_gettext("About X_ITE"),
            className: "context-menu-icon x_ite-private-icon-help-about",
            callback ()
            {
               window .open (browser .getProviderURL ());
            },
         },
      });

      if (ContextMenu_$.isEmptyObject (menu .items .viewpoints .items))
         delete menu .items ["viewpoints"];

      if (Object .keys (menu .items ["available-viewers"] .items) .length < 2)
      {
         delete menu .items ["available-viewers"];
      }

      if (! browser .getCurrentViewer () .match (/^(?:EXAMINE|FLY)$/))
      {
         delete menu .items ["straighten-horizon"];
      }

      if (! browser .getBrowserOption ("Debug"))
      {
         delete menu .items ["shading"];
      }

      const worldInfo = browser .getExecutionContext () .getWorldInfos () [0];

      if (! worldInfo || (worldInfo .title .length === 0 && worldInfo .info .length === 0))
      {
         delete menu .items ["world-info"];
      }

      return menu;
   },
   getViewpoints ()
   {
      const
         browser     = this .getBrowser (),
         activeLayer = browser .getActiveLayer ();

      if (! activeLayer)
         return { };

      const
         enableInlineViewpoints = browser .getBrowserOption ("EnableInlineViewpoints"),
         currentScene           = browser .currentScene,
         viewpoints             = activeLayer .getViewpoints () .get (),
         currentViewpoint       = activeLayer .getViewpoint (),
         menu                   = { };

      for (const viewpoint of viewpoints)
      {
         const description = viewpoint .getDescriptions () .join (" » ");

         if (description === "")
            continue;

         if (! enableInlineViewpoints && viewpoint .getScene () !== currentScene)
            continue;

         const item = {
            name: description,
            callback: () =>
            {
               browser .bindViewpoint (browser .getActiveLayer (), viewpoint);
               browser .getSurface () .focus ();
            },
         };

         if (viewpoint === currentViewpoint)
            item .className = "context-menu-selected";

         menu ["Viewpoint" + viewpoint .getId ()] = item;
      }

      return menu;
   },
   getAvailableViewers ()
   {
      const
         browser          = this .getBrowser (),
         currentViewer    = browser ._viewer .getValue (),
         availableViewers = browser ._availableViewers,
         menu             = { };

      for (const viewer of availableViewers)
      {
         menu [viewer] = {
            name: locale_gettext(this .getViewerName (viewer)),
            className: "context-menu-icon x_ite-private-icon-" + viewer .toLowerCase () + "-viewer",
            callback: () =>
            {
               browser ._viewer = viewer;
               browser .getNotification () ._string = locale_gettext(this .getViewerName (viewer));
               browser .getSurface () .focus ();
            },
         };

         if (viewer === currentViewer)
            menu [viewer] .className += " context-menu-selected";
      }

      return menu;
   },
   getViewerName (viewer)
   {
      switch (viewer)
      {
         case "EXAMINE":
            return locale_gettext("Examine Viewer");
         case "WALK":
            return locale_gettext("Walk Viewer");
         case "FLY":
            return locale_gettext("Fly Viewer");
         case "PLANE":
            return locale_gettext("Plane Viewer");
         case "LOOKAT":
            return locale_gettext("Look At Viewer");
         case "NONE":
            return locale_gettext("None Viewer");
      }
   },
   init (options)
   {
      this .show = this .createRoot .bind (this, options);

      options .element .on ("contextmenu", this .show);
   },
   show (event)
   { },
   hide (event)
   { },
   createRoot (options, event)
   {
      const
         menu  = options .build (event),
         level = 1;

      if (! menu) return;

      // Layer

      const layer = ContextMenu_$("<div></div>")
         .addClass ("context-menu-layer")
         .addClass (menu .className)
         .appendTo (options .appendTo);

      const hide = this .hide = () =>
      {
         delete this .hide;

         layer .remove ();

         ul [options .animation .hide] (options .animation .duration, function ()
         {
            ul .remove ();

            if (options .events && typeof options .events .hide === "function")
               options .events .hide ();
         });

         return false;
      };

      // Menu

      const ul = ContextMenu_$("<ul></ul>")
         .hide ()
         .addClass ("context-menu-root")
         .addClass ("context-menu-list")
         .addClass (menu .className)
         .appendTo (options .appendTo)
         .offset ({ "left": event .pageX, "top": event .pageY });

      for (const k in menu .items)
         ul .append (this .createItem (menu .items [k], "context-menu-root", k, level + 1, hide));

      ul [options .animation .show] (options .animation .duration);

      // Reposition menu if to right or to low.

		ul .offset ({ "left": event .pageX, "top": event .pageY }); // Do it again!

      if (ul .offset () .left - ContextMenu_$(document) .scrollLeft () + ul .outerWidth () > ContextMenu_$(window) .width ())
         ul .offset ({ "left":  ContextMenu_$(document) .scrollLeft () + Math .max (0, ContextMenu_$(window) .width () - ul .outerWidth ()) });

      if (ul .offset () .top - ContextMenu_$(document) .scrollTop () + ul .outerHeight () > ContextMenu_$(window) .height ())
         ul .offset ({ "top": ContextMenu_$(document) .scrollTop () + Math .max (0, ContextMenu_$(window) .height () - ul .outerHeight ()) });

      // Display submenus on the left or right side.
      // If the submenu is higher than vh, add scrollbars.

      ul .find ("ul") .each ((i, e) =>
      {
         e = ContextMenu_$(e);

         const
            width    = e .outerWidth () + ul .outerWidth (),
            position = ul .offset () .left - ContextMenu_$(document) .scrollLeft () + width > ContextMenu_$(window) .width () ? "right" : "left";

         e .css ("width", e .outerWidth ());
         e .css (position, e .parent () .closest ("ul") .width ());

         if (e .outerHeight () >= ContextMenu_$(window) .height ())
            e .css ({ "max-height": "100vh", "overflow-y": "scroll" });
      });

      // If the submenu is higher than vh, reposition it.

      ul .find ("li") .on ("mouseenter touchstart", function (event)
      {
         event .stopImmediatePropagation ();

         const
            t = ContextMenu_$(event .target) .closest ("li"),
            e = t .children ("ul");

         if (! e .length)
            return;

         e .css ("top", "");

         const bottom = e .offset () .top + e .outerHeight () - ContextMenu_$(window) .scrollTop () - ContextMenu_$(window) .height ();

         if (bottom > 0)
            e .offset ({ "top": e .offset () .top - bottom });
      });

      // Layer

      layer .on ("click contextmenu", hide);
      ul .on ("contextmenu", hide);

      // Show

      if (options .events && typeof options .events .show === "function")
         options .events .show (ul);

      return false;
   },
   createItem (item, parent, key, level, hide)
   {
      const li = ContextMenu_$("<li></li>") .addClass ("context-menu-item");

      switch (typeof item)
      {
         case "string":
         {
            if (item .match (/^-+$/))
               li .addClass (["context-menu-separator", "context-menu-not-selectable"]);

            break;
         }
         case "object":
         {
            if (item .className)
               li .addClass (item .className);

            switch (item .type)
            {
               case "radio":
               case "checkbox":
               {
                  const
                     label = ContextMenu_$("<label></label>") .appendTo (li),
                     input = ContextMenu_$("<input></input>") .appendTo (label);

                  input
                     .attr ("type", item .type)
                     .attr ("name", "context-menu-input-" + (item .radio || parent));

                  ContextMenu_$("<span></span>") .text (item .name) .appendTo (label);

                  if (item .selected)
                     input .attr ("checked", "checked");

                  for (const k in item .events)
                  {
                     if (typeof item .events [k] === "function")
                        input .on (k, item .events [k]);
                  }

                  li .addClass ("context-menu-input");

                  break;
               }
               default:
               {
                  if (item .name)
                     ContextMenu_$("<span></span>") .text (item .name) .appendTo (li);

                  if (typeof item .callback === "function")
                     li .on ("click", item .callback) .on ("click", hide);

                  break;
               }
            }

            break;
         }
      }

      if (typeof item .items === "object" && level < 3)
      {
         const ul = ContextMenu_$("<ul></ul>")
            .addClass ("context-menu-list")
            .css ({ "z-index": level })
            .appendTo (li);

         for (const k in item .items)
            ul .append (this .createItem (item .items [k], key, k, level + 1, hide));

         li .addClass ("context-menu-submenu");
      }

      return li;
   },
});

Object .defineProperties (ContextMenu,
{
   typeName:
   {
      value: "ContextMenu",
      enumerable: true,
   },
});

const ContextMenu_default_ = ContextMenu;
;

x_ite_Namespace .add ("ContextMenu", "x_ite/Browser/Core/ContextMenu", ContextMenu_default_);
/* harmony default export */ const Core_ContextMenu = (ContextMenu_default_);
;// CONCATENATED MODULE: ./src/x_ite/Configuration/ComponentInfo.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function ComponentInfo (name, level, title, providerURL, external = false, dependencies = [ ])
{
   Object .defineProperties (this,
   {
      name: { value: name, enumerable: true },
      level: { value: level, enumerable: true },
      title: { value: title, enumerable: true },
      providerURL: { value: providerURL || Networking_URLs .getProviderURL (external && name), enumerable: true },
      external: { value: external },
      dependencies: { value: dependencies },
   });
}

Object .assign (Object .setPrototypeOf (ComponentInfo .prototype, Base_X3DObject .prototype),
{
   toVRMLStream (generator)
   {
      generator .string += generator .Indent ();
      generator .string += "COMPONENT";
      generator .string += generator .Space ();
      generator .string += this .name;
      generator .string += generator .TidySpace ();
      generator .string += ":";
      generator .string += generator .TidySpace ();
      generator .string += this .level;
   },
   toXMLStream (generator)
   {
      generator .string += generator .Indent ();
      generator .string += "<component";
      generator .string += generator .Space ();
      generator .string += "name='";
      generator .string += this .name;
      generator .string += "'";
      generator .string += generator .Space ();
      generator .string += "level='";
      generator .string += this .level;
      generator .string += "'";
      generator .string += generator .closingTags ? "></component>" : "/>";
   },
   toJSONStream (generator)
   {
      generator .string += generator .Indent ();
      generator .string += '{';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "@name";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += this .name;
      generator .string += '"';
      generator .string += ',';
      generator .string += generator .TidyBreak ();

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "@level";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += this .level;
      generator .string += generator .TidyBreak ();

      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';
   },
});

for (const key of Object .keys (ComponentInfo .prototype))
   Object .defineProperty (ComponentInfo .prototype, key, { enumerable: false });

Object .defineProperties (ComponentInfo,
{
   typeName:
   {
      value: "ComponentInfo",
      enumerable: true,
   },
});

Object .defineProperties (ComponentInfo .prototype,
{
   providerUrl: // legacy
   {
      get: function () { return this .providerURL; },
   },
});

const ComponentInfo_default_ = ComponentInfo;
;

x_ite_Namespace .add ("ComponentInfo", "x_ite/Configuration/ComponentInfo", ComponentInfo_default_);
/* harmony default export */ const Configuration_ComponentInfo = (ComponentInfo_default_);
;// CONCATENATED MODULE: ./src/x_ite/Configuration/ComponentInfoArray.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function ComponentInfoArray (values = [ ])
{
   return Base_X3DInfoArray .call (this, Array .from (values, value => [value .name, value]), Configuration_ComponentInfo);
}

Object .assign (Object .setPrototypeOf (ComponentInfoArray .prototype, Base_X3DInfoArray .prototype),
{
   add (name, { level, title, providerURL, external = false, dependencies = [ ] })
   {
      Base_X3DInfoArray .prototype .add .call (this, name, new Configuration_ComponentInfo (name, level, title, providerURL, external, dependencies));
   },
});

for (const key of Object .keys (ComponentInfoArray .prototype))
   Object .defineProperty (ComponentInfoArray .prototype, key, { enumerable: false });

Object .defineProperties (ComponentInfoArray,
{
   typeName:
   {
      value: "ComponentInfoArray",
      enumerable: true,
   },
});

const ComponentInfoArray_default_ = ComponentInfoArray;
;

x_ite_Namespace .add ("ComponentInfoArray", "x_ite/Configuration/ComponentInfoArray", ComponentInfoArray_default_);
/* harmony default export */ const Configuration_ComponentInfoArray = (ComponentInfoArray_default_);
;// CONCATENATED MODULE: ./src/x_ite/Configuration/UnitInfo.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function UnitInfo (category, name, conversionFactor)
{
   Object .defineProperties (this,
   {
      category: { value: category, enumerable: true },
      name: { value: name, enumerable: true },
      conversionFactor: { value: conversionFactor, enumerable: true },
   });
}

Object .assign (Object .setPrototypeOf (UnitInfo .prototype, Base_X3DObject .prototype),
{
   toVRMLStream (generator)
   {
      generator .string += generator .Indent ();
      generator .string += "UNIT";
      generator .string += generator .Space ();
      generator .string += this .category;
      generator .string += generator .Space ();
      generator .string += this .name;
      generator .string += generator .Space ();
      generator .string += this .conversionFactor;
   },
   toXMLStream (generator)
   {
      generator .string += generator .Indent ();
      generator .string += "<unit";
      generator .string += generator .Space ();
      generator .string += "category='";
      generator .string += this .category;
      generator .string += "'";
      generator .string += generator .Space ();
      generator .string += "name='";
      generator .string += generator .XMLEncode (this .name);
      generator .string += "'";
      generator .string += generator .Space ();
      generator .string += "conversionFactor='";
      generator .string += this .conversionFactor;
      generator .string += "'";
      generator .string += generator .closingTags ? "></unit>" : "/>";
   },
   toJSONStream (generator, _throw)
   {
      if (this .conversionFactor === 1)
         throw new Error ("conversionFactor is 1");

      generator .string += generator .Indent ();

      generator .string += '{';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "@category";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += this .category;
      generator .string += '"';
      generator .string += ',';
      generator .string += generator .TidyBreak ();

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "@name";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += generator .JSONEncode (this .name);
      generator .string += '"';
      generator .string += ',';
      generator .string += generator .TidyBreak ();

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "@conversionFactor";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += this .conversionFactor;
      generator .string += generator .TidyBreak ();

      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';
   },
});

for (const key of Object .keys (UnitInfo .prototype))
   Object .defineProperty (UnitInfo .prototype, key, { enumerable: false });

Object .defineProperty (UnitInfo .prototype, "conversion_factor",
{
   get () { return this .conversionFactor; },
});

Object .defineProperties (UnitInfo,
{
   typeName:
   {
      value: "UnitInfo",
      enumerable: true,
   },
});

const UnitInfo_default_ = UnitInfo;
;

x_ite_Namespace .add ("UnitInfo", "x_ite/Configuration/UnitInfo", UnitInfo_default_);
/* harmony default export */ const Configuration_UnitInfo = (UnitInfo_default_);
;// CONCATENATED MODULE: ./src/x_ite/Configuration/UnitInfoArray.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function UnitInfoArray (values = [ ])
{
   return Base_X3DInfoArray .call (this, Array .from (values, value => [value .category, value]), Configuration_UnitInfo);
}

Object .setPrototypeOf (UnitInfoArray .prototype, Base_X3DInfoArray .prototype);

for (const key of Object .keys (UnitInfoArray .prototype))
   Object .defineProperty (UnitInfoArray .prototype, key, { enumerable: false });

Object .defineProperties (UnitInfoArray,
{
   typeName:
   {
      value: "UnitInfoArray",
      enumerable: true,
   },
});

const UnitInfoArray_default_ = UnitInfoArray;
;

x_ite_Namespace .add ("UnitInfoArray", "x_ite/Configuration/UnitInfoArray", UnitInfoArray_default_);
/* harmony default export */ const Configuration_UnitInfoArray = (UnitInfoArray_default_);
;// CONCATENATED MODULE: ./src/x_ite/Execution/X3DExportedNode.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




const
   X3DExportedNode_exportedName = Symbol (),
   _localNode    = Symbol ();

function X3DExportedNode (exportedName, localNode)
{
   Base_X3DObject .call (this);

   this [X3DExportedNode_exportedName] = exportedName;
   this [_localNode]    = localNode;
}

Object .assign (Object .setPrototypeOf (X3DExportedNode .prototype, Base_X3DObject .prototype),
{
   getExportedName ()
   {
      return this [X3DExportedNode_exportedName];
   },
   getLocalNode ()
   {
      return this [_localNode];
   },
   toVRMLStream (generator)
   {
      const localName = generator .LocalName (this [_localNode]);

      generator .string += generator .Indent ();
      generator .string += "EXPORT";
      generator .string += generator .Space ();
      generator .string += localName;

      if (this [X3DExportedNode_exportedName] !== localName)
      {
         generator .string += generator .Space ();
         generator .string += "AS";
         generator .string += generator .Space ();
         generator .string += this [X3DExportedNode_exportedName];
      }
   },
   toXMLStream (generator)
   {
      const localName = generator .LocalName (this [_localNode]);

      generator .string += generator .Indent ();
      generator .string += "<EXPORT";
      generator .string += generator .Space ();
      generator .string += "localDEF='";
      generator .string += generator .XMLEncode (localName);
      generator .string += "'";

      if (this [X3DExportedNode_exportedName] !== localName)
      {
         generator .string += generator .Space ();
         generator .string += "AS='";
         generator .string += generator .XMLEncode (this [X3DExportedNode_exportedName]);
         generator .string += "'";
      }

      generator .string += generator .closingTags ? "></EXPORT>" : "/>";
   },
   toJSONStream (generator)
   {
      const localName = generator .LocalName (this [_localNode]);

      generator .string += generator .Indent ();
      generator .string += '{';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += "EXPORT";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();
      generator .string += generator .Indent ();
      generator .string += '{';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "@localDEF";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += generator .JSONEncode (localName);
      generator .string += '"';

      if (this [X3DExportedNode_exportedName] !== localName)
      {
         generator .string += ',';
         generator .string += generator .TidyBreak ();
         generator .string += generator .Indent ();
         generator .string += '"';
         generator .string += "@AS";
         generator .string += '"';
         generator .string += ':';
         generator .string += generator .TidySpace ();
         generator .string += '"';
         generator .string += generator .JSONEncode (this [X3DExportedNode_exportedName]);
         generator .string += '"';
         generator .string += generator .TidyBreak ();
      }
      else
      {
         generator .string += generator .TidyBreak ();
      }

      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';
      generator .string += generator .TidyBreak ();
      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';
   },
});

for (const key of Object .keys (X3DExportedNode .prototype))
   Object .defineProperty (X3DExportedNode .prototype, key, { enumerable: false });

Object .defineProperties (X3DExportedNode .prototype,
{
   exportedName:
   {
      get ()
      {
         return this [X3DExportedNode_exportedName];
      },
      enumerable: true,
   },
   localNode:
   {
      get ()
      {
         return Fields_SFNodeCache .get (this [_localNode]);
      },
      enumerable: true,
   },
});

Object .defineProperties (X3DExportedNode,
{
   typeName:
   {
      value: "X3DExportedNode",
      enumerable: true,
   },
});

const X3DExportedNode_default_ = X3DExportedNode;
;

x_ite_Namespace .add ("X3DExportedNode", "x_ite/Execution/X3DExportedNode", X3DExportedNode_default_);
/* harmony default export */ const Execution_X3DExportedNode = (X3DExportedNode_default_);
;// CONCATENATED MODULE: ./src/x_ite/Execution/ExportedNodesArray.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function ExportedNodesArray (values = [ ])
{
   return Base_X3DInfoArray .call (this, Array .from (values, value => [value .getExportedName (), value]), Execution_X3DExportedNode);
}

Object .setPrototypeOf (ExportedNodesArray .prototype, Base_X3DInfoArray .prototype);

for (const key of Object .keys (ExportedNodesArray .prototype))
   Object .defineProperty (ExportedNodesArray .prototype, key, { enumerable: false });

Object .defineProperties (ExportedNodesArray,
{
   typeName:
   {
      value: "ExportedNodesArray",
      enumerable: true,
   },
});

const ExportedNodesArray_default_ = ExportedNodesArray;
;

x_ite_Namespace .add ("ExportedNodesArray", "x_ite/Execution/ExportedNodesArray", ExportedNodesArray_default_);
/* harmony default export */ const Execution_ExportedNodesArray = (ExportedNodesArray_default_);
;// CONCATENATED MODULE: ./src/x_ite/Execution/X3DScene.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/














const
   _specificationVersion = Symbol (),
   _encoding             = Symbol (),
   _profile              = Symbol (),
   _components           = Symbol (),
   _worldURL             = Symbol (),
   _units                = Symbol (),
   _metadata             = Symbol (),
   _exportedNodes        = Symbol (),
   _loadingObjects       = Symbol ();

const X3D_LATEST_VERSION = "4.0";

function X3DScene (browser)
{
   Execution_X3DExecutionContext .call (this, this, null, browser);

   this .addType (Base_X3DConstants .X3DScene)

   this .addChildObjects (Base_X3DConstants .outputOnly, "profile_changed",  new x_ite_Fields .SFTime (),
                          Base_X3DConstants .outputOnly, "metadata_changed", new x_ite_Fields .SFTime (),
                          Base_X3DConstants .outputOnly, "initLoadCount",    new x_ite_Fields .SFInt32 (),
                          Base_X3DConstants .outputOnly, "loadCount",        new x_ite_Fields .SFInt32 ())

   this [_specificationVersion] = X3D_LATEST_VERSION;
   this [_encoding]             = "SCRIPTED";
   this [_profile]              = null;
   this [_components]           = new Configuration_ComponentInfoArray ([ ]);
   this [_worldURL]             = location .toString ();
   this [_units]                = new Configuration_UnitInfoArray ();

   this [_units] .add ("angle",  new Configuration_UnitInfo ("angle",  "radian",   1));
   this [_units] .add ("force",  new Configuration_UnitInfo ("force",  "newton",   1));
   this [_units] .add ("length", new Configuration_UnitInfo ("length", "metre",    1));
   this [_units] .add ("mass",   new Configuration_UnitInfo ("mass",   "kilogram", 1));

   this [_metadata]       = new Map ();
   this [_exportedNodes]  = new Execution_ExportedNodesArray ();
   this [_loadingObjects] = new Set ();

   this [_components]    .addParent (this);
   this [_units]         .addParent (this);
   this [_exportedNodes] .addParent (this);

   this .getRootNodes () .setAccessType (Base_X3DConstants .inputOutput);

   this .setLive (false);
}

Object .assign (Object .setPrototypeOf (X3DScene .prototype, Execution_X3DExecutionContext .prototype),
{
   isMainScene ()
   {
      return this === this .getExecutionContext ();
   },
   isScene ()
   {
      return true;
   },
   setSpecificationVersion (specificationVersion)
   {
      this [_specificationVersion] = String (specificationVersion);
   },
   getSpecificationVersion ()
   {
      return this [_specificationVersion];
   },
   setEncoding (encoding)
   {
      this [_encoding] = String (encoding);
   },
   getEncoding ()
   {
      return this [_encoding];
   },
   setWorldURL (url)
   {
      this [_worldURL] = String (url);
   },
   getWorldURL ()
   {
      return this [_worldURL];
   },
   getBaseURL ()
   {
      if (this [_worldURL] .match (/^(?:data|blob):/))
      {
         if (this .isMainScene ())
            return this .getBrowser () .getBaseURL ();

         return this .getExecutionContext () .getBaseURL ();
      }

      return this [_worldURL];
   },
   setProfile (profile)
   {
      this [_profile] = profile;

      this ._profile_changed = this .getBrowser () .getCurrentTime ();
   },
   getProfile ()
   {
      return this [_profile];
   },
   hasComponent (name, level = 0)
   {
      if (!this [_profile])
         return true;

      if (name instanceof Configuration_ComponentInfo)
         var { name, level } = name;

      const component = this [_profile] .components .get (name) ?? this [_components] .get (name);

      if (component)
         return level <= component .level;

      return false;
   },
   addComponent (component)
   {
      this [_components] .add (component .name, component);

      this ._components_changed = this .getBrowser () .getCurrentTime ();
   },
   updateComponent (component)
   {
      this [_components] .update (component .name, component .name, component);

      this ._components_changed = this .getBrowser () .getCurrentTime ();
   },
   removeComponent (name)
   {
      this [_components] .remove (name);

      this ._components_changed = this .getBrowser () .getCurrentTime ();
   },
   getComponents ()
   {
      return this [_components];
   },
   updateUnit (category, name, conversionFactor)
   {
      // Private function.

      if (!this [_units] .has (category))
         return;

      this [_units] .update (category, category, new Configuration_UnitInfo (category, String (name),  Number (conversionFactor)));

      this ._units_changed = this .getBrowser () .getCurrentTime ();
   },
   getUnit (category)
   {
      return this [_units] .get (category);
   },
   getUnits ()
   {
      return this [_units];
   },
   fromUnit (category, value)
   {
      switch (category)
      {
         // Base units

         case "angle":
         case "force":
         case "length":
         case "mass":
            return value * this .getUnits () .get (category) .conversionFactor;

         // Derived units

         case "acceleration:":
            return value * this .getUnits () .get ("length") .conversionFactor;
         case "angularRate":
            return value * this .getUnits () .get ("angle") .conversionFactor;
         case "area":
            return value * this .getUnits () .get ("length") .conversionFactor ** 2;
         case "speed":
            return value * this .getUnits () .get ("length") .conversionFactor;
         case "volume":
            return value * this .getUnits () .get ("length") .conversionFactor ** 3;
      }

      return value;
   },
   toUnit (category, value)
   {
      switch (category)
      {
         // Base units

         case "angle":
         case "force":
         case "length":
         case "mass":
            return value / this .getUnits () .get (category) .conversionFactor;

         // Derived units

         case "acceleration:":
            return value / this .getUnits () .get ("length") .conversionFactor;
         case "angularRate":
            return value / this .getUnits () .get ("angle") .conversionFactor;
         case "area":
            return value / this .getUnits () .get ("length") .conversionFactor ** 2;
         case "speed":
            return value / this .getUnits () .get ("length") .conversionFactor;
         case "volume":
            return value / this .getUnits () .get ("length") .conversionFactor ** 3;
      }

      return value;
   },
   setMetaData (name, values)
   {
      name = String (name);

      if (!name .length)
         throw new Error ("Couldn't add metadata: name is empty.");

      if (!Array .isArray (values))
         values = [String (values)];

      if (!values .length)
         throw new Error ("Couldn't add metadata: values length is 0.");

      this [_metadata] .set (name, values .map (value => String (value)));

      this ._metadata_changed = this .getBrowser () .getCurrentTime ();
   },
   addMetaData (name, value)
   {
      name  = String (name);
      value = String (value);

      if (!name .length)
         throw new Error ("Couldn't add metadata: name is empty.");

      let values = this [_metadata] .get (name);

      if (!values)
         this [_metadata] .set (name, values = [ ]);

      values .push (value);
   },
   removeMetaData (name)
   {
      name = String (name);

      this [_metadata] .delete (name);

      this ._metadata_changed = this .getBrowser () .getCurrentTime ();
   },
   getMetaData (name)
   {
      name = String (name);

      const values = this [_metadata] .get (name);

      if (values)
         return Array .from (values);

      return undefined;
   },
   getMetaDatas ()
   {
      return new Map (this [_metadata]);
   },
   addExportedNode (exportedName, node)
   {
      exportedName = String (exportedName);

      if (this [_exportedNodes] .has (exportedName))
         throw new Error (`Couldn't add exported node: exported name '${exportedName}' already in use.`);

      this .updateExportedNode (exportedName, node);

      this ._exportedNodes_changed = this .getBrowser () .getCurrentTime ();
   },
   updateExportedNode (exportedName, node)
   {
      exportedName = String (exportedName);
      node         = Base_X3DCast (Base_X3DConstants .X3DNode, node, false);

      if (exportedName .length === 0)
         throw new Error ("Couldn't update exported node: node exported name is empty.");

      if (!node)
         throw new Error ("Couldn't update exported node: node must be of type X3DNode.");

      //if (node .getExecutionContext () !== this)
      //	throw new Error ("Couldn't update exported node: node does not belong to this execution context.");

      this .removeExportedNode (exportedName);

      const exportedNode = new Execution_X3DExportedNode (exportedName, node);

      this [_exportedNodes] .add (exportedName, exportedNode);

      this ._exportedNodes_changed = this .getBrowser () .getCurrentTime ();
   },
   removeExportedNode (exportedName)
   {
      exportedName = String (exportedName);

      this [_exportedNodes] .remove (exportedName);

      this ._exportedNodes_changed = this .getBrowser () .getCurrentTime ();
   },
   getExportedNode (exportedName)
   {
      exportedName = String (exportedName);

      const exportedNode = this [_exportedNodes] .get (exportedName);

      if (exportedNode)
         return Fields_SFNodeCache .get (exportedNode .getLocalNode ());

      throw new Error (`Exported node '${exportedName}' not found.`);
   },
   getExportedNodes ()
   {
      return this [_exportedNodes];
   },
   getUniqueExportName (name)
   {
      return getUniqueName (this [_exportedNodes], name);
   },
   addRootNode (node)
   {
      node = Fields_SFNodeCache .get (Base_X3DCast (Base_X3DConstants .X3DNode, node, false));

      const rootNodes = this .getRootNodes ();

      for (const rootNode of rootNodes)
      {
         if (rootNode .equals (node))
            return;
      }

      rootNodes .push (node);
   },
   removeRootNode (node)
   {
      node = Fields_SFNodeCache .get (Base_X3DCast (Base_X3DConstants .X3DNode, node, false));

      const rootNodes = this .getRootNodes ();

      rootNodes .assign (rootNodes .filter (rootNode => rootNode !== node));
   },
   setRootNodes (value)
   {
      if (!(value instanceof x_ite_Fields .MFNode))
         throw new Error ("Value must be of type MFNode.");

      this .getRootNodes () .assign (value);
   },
   toVRMLStream (generator)
   {
      generator .string += generator .Indent ();
      generator .string += "#X3D V";
      generator .string += X3D_LATEST_VERSION;
      generator .string += generator .Space ();
      generator .string += "utf8";
      generator .string += generator .Space ();
      generator .string += this .getBrowser () .name;
      generator .string += generator .Space ();
      generator .string += "V";
      generator .string += this .getBrowser () .version;
      generator .string += generator .ForceBreak ();
      generator .string += generator .ForceBreak ();

      const profile = this .getProfile ();

      if (profile)
      {
         profile .toVRMLStream (generator);

         generator .string += generator .Break ();
         generator .string += generator .TidyBreak ();
      }

      const components = this .getComponents ();

      if (components .length)
      {
         components .toVRMLStream (generator);

         generator .string += generator .TidyBreak ();
      }

      const units = this .getUnits () .filter (unit => unit .conversionFactor !== 1);

      if (units .length)
      {
         for (const unit of units)
         {
            unit .toVRMLStream (generator);

            generator .string += generator .Break ();
         }

         generator .string += generator .TidyBreak ();
      }

      const metadata = this .getMetaDatas ();

      if (metadata .size)
      {
         for (const [key, values] of metadata)
         {
            for (const value of values)
            {
               generator .string += generator .Indent ();
               generator .string += "META";
               generator .string += generator .Space ();
               generator .string += new x_ite_Fields .SFString (key) .toString ();
               generator .string += generator .Space ();
               generator .string += new x_ite_Fields .SFString (value) .toString ();
               generator .string += generator .Break ();
            }
         }

         generator .string += generator .TidyBreak ();
      }

      const exportedNodes = this .getExportedNodes ();

      generator .PushExecutionContext (this);
      generator .EnterScope ();
      generator .ExportedNodes (exportedNodes);

      Execution_X3DExecutionContext .prototype .toVRMLStream .call (this, generator);

      if (exportedNodes .length)
      {
         generator .string += generator .TidyBreak ();

         exportedNodes .toVRMLStream (generator);
      }

      generator .LeaveScope ();
      generator .PopExecutionContext ();
   },
   toXMLStream (generator)
   {
      if (!generator .html)
      {
         generator .string += generator .Indent ();
         generator .string += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
         generator .string += generator .TidyBreak ();
         generator .string += generator .Indent ();
         generator .string += "<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D ";
         generator .string += X3D_LATEST_VERSION;
         generator .string += "//EN\" \"http://www.web3d.org/specifications/x3d-";
         generator .string += X3D_LATEST_VERSION;
         generator .string += ".dtd\">";
         generator .string += generator .TidyBreak ();
      }

      generator .string += generator .Indent ();
      generator .string += "<X3D";
      generator .string += generator .Space ();
      generator .string += "profile='";
      generator .string += this .getProfile () ? this .getProfile () .name : "Full";
      generator .string += "'";
      generator .string += generator .Space ();
      generator .string += "version='";
      generator .string += X3D_LATEST_VERSION;
      generator .string += "'";
      generator .string += generator .Space ();
      generator .string += "xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance'";
      generator .string += generator .Space ();
      generator .string += "xsd:noNamespaceSchemaLocation='http://www.web3d.org/specifications/x3d-";
      generator .string += X3D_LATEST_VERSION;
      generator .string += ".xsd'>";
      generator .string += generator .TidyBreak ();

      generator .IncIndent ();

      if (this .getComponents () .length ||
          this .getUnits () .some (unit => unit .conversionFactor !== 1) ||
          this .getMetaDatas () .size)
      {
         generator .string += generator .Indent ();
         generator .string += "<head>";
         generator .string += generator .TidyBreak ();

         generator .IncIndent ();

         // <head>

         this .getComponents () .toXMLStream (generator);

         for (const unit of this .getUnits ())
         {
            if (unit .conversionFactor !== 1)
            {
               unit .toXMLStream (generator);

               generator .string += generator .TidyBreak ();
            }
         }

         for (const [key, values] of this .getMetaDatas ())
         {
            for (const value of values)
            {
               generator .string += generator .Indent ();
               generator .string += "<meta";
               generator .string += generator .Space ();
               generator .string += "name='";
               generator .string += generator .XMLEncode (key);
               generator .string += "'";
               generator .string += generator .Space ();
               generator .string += "content='";
               generator .string += generator .XMLEncode (value);
               generator .string += "'";
               generator .string += generator .closingTags ? "></meta>" : "/>";
               generator .string += generator .TidyBreak ();
            }
         }

         // </head>

         generator .DecIndent ();

         generator .string += generator .Indent ();
         generator .string += "</head>";
         generator .string += generator .TidyBreak ();
      }

      if (this .getExternProtoDeclarations () .length ||
          this .getProtoDeclarations () .length ||
          this .getRootNodes () .length)
      {
         generator .string += generator .Indent ();
         generator .string += "<Scene>";
         generator .string += generator .TidyBreak ();

         generator .IncIndent ();

         // <Scene>

         const exportedNodes = this .getExportedNodes ();

         generator .PushExecutionContext (this);
         generator .EnterScope ();
         generator .ExportedNodes (exportedNodes);

         Execution_X3DExecutionContext .prototype .toXMLStream .call (this, generator);

         exportedNodes .toXMLStream (generator);

         generator .LeaveScope ();
         generator .PopExecutionContext ();

         // </Scene>

         generator .DecIndent ();

         generator .string += generator .Indent ();
         generator .string += "</Scene>";
         generator .string += generator .TidyBreak ();
      }
      else
      {
         generator .string += generator .Indent ();
         generator .string += "<Scene/>";
         generator .string += generator .TidyBreak ();
      }

      generator .DecIndent ();

      generator .string += generator .Indent ();
      generator .string += "</X3D>";
      generator .string += generator .TidyBreak ();
   },
   toJSONStream (generator)
   {
      // X3D

      generator .string += generator .Indent ();
      generator .string += '{';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += "X3D";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '{';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();
      generator .string += generator .IncIndent ();


      // Encoding

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "encoding";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += "UTF-8";
      generator .string += '"';
      generator .string += ',';
      generator .string += generator .TidyBreak ();


      // Profile

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "@profile";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += this .getProfile () ? this .getProfile () .name : "Full";
      generator .string += '"';
      generator .string += ',';
      generator .string += generator .TidyBreak ();


      // Version

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "@version";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += X3D_LATEST_VERSION;
      generator .string += '"';
      generator .string += ',';
      generator .string += generator .TidyBreak ();


      // XSD noNamespaceSchemaLocation

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "@xsd:noNamespaceSchemaLocation";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += "http://www.web3d.org/specifications/x3d-";
      generator .string += X3D_LATEST_VERSION;
      generator .string += ".xsd";
      generator .string += '"';
      generator .string += ',';
      generator .string += generator .TidyBreak ();


      // JSON schema

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "JSON schema";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '"';
      generator .string += "http://www.web3d.org/specifications/x3d-";
      generator .string += X3D_LATEST_VERSION;
      generator .string += "-JSONSchema.json";
      generator .string += '"';
      generator .string += ',';
      generator .string += generator .TidyBreak ();


      // Head

      const outputUnits = this .getUnits () .some (unit => unit .conversionFactor !== 1);

      if (this .getComponents () .length || outputUnits || this .getMetaDatas () .size)
      {
         let headLastProperty = false;

         generator .string += generator .Indent ();
         generator .string += '"';
         generator .string += "head";
         generator .string += '"';
         generator .string += ':';
         generator .string += generator .TidySpace ();
         generator .string += '{';
         generator .string += generator .TidyBreak ();
         generator .string += generator .IncIndent ();


         // Meta data

         if (this .getMetaDatas () .size)
         {
            if (headLastProperty)
            {
               generator .string += ',';
               generator .string += generator .TidyBreak ();
            }


            // Meta data begin

            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "meta";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '[';
            generator .string += generator .TidyBreak ();
            generator .string += generator .IncIndent ();


            // Meta data

            for (const [i, [key, values]] of [... this .getMetaDatas ()] .entries ())
            {
               for (const [j, value] of values .entries ())
               {
                  generator .string += generator .Indent ();
                  generator .string += '{';
                  generator .string += generator .TidyBreak ();
                  generator .string += generator .IncIndent ();

                  generator .string += generator .Indent ();
                  generator .string += '"';
                  generator .string += "@name";
                  generator .string += '"';
                  generator .string += ':';
                  generator .string += generator .TidySpace ();
                  generator .string += '"';
                  generator .string += generator .JSONEncode (key);
                  generator .string += '"';
                  generator .string += ',';
                  generator .string += generator .TidyBreak ();

                  generator .string += generator .Indent ();
                  generator .string += '"';
                  generator .string += "@content";
                  generator .string += '"';
                  generator .string += ':';
                  generator .string += generator .TidySpace ();
                  generator .string += '"';
                  generator .string += generator .JSONEncode (value);
                  generator .string += '"';
                  generator .string += generator .TidyBreak ();

                  generator .string += generator .DecIndent ();
                  generator .string += generator .Indent ();
                  generator .string += '}';

                  if (!(i === this .getMetaDatas () .size - 1 && j === values .length - 1))
                     generator .string += ',';

                  generator .string += generator .TidyBreak ();
               }
            }


            // Meta data end

            generator .string += generator .DecIndent ();
            generator .string += generator .Indent ();
            generator .string += ']';

            headLastProperty = true;
         }


         // Components

         if (this .getComponents () .length)
         {
            if (headLastProperty)
            {
               generator .string += ',';
               generator .string += generator .TidyBreak ();
            }


            // Components begin

            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "component";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '[';
            generator .string += generator .TidyBreak ();
            generator .string += generator .IncIndent ();


            // Components

            this .getComponents () .toJSONStream (generator);


            // Components end

            generator .string += generator .DecIndent ();
            generator .string += generator .Indent ();
            generator .string += ']';

            headLastProperty = true;
         }


         // Units

         if (outputUnits)
         {
            if (headLastProperty)
            {
               generator .string += ',';
               generator .string += generator .TidyBreak ();
            }


            // Units begin

            generator .string += generator .Indent ();
            generator .string += '"';
            generator .string += "unit";
            generator .string += '"';
            generator .string += ':';
            generator .string += generator .TidySpace ();
            generator .string += '[';
            generator .string += generator .TidyBreak ();
            generator .string += generator .IncIndent ();


            // Units

            this .getUnits ()  .toJSONStream (generator);


            // Unit end

            generator .string += generator .DecIndent ();
            generator .string += generator .Indent ();
            generator .string += ']';

            headLastProperty = true;
         }


         // Head end

         generator .string += generator .TidyBreak ();
         generator .string += generator .DecIndent ();
         generator .string += generator .Indent ();
         generator .string += '}';
         generator .string += ',';
         generator .string += generator .TidyBreak ();
      }

      // Scene

      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "Scene";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '{';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();
      generator .string += generator .Indent ();
      generator .string += '"';
      generator .string += "-children";
      generator .string += '"';
      generator .string += ':';
      generator .string += generator .TidySpace ();
      generator .string += '[';
      generator .string += generator .TidyBreak ();
      generator .string += generator .IncIndent ();

      const exportedNodes = this .getExportedNodes ();

      generator .PushExecutionContext (this);
      generator .EnterScope ();
      generator .ExportedNodes (exportedNodes);

      Execution_X3DExecutionContext .prototype .toJSONStream .call (this, generator);

      // Exported nodes

      this .getExportedNodes () .toJSONStream (generator, true);

      generator .JSONRemoveComma ();

      generator .LeaveScope ();
      generator .PopExecutionContext ();

      // Scene end

      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += ']';
      generator .string += generator .TidyBreak ();
      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';


      // X3D end

      generator .string += generator .TidyBreak ();
      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';
      generator .string += generator .TidyBreak ();
      generator .string += generator .DecIndent ();
      generator .string += generator .Indent ();
      generator .string += '}';
      generator .string += generator .TidyBreak ();
   },
},
{
   setExecutionContext (value)
   {
      if (!this .isMainScene ())
      {
         const scene = this .getScene ();

         for (const object of this [_loadingObjects])
            scene .removeLoadingObject (object);
      }

      Execution_X3DExecutionContext .prototype .setExecutionContext .call (this, value);

      if (!this .isMainScene ())
      {
         const scene = this .getScene ();

         for (const object of this [_loadingObjects])
            scene .addLoadingObject (object);
      }
   },
   addInitLoadCount (node)
   {
      this ._initLoadCount = this ._initLoadCount .getValue () + 1;
   },
   removeInitLoadCount (node)
   {
      this ._initLoadCount = this ._initLoadCount .getValue () - 1;
   },
   getLoadingObjects ()
   {
      return this [_loadingObjects];
   },
   addLoadingObject (node)
   {
      if (this [_loadingObjects] .has (node))
         return;

      this [_loadingObjects] .add (node);

      this ._loadCount = this [_loadingObjects] .size;

      const
         browser = this .getBrowser (),
         scene   = this .getScene ();

      if (this === browser .getExecutionContext () || this .loader === browser .loader)
         browser .addLoadingObject (node);

      if (!this .isMainScene ())
         scene .addLoadingObject (node);
   },
   removeLoadingObject (node)
   {
      if (!this [_loadingObjects] .has (node))
         return;

      this [_loadingObjects] .delete (node);

      this ._loadCount = this [_loadingObjects] .size;

      const
         browser = this .getBrowser (),
         scene   = this .getScene ();

      if (this === browser .getExecutionContext () || this .loader === browser .loader)
         browser .removeLoadingObject (node);

      if (!this .isMainScene ())
         scene .removeLoadingObject (node);
   },
});

for (const key of Object .keys (X3DScene .prototype))
   Object .defineProperty (X3DScene .prototype, key, { enumerable: false });

Object .defineProperties (X3DScene .prototype,
{
   specificationVersion:
   {
      get: X3DScene .prototype .getSpecificationVersion,
      enumerable: true,
   },
   encoding:
   {
      get: X3DScene .prototype .getEncoding,
      enumerable: true,
   },
   profile:
   {
      get: X3DScene .prototype .getProfile,
      enumerable: true,
   },
   profile_changed:
   {
      get () { return this ._profile_changed; },
      enumerable: false,
   },
   components:
   {
      get: X3DScene .prototype .getComponents,
      enumerable: true,
   },
   worldURL:
   {
      get: X3DScene .prototype .getWorldURL,
      enumerable: true,
   },
   units:
   {
      get: X3DScene .prototype .getUnits,
      enumerable: true,
   },
   metadata_changed:
   {
      get () { return this ._metadata_changed; },
      enumerable: false,
   },
   rootNodes:
   {
      get: X3DScene .prototype .getRootNodes,
      set: X3DScene .prototype .setRootNodes,
      enumerable: true,
   },
   exportedNodes:
   {
      get: X3DScene .prototype .getExportedNodes,
      enumerable: true,
   },
   sceneGraph_changed:
   {
      get () { return this ._sceneGraph_changed; },
      enumerable: false,
   },
});

Object .defineProperties (X3DScene,
{
   typeName:
   {
      value: "X3DScene",
      enumerable: true,
   },
});

Base_X3DConstants .addNode (X3DScene);

const X3DScene_default_ = X3DScene;
;

x_ite_Namespace .add ("X3DScene", "x_ite/Execution/X3DScene", X3DScene_default_);
/* harmony default export */ const Execution_X3DScene = (X3DScene_default_);
;// CONCATENATED MODULE: ./src/standard/Utility/DataStorage.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

const
   storages   = new WeakMap (),
   namespaces = new WeakMap (),
   defaults   = new WeakMap ();

const DataStorage_handler =
{
   get (target, key)
   {
      const property = target [key];

      if (property !== undefined)
         return property;

      const string = target .getStorage () [target .getNameSpace () + key];

      if (string === undefined || string === "undefined" || string === null)
         return target .getDefaultValue (key);

      const value = JSON .parse (string);

      return value;
   },
   set (target, key, value)
   {
      if (value === undefined)
         target .getStorage () .removeItem (target .getNameSpace () + key);

      else
         target .getStorage () [target .getNameSpace () + key] = JSON .stringify (value);

      return true;
   },
};

function DataStorage (storage, namespace)
{
   this .target  = this;

   storages   .set (this, storage);
   namespaces .set (this, namespace);
   defaults   .set (this, { });

   return new Proxy (this, DataStorage_handler);
}

Object .assign (DataStorage .prototype,
{
   getStorage ()
   {
      return storages .get (this .target);
   },
   getNameSpace ()
   {
      return namespaces .get (this .target);
   },
   addNameSpace (namespace)
   {
      return new DataStorage (this .getStorage (), this .getNameSpace () + namespace);
   },
   setDefaultValues (object)
   {
      Object .assign (defaults .get (this .target), object);
   },
   getDefaultValue (key)
   {
      const value = defaults .get (this .target) [key];

      return value === undefined ? undefined : JSON .parse (JSON .stringify (value));
   },
   clear ()
   {
      const
         storage   = this .getStorage (),
         namespace = this .getNameSpace ();

      for (const key of Object .keys (storage))
      {
         if (key .startsWith (namespace))
            storage .removeItem (key)
      }
   },
});

const DataStorage_default_ = DataStorage;
;

x_ite_Namespace .add ("DataStorage", "standard/Utility/DataStorage", DataStorage_default_);
/* harmony default export */ const Utility_DataStorage = (DataStorage_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Core/X3DCoreContext.js
/* provided dependency */ var X3DCoreContext_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/
















const WEBGL_LATEST_VERSION = 2;

const
   _instanceId               = Symbol (),
   _element                  = Symbol (),
   _shadow                   = Symbol (),
   _surface                  = Symbol (),
   _canvas                   = Symbol (),
   _context                  = Symbol (),
   _splashScreen             = Symbol (),
   _localStorage             = Symbol (),
   _mobile                   = Symbol (),
   _browserTimings           = Symbol (),
   _browserOptions           = Symbol (),
   _browserProperties        = Symbol (),
   _renderingProperties      = Symbol (),
   _notification             = Symbol (),
   _contextMenu              = Symbol (),
   _privateScene             = Symbol (),
   _keydown                  = Symbol (),
   _keyup                    = Symbol (),
   _pixelPerPoint            = Symbol ();

let instanceId = 0;

function X3DCoreContext (element)
{
   // Get canvas & context.

   const
      browser      = X3DCoreContext_$("<div></div>") .addClass ("x_ite-private-browser") .attr ("tabindex", 0),
      surface      = X3DCoreContext_$("<div></div>") .addClass ("x_ite-private-surface") .appendTo (browser),
      splashScreen = X3DCoreContext_$("<div></div>") .hide () .addClass ("x_ite-private-splash-screen") .appendTo (browser),
      spinner      = X3DCoreContext_$("<div></div>") .addClass ("x_ite-private-spinner") .appendTo (splashScreen),
      progress     = X3DCoreContext_$("<div></div>") .addClass ("x_ite-private-progress") .appendTo (splashScreen);

   if (element .prop ("nodeName") .toLowerCase () === "x3d-canvas")
   {
      const
         shadow = X3DCoreContext_$(element [0] .attachShadow ({ mode: "open", delegatesFocus: true })),
         link   = X3DCoreContext_$("<link/>");

      link
         .on ("load", () => browser .show ())
         .attr ("rel", "stylesheet")
         .attr ("type", "text/css")
         .attr ("href", new URL ("x_ite.css", Networking_URLs .getScriptURL ()) .href);

      this [_shadow] = shadow
         .append (link)
         .append (browser .hide ());
   }
   else
   {
      this [_shadow] = element .prepend (browser);
   }

   X3DCoreContext_$("<div></div>") .addClass ("x_ite-private-x_ite") .html (this .getName () + "<span class='x_ite-private-x3d'>X3D</span>") .appendTo (progress);
   X3DCoreContext_$("<div></div>") .addClass ("x_ite-private-progressbar")  .appendTo (progress) .append (X3DCoreContext_$("<div></div>"));
   X3DCoreContext_$("<div></div>") .addClass ("x_ite-private-spinner-text") .appendTo (progress);

   this [_instanceId]   = ++ instanceId;
   this [_localStorage] = new Utility_DataStorage (localStorage, "X_ITE.X3DBrowser(" + this [_instanceId] + ").");
   this [_mobile]       = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i .test (navigator .userAgent);
   this [_element]      = element;
   this [_surface]      = surface;
   this [_canvas]       = X3DCoreContext_$("<canvas></canvas>") .addClass ("x_ite-private-canvas") .prependTo (surface);
   this [_context]      = Core_Context .create (this [_canvas] [0], WEBGL_LATEST_VERSION, element .attr ("preserveDrawingBuffer") === "true", this [_mobile]);
   this [_splashScreen] = splashScreen;

   this [_renderingProperties] = new Core_RenderingProperties (this .getPrivateScene ());
   this [_browserOptions]      = new Core_BrowserOptions      (this .getPrivateScene ());
   this [_browserProperties]   = new Core_BrowserProperties   (this .getPrivateScene ());
   this [_browserTimings]      = new Core_BrowserTimings      (this .getPrivateScene ());
   this [_notification]        = new Core_Notification        (this .getPrivateScene ());
   this [_contextMenu]         = new Core_ContextMenu         (this .getPrivateScene ());

   const inches = X3DCoreContext_$("<div></div>") .hide () .css ("height", "10in") .appendTo (X3DCoreContext_$("body"));
   this [_pixelPerPoint] = inches .height () / 720 || 1;
   inches .remove ();

   this .addChildObjects (Base_X3DConstants .outputOnly, "controlKey", new x_ite_Fields .SFBool (),
                          Base_X3DConstants .outputOnly, "shiftKey",   new x_ite_Fields .SFBool (),
                          Base_X3DConstants .outputOnly, "altKey",     new x_ite_Fields .SFBool (),
                          Base_X3DConstants .outputOnly, "commandKey", new x_ite_Fields .SFBool (),
                          Base_X3DConstants .outputOnly, "altGrKey",   new x_ite_Fields .SFBool ());
}

Object .assign (X3DCoreContext .prototype,
{
   initialize ()
   {
      // Setup browser nodes.

      this [_renderingProperties] .setup ();
      this [_browserOptions]      .setup ();
      this [_browserProperties]   .setup ();
      this [_browserTimings]      .setup ();
      this [_notification]        .setup ();
      this [_contextMenu]         .setup ();

      // Define properties of X3DCanvasElement.

      Object .defineProperties (this .getElement () .get (0),
      {
         browser:
         {
            value: this,
            enumerable: true,
         },
         src:
         {
            get: () =>
            {
               return this .getExecutionContext () .getWorldURL ();
            },
            set: (value) =>
            {
               this .loadURL (new x_ite_Fields .MFString (value))
                  .catch (error => console .error (error));
            },
            enumerable: true,
         },
         url:
         {
            get: () =>
            {
               return new x_ite_Fields .MFString (this .getExecutionContext () .getWorldURL ());
            },
            set: (value) =>
            {
               this .loadURL (value)
                  .catch (error => console .error (error));
            },
            enumerable: true,
         },
      });

      // Configure browser event handlers.

      this .getElement ()
         .on ("keydown.X3DCoreContext", this [_keydown] .bind (this))
         .on ("keyup.X3DCoreContext",   this [_keyup]   .bind (this));
   },
   getInstanceId ()
   {
      return this [_instanceId];
   },
   isStrict ()
   {
      return false;
   },
   getElement ()
   {
      return this [_element];
   },
   getShadow ()
   {
      return this [_shadow];
   },
   getSurface ()
   {
      return this [_surface];
   },
   getSplashScreen ()
   {
      return this [_splashScreen];
   },
   getCanvas ()
   {
      return this [_canvas];
   },
   getContext ()
   {
      return this [_context];
   },
   getMobile ()
   {
      return this [_mobile];
   },
   getLocalStorage ()
   {
      return this [_localStorage];
   },
   getBrowserTimings ()
   {
      return this [_browserTimings];
   },
   getBrowserOptions ()
   {
      return this [_browserOptions];
   },
   getBrowserProperties ()
   {
      return this [_browserProperties];
   },
   getRenderingProperties ()
   {
      return this [_renderingProperties];
   },
   getNotification ()
   {
      return this [_notification];
   },
   getContextMenu ()
   {
      return this [_contextMenu];
   },
   getPrivateScene ()
   {
      if (this [_privateScene])
         return this [_privateScene];

      // X3DScene for default nodes.

      this [_privateScene] = new Execution_X3DScene (this);

      this [_privateScene] .setLive (true);
      this [_privateScene] .setup ();

      return this [_privateScene];
   },
   getPixelPerPoint ()
   {
      return this [_pixelPerPoint] * this .getRenderingProperty ("ContentScale");
   },
   connectedCallback ()
   { },
   attributeChangedCallback (name, oldValue, newValue)
   {
      switch (name)
      {
         case "antialiased":
         {
            this .setBrowserOption ("Antialiased", this .parseBooleanAttribute (newValue, true));
            break;
         }
         case "baseURL":
         case "baseurl":
         {
            this .setBaseURL (newValue);
            break;
         }
         case "cache":
         {
            this .setBrowserOption ("Cache", this .parseBooleanAttribute (newValue, true));
            break;
         }
         case "contentScale":
         case "contentscale":
         {
            this .setBrowserOption ("ContentScale", newValue === "auto" ? -1 : parseFloat (newValue));
            break;
         }
         case "contextMenu":
         case "contextmenu":
         {
            this .setBrowserOption ("ContextMenu", this .parseBooleanAttribute (newValue, true));
            break;
         }
         case "debug":
         {
            this .setBrowserOption ("Debug", this .parseBooleanAttribute (newValue, false));
            break;
         }
         case "multisampling":
         {
            const samples = parseInt (newValue);

            this .setBrowserOption ("Multisampling", isNaN (samples) ? 4 : samples);
            break;
         }
         case "notifications":
         {
            this .setBrowserOption ("Notifications", this .parseBooleanAttribute (newValue, true));
            break;
         }
         case "oninitialized":
         case "onshutdown":
         {
            try
            {
               this .getElement () [0] [name] = new Function ("event", newValue);
            }
            catch (error)
            {
               console .error (error);
            }

            break;
         }
         case "orderIndependentTransparency":
         case "orderindependenttransparency":
         {
            this .setBrowserOption ("OrderIndependentTransparency", this .parseBooleanAttribute (newValue, false));
            break;
         }
         case "splashScreen":
         case "splashscreen":
         {
            this .setBrowserOption ("SplashScreen", this .parseBooleanAttribute (newValue, true));

            if (! this .getBrowserOption ("SplashScreen"))
            {
               this .getCanvas () .show ();
               this .getSplashScreen () .stop (true, true) .hide ();
            }

            break;
         }
         case "src":
         {
            if (newValue)
            {
               this .loadURL (new x_ite_Fields .MFString (newValue))
                  .catch (error => console .error (error));
            }

            break;
         }
         case "timings":
         {
            this .setBrowserOption ("Timings", this .parseBooleanAttribute (newValue, false));
            break;
         }
         case "update":
         {
            if (newValue === "auto")
            {
               this .setBrowserOption ("AutoUpdate", true);
            }
            else
            {
               this .setBrowserOption ("AutoUpdate", false);

               if (this .parseBooleanAttribute (newValue, true))
                  this .beginUpdate ();
               else
                  this .endUpdate ();
            }

            break;
         }
         case "url":
         {
            if (newValue)
            {
               this .loadURL (this .parseUrlAttribute (newValue))
                  .catch (error => console .error (error));
            }

            break;
         }
      }
   },
   parseBooleanAttribute  (value, defaultValue)
   {
      if (value === "true")
         return true;

      if (value === "false")
         return false;

      return defaultValue;
   },
   parseUrlAttribute (urlCharacters)
   {
      try
      {
         const url = new x_ite_Fields .MFString ();

         url .fromString ("[" + urlCharacters + "]", this .getExecutionContext ());

         return url;
      }
      catch
      {
         throw new Error ("Couldn't parse url attribute.");
      }
   },
   callBrowserEventHandler: (() =>
   {
      const build_in = new Set (["error", "load"]);

      return function (events)
      {
         const element = this .getElement () [0];

         for (const name of events .split (" "))
         {
            // Order is attribute, then dispatch.

            const event = new CustomEvent (name);

            try
            {
               if (!build_in .has (name))
                  element [`on${name}`] ?.(event);
            }
            catch (error)
            {
               console .error (error);
            }

            element .dispatchEvent (event);
         }
      };
   })(),
   getShiftKey ()
   {
      return this ._shiftKey .getValue ();
   },
   getControlKey ()
   {
      return this ._controlKey .getValue ();
   },
   getAltKey ()
   {
      return this ._altKey .getValue ();
   },
   getCommandKey ()
   {
      return this ._commandKey .getValue ();
   },
   getAltGrKey ()
   {
      return this ._altGrKey .getValue ();
   },
   [_keydown] (event)
   {
      switch (event .keyCode)
      {
         case 16: // Shift
         {
            this ._shiftKey = true;
            break;
         }
         case 17: // Ctrl
         {
            this ._controlKey = true;
            break;
         }
         case 18: // Alt
         {
            this ._altKey = true;
            break;
         }
         case 49: // 1
         {
            if (this .getBrowserOption ("Debug"))
            {
               if (this .getControlKey ())
               {
                  event .preventDefault ();
                  this .setBrowserOption ("Shading", "POINT");
                  this .getNotification () ._string = "Shading: Pointset";
               }
            }

            break;
         }
         case 50: // 2
         {
            if (this .getBrowserOption ("Debug"))
            {
               if (this .getControlKey ())
               {
                  event .preventDefault ();
                  this .setBrowserOption ("Shading", "WIREFRAME");
                  this .getNotification () ._string = "Shading: Wireframe";
               }
            }

            break;
         }
         case 51: // 3
         {
            if (this .getBrowserOption ("Debug"))
            {
               if (this .getControlKey ())
               {
                  event .preventDefault ();
                  this .setBrowserOption ("Shading", "FLAT");
                  this .getNotification () ._string = "Shading: Flat";
               }
            }

            break;
         }
         case 52: // 4
         {
            if (this .getBrowserOption ("Debug"))
            {
               if (this .getControlKey ())
               {
                  event .preventDefault ();
                  this .setBrowserOption ("Shading", "GOURAUD");
                  this .getNotification () ._string = "Shading: Gouraud";
               }
            }

            break;
         }
         case 53: // 5
         {
            if (this .getBrowserOption ("Debug"))
            {
               if (this .getControlKey ())
               {
                  event .preventDefault ();
                  this .setBrowserOption ("Shading", "PHONG");
                  this .getNotification () ._string = "Shading: Phong";
               }
            }

            break;
         }
         case 83: // s
         {
            if (this .getBrowserOption ("Debug"))
            {
               if (this .getControlKey ())
               {
                  event .preventDefault ();

                  if (this .isLive ())
                     this .endUpdate ();
                  else
                     this .beginUpdate ();

                  this .getNotification () ._string = this .getLive () .getValue () ? "Begin Update" : "End Update";
               }
            }

            break;
         }
         case 91: // Command
         {
            this ._commandKey = true;
            break;
         }
         case 225: // Alt Gr
         {
            this ._altGrKey = true;
            break;
         }
         case 171: // Plus // Firefox
         case 187: // Plus // Opera
         {
            if (this .getControlKey ())
            {
               event .preventDefault ();
               this .setBrowserOption ("Timings", !this .getBrowserOption ("Timings"));
            }

            break;
         }
         case 36: // Pos 1
         {
            event .preventDefault ();
            this .firstViewpoint ();
            break;
         }
         case 35: // End
         {
            event .preventDefault ();
            this .lastViewpoint ();
            break;
         }
         case 33: // Page Up
         {
            event .preventDefault ();
            this .previousViewpoint ();
            break;
         }
         case 34: // Page Down
         {
            event .preventDefault ();
            this .nextViewpoint ();
            break;
         }
         case 119: // F8
         {
            if (this .getShiftKey ())
            {
               event .preventDefault ();

               const viewpoint = this .getActiveViewpoint ();

               if (!viewpoint)
                  break;

               const vp = this .getPrivateScene () .createNode (viewpoint .getTypeName ());

               switch (viewpoint .getTypeName ())
               {
                  case "Viewpoint":
                  {
                     vp .position         = viewpoint .getUserPosition ();
                     vp .orientation      = viewpoint .getUserOrientation ();
                     vp .centerOfRotation = viewpoint .getUserCenterOfRotation ();
                     vp .fieldOfView      = viewpoint .getFieldOfView ();
                     break;
                  }
                  case "OrthoViewpoint":
                  {
                     vp .position         = viewpoint .getUserPosition ();
                     vp .orientation      = viewpoint .getUserOrientation ();
                     vp .centerOfRotation = viewpoint .getUserCenterOfRotation ();
                     vp .fieldOfView      = new x_ite_Fields .MFFloat (viewpoint .getMinimumX (), viewpoint .getMinimumY (), viewpoint .getMaximumX (), viewpoint .getMaximumY ());
                     break;
                  }
                  case "GeoViewpoint":
                  {
                     const
                        geoOrigin = viewpoint ._geoOrigin,
                        geoCoord  = new Numbers_Vector3 (0, 0, 0);

                     if (geoOrigin .getValue () && geoOrigin .getNodeTypeName () === "GeoOrigin")
                     {
                        const go = this .getPrivateScene () .createNode ("GeoOrigin");

                        vp .geoOrigin = go;
                        go .geoSystem = geoOrigin .geoSystem;
                        go .geoCoords = geoOrigin .geoCoords;
                        go .rotateYUp = geoOrigin .rotateYUp;
                     }

                     vp .geoSystem        = viewpoint ._geoSystem;
                     vp .position         = viewpoint .getGeoCoord (viewpoint .getUserPosition (), geoCoord);
                     vp .orientation      = viewpoint .getUserOrientation ();
                     vp .centerOfRotation = viewpoint .getGeoCoord (viewpoint .getUserCenterOfRotation (), geoCoord);
                     vp .fieldOfView      = viewpoint .getFieldOfView ();
                     break;
                  }
               }

               let text;

               switch (this .getExecutionContext () .getEncoding ())
               {
                  case "ASCII":
                  case "VRML": text = vp .toVRMLString (); break;
                  case "JSON": text = vp .toJSONString (); break;
                  default:     text = vp .toXMLString ();  break;
               }

               text += "\n";

               this .copyToClipboard (text);
               this .getNotification () ._string = locale_gettext ("Viewpoint copied to clipboard.");

               console .log ("Viewpoint copied to clipboard.");
               console .debug (text);
            }

            break;
         }
      }
   },
   [_keyup] (event)
   {
      //console .log (event .which);

      switch (event .which)
      {
         case 16: // Shift
         {
            this ._shiftKey = false;
            break;
         }
         case 17: // Ctrl
         {
            this ._controlKey = false;
            break;
         }
         case 18: // Alt
         {
            this ._altKey = false;
            break;
         }
         case 91: // Command
         {
            this ._commandKey = false;
            break;
         }
         case 225: // Alt Gr
         {
            this ._altGrKey = false;
            break;
         }
      }
   },
   copyToClipboard (text)
   {
      // The textarea must be visible to make copy work.
      const tmp = X3DCoreContext_$("<textarea></textarea>");
      this .getShadow () .find (".x_ite-private-browser") .prepend (tmp);
      tmp .text (text) .trigger ("select");
      document .execCommand ("copy");
      tmp .remove ();
   },
   dispose ()
   {
      this [_context] .getExtension ("WEBGL_lose_context") ?.loseContext ();
   },
});

const X3DCoreContext_default_ = X3DCoreContext;
;

x_ite_Namespace .add ("X3DCoreContext", "x_ite/Browser/Core/X3DCoreContext", X3DCoreContext_default_);
/* harmony default export */ const Core_X3DCoreContext = (X3DCoreContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/EnvironmentalEffects/X3DEnvironmentalEffectsContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



const _backgroundTextureProperties = Symbol ();

function X3DEnvironmentalEffectsContext () { }

Object .assign (X3DEnvironmentalEffectsContext .prototype,
{
   getBackgroundTextureProperties ()
   {
      this [_backgroundTextureProperties] = new Texturing_TextureProperties (this .getPrivateScene ());

      this [_backgroundTextureProperties] ._boundaryModeS       = "CLAMP_TO_EDGE";
      this [_backgroundTextureProperties] ._boundaryModeT       = "CLAMP_TO_EDGE";
      this [_backgroundTextureProperties] ._boundaryModeR       = "CLAMP_TO_EDGE";
      this [_backgroundTextureProperties] ._minificationFilter  = "NICEST";
      this [_backgroundTextureProperties] ._magnificationFilter = "NICEST";
      this [_backgroundTextureProperties] ._textureCompression  = "DEFAULT";
      this [_backgroundTextureProperties] .setup ();

      this .getBackgroundTextureProperties = function () { return this [_backgroundTextureProperties]; };

      Object .defineProperty (this, "getBackgroundTextureProperties", { enumerable: false });

      return this [_backgroundTextureProperties];
   },
});

const X3DEnvironmentalEffectsContext_default_ = X3DEnvironmentalEffectsContext;
;

x_ite_Namespace .add ("X3DEnvironmentalEffectsContext", "x_ite/Browser/EnvironmentalEffects/X3DEnvironmentalEffectsContext", X3DEnvironmentalEffectsContext_default_);
/* harmony default export */ const EnvironmentalEffects_X3DEnvironmentalEffectsContext = (X3DEnvironmentalEffectsContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Geometry3D/BoxOptions.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function BoxOptions (executionContext)
{
   Base_X3DBaseNode .call (this, executionContext);
}

Object .assign (Object .setPrototypeOf (BoxOptions .prototype, Base_X3DBaseNode .prototype),
{
   initialize ()
   {
      Base_X3DBaseNode .prototype .initialize .call (this);
   },
   getGeometry ()
   {
      if (this .geometry)
         return this .geometry;

      this .geometry            = new Geometry3D_IndexedFaceSet (this .getExecutionContext ());
      this .geometry ._texCoord = new Texturing_TextureCoordinate (this .getExecutionContext ());
      this .geometry ._coord    = new Rendering_Coordinate (this .getExecutionContext ());

      const
         geometry = this .geometry,
         texCoord = this .geometry ._texCoord .getValue (),
         coord    = this .geometry ._coord .getValue ();

      geometry ._texCoordIndex = new x_ite_Fields .MFInt32 (
         0, 1, 2, 3, -1, // front
         0, 1, 2, 3, -1, // back
         0, 1, 2, 3, -1, // left
         0, 1, 2, 3, -1, // right
         0, 1, 2, 3, -1, // top
         0, 1, 2, 3, -1  // bottom
      );

      geometry ._coordIndex = new x_ite_Fields .MFInt32 (
         0, 1, 2, 3, -1, // front
         5, 4, 7, 6, -1, // back
         1, 5, 6, 2, -1, // left
         4, 0, 3, 7, -1, // right
         4, 5, 1, 0, -1, // top
         3, 2, 6, 7, -1  // bottom
      );

      texCoord ._point = new x_ite_Fields .MFVec2f (
         new x_ite_Fields .SFVec2f (1, 1), new x_ite_Fields .SFVec2f (0, 1), new x_ite_Fields .SFVec2f (0, 0), new x_ite_Fields .SFVec2f (1, 0)
      );

      coord ._point = new x_ite_Fields .MFVec3f (
         new x_ite_Fields .SFVec3f ( 1,  1,  1), new x_ite_Fields .SFVec3f (-1,  1,  1), new x_ite_Fields .SFVec3f (-1, -1,  1), new x_ite_Fields .SFVec3f ( 1, -1,  1),
         new x_ite_Fields .SFVec3f ( 1,  1, -1), new x_ite_Fields .SFVec3f (-1,  1, -1), new x_ite_Fields .SFVec3f (-1, -1, -1), new x_ite_Fields .SFVec3f ( 1, -1, -1)
      );

      texCoord .setup ();
      coord    .setup ();
      geometry .setup ();

      return this .geometry;
   },
});

Object .defineProperties (BoxOptions,
{
   typeName:
   {
      value: "BoxOptions",
      enumerable: true,
   },
});

const BoxOptions_default_ = BoxOptions;
;

x_ite_Namespace .add ("BoxOptions", "x_ite/Browser/Geometry3D/BoxOptions", BoxOptions_default_);
/* harmony default export */ const Geometry3D_BoxOptions = (BoxOptions_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Geometry3D/ConeOptions.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function ConeOptions (executionContext)
{
   Base_X3DBaseNode .call (this, executionContext);

   this .addChildObjects (Base_X3DConstants .inputOutput, "xDimension", new x_ite_Fields .SFInt32 (20),
                          Base_X3DConstants .inputOutput, "yDimension", new x_ite_Fields .SFInt32 (1))
}

Object .setPrototypeOf (ConeOptions .prototype, Base_X3DBaseNode .prototype);

Object .defineProperties (ConeOptions,
{
   typeName:
   {
      value: "ConeOptions",
      enumerable: true,
   },
});

const ConeOptions_default_ = ConeOptions;
;

x_ite_Namespace .add ("ConeOptions", "x_ite/Browser/Geometry3D/ConeOptions", ConeOptions_default_);
/* harmony default export */ const Geometry3D_ConeOptions = (ConeOptions_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Geometry3D/CylinderOptions.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function CylinderOptions (executionContext)
{
   Base_X3DBaseNode .call (this, executionContext);

   this .addChildObjects (Base_X3DConstants .inputOutput, "xDimension", new x_ite_Fields .SFInt32 (20),
                          Base_X3DConstants .inputOutput, "yDimension", new x_ite_Fields .SFInt32 (1))
}

Object .setPrototypeOf (CylinderOptions .prototype, Base_X3DBaseNode .prototype);

Object .defineProperties (CylinderOptions,
{
   typeName:
   {
      value: "CylinderOptions",
      enumerable: true,
   },
});

const CylinderOptions_default_ = CylinderOptions;
;

x_ite_Namespace .add ("CylinderOptions", "x_ite/Browser/Geometry3D/CylinderOptions", CylinderOptions_default_);
/* harmony default export */ const Geometry3D_CylinderOptions = (CylinderOptions_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Geometry3D/QuadSphereOptions.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/











function QuadSphereOptions (executionContext)
{
   Base_X3DBaseNode .call (this, executionContext);

   this .addChildObjects (Base_X3DConstants .inputOutput, "xDimension", new x_ite_Fields .SFInt32 (32),
                          Base_X3DConstants .inputOutput, "yDimension", new x_ite_Fields .SFInt32 (15))
}

Object .assign (Object .setPrototypeOf (QuadSphereOptions .prototype, Base_X3DBaseNode .prototype),
{
   initialize ()
   {
      Base_X3DBaseNode .prototype .initialize .call (this);

      this .addInterest ("eventsProcessed", this);
   },
   getGeometry ()
   {
      if (! this .geometry)
         this .eventsProcessed ();

      return this .geometry;
   },
   createTexCoordIndex ()
   {
      const
         xDimension    = this ._xDimension .getValue () + 1,
         yDimension    = this ._yDimension .getValue (),
         texCoordIndex = this .geometry ._texCoordIndex;

      // North pole

      for (let u = 0, uLength = xDimension - 1; u < uLength; ++ u)
      {
         texCoordIndex .push (u);
         texCoordIndex .push (u + xDimension - 1);
         texCoordIndex .push (u + xDimension);
         texCoordIndex .push (-1);
      }

      // Sphere segments

      for (let p = xDimension - 1, v = 0, vLength = yDimension - 3; v < vLength; ++ v, ++ p)
      {
         for (let u = 0, uLength = xDimension - 1; u < uLength; ++ u, ++ p)
         {
            texCoordIndex .push (p);
            texCoordIndex .push (p + xDimension);
            texCoordIndex .push (p + xDimension + 1);
            texCoordIndex .push (p + 1);
            texCoordIndex .push (-1);
         }
      }

      // South pole

      let p = (yDimension - 2) * xDimension - 1;

      for (let u = 0, uLength = xDimension - 1; u < uLength; ++ u, ++ p)
      {
         texCoordIndex .push (p + xDimension);
         texCoordIndex .push (p + 1);
         texCoordIndex .push (p);
         texCoordIndex .push (-1);
      }
   },
   createTexCoord ()
   {
      const
         xDimension = this ._xDimension .getValue () + 1,
         yDimension = this ._yDimension .getValue (),
         point      = this .geometry ._texCoord .getValue () ._point;

      const poleOffset = -0.5 / (xDimension - 1);

      // North pole

      for (let u = 1; u < xDimension; ++ u)
      {
         const x = u / (xDimension - 1) + poleOffset;

         point .push (new Numbers_Vector2 (x, 1));
      }

      // Sphere segments

      for (let v = 1, vLength = yDimension - 1; v < vLength; ++ v)
      {
         const y = 1 - v / (yDimension - 1);

         for (let u = 0; u < xDimension; ++ u)
         {
            const x = u / (xDimension - 1);

            point .push (new Numbers_Vector2 (x, y));
         }
      }

      // South pole

      for (let u = 1; u < xDimension; ++ u)
      {
         const x = u / (xDimension - 1) + poleOffset;

         point .push (new Numbers_Vector2 (x, 0));
      }
   },
   createCoordIndex ()
   {
      const
         xDimension = this ._xDimension .getValue () + 1,
         yDimension = this ._yDimension .getValue (),
         coordIndex = this .geometry ._coordIndex;

      // North pole

      let u = 1;

      for (const uLength = xDimension - 1; u < uLength; ++ u)
      {
         coordIndex .push (0);
         coordIndex .push (u);
         coordIndex .push (u + 1);
         coordIndex .push (-1);
      }

      coordIndex .push (0);
      coordIndex .push (u);
      coordIndex .push (1);
      coordIndex .push (-1);

      // Sphere segments

      let p = 1;

      for (let v = 0, vLength = yDimension - 3; v < vLength; ++ v, ++ p)
      {
         for (let u = 0, uLength = xDimension - 2; u < uLength; ++ u, ++ p)
         {
            coordIndex .push (p);
            coordIndex .push (p + xDimension - 1);
            coordIndex .push (p + xDimension);
            coordIndex .push (p + 1);
            coordIndex .push (-1);
         }

         coordIndex .push (p);
         coordIndex .push (p + xDimension - 1);
         coordIndex .push (p + 1);
         coordIndex .push (p - xDimension + 2);
         coordIndex .push (-1);
      }

      // South pole

      const last = p + xDimension - 1;

      for (let u = 0, uLength = xDimension - 2; u < uLength; ++ u, ++ p)
      {
         coordIndex .push (last);
         coordIndex .push (p + 1);
         coordIndex .push (p);
         coordIndex .push (-1);
      }

      coordIndex .push (last);
      coordIndex .push (last - xDimension + 1);
      coordIndex .push (p);
      coordIndex .push (-1);
   },
   createPoints ()
   {
      const
         xDimension = this ._xDimension .getValue () + 1,
         yDimension = this ._yDimension .getValue (),
         point      = this .geometry ._coord .getValue () ._point;

      // North pole
      point .push (new Numbers_Vector3 (0, 1, 0));

      // Sphere segments
      for (let v = 1, vLength = yDimension - 1; v < vLength; ++ v)
      {
         const zPlane = Numbers_Complex .Polar (1, -Math .PI * v / vLength);

         for (let u = 0, uLength = xDimension - 1; u < uLength; ++ u)
         {
            const yPlane = Numbers_Complex .Polar (zPlane .imag, 2 * Math .PI * u / uLength);

            point .push (new Numbers_Vector3 (yPlane .imag, zPlane .real, yPlane .real));
         }
      }

      // South pole
      point .push (new Numbers_Vector3 (0, -1, 0));
   },
   eventsProcessed ()
   {
      this .geometry            = new Geometry3D_IndexedFaceSet (this .getExecutionContext ());
      this .geometry ._texCoord = new Texturing_TextureCoordinate (this .getExecutionContext ());
      this .geometry ._coord    = new Rendering_Coordinate (this .getExecutionContext ());

      this .createTexCoordIndex ();
      this .createTexCoord ();
      this .createCoordIndex ();
      this .createPoints ();

      const
         geometry = this .geometry,
         texCoord = this .geometry ._texCoord .getValue (),
         coord    = this .geometry ._coord .getValue ();

      geometry ._creaseAngle = Math .PI;

      texCoord .setup ();
      coord    .setup ();
      geometry .setup ();
   },
});

Object .defineProperties (QuadSphereOptions,
{
   typeName:
   {
      value: "QuadSphereOptions",
      enumerable: true,
   },
});

const QuadSphereOptions_default_ = QuadSphereOptions;
;

x_ite_Namespace .add ("QuadSphereOptions", "x_ite/Browser/Geometry3D/QuadSphereOptions", QuadSphereOptions_default_);
/* harmony default export */ const Geometry3D_QuadSphereOptions = (QuadSphereOptions_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Geometry3D/X3DGeometry3DContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function X3DGeometry3DContext () { }

Object .assign (X3DGeometry3DContext .prototype,
{
   initialize ()
   {
      this .setPrimitiveQuality3D (this .getBrowserOptions () .getPrimitiveQuality ());
   },
   getBoxOptions ()
   {
      return getOptionNode .call (this, "getBoxOptions", Geometry3D_BoxOptions);
   },
   getConeOptions ()
   {
      return getOptionNode .call (this, "getConeOptions", Geometry3D_ConeOptions);
   },
   getCylinderOptions ()
   {
      return getOptionNode .call (this, "getCylinderOptions", Geometry3D_CylinderOptions);
   },
   getSphereOptions ()
   {
      return getOptionNode .call (this, "getSphereOptions", Geometry3D_QuadSphereOptions);
   },
   setPrimitiveQuality3D (primitiveQuality)
   {
      const
         cone     = this .getConeOptions (),
         cylinder = this .getCylinderOptions (),
         sphere   = this .getSphereOptions ();

      switch (primitiveQuality)
      {
         case Core_PrimitiveQuality .LOW:
         {
            cone     ._xDimension = 16;
            cylinder ._xDimension = 16;
            sphere   ._xDimension = 20;
            sphere   ._yDimension = 9;
            break;
         }
         case Core_PrimitiveQuality .MEDIUM:
         {
            cone     ._xDimension = 20;
            cylinder ._xDimension = 20;
            sphere   ._xDimension = 32;
            sphere   ._yDimension = 15;
            break;
         }
         case Core_PrimitiveQuality .HIGH:
         {
            cone     ._xDimension = 32;
            cylinder ._xDimension = 32;
            sphere   ._xDimension = 64;
            sphere   ._yDimension = 31;
            break;
         }
      }
   },
});

function getOptionNode (key, OptionNode)
{
   const optionNode = new OptionNode (this .getPrivateScene ());

   optionNode .setup ();

   this [key] = function () { return optionNode; };

   Object .defineProperty (this, key, { enumerable: false });

   return optionNode;
}

const X3DGeometry3DContext_default_ = X3DGeometry3DContext;
;

x_ite_Namespace .add ("X3DGeometry3DContext", "x_ite/Browser/Geometry3D/X3DGeometry3DContext", X3DGeometry3DContext_default_);
/* harmony default export */ const Geometry3D_X3DGeometry3DContext = (X3DGeometry3DContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Grouping/X3DGroupingContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





const _bboxShape = Symbol ();

function X3DGroupingContext () { }

Object .assign (X3DGroupingContext .prototype,
{
   getBBoxNode ()
   {
      const
         bboxShape      = new Shape_Shape (this .getPrivateScene ()),
         bboxGeometry   = new Rendering_IndexedLineSet (this .getPrivateScene ()),
         bboxCoordinate = new Rendering_Coordinate (this .getPrivateScene ());

      bboxShape ._geometry      = bboxGeometry;
      bboxGeometry ._coordIndex = [0, 1, 2, 3, 0, -1, 4, 5, 6, 7, 4, -1, 0, 4, -1, 1, 5, -1, 2, 6, -1, 3, 7, -1];
      bboxGeometry ._coord      = bboxCoordinate;
      bboxCoordinate ._point    = [0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5];

      bboxCoordinate .setup ();
      bboxGeometry   .setup ();
      bboxShape      .setup ();

      this [_bboxShape] = bboxShape;

      this .getBBoxNode = function () { return this [_bboxShape]; };

      Object .defineProperty (this, "getBBoxNode", { enumerable: false });

      return bboxShape;
   },
});

const X3DGroupingContext_default_ = X3DGroupingContext;
;

x_ite_Namespace .add ("X3DGroupingContext", "x_ite/Browser/Grouping/X3DGroupingContext", X3DGroupingContext_default_);
/* harmony default export */ const Grouping_X3DGroupingContext = (X3DGroupingContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Layering/X3DLayeringContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



const _defaultViewport = Symbol ();

function X3DLayeringContext ()
{
   this [_defaultViewport] = new Layering_Viewport (this .getPrivateScene ());
}

Object .assign (X3DLayeringContext .prototype,
{
   initialize ()
   {
      this [_defaultViewport] .setPrivate (true);
      this [_defaultViewport] .setup ();
   },
   getDefaultViewport ()
   {
      return this [_defaultViewport];
   },
});

const X3DLayeringContext_default_ = X3DLayeringContext;
;

x_ite_Namespace .add ("X3DLayeringContext", "x_ite/Browser/Layering/X3DLayeringContext", X3DLayeringContext_default_);
/* harmony default export */ const Layering_X3DLayeringContext = (X3DLayeringContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Lighting/X3DLightingContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



const
   _maxLights     = Symbol (),
   _shadowBuffers = Symbol ();

function X3DLightingContext ()
{
   const
      gl                   = this .getContext (),
      maxTextureImageUnits = gl .getParameter (gl .MAX_TEXTURE_IMAGE_UNITS);

   if (maxTextureImageUnits > 8)
      this [_maxLights] = 8;
   else
      this [_maxLights] = 2;

   this [_shadowBuffers] = [ ]; // Shadow buffer cache
}

Object .assign (X3DLightingContext .prototype,
{
   getMaxLights ()
   {
      return this [_maxLights];
   },
   popShadowBuffer (shadowMapSize)
   {
      try
      {
         const shadowBuffers = this [_shadowBuffers] [shadowMapSize];

         if (shadowBuffers)
         {
            if (shadowBuffers .length)
               return shadowBuffers .pop ();
         }
         else
            this [_shadowBuffers] [shadowMapSize] = [ ];

         return new Rendering_TextureBuffer (this, shadowMapSize, shadowMapSize, true);
      }
      catch (error)
      {
         // Couldn't create texture buffer.
         console .error (error);

         return null;
      }
   },
   pushShadowBuffer (buffer)
   {
      if (buffer)
         this [_shadowBuffers] [buffer .getWidth ()] .push (buffer);
   },
});

const X3DLightingContext_default_ = X3DLightingContext;
;

x_ite_Namespace .add ("X3DLightingContext", "x_ite/Browser/Lighting/X3DLightingContext", X3DLightingContext_default_);
/* harmony default export */ const Lighting_X3DLightingContext = (X3DLightingContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Navigation/X3DViewer.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









function X3DViewer (executionContext, navigationInfo)
{
   Base_X3DBaseNode .call (this, executionContext);

   this .navigationInfo = navigationInfo;
}

Object .assign (Object .setPrototypeOf (X3DViewer .prototype, Base_X3DBaseNode .prototype),
{
   getActiveLayer ()
   {
      return this .getBrowser () .getActiveLayer ();
   },
   getViewport ()
   {
      return this .getBrowser () .getActiveLayer () .getViewport () .getRectangle ();
   },
   getNavigationInfo ()
   {
      return this .navigationInfo;
   },
   getActiveViewpoint ()
   {
      return this .getBrowser () .getActiveLayer () .getViewpoint ();
   },
   getStraightenHorizon ()
   {
      return this .getBrowser () .getBrowserOption ("StraightenHorizon");
   },
   getButton (button)
   {
      // If Alt key is pressed and button 0, then emulate button 1 (middle).
      if (button === 0)
      {
         if (this .getBrowser () .getAltKey ())
         {
            return 1;
         }
      }

      return button;
   },
   isPointerInRectangle: (() =>
   {
      const pointer = new Numbers_Vector2 (0, 0);

      return function (x, y)
      {
         const
            browser   = this .getBrowser (),
            rectangle = this .getViewport ();

         return browser .isPointerInRectangle (rectangle, pointer .set (x, y));
      };
   })(),
   getPointOnCenterPlane: (() =>
   {
      const
         axis     = new Numbers_Vector3 (0, 0, -1),
         distance = new Numbers_Vector3 (0, 0, 0),
         far      = new Numbers_Vector3 (0, 0, 0);

      return function (x, y, result)
      {
         const
            navigationInfo   = this .getNavigationInfo (),
            viewpoint        = this .getActiveViewpoint (),
            viewport         = this .getViewport (),
            projectionMatrix = viewpoint .getProjectionMatrixWithLimits (navigationInfo .getNearValue (), navigationInfo .getFarValue (viewpoint), viewport);

         // Far plane point
         Geometry_ViewVolume .unProjectPoint (x, y, 0.9, Numbers_Matrix4 .Identity, projectionMatrix, viewport, far);

         if (viewpoint instanceof Navigation_OrthoViewpoint)
            return result .set (far .x, far .y, -this .getDistanceToCenter (distance) .magnitude ());

         const direction = far .normalize ();

         return result .assign (direction) .multiply (this .getDistanceToCenter (distance) .magnitude () / direction .dot (axis));
      };
   })(),
   getDistanceToCenter (distance, positionOffset)
   {
      const viewpoint = this .getActiveViewpoint ();

      return (distance
         .assign (viewpoint .getPosition ())
         .add (positionOffset || viewpoint ._positionOffset .getValue ())
         .subtract (viewpoint .getUserCenterOfRotation ()));
   },
   trackballProjectToSphere (x, y, vector)
   {
      const viewport = this .getViewport ();

      x = (x - viewport [0]) / viewport [2] - 0.5;
      y = (y - viewport [1]) / viewport [3] - 0.5;

      return vector .set (x, y, tbProjectToSphere (0.5, x, y));
   },
   lookAtPoint (x, y, straightenHorizon)
   {
      if (! this .touch (x, y))
         return;

      const
         viewpoint = this .getActiveViewpoint (),
         hit       = this .getBrowser () .getHit ();

      viewpoint .lookAtPoint (this .getActiveLayer (), hit .point, 1, 2 - 1.618034, straightenHorizon);
   },
   lookAtBBox (x, y, straightenHorizon)
   {
      if (! this .touch (x, y))
         return;

      const
         viewpoint = this .getActiveViewpoint (),
         hit       = this .getBrowser () .getHit ();

      const bbox = hit .shapeNode .getBBox (new Geometry_Box3 ())
         .multRight (hit .modelViewMatrix)
         .multRight (viewpoint .getCameraSpaceMatrix ());

      viewpoint .lookAtBBox (this .getActiveLayer (), bbox, 1, 2 - 1.618034, straightenHorizon);
   },
   touch (x, y)
   {
      return this .getBrowser () .touch (x, y);
   },

});

function tbProjectToSphere (r, x, y)
{
   const d = Math .hypot (x, y);

   if (d < r * Math .sqrt (0.5)) // Inside sphere
   {
      return Math .sqrt (r * r - d * d);
   }

   // On hyperbola

   const t = r / Math .sqrt (2);

   return t * t / d;
}

const X3DViewer_default_ = X3DViewer;
;

x_ite_Namespace .add ("X3DViewer", "x_ite/Browser/Navigation/X3DViewer", X3DViewer_default_);
/* harmony default export */ const Navigation_X3DViewer = (X3DViewer_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Navigation/ExamineViewer.js
/* provided dependency */ var jquery_mousewheel = __webpack_require__(946);
/* provided dependency */ var ExamineViewer_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/













typeof jquery_mousewheel; // import plugin

const macOS = /Mac OS X/i .test (navigator .userAgent)

const
   MOTION_TIME       = 0.05 * 1000,
   SPIN_RELEASE_TIME = 0.04 * 1000,
   SPIN_ANGLE        = 0.003,
   SPIN_FACTOR       = 0.4,
   SCROLL_FACTOR     = macOS ? 1 / 120 : 1 / 20,
   MOVE_TIME         = 0.2,
   ROTATE_TIME       = 0.2,
   CRITICAL_ANGLE    = 0.97;

function ExamineViewer (executionContext, navigationInfo)
{
   Navigation_X3DViewer .call (this, executionContext, navigationInfo);

   this .button                   = -1;
   this .orientationOffset        = new Numbers_Rotation4 ();
   this .fromVector               = new Numbers_Vector3 (0, 0, 0);
   this .toVector                 = new Numbers_Vector3 (0, 0, 0);
   this .fromPoint                = new Numbers_Vector3 (0, 0, 0);
   this .toPoint                  = new Numbers_Vector3 (0, 0, 0);
   this .rotation                 = new Numbers_Rotation4 ();
   this .direction                = new Numbers_Vector3 (0, 0, 0);
   this .axis                     = new Numbers_Vector3 (0, 0, 0);
   this .pressTime                = 0;
   this .motionTime               = 0;

   this .touchMode                = 0;
   this .touch1                   = new Numbers_Vector2 (0, 0);
   this .touch2                   = new Numbers_Vector2 (0, 0);
   this .tapStart                 = 0;
   this .dblTapInterval           = 0.4;

   this .initialPositionOffset    = new Numbers_Vector3 (0, 0, 0);
   this .initialOrientationOffset = new Numbers_Rotation4 ();
   this .positionChaser           = new Followers_PositionChaser (executionContext);
   this .centerOfRotationChaser   = new Followers_PositionChaser (executionContext);
   this .rotationChaser           = new Followers_OrientationChaser (executionContext);

   this .timeSensor = new Time_TimeSensor (executionContext);
}

Object .assign (Object .setPrototypeOf (ExamineViewer .prototype, Navigation_X3DViewer .prototype),
{
   initialize ()
   {
      Navigation_X3DViewer .prototype .initialize .call (this);

      const
         browser = this .getBrowser (),
         element = browser .getSurface ();

      // Disconnect from spin.

      this .getNavigationInfo () ._transitionStart .addInterest ("disconnect", this);
      browser .getBrowserOptions () ._StraightenHorizon .addInterest ("disconnect", this);
      browser ._activeViewpoint .addInterest ("set_activeViewpoint__", this);

      // Bind pointing device events.

      element .on ("mousedown.ExamineViewer",  this .mousedown  .bind (this));
      element .on ("mouseup.ExamineViewer",    this .mouseup    .bind (this));
      element .on ("dblclick.ExamineViewer",   this .dblclick   .bind (this));
      element .on ("mousewheel.ExamineViewer", this .mousewheel .bind (this));

      element .on ("touchstart.ExamineViewer",  this .touchstart .bind (this));
      element .on ("touchend.ExamineViewer",    this .touchend   .bind (this));

      // Setup scroll chaser.

      this .positionChaser ._duration = MOVE_TIME;
      this .positionChaser .setup ();

      this .centerOfRotationChaser ._duration = MOVE_TIME;
      this .centerOfRotationChaser .setup ();

      this .rotationChaser ._duration = ROTATE_TIME;
      this .rotationChaser .setup ();

      this .timeSensor ._loop     = true;
      this .timeSensor ._stopTime = browser .getCurrentTime ();
      this .timeSensor .setup ();

      this .timeSensor ._fraction_changed  .addInterest ("spin", this);

      this .set_activeViewpoint__ ();
   },
   set_activeViewpoint__ ()
   {
      if (this .getStraightenHorizon ())
      {
         const viewpoint = this .getActiveViewpoint ();

         if (viewpoint)
            viewpoint ._orientationOffset = this .getOrientationOffset (Numbers_Rotation4 .Identity, viewpoint ._orientationOffset .getValue (), false);
      }

      this .disconnect ();
   },
   mousedown (event)
   {
      if (this .button >= 0)
         return;

      this .pressTime = Date .now ();

      const { x, y } = this .getBrowser () .getPointerFromEvent (event);

      if (!this .isPointerInRectangle (x, y))
         return;

      switch (this .getButton (event .button))
      {
         case 0:
         {
            // Start rotate.

            // Stop event propagation.
            event .preventDefault ();
            event .stopImmediatePropagation ();

            this .button = event .button;

            ExamineViewer_$(document) .on ("mouseup.ExamineViewer"   + this .getId (), this .mouseup   .bind (this));
            ExamineViewer_$(document) .on ("mousemove.ExamineViewer" + this .getId (), this .mousemove .bind (this));
            ExamineViewer_$(document) .on ("touchend.ExamineViewer"  + this .getId (), this .touchend  .bind (this));
            ExamineViewer_$(document) .on ("touchmove.ExamineViewer" + this .getId (), this .touchmove .bind (this));

            this .disconnect ();
            this .getActiveViewpoint () .transitionStop ();
            this .getBrowser () .setCursor ("MOVE");

            this .trackballProjectToSphere (x, y, this .fromVector);
            this .rotation .assign (Numbers_Rotation4 .Identity);

            this .motionTime = 0;

            this ._isActive = true;
            break;
         }
         case 1:
         {
            // Start pan.

            // Stop event propagation.
            event .preventDefault ();
            event .stopImmediatePropagation ();

            this .button = event .button;

            ExamineViewer_$(document) .on ("mouseup.ExamineViewer"   + this .getId (), this .mouseup   .bind (this));
            ExamineViewer_$(document) .on ("mousemove.ExamineViewer" + this .getId (), this .mousemove .bind (this));
            ExamineViewer_$(document) .on ("touchend.ExamineViewer"  + this .getId (), this .touchend  .bind (this));
            ExamineViewer_$(document) .on ("touchmove.ExamineViewer" + this .getId (), this .touchmove .bind (this));

            this .disconnect ();
            this .getActiveViewpoint () .transitionStop ();
            this .getBrowser () .setCursor ("MOVE");

            this .getPointOnCenterPlane (x, y, this .fromPoint);

            this ._isActive = true;
            break;
         }
      }
   },
   mouseup (event)
   {
      if (event .button !== this .button)
         return;

      this .button = -1;

      ExamineViewer_$(document) .off (".ExamineViewer" + this .getId ());

      switch (this .getButton (event .button))
      {
         case 0:
         {
            // End rotate.

            // Stop event propagation.
            event .preventDefault ();
            event .stopImmediatePropagation ();

            this .getBrowser () .setCursor ("DEFAULT");

            if (Math .abs (this .rotation .angle) > SPIN_ANGLE && Date .now () - this .motionTime < SPIN_RELEASE_TIME)
               this .addSpinning (this .rotation);

            this ._isActive = false;
            break;
         }
         case 1:
         {
            // End pan.

            // Stop event propagation.
            event .preventDefault ();
            event .stopImmediatePropagation ();

            this .getBrowser () .setCursor ("DEFAULT");

            this ._isActive = false;
            break;
         }
      }
   },
   dblclick (event)
   {
      // Stop event propagation.
      event .preventDefault ();
      event .stopImmediatePropagation ();

      const { x, y } = this .getBrowser () .getPointerFromEvent (event);

      this .disconnect ();
      this .lookAtBBox (x, y, this .getStraightenHorizon ());
   },
   mousemove: (() =>
   {
      const fromPoint = new Numbers_Vector3 (0, 0, 0);

      return function (event)
      {
         const { x, y } = this .getBrowser () .getPointerFromEvent (event);

         switch (this .getButton (this .button))
         {
            case 0:
            {
               // Rotate view around Viewpoint.centerOfRotation.

               // Stop event propagation.
               event .preventDefault ();
               event .stopImmediatePropagation ();

               const toVector = this .trackballProjectToSphere (x, y, this .toVector);

               this .rotation .setFromToVec (toVector, this .fromVector);

               if (Math .abs (this .rotation .angle) < SPIN_ANGLE && Date .now () - this .pressTime < MOTION_TIME)
                  return;

               this .addRotate (this .rotation);

               this .fromVector .assign (toVector);
               this .motionTime = Date .now ();
               break;
            }
            case 1:
            {
               // Move view along center plane.

               // Stop event propagation.
               event .preventDefault ();
               event .stopImmediatePropagation ();

               const
                  viewpoint   = this .getActiveViewpoint (),
                  toPoint     = this .getPointOnCenterPlane (x, y, this .toPoint),
                  translation = viewpoint .getUserOrientation () .multVecRot (fromPoint .assign (this .fromPoint) .subtract (toPoint));

               this .addMove (translation, translation);

               this .fromPoint .assign (toPoint);
               break;
            }
         }
      };
   })(),
   mousewheel: (() =>
   {
      const
         step        = new Numbers_Vector3 (0, 0, 0),
         translation = new Numbers_Vector3 (0, 0, 0);

      return function (event)
      {
         const { x, y } = this .getBrowser () .getPointerFromEvent (event);

         if (!this .isPointerInRectangle (x, y))
            return;

         // Stop event propagation.

         event .preventDefault ();
         event .stopImmediatePropagation ();

         // Change viewpoint position.

         const
            browser   = this .getBrowser (),
            viewpoint = this .getActiveViewpoint ();

         browser .prepareEvents () .removeInterest ("spin", this);
         viewpoint .transitionStop ();

         this .getDistanceToCenter (step) .multiply (event .zoomFactor || SCROLL_FACTOR);
         viewpoint .getUserOrientation () .multVecRot (translation .set (0, 0, step .magnitude ()));

         if (event .deltaY > 0)
            this .addMove (translation .negate (), Numbers_Vector3 .Zero);

         else if (event .deltaY < 0)
            this .addMove (translation, Numbers_Vector3 .Zero);
      };
   })(),
   touchstart (event)
   {
      const touches = event .originalEvent .touches;

      switch (touches .length)
      {
         case 1:
         {
            // Start rotate (button 0).

            event .button = 0;
            event .pageX  = touches [0] .pageX;
            event .pageY  = touches [0] .pageY;

            this .mousedown (event);

            // Remember tap.

            this .touch1 .set (touches [0] .pageX, touches [0] .pageY);
            break;
         }
         case 2:
         {
            // End rotate (button 0).

            this .touchend (event);

            // Start move (button 1).

            event .button = 1;
            event .pageX  = (touches [0] .pageX + touches [1] .pageX) / 2;
            event .pageY  = (touches [0] .pageY + touches [1] .pageY) / 2;

            this .mousedown (event);

            // Start zoom (mouse wheel).

            this .touch1 .set (touches [0] .pageX, touches [0] .pageY);
            this .touch2 .set (touches [1] .pageX, touches [1] .pageY);
            break;
         }
         case 3:
         {
            // End move (button 1).
            this .touchend (event);
            break;
         }
      }
   },
   touchend (event)
   {
      switch (this .button)
      {
         case 0:
         {
            // End rotate (button 0).

            event .button = 0;
            event .pageX  = this .touch1 .x;
            event .pageY  = this .touch1 .y;

            this .mouseup (event);

            // Start dblclick (button 0).

            if (this .tapedTwice)
            {
               this .dblclick (event);
            }
            else
            {
               this .tapedTwice = true;

               setTimeout (() => this .tapedTwice = false, 300);
            }

            break;
         }
         case 1:
         {
            // End move (button 1).

            this .touchMode = 0;
            event .button   = 1;

            this .mouseup (event);
            break;
         }
      }
   },
   touchmove: (() =>
   {
      const
         MOVE_ANGLE   = 0.7,
         ZOOM_ANGLE   = -0.7,
         touch1Change = new Numbers_Vector2 (0, 0),
         touch2Change = new Numbers_Vector2 (0, 0);

      return function (event)
      {
         const touches = event .originalEvent .touches;

         switch (touches .length)
         {
            case 1:
            {
               // Rotate (button 0).

               event .pageX = touches [0] .pageX;
               event .pageY = touches [0] .pageY;

               this .mousemove (event);
               break;
            }
            case 2:
            {
               touch1Change .set (touches [0] .pageX, touches [0] .pageY) .subtract (this .touch1) .normalize ();
               touch2Change .set (touches [1] .pageX, touches [1] .pageY) .subtract (this .touch2) .normalize ();

               const
                  move = touch1Change .dot (touch2Change) > MOVE_ANGLE,
                  zoom = touch1Change .dot (touch2Change) < ZOOM_ANGLE,
                  mode = this .touchMode || (move ? 1 : (zoom ? 2 : 0));

               switch (mode)
               {
                  case 1:
                  {
                     // Move (button 1).

                     this .touchMode = 1;

                     event .pageX = (touches [0] .pageX + touches [1] .pageX) / 2;
                     event .pageY = (touches [0] .pageY + touches [1] .pageY) / 2;

                     this .mousemove (event);

                     break;
                  }
                  case 2:
                  {
                     // Zoom (mouse wheel).

                     this .touchMode = 2;

                     const distance1 = this .touch1 .distance (this .touch2);

                     this .touch1 .set (touches [0] .pageX, touches [0] .pageY);
                     this .touch2 .set (touches [1] .pageX, touches [1] .pageY);

                     const
                        distance2 = this .touch1 .distance (this .touch2),
                        delta     = distance2 - distance1;

                     event .deltaY     = delta;
                     event .zoomFactor = Math .abs (delta) / ExamineViewer_$(window) .width ();

                     event .pageX = (touches [0] .pageX + touches [1] .pageX) / 2;
                     event .pageY = (touches [0] .pageY + touches [1] .pageY) / 2;

                     this .mousewheel (event);

                     break;
                  }
               }

               this .touch1 .set (touches [0] .pageX, touches [0] .pageY);
               this .touch2 .set (touches [1] .pageX, touches [1] .pageY);
               break;
            }
         }
      };
   })(),
   set_positionOffset__ (value)
   {
      const viewpoint = this .getActiveViewpoint ();

      viewpoint ._positionOffset = value;
   },
   set_centerOfRotationOffset__ (value)
   {
      const viewpoint = this .getActiveViewpoint ();

      viewpoint ._centerOfRotationOffset = value;
   },
   set_rotation__ (value)
   {
      const viewpoint = this .getActiveViewpoint ();

      viewpoint ._orientationOffset = this .getOrientationOffset (value .getValue (), this .initialOrientationOffset, false);
      viewpoint ._positionOffset    = this .getPositionOffset (this .initialPositionOffset, this .initialOrientationOffset, viewpoint ._orientationOffset .getValue ());
   },
   addRotate: (() =>
   {
      const destination = new Numbers_Rotation4 ();

      return function (rotationChange)
      {
         const viewpoint = this .getActiveViewpoint ();

         if (this .rotationChaser ._isActive .getValue () && this .rotationChaser ._value_changed .hasInterest ("set_rotation__", this))
         {
            try
            {
               destination .assign (this .rotationChaser ._set_destination .getValue ())
                  .multLeft (rotationChange);

               // Check for critical angle.
               this .getOrientationOffset (destination, this .initialOrientationOffset, true);

               this .rotationChaser ._set_destination = destination;
            }
            catch
            {
               // Slide along critical angle.

               rotationChange = this .getHorizonRotation (rotationChange);

               destination .assign (this .rotationChaser ._set_destination .getValue ())
                  .multLeft (rotationChange);

               this .rotationChaser ._set_destination = destination;
            }
         }
         else
         {
            try
            {
               this .initialOrientationOffset .assign (viewpoint ._orientationOffset .getValue ());
               this .initialPositionOffset    .assign (viewpoint ._positionOffset    .getValue ());

               // Check for critical angle.
               this .getOrientationOffset (rotationChange, this .initialOrientationOffset, true);

               this .rotationChaser ._set_value       = Numbers_Rotation4 .Identity;
               this .rotationChaser ._set_destination = rotationChange;
            }
            catch
            {
               // Slide along critical angle.

               this .rotationChaser ._set_value       = Numbers_Rotation4 .Identity;
               this .rotationChaser ._set_destination = this .getHorizonRotation (rotationChange);
            }
         }

         this .disconnect ();
         this .rotationChaser ._value_changed .addInterest ("set_rotation__", this);
      };
   })(),
   addSpinning (rotationChange)
   {
      this .disconnect ();

      if (this .getStraightenHorizon ())
      {
         const
            viewpoint            = this .getActiveViewpoint (),
            userPosition         = viewpoint .getUserPosition (),
            userCenterOfRotation = viewpoint .getUserCenterOfRotation (),
            direction            = userPosition .copy () .subtract (userCenterOfRotation),
            rotation             = this .getHorizonRotation (rotationChange),
            axis                 = viewpoint .getUpVector (true);

         this .axis .assign (axis);

         if (rotation .getAxis (new Numbers_Vector3 (0, 0, 0)) .dot (Numbers_Vector3 .yAxis) < 0 !== rotation .angle < 0)
            this .axis .negate ();

         this .timeSensor ._cycleInterval = Math .PI / (rotationChange .angle * SPIN_FACTOR * 30);
         this .timeSensor ._startTime     = this .getBrowser () .getCurrentTime ();

         const lookAtRotation = viewpoint .getLookAtRotation (userPosition, userCenterOfRotation);

         this .direction .assign (direction);
         this .orientationOffset .assign (viewpoint .getUserOrientation ()) .multRight (lookAtRotation .inverse ());
      }
      else
      {
         this .getBrowser () .prepareEvents () .addInterest ("spin", this);
         this .rotation .assign (rotationChange);
      }
   },
   spin: (() =>
   {
      const
         direction         = new Numbers_Vector3 (0, 0, 0),
         positionOffset    = new Numbers_Vector3 (0, 0, 0),
         orientationOffset = new Numbers_Rotation4 (),
         rotation          = new Numbers_Rotation4 ();

      return function ()
      {
         const viewpoint = this .getActiveViewpoint ();

         if (this .getStraightenHorizon ())
         {
            const
               userCenterOfRotation = viewpoint .getUserCenterOfRotation (),
               fraction             = this .timeSensor ._fraction_changed .getValue (),
               rotation             = new Numbers_Rotation4 (this .axis, 2 * Math .PI * fraction),
               userPosition         = rotation .multVecRot (direction .assign (this .direction)) .add (userCenterOfRotation),
               lookAtRotation       = viewpoint .getLookAtRotation (userPosition, viewpoint .getUserCenterOfRotation ());

            positionOffset .assign (userPosition) .subtract (viewpoint .getPosition ());

            orientationOffset .assign (viewpoint .getOrientation ()) .inverse ()
               .multRight (this .orientationOffset) .multRight (lookAtRotation);

            viewpoint ._positionOffset    = positionOffset;
            viewpoint ._orientationOffset = orientationOffset;
         }
         else
         {
            rotation .assign (Numbers_Rotation4 .Identity) .slerp (this .rotation, SPIN_FACTOR * 60 / this .getBrowser () .getCurrentFrameRate ());

            this .orientationOffset .assign (viewpoint ._orientationOffset .getValue ());

            viewpoint ._orientationOffset = this .getOrientationOffset (rotation, this .orientationOffset);
            viewpoint ._positionOffset    = this .getPositionOffset (viewpoint ._positionOffset .getValue (), this .orientationOffset, viewpoint ._orientationOffset .getValue ());
         }
      };
   })(),
   addMove: (() =>
   {
      const
         positionOffset         = new Numbers_Vector3 (0, 0, 0),
         centerOfRotationOffset = new Numbers_Vector3 (0, 0, 0);

      return function (positionOffsetChange, centerOfRotationOffsetChange)
      {
         const viewpoint = this .getActiveViewpoint ();

         if (this .positionChaser ._isActive .getValue () && this .positionChaser ._value_changed .hasInterest ("set_positionOffset__", this))
         {
            positionOffset
               .assign (this .positionChaser ._set_destination .getValue ())
               .add (positionOffsetChange);

            this .positionChaser ._set_destination = positionOffset;
         }
         else
         {
            positionOffset
               .assign (viewpoint ._positionOffset .getValue ())
               .add (positionOffsetChange);

            this .positionChaser ._set_value       = viewpoint ._positionOffset;
            this .positionChaser ._set_destination = positionOffset;
         }

         if (this .centerOfRotationChaser ._isActive .getValue () && this .centerOfRotationChaser ._value_changed .hasInterest ("set_centerOfRotationOffset__", this))
         {
            centerOfRotationOffset
               .assign (this .centerOfRotationChaser ._set_destination .getValue ())
               .add (centerOfRotationOffsetChange);

            this .centerOfRotationChaser ._set_destination = centerOfRotationOffset;
         }
         else
         {
            centerOfRotationOffset
               .assign (viewpoint ._centerOfRotationOffset .getValue ())
               .add (centerOfRotationOffsetChange);

            this .centerOfRotationChaser ._set_value       = viewpoint ._centerOfRotationOffset;
            this .centerOfRotationChaser ._set_destination = centerOfRotationOffset;
         }

         this .disconnect ();
         this .positionChaser         ._value_changed .addInterest ("set_positionOffset__",         this);
         this .centerOfRotationChaser ._value_changed .addInterest ("set_centerOfRotationOffset__", this);
      };
   })(),
   getPositionOffset: (() =>
   {
      const
         distance = new Numbers_Vector3 (0, 0, 0),
         d        = new Numbers_Vector3 (0, 0, 0),
         oob      = new Numbers_Rotation4 ();

      return function (positionOffsetBefore, orientationOffsetBefore, orientationOffsetAfter)
      {
         this .getDistanceToCenter (distance, positionOffsetBefore);

         return (oob
            .assign (orientationOffsetBefore)
            .inverse ()
            .multRight (orientationOffsetAfter)
            .multVecRot (d .assign (distance))
            .subtract (distance)
            .add (positionOffsetBefore));
      };
   })(),
   getOrientationOffset: (() =>
   {
      const
         userOrientation   = new Numbers_Rotation4 (),
         orientationOffset = new Numbers_Rotation4 (),
         zAxis             = new Numbers_Vector3 (0, 0, 0);

      return function (rotation, orientationOffsetBefore, _throw)
      {
         const
            viewpoint         = this .getActiveViewpoint (),
            straightenHorizon = this .getStraightenHorizon ();

         userOrientation
            .assign (rotation)
            .multRight (viewpoint .getOrientation ())
            .multRight (orientationOffsetBefore);

         if (straightenHorizon)
            viewpoint .straightenHorizon (userOrientation);

         const orientationOffsetAfter = orientationOffset
            .assign (viewpoint .getOrientation ())
            .inverse ()
            .multRight (userOrientation);

         if (straightenHorizon)
         {
            if (! _throw)
               return orientationOffsetAfter;

            const userVector = userOrientation .multVecRot (zAxis .assign (Numbers_Vector3 .zAxis));

            if (Math .abs (viewpoint .getUpVector (true) .dot (userVector)) < CRITICAL_ANGLE)
               return orientationOffsetAfter;

            throw new Error ("Critical angle");
         }
         else
         {
            return orientationOffsetAfter;
         }
      };
   })(),
   getHorizonRotation: (() =>
   {
      const zAxis = new Numbers_Vector3 (0, 0, 0);

      return function (rotation)
      {
         const
            V = rotation .multVecRot (zAxis .assign (Numbers_Vector3 .zAxis)),
            N = Numbers_Vector3 .yAxis .copy () .cross (V),
            H = N .copy () .cross (Numbers_Vector3 .yAxis),
            r = new Numbers_Rotation4 (Numbers_Vector3 .zAxis, H);

         return r;
      };
   })(),
   disconnect ()
   {
      const browser = this .getBrowser ();

      this .positionChaser         ._value_changed .removeInterest ("set_positionOffset__",         this);
      this .centerOfRotationChaser ._value_changed .removeInterest ("set_centerOfRotationOffset__", this);
      this .rotationChaser         ._value_changed .removeInterest ("set_rotation__",               this);

      this .timeSensor ._stopTime = browser .getCurrentTime ();
      browser .prepareEvents () .removeInterest ("spin", this);
   },
   dispose ()
   {
      const browser = this .getBrowser ();

      this .disconnect ();
      this .getNavigationInfo () ._transitionStart .removeInterest ("disconnect", this);
      browser .getBrowserOptions () ._StraightenHorizon .removeInterest ("disconnect", this);

      browser ._activeViewpoint .removeInterest ("set_activeViewpoint__", this);

      browser .getSurface () .off (".ExamineViewer");
      ExamineViewer_$(document) .off (".ExamineViewer" + this .getId ());
   },
});

Object .defineProperties (ExamineViewer,
{
   typeName:
   {
      value: "ExamineViewer",
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly, "isActive", new x_ite_Fields .SFBool ()),
      ]),
      enumerable: true,
   },
});

const ExamineViewer_default_ = ExamineViewer;
;

x_ite_Namespace .add ("ExamineViewer", "x_ite/Browser/Navigation/ExamineViewer", ExamineViewer_default_);
/* harmony default export */ const Navigation_ExamineViewer = (ExamineViewer_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Navigation/X3DFlyViewer.js
/* provided dependency */ var X3DFlyViewer_jquery_mousewheel = __webpack_require__(946);
/* provided dependency */ var X3DFlyViewer_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










typeof X3DFlyViewer_jquery_mousewheel; // import plugin

const X3DFlyViewer_macOS = /Mac OS X/i .test (navigator .userAgent)

const
   SPEED_FACTOR           = 0.007,
   SHIFT_SPEED_FACTOR     = 4 * SPEED_FACTOR,
   ROTATION_SPEED_FACTOR  = 1.4,
   ROTATION_LIMIT         = 40,
   PAN_SPEED_FACTOR       = SPEED_FACTOR,
   PAN_SHIFT_SPEED_FACTOR = 1.4 * PAN_SPEED_FACTOR,
   ROLL_ANGLE             = X3DFlyViewer_macOS ? Math .PI / 512 : Math .PI / 32,
   X3DFlyViewer_ROTATE_TIME            = 0.3;

const
   MOVE = 0,
   PAN  = 1;

function X3DFlyViewer (executionContext, navigationInfo)
{
   Navigation_X3DViewer .call (this, executionContext, navigationInfo);

   const
      browser = this .getBrowser (),
      gl      = browser .getContext ();

   this .button                = -1;
   this .fromVector            = new Numbers_Vector3 (0, 0, 0);
   this .toVector              = new Numbers_Vector3 (0, 0, 0);
   this .direction             = new Numbers_Vector3 (0, 0, 0);
   this .startTime             = 0;
   this .event                 = null;
   this .lookAround            = false;
   this .orientationChaser     = new Followers_OrientationChaser (executionContext);
   this .lineIndexBuffer       = gl .createBuffer ();
   this .lineColorBuffer       = gl .createBuffer ();
   this .lineVertexBuffer      = gl .createBuffer ();
   this .lineVertexArrayObject = new Rendering_VertexArray (gl);
   this .lineVertexArray       = new Float32Array (8 * 4) .fill (1);
   this .geometryContext       = new Rendering_GeometryContext ({ geometryType: 2, colorMaterial: true });

   gl .bindBuffer (gl .ELEMENT_ARRAY_BUFFER, this .lineIndexBuffer);
   gl .bufferData (gl .ELEMENT_ARRAY_BUFFER, new Uint8Array ([0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7]), gl .STATIC_DRAW);
   gl .bindBuffer (gl .ARRAY_BUFFER, this .lineColorBuffer);
   gl .bufferData (gl .ARRAY_BUFFER, new Float32Array ([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]), gl .STATIC_DRAW);
}

Object .assign (Object .setPrototypeOf (X3DFlyViewer .prototype, Navigation_X3DViewer .prototype),
{
   initialize ()
   {
      Navigation_X3DViewer .prototype .initialize .call (this);

      const
         browser = this .getBrowser (),
         element = browser .getSurface ();

      // Bind pointing device events.

      element .on ("mousedown.X3DFlyViewer",  this .mousedown  .bind (this));
      element .on ("mouseup.X3DFlyViewer",    this .mouseup    .bind (this));
      element .on ("mousewheel.X3DFlyViewer", this .mousewheel .bind (this));

      element .on ("touchstart.X3DFlyViewer", this .touchstart .bind (this));
      element .on ("touchend.X3DFlyViewer",   this .touchend   .bind (this));

      browser ._controlKey .addInterest ("set_controlKey__", this);

      // Setup look around chaser.

      this .orientationChaser ._duration = X3DFlyViewer_ROTATE_TIME;
      this .orientationChaser .setup ();
   },
   addCollision () { },
   removeCollision () { },
   set_controlKey__ ()
   {
      if (this .event && this .event .button === 0)
      {
         this .button = -1;
         this .mousedown (this .event);
      }
   },
   mousedown (event)
   {
      if (this .button >= 0)
         return;

      this .event = event;

      const { x, y } = this .getBrowser () .getPointerFromEvent (event);

      if (!this .isPointerInRectangle (x, y))
         return;

      switch (this .getButton (event .button))
      {
         case 0:
         {
            // Start walk or fly.

            // Stop event propagation.
            event .preventDefault ();
            event .stopImmediatePropagation ();

            this .button = event .button;

            X3DFlyViewer_$(document) .on ("mouseup.X3DFlyViewer"   + this .getId (), this .mouseup   .bind (this));
            X3DFlyViewer_$(document) .on ("mousemove.X3DFlyViewer" + this .getId (), this .mousemove .bind (this));
            X3DFlyViewer_$(document) .on ("touchend.X3DFlyViewer"  + this .getId (), this .touchend  .bind (this));
            X3DFlyViewer_$(document) .on ("touchmove.X3DFlyViewer" + this .getId (), this .touchmove .bind (this));

            this .disconnect ();
            this .getActiveViewpoint () .transitionStop ();
            this .getBrowser () .setCursor ("MOVE");
            this .addCollision ();

            if (this .getBrowser () .getControlKey () || this .getBrowser () .getCommandKey () || this .lookAround)
            {
               // Look around.

               this .trackballProjectToSphere (x, y, this .fromVector);
            }
            else
            {
               // Move.

               this .fromVector .set (x, 0, -y);
               this .toVector   .assign (this .fromVector);

               this .getFlyDirection (this .fromVector, this .toVector, this .direction);
               this .addFly ();

               if (this .getBrowser () .getBrowserOption ("Rubberband"))
                  this .getBrowser () .finishedEvents () .addInterest ("display", this, MOVE);
            }

            this ._isActive = true;
            break;
         }
         case 1:
         {
            // Start pan.

            // Stop event propagation.
            event .preventDefault ();
            event .stopImmediatePropagation ();

            this .button = event .button;

            X3DFlyViewer_$(document) .on ("mouseup.X3DFlyViewer"   + this .getId (), this .mouseup   .bind (this));
            X3DFlyViewer_$(document) .on ("mousemove.X3DFlyViewer" + this .getId (), this .mousemove .bind (this));

            this .disconnect ();
            this .getActiveViewpoint () .transitionStop ();
            this .getBrowser () .setCursor ("MOVE");
            this .addCollision ();

            this .fromVector .set (x, y, 0);
            this .toVector   .assign (this .fromVector);
            this .direction  .set (0, 0, 0);

            this .addPan ();

            if (this .getBrowser () .getBrowserOption ("Rubberband"))
               this .getBrowser () .finishedEvents () .addInterest ("display", this, PAN);

            this ._isActive = true;
            break;
         }
      }
   },
   mouseup (event)
   {
      event .preventDefault ();

      if (event .button !== this .button)
         return;

      this .event  = null;
      this .button = -1;

      X3DFlyViewer_$(document) .off (".X3DFlyViewer" + this .getId ());

      this .disconnect ();
      this .getBrowser () .setCursor ("DEFAULT");
      this .removeCollision ();

      this ._isActive = false;
   },
   mousemove (event)
   {
      const browser = this .getBrowser ();

      browser .addBrowserEvent ();

      this .event = event;

      const { x, y } = this .getBrowser () .getPointerFromEvent (event);

      switch (this .getButton (this .button))
      {
         case 0:
         {
            if (browser .getControlKey () || browser .getCommandKey () || this .lookAround)
            {
               // Stop event propagation.
               event .preventDefault ();
               event .stopImmediatePropagation ();

               // Look around

               const toVector = this .trackballProjectToSphere (x, y, this .toVector);

               this .addRotation (this .fromVector, toVector);
               this .fromVector .assign (toVector);
               break;
            }
            else
            {
               // Fly

               this .toVector .set (x, 0, -y);
               this .getFlyDirection (this .fromVector, this .toVector, this .direction);
               this .direction .divide (browser .getRenderingProperty ("ContentScale"));
               break;
            }
         }
         case 1:
         {
            // Stop event propagation.
            event .preventDefault ();
            event .stopImmediatePropagation ();

            // Pan

            this .toVector  .set (x, y, 0);
            this .direction .assign (this .toVector) .subtract (this .fromVector);
            this .direction .divide (browser .getRenderingProperty ("ContentScale"));
            break;
         }
      }
   },
   mousewheel (event)
   {
      const { x, y } = this .getBrowser () .getPointerFromEvent (event);

      if (!this .isPointerInRectangle (x, y))
         return;

      // Stop event propagation.

      event .preventDefault ();
      event .stopImmediatePropagation ();

      // Change viewpoint position.

      const viewpoint = this .getActiveViewpoint ();

      viewpoint .transitionStop ();

      if (event .deltaY > 0)
         this .addRoll (-ROLL_ANGLE);

      else if (event .deltaY < 0)
         this .addRoll (ROLL_ANGLE);
   },
   touchstart (event)
   {
      const touches = event .originalEvent .touches;

      switch (touches .length)
      {
         case 1:
         {
            // Start fly or walk (button 0).

            event .button = 0;
            event .pageX  = touches [0] .pageX;
            event .pageY  = touches [0] .pageY;

            this .mousedown (event);
            break;
         }
         case 2:
         {
            // End fly or walk (button 0).

            this .touchend (event);

            // Start look around (button 0).

            this .lookAround = true;
            event .button    = 0;
            event .pageX     = (touches [0] .pageX + touches [1] .pageX) / 2;
            event .pageY     = (touches [0] .pageY + touches [1] .pageY) / 2;

            this .mousedown (event);
            break;
         }
         case 3:
         {
            // End look around (button 0).

            this .touchend (event);
            break;
         }
      }
   },
   touchend (event)
   {
      switch (this .button)
      {
         case 0:
         {
            // End move or look around (button 0).
            this .lookAround = false;
            event .button    = 0;

            this .mouseup (event);
            break;
         }
      }
   },
   touchmove (event)
   {
      const touches = event .originalEvent .touches;

      switch (touches .length)
      {
         case 1:
         {
            // Fly or walk (button 0).

            event .button = 0;
            event .pageX  = touches [0] .pageX;
            event .pageY  = touches [0] .pageY;

            this .mousemove (event);
            break;
         }
         case 2:
         {
            // Fly or walk (button 0).

            event .button = 0;
            event .pageX  = (touches [0] .pageX + touches [1] .pageX) / 2;
            event .pageY  = (touches [0] .pageY + touches [1] .pageY) / 2;

            this .mousemove (event);
            break;
         }
      }
   },
   fly: (() =>
   {
      const
         upVector           = new Numbers_Vector3 (0, 0, 0),
         direction          = new Numbers_Vector3 (0, 0, 0),
         axis               = new Numbers_Vector3 (0, 0, 0),
         userOrientation    = new Numbers_Rotation4 (),
         orientationOffset  = new Numbers_Rotation4 (),
         rubberBandRotation = new Numbers_Rotation4 ();

      return function ()
      {
         const
            navigationInfo = this .getNavigationInfo (),
            viewpoint      = this .getActiveViewpoint (),
            now            = Date .now (),
            dt             = (now - this .startTime) / 1000;

         upVector .assign (viewpoint .getUpVector ());

         // Rubberband values

         if (this .direction .z > 0)
            rubberBandRotation .setFromToVec (this .direction, axis .set (0, 0, 1));
         else
            rubberBandRotation .setFromToVec (axis .set (0, 0, -1), this .direction);

            const rubberBandLength = this .direction .magnitude ();

         // Determine positionOffset.

         let speedFactor = 1 - rubberBandRotation .angle / (Math .PI / 2);

         speedFactor *= navigationInfo ._speed .getValue ();
         speedFactor *= viewpoint .getSpeedFactor ();
         speedFactor *= this .getBrowser () .getShiftKey () ? SHIFT_SPEED_FACTOR : SPEED_FACTOR;
         speedFactor *= dt;

         const translation = this .getTranslationOffset (direction .assign (this .direction) .multiply (speedFactor));

         this .getActiveLayer () .constrainTranslation (translation, true);

         viewpoint ._positionOffset = translation .add (viewpoint ._positionOffset .getValue ());

         // Determine weight for rubberBandRotation.

         const weight = ROTATION_SPEED_FACTOR * dt * (rubberBandLength / (rubberBandLength + ROTATION_LIMIT)) ** 2;

         // Determine userOrientation.

         userOrientation
            .assign (Numbers_Rotation4 .Identity)
            .slerp (rubberBandRotation, weight)
            .multRight (viewpoint .getUserOrientation ());

         // Straighten horizon of userOrientation.

         if (this .getStraightenHorizon ())
            viewpoint .straightenHorizon (userOrientation);

         // Determine orientationOffset.

         orientationOffset
            .assign (viewpoint .getOrientation ())
            .inverse ()
            .multRight (userOrientation);

         // Set orientationOffset.

         viewpoint ._orientationOffset = orientationOffset;

         this .startTime = now;
      };
   })(),
   pan: (() =>
   {
      const
         direction = new Numbers_Vector3 (0, 0, 0),
         axis      = new Numbers_Vector3 (0, 0, 0);

      return function ()
      {
         const
            navigationInfo = this .getNavigationInfo (),
            viewpoint      = this .getActiveViewpoint (),
            now            = Date .now (),
            dt             = (now - this .startTime) / 1000,
            upVector       = viewpoint .getUpVector ();

         this .constrainPanDirection (direction .assign (this .direction));

         let speedFactor = 1;

         speedFactor *= navigationInfo ._speed .getValue ();
         speedFactor *= viewpoint .getSpeedFactor ();
         speedFactor *= this .getBrowser () .getShiftKey () ? PAN_SHIFT_SPEED_FACTOR : PAN_SPEED_FACTOR;
         speedFactor *= dt;

         const
            orientation = viewpoint .getUserOrientation () .multRight (new Numbers_Rotation4 (viewpoint .getUserOrientation () .multVecRot (axis .assign (Numbers_Vector3 .yAxis)), upVector)),
            translation = orientation .multVecRot (direction .multiply (speedFactor));

         this .getActiveLayer () .constrainTranslation (translation, true);

         viewpoint ._positionOffset = translation .add (viewpoint ._positionOffset .getValue ());

         this .startTime = now;
      };
   })(),
   set_orientationOffset__ (value)
   {
      const viewpoint = this .getActiveViewpoint ();

      viewpoint ._orientationOffset = value;
   },
   addFly ()
   {
      if (this .startTime)
         return;

      this .getBrowser () .prepareEvents () .addInterest ("fly", this);
      this .getBrowser () .addBrowserEvent ();

      this .startTime = Date .now ();
   },
   addPan ()
   {
      if (this .startTime)
         return;

      this .disconnect ();
      this .getBrowser () .prepareEvents () .addInterest ("pan", this);
      this .getBrowser () .addBrowserEvent ();

      this .startTime = Date .now ();
   },
   addRoll: (() =>
   {
      const
         orientationOffset = new Numbers_Rotation4 (),
         roll              = new Numbers_Rotation4 ();

      return function (rollAngle)
      {
         const viewpoint = this .getActiveViewpoint ();

         if (this .orientationChaser ._isActive .getValue () && this .orientationChaser ._value_changed .hasInterest ("set_orientationOffset__", this))
         {
            orientationOffset
               .assign (viewpoint .getOrientation ())
               .inverse ()
               .multRight (roll .set (1, 0, 0, rollAngle))
               .multRight (viewpoint .getOrientation ())
               .multRight (this .orientationChaser ._set_destination .getValue ());

            this .orientationChaser ._set_destination = orientationOffset;
         }
         else
         {
            orientationOffset
               .assign (viewpoint .getOrientation ())
               .inverse ()
               .multRight (roll .set (1, 0, 0, rollAngle))
               .multRight (viewpoint .getUserOrientation ());

            this .orientationChaser ._set_value       = viewpoint ._orientationOffset;
            this .orientationChaser ._set_destination = orientationOffset;
         }

         this .disconnect ();
         this .orientationChaser ._value_changed .addInterest ("set_orientationOffset__", this);
      };
   })(),
   addRotation: (() =>
   {
      const
         userOrientation   = new Numbers_Rotation4 (),
         orientationOffset = new Numbers_Rotation4 ();

      return function (fromVector, toVector)
      {
         const viewpoint = this .getActiveViewpoint ();

         if (this .orientationChaser ._isActive .getValue () && this .orientationChaser ._value_changed .hasInterest ("set_orientationOffset__", this))
         {
            userOrientation
               .setFromToVec (toVector, fromVector)
               .multRight (viewpoint .getOrientation ())
               .multRight (this .orientationChaser ._set_destination .getValue ());

            if (this .getStraightenHorizon ())
               viewpoint .straightenHorizon (userOrientation);

            orientationOffset .assign (viewpoint .getOrientation ()) .inverse () .multRight (userOrientation);

            this .orientationChaser ._set_destination = orientationOffset;
         }
         else
         {
            userOrientation
               .setFromToVec (toVector, fromVector)
               .multRight (viewpoint .getUserOrientation ());

            if (this .getStraightenHorizon ())
               viewpoint .straightenHorizon (userOrientation);

            orientationOffset .assign (viewpoint .getOrientation ()) .inverse () .multRight (userOrientation);

            this .orientationChaser ._set_value       = viewpoint ._orientationOffset;
            this .orientationChaser ._set_destination = orientationOffset;
         }

         this .disconnect ();
         this .orientationChaser ._value_changed .addInterest ("set_orientationOffset__", this);
      };
   })(),
   display: (() =>
   {
      const
         fromPoint             = new Numbers_Vector3 (0, 0, 0),
         toPoint               = new Numbers_Vector3 (0, 0, 0),
         normal                = new Numbers_Vector3 (0, 0, 0),
         vertex                = new Numbers_Vector3 (0, 0, 0),
         projectionMatrix      = new Numbers_Matrix4 (),
         projectionMatrixArray = new Float32Array (Numbers_Matrix4 .Identity),
         modelViewMatrixArray  = new Float32Array (Numbers_Matrix4 .Identity),
         clipPlanes            = [ ];

      return function (type)
      {
         // Configure HUD

         const
            browser      = this .getBrowser (),
            gl           = browser .getContext (),
            viewport     = browser .getViewport (),
            width        = viewport [2],
            height       = viewport [3],
            contentScale = browser .getRenderingProperty ("ContentScale");

         projectionMatrixArray .set (Geometry_Camera .ortho (0, width, 0, height, -1, 1, projectionMatrix));

         // Display Rubberband.

         switch (type)
         {
            case MOVE:
            {
               fromPoint .set (this .fromVector .x, -this .fromVector .z, 0);
               toPoint   .set (this .toVector   .x, -this .toVector   .z, 0);
               break;
            }
            case PAN:
            {
               fromPoint .set (this .fromVector .x, this .fromVector .y, 0);
               toPoint   .set (this .toVector   .x, this .toVector   .y, 0);
               break;
            }
         }

         // Set black line quad vertices.

         normal .assign (toPoint)
            .subtract (fromPoint)
            .normalize ()
            .multiply (contentScale)
            .set (-normal .y, normal .x, 0);

         this .lineVertexArray .set (vertex .assign (fromPoint) .add (normal),      0);
         this .lineVertexArray .set (vertex .assign (fromPoint) .subtract (normal), 4);
         this .lineVertexArray .set (vertex .assign (toPoint)   .subtract (normal), 8);
         this .lineVertexArray .set (vertex .assign (toPoint)   .add (normal),      12);

         // Set white line quad vertices.

         normal .assign (toPoint)
            .subtract (fromPoint)
            .normalize ()
            .multiply (contentScale / 2)
            .set (-normal .y, normal .x, 0);

         this .lineVertexArray .set (vertex .assign (fromPoint) .add (normal),      16);
         this .lineVertexArray .set (vertex .assign (fromPoint) .subtract (normal), 20);
         this .lineVertexArray .set (vertex .assign (toPoint)   .subtract (normal), 24);
         this .lineVertexArray .set (vertex .assign (toPoint)   .add (normal),      28);

         // Transfer line.

         gl .bindBuffer (gl .ARRAY_BUFFER, this .lineVertexBuffer);
         gl .bufferData (gl .ARRAY_BUFFER, this .lineVertexArray, gl .DYNAMIC_DRAW);

         // Set uniforms and attributes.

         const shaderNode = browser .getDefaultMaterial () .getShader (this .geometryContext);

         shaderNode .enable (gl);
         shaderNode .setClipPlanes (gl, clipPlanes);

         gl .uniformMatrix4fv (shaderNode .x3d_ProjectionMatrix, false, projectionMatrixArray);
         gl .uniformMatrix4fv (shaderNode .x3d_ModelViewMatrix,  false, modelViewMatrixArray);
         gl .uniform3f        (shaderNode .x3d_EmissiveColor, 1, 1, 1);
         gl .uniform1f        (shaderNode .x3d_Transparency,  0);

         if (this .lineVertexArrayObject .enable (shaderNode))
         {
            gl .bindBuffer (gl .ELEMENT_ARRAY_BUFFER, this .lineIndexBuffer);

            shaderNode .enableColorAttribute  (gl, this .lineColorBuffer,  0, 0);
            shaderNode .enableVertexAttribute (gl, this .lineVertexBuffer, 0, 0);
         }

         // Draw a black and a white line.

         gl .disable (gl .DEPTH_TEST);
         gl .enable (gl .CULL_FACE);
         gl .frontFace (gl .CCW);
         gl .drawElements (gl .TRIANGLES, 12, gl .UNSIGNED_BYTE, 0);
         gl .enable (gl .DEPTH_TEST);
      };
   })(),
   disconnect ()
   {
      const browser = this .getBrowser ();

      browser .addBrowserEvent ();

      browser .prepareEvents ()  .removeInterest ("fly", this);
      browser .prepareEvents ()  .removeInterest ("pan", this);
      browser .finishedEvents () .removeInterest ("display", this);

      this .orientationChaser ._value_changed .removeInterest ("set_orientationOffset__", this);

      this .startTime = 0;
   },
   dispose ()
   {
      const gl = this .getBrowser () .getContext ();

      gl .deleteBuffer (this .lineVertexBuffer);
      this .lineVertexArrayObject .delete (gl);

      this .disconnect ();
      this .getBrowser () ._controlKey .removeInterest ("set_controlKey__", this);
      this .getBrowser () .getSurface () .off (".X3DFlyViewer");
      X3DFlyViewer_$(document) .off (".X3DFlyViewer" + this .getId ());
   },
});

const X3DFlyViewer_default_ = X3DFlyViewer;
;

x_ite_Namespace .add ("X3DFlyViewer", "x_ite/Browser/Navigation/X3DFlyViewer", X3DFlyViewer_default_);
/* harmony default export */ const Navigation_X3DFlyViewer = (X3DFlyViewer_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Navigation/WalkViewer.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









function WalkViewer (executionContext, navigationInfo)
{
   Navigation_X3DFlyViewer .call (this, executionContext, navigationInfo);
}

Object .assign (Object .setPrototypeOf (WalkViewer .prototype, Navigation_X3DFlyViewer .prototype),
{
   initialize ()
   {
      Navigation_X3DFlyViewer .prototype .initialize .call (this);

      this .getBrowser () .addCollision (this);
   },
   getStraightenHorizon ()
   {
      return true;
   },
   getFlyDirection (fromVector, toVector, direction)
   {
      return direction .assign (toVector) .subtract (fromVector);
   },
   getTranslationOffset: (() =>
   {
      const
         localYAxis      = new Numbers_Vector3 (0, 0, 0),
         userOrientation = new Numbers_Rotation4 (),
         rotation        = new Numbers_Rotation4 ();

      return function (velocity)
      {
         const
            viewpoint = this .getActiveViewpoint (),
            upVector  = viewpoint .getUpVector ();

         userOrientation .assign (viewpoint .getUserOrientation ());
         userOrientation .multVecRot (localYAxis .assign (Numbers_Vector3 .yAxis));
         rotation        .setFromToVec (localYAxis, upVector);

         const orientation = userOrientation .multRight (rotation);

         return orientation .multVecRot (velocity);
      };
   })(),
   constrainPanDirection (direction)
   {
      if (direction .y < 0)
         direction .y = 0;

      return direction;
   },
   dispose ()
   {
      this .getBrowser () .removeCollision (this);

      Navigation_X3DFlyViewer .prototype .dispose .call (this);
   },
});

Object .defineProperties (WalkViewer,
{
   typeName:
   {
      value: "WalkViewer",
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly, "isActive", new x_ite_Fields .SFBool ()),
      ]),
      enumerable: true,
   },
});

const WalkViewer_default_ = WalkViewer;
;

x_ite_Namespace .add ("WalkViewer", "x_ite/Browser/Navigation/WalkViewer", WalkViewer_default_);
/* harmony default export */ const Navigation_WalkViewer = (WalkViewer_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Navigation/FlyViewer.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function FlyViewer (executionContext, navigationInfo)
{
   Navigation_X3DFlyViewer .call (this, executionContext, navigationInfo);
}

Object .assign (Object .setPrototypeOf (FlyViewer .prototype, Navigation_X3DFlyViewer .prototype),
{
   addCollision ()
   {
      this .getBrowser () .addCollision (this);
   },
   removeCollision ()
   {
      this .getBrowser () .removeCollision (this);
   },
   getFlyDirection (fromVector, toVector, direction)
   {
      return direction .assign (toVector) .subtract (fromVector);
   },
   getTranslationOffset (velocity)
   {
      return this .getActiveViewpoint () .getUserOrientation () .multVecRot (velocity);
   },
   constrainPanDirection (direction)
   {
      return direction;
   },
});

Object .defineProperties (FlyViewer,
{
   typeName:
   {
      value: "FlyViewer",
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly, "isActive", new x_ite_Fields .SFBool ()),
      ]),
      enumerable: true,
   },
});

const FlyViewer_default_ = FlyViewer;
;

x_ite_Namespace .add ("FlyViewer", "x_ite/Browser/Navigation/FlyViewer", FlyViewer_default_);
/* harmony default export */ const Navigation_FlyViewer = (FlyViewer_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Navigation/PlaneViewer.js
/* provided dependency */ var PlaneViewer_jquery_mousewheel = __webpack_require__(946);
/* provided dependency */ var PlaneViewer_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/








typeof PlaneViewer_jquery_mousewheel; // import plugin

const PlaneViewer_macOS = /Mac OS X/i .test (navigator .userAgent)

const PlaneViewer_SCROLL_FACTOR = PlaneViewer_macOS ? 1 / 160 : 1 / 20;

const
   PlaneViewer_vector                 = new Numbers_Vector3 (0 ,0, 0),
   positionOffset         = new Numbers_Vector3 (0 ,0, 0),
   centerOfRotationOffset = new Numbers_Vector3 (0, 0, 0);

function PlaneViewer (executionContext, navigationInfo)
{
   Navigation_X3DViewer .call (this, executionContext, navigationInfo);

   this .button    = -1;
   this .fromPoint = new Numbers_Vector3 (0, 0, 0);
   this .toPoint   = new Numbers_Vector3 (0, 0, 0);
}

Object .assign (Object .setPrototypeOf (PlaneViewer .prototype, Navigation_X3DViewer .prototype),
{
   initialize ()
   {
      Navigation_X3DViewer .prototype .initialize .call (this);

      const
         browser = this .getBrowser (),
         element = browser .getSurface ();

      element .on ("mousedown.PlaneViewer",  this .mousedown  .bind (this));
      element .on ("mouseup.PlaneViewer",    this .mouseup    .bind (this));
      element .on ("mousemove.PlaneViewer",  this .mousemove  .bind (this));
      element .on ("mousewheel.PlaneViewer", this .mousewheel .bind (this));
   },
   mousedown (event)
   {
      if (this .button >= 0)
         return;

      const { x, y } = this .getBrowser () .getPointerFromEvent (event);

      if (!this .isPointerInRectangle (x, y))
         return;

      switch (this .getButton (event .button))
      {
         case 1:
         {
            // Stop event propagation.

            event .preventDefault ();
            event .stopImmediatePropagation ();

            this .button = event .button;

            this .getBrowser () .getSurface () .off ("mousemove.PlaneViewer");
            PlaneViewer_$(document) .on ("mouseup.PlaneViewer"   + this .getId (), this .mouseup .bind (this));
            PlaneViewer_$(document) .on ("mousemove.PlaneViewer" + this .getId (), this .mousemove .bind (this));

            this .getActiveViewpoint () .transitionStop ();
            this .getBrowser () .setCursor ("MOVE");

            this .getPointOnCenterPlane (x, y, this .fromPoint);

            this ._isActive = true;
            break;
         }
      }
   },
   mouseup (event)
   {
      // Stop event propagation.

      event .preventDefault ();
      event .stopImmediatePropagation ();

      if (event .button !== this .button)
         return;

      this .button = -1;

      PlaneViewer_$(document) .off (".PlaneViewer" + this .getId ());
      this .getBrowser () .getSurface () .on ("mousemove.PlaneViewer", this .mousemove .bind (this));

      this .getBrowser () .setCursor ("DEFAULT");

      this ._isActive = false;
   },
   mousemove (event)
   {
      const { x, y } = this .getBrowser () .getPointerFromEvent (event);

      switch (this .getButton (this .button))
      {
         case 1:
         {
            // Stop event propagation.

            event .preventDefault ();
            event .stopImmediatePropagation ();

            // Move.

            const
               viewpoint   = this .getActiveViewpoint (),
               toPoint     = this .getPointOnCenterPlane (x, y, this .toPoint),
               translation = viewpoint .getUserOrientation () .multVecRot (this .fromPoint .subtract (toPoint));

            viewpoint ._positionOffset         = positionOffset         .assign (viewpoint ._positionOffset         .getValue ()) .add (translation);
            viewpoint ._centerOfRotationOffset = centerOfRotationOffset .assign (viewpoint ._centerOfRotationOffset .getValue ()) .add (translation);

            this .fromPoint .assign (toPoint);
            break;
         }
      }
   },
   mousewheel (event)
   {
      const { x, y } = this .getBrowser () .getPointerFromEvent (event);

      if (!this .isPointerInRectangle (x, y))
         return;

      // Stop event propagation.

      event .preventDefault ();
      event .stopImmediatePropagation ();

      // Change viewpoint position.

      const
         viewpoint = this .getActiveViewpoint (),
         fromPoint = this .getPointOnCenterPlane (x, y, this .fromPoint);

      viewpoint .transitionStop ();

      if (event .deltaY > 0) // Move backwards.
      {
         viewpoint ._fieldOfViewScale = Math .max (0.00001, viewpoint ._fieldOfViewScale .getValue () * (1 - PlaneViewer_SCROLL_FACTOR));
      }
      else if (event .deltaY < 0) // Move forwards.
      {
         viewpoint ._fieldOfViewScale = viewpoint ._fieldOfViewScale .getValue () * (1 + PlaneViewer_SCROLL_FACTOR);

         this .constrainFieldOfViewScale ();
      }

      const
         toPoint     = this .getPointOnCenterPlane (x, y, this .toPoint),
         translation = viewpoint .getUserOrientation () .multVecRot (PlaneViewer_vector .assign (fromPoint) .subtract (toPoint));

      viewpoint ._positionOffset         = positionOffset         .assign (viewpoint ._positionOffset         .getValue ()) .add (translation);
      viewpoint ._centerOfRotationOffset = centerOfRotationOffset .assign (viewpoint ._centerOfRotationOffset .getValue ()) .add (translation);
   },
   constrainFieldOfViewScale ()
   {
      const viewpoint = this .getActiveViewpoint ();

      if (viewpoint .getTypeName () .match (/^(?:Viewpoint|GeoViewpoint)$/))
      {
         if (viewpoint ._fieldOfView .getValue () * viewpoint ._fieldOfViewScale .getValue () >= Math .PI)
            viewpoint ._fieldOfViewScale = (Math .PI - 0.001) / viewpoint ._fieldOfView .getValue ();
      }
   },
   dispose ()
   {
      this .getBrowser () .getSurface () .off (".PlaneViewer");
      PlaneViewer_$(document) .off (".PlaneViewer" + this .getId ());
   },
});

Object .defineProperties (PlaneViewer,
{
   typeName:
   {
      value: "PlaneViewer",
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly, "isActive", new x_ite_Fields .SFBool ()),
      ]),
      enumerable: true,
   },
});

const PlaneViewer_default_ = PlaneViewer;
;

x_ite_Namespace .add ("PlaneViewer", "x_ite/Browser/Navigation/PlaneViewer", PlaneViewer_default_);
/* harmony default export */ const Navigation_PlaneViewer = (PlaneViewer_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Navigation/NoneViewer.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/







function NoneViewer (executionContext, navigationInfo)
{
   Navigation_X3DViewer .call (this, executionContext, navigationInfo);
}

Object .setPrototypeOf (NoneViewer .prototype, Navigation_X3DViewer .prototype);

Object .defineProperties (NoneViewer,
{
   typeName:
   {
      value: "NoneViewer",
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly, "isActive", new x_ite_Fields .SFBool ()),
      ]),
      enumerable: true,
   },
});

const NoneViewer_default_ = NoneViewer;
;

x_ite_Namespace .add ("NoneViewer", "x_ite/Browser/Navigation/NoneViewer", NoneViewer_default_);
/* harmony default export */ const Navigation_NoneViewer = (NoneViewer_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Navigation/LookAtViewer.js
/* provided dependency */ var LookAtViewer_jquery_mousewheel = __webpack_require__(946);
/* provided dependency */ var LookAtViewer_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/












typeof LookAtViewer_jquery_mousewheel; // import plugin

const LookAtViewer_macOS = /Mac OS X/i .test (navigator .userAgent)

const
   LookAtViewer_SCROLL_FACTOR = LookAtViewer_macOS ? 1 / 120 : 1 / 20,
   LookAtViewer_MOVE_TIME     = 0.3,
   LookAtViewer_ROTATE_TIME   = 0.3;

function LookAtViewer (executionContext, navigationInfo)
{
   Navigation_X3DViewer .call (this, executionContext, navigationInfo);

   this .button                 = -1;
   this .fromVector             = new Numbers_Vector3 (0, 0, 0);
   this .toVector               = new Numbers_Vector3 (0, 0, 0);

   this .touch1                 = new Numbers_Vector2 (0, 0);
   this .touch2                 = new Numbers_Vector2 (0, 0);
   this .tapStart               = 0;
   this .dblTapInterval         = 0.4;

   this .positionChaser         = new Followers_PositionChaser (executionContext);
   this .centerOfRotationChaser = new Followers_PositionChaser (executionContext);
   this .orientationChaser      = new Followers_OrientationChaser (executionContext);
}

Object .assign (Object .setPrototypeOf (LookAtViewer .prototype, Navigation_X3DViewer .prototype),
{
   initialize ()
   {
      Navigation_X3DViewer .prototype .initialize .call (this);

      const
         browser = this .getBrowser (),
         element = browser .getSurface ();

      // Bind pointing device events.

      element .on ("mousedown.LookAtViewer",  this .mousedown  .bind (this));
      element .on ("mouseup.LookAtViewer",    this .mouseup    .bind (this));
      element .on ("dblclick.LookAtViewer",   this .dblclick   .bind (this));
      element .on ("mousewheel.LookAtViewer", this .mousewheel .bind (this));

      element .on ("touchstart.LookAtViewer", this .touchstart .bind (this));
      element .on ("touchend.LookAtViewer",   this .touchend   .bind (this));

      // Setup chaser.

      this .positionChaser ._duration = LookAtViewer_MOVE_TIME;
      this .positionChaser .setup ();

      this .centerOfRotationChaser ._duration = LookAtViewer_MOVE_TIME;
      this .centerOfRotationChaser .setup ();

      this .orientationChaser ._duration = LookAtViewer_ROTATE_TIME;
      this .orientationChaser .setup ();
   },
   mousedown (event)
   {
      if (this .button >= 0)
         return;

      const { x, y } = this .getBrowser () .getPointerFromEvent (event);

      if (!this .isPointerInRectangle (x, y))
         return;

      switch (event .button)
      {
         case 0:
         {
            // Stop event propagation.

            event .preventDefault ();
            event .stopImmediatePropagation ();

            this .button = event .button;

            LookAtViewer_$(document) .on ("mouseup.LookAtViewer"   + this .getId (), this .mouseup   .bind (this));
            LookAtViewer_$(document) .on ("mousemove.LookAtViewer" + this .getId (), this .mousemove .bind (this));
            LookAtViewer_$(document) .on ("touchend.LookAtViewer"  + this .getId (), this .mouseup   .bind (this));
            LookAtViewer_$(document) .on ("touchmove.LookAtViewer" + this .getId (), this .touchmove .bind (this));

            this .getActiveViewpoint () .transitionStop ();

            // Look around.

            this .trackballProjectToSphere (x, y, this .fromVector);

            this ._isActive = true;
            break;
         }
      }
   },
   mouseup (event)
   {
      if (event .button !== this .button)
         return;

      this .button = -1;

      LookAtViewer_$(document) .off (".LookAtViewer" + this .getId ());

      switch (event .button)
      {
         case 0:
         {
            // Stop event propagation.

            event .preventDefault ();
            event .stopImmediatePropagation ();

            this ._isActive = false;
            break;
         }
      }
   },
   dblclick (event)
   {
      // Stop event propagation.
      event .preventDefault ();
      event .stopImmediatePropagation ();

      const { x, y } = this .getBrowser () .getPointerFromEvent (event);

      this .disconnect ();
      this .lookAtPoint (x, y, this .getStraightenHorizon ());
   },
   mousemove (event)
   {
      this .getBrowser () .addBrowserEvent ();

      this .event = event;

      const { x, y } = this .getBrowser () .getPointerFromEvent (event);

      switch (this .button)
      {
         case 0:
         {
            // Stop event propagation.
            event .preventDefault ();
            event .stopImmediatePropagation ();

            // Look around

            const toVector = this .trackballProjectToSphere (x, y, this .toVector);

            this .addRotation (this .fromVector, toVector);
            this .fromVector .assign (toVector);
            break;
         }
      }
   },
   mousewheel: (() =>
   {
      const
         step        = new Numbers_Vector3 (0, 0, 0),
         translation = new Numbers_Vector3 (0, 0, 0);

      return function (event)
      {
         const { x, y } = this .getBrowser () .getPointerFromEvent (event);

         if (!this .isPointerInRectangle (x, y))
            return;

         // Stop event propagation.

         event .preventDefault ();
         event .stopImmediatePropagation ();

         // Change viewpoint position.

         const viewpoint = this .getActiveViewpoint ();

         viewpoint .transitionStop ();

         this .getDistanceToCenter (step) .multiply (event .zoomFactor || LookAtViewer_SCROLL_FACTOR),
         viewpoint .getUserOrientation () .multVecRot (translation .set (0, 0, step .magnitude ()));

         if (event .deltaY > 0)
            this .addMove (translation .negate (), Numbers_Vector3 .Zero);

         else if (event .deltaY < 0)
            this .addMove (translation, Numbers_Vector3 .Zero);
      };
   })(),
   touchstart (event)
   {
      const touches = event .originalEvent .touches;

      switch (touches .length)
      {
         case 1:
         {
            // Start move (button 0).

            this .touch1 .set (touches [0] .pageX, touches [0] .pageY);
            break;
         }
         case 2:
         {
            // End move (button 0).

            this .touchend (event);

            // Start look around (button 0).

            event .button = 0;
            event .pageX  = (touches [0] .pageX + touches [1] .pageX) / 2;
            event .pageY  = (touches [0] .pageY + touches [1] .pageY) / 2;

            this .mousedown (event);

            // Start zoom (mouse wheel).

            this .touch1 .set (touches [0] .pageX, touches [0] .pageY);
            this .touch2 .set (touches [1] .pageX, touches [1] .pageY);
            break;
         }
         case 3:
         {
            this .touchend (event);
            break;
         }
      }
   },
   touchend (event)
   {
      switch (this .button)
      {
         case 0:
         {
            // End look around (button 0).
            this .mouseup (event);
            break;
         }
      }

      // Start dblclick (button 0).

      if (this .getBrowser () .getCurrentTime () - this .tapStart < this .dblTapInterval)
      {
         event .button = 1;
         event .pageX  = this .touch1 .x;
         event .pageY  = this .touch1 .y;

         this .dblclick (event);
      }

      this .tapStart = this .getBrowser () .getCurrentTime ();
   },
   touchmove: (() =>
   {
      const
         MOVE_ANGLE   = 0.7,
         ZOOM_ANGLE   = -0.7,
         touch1Change = new Numbers_Vector2 (0, 0),
         touch2Change = new Numbers_Vector2 (0, 0);

      return function (event)
      {
         const touches = event .originalEvent .touches;

         switch (touches .length)
         {
            case 1:
            {
               // Move (button 0).
               break;
            }
            case 2:
            {
               touch1Change .set (touches [0] .pageX, touches [0] .pageY) .subtract (this .touch1) .normalize ();
               touch2Change .set (touches [1] .pageX, touches [1] .pageY) .subtract (this .touch2) .normalize ();

               const
                  move = touch1Change .dot (touch2Change) > MOVE_ANGLE,
                  zoom = touch1Change .dot (touch2Change) < ZOOM_ANGLE;

               if (move)
               {
                  // Look around (button 0).

                  event .button = 0;
                  event .pageX  = (touches [0] .pageX + touches [1] .pageX) / 2;
                  event .pageY  = (touches [0] .pageY + touches [1] .pageY) / 2;

                  this .mousemove (event);
               }
               else if (zoom)
               {
                  // Zoom (mouse wheel).

                  const distance1 = this .touch1 .distance (this .touch2);

                  this .touch1 .set (touches [0] .pageX, touches [0] .pageY);
                  this .touch2 .set (touches [1] .pageX, touches [1] .pageY);

                  const
                     distance2 = this .touch1 .distance (this .touch2),
                     delta     = distance2 - distance1;

                  event .deltaY     = delta;
                  event .zoomFactor = Math .abs (delta) / LookAtViewer_$(window) .width ();

                  event .pageX  = (touches [0] .pageX + touches [1] .pageX) / 2;
                  event .pageY  = (touches [0] .pageY + touches [1] .pageY) / 2;

                  this .mousewheel (event);
               }

               this .touch1 .set (touches [0] .pageX, touches [0] .pageY);
               this .touch2 .set (touches [1] .pageX, touches [1] .pageY);
               break;
            }
         }
      };
   })(),
   set_positionOffset__ (value)
   {
      const viewpoint = this .getActiveViewpoint ();

      viewpoint ._positionOffset = value;
   },
   set_centerOfRotationOffset__ (value)
   {
      const viewpoint = this .getActiveViewpoint ();

      viewpoint ._centerOfRotationOffset = value;
   },
   set_orientationOffset__ (value)
   {
      const viewpoint = this .getActiveViewpoint ();

      viewpoint ._orientationOffset = value;
   },
   addMove: (() =>
   {
      const
         positionOffset         = new Numbers_Vector3 (0, 0, 0),
         centerOfRotationOffset = new Numbers_Vector3 (0, 0, 0);

      return function (positionOffsetChange, centerOfRotationOffsetChange)
      {
         const viewpoint = this .getActiveViewpoint ();

         if (this .positionChaser ._isActive .getValue () && this .positionChaser ._value_changed .hasInterest ("set_positionOffset__", this))
         {
            positionOffset
               .assign (this .positionChaser ._set_destination .getValue ())
               .add (positionOffsetChange);

            this .positionChaser ._set_destination = positionOffset;
         }
         else
         {
            positionOffset
               .assign (viewpoint ._positionOffset .getValue ())
               .add (positionOffsetChange);

            this .positionChaser ._set_value       = viewpoint ._positionOffset;
            this .positionChaser ._set_destination = positionOffset;
         }

         if (this .centerOfRotationChaser ._isActive .getValue () && this .centerOfRotationChaser ._value_changed .hasInterest ("set_centerOfRotationOffset__", this))
         {
            centerOfRotationOffset
               .assign (this .centerOfRotationChaser ._set_destination .getValue ())
               .add (centerOfRotationOffsetChange);

            this .centerOfRotationChaser ._set_destination = centerOfRotationOffset;
         }
         else
         {
            centerOfRotationOffset
               .assign (viewpoint ._centerOfRotationOffset .getValue ())
               .add (centerOfRotationOffsetChange);

            this .centerOfRotationChaser ._set_value       = viewpoint ._centerOfRotationOffset;
            this .centerOfRotationChaser ._set_destination = centerOfRotationOffset;
         }

         this .disconnect ();
         this .positionChaser         ._value_changed .addInterest ("set_positionOffset__",         this);
         this .centerOfRotationChaser ._value_changed .addInterest ("set_centerOfRotationOffset__", this);
      };
   })(),
   addRotation: (() =>
   {
      const
         userOrientation   = new Numbers_Rotation4 (),
         orientationOffset = new Numbers_Rotation4 ();

      return function (fromVector, toVector)
      {
         const viewpoint = this .getActiveViewpoint ();

         if (this .orientationChaser ._isActive .getValue () && this .orientationChaser ._value_changed .hasInterest ("set_orientationOffset__", this))
         {
            userOrientation
               .setFromToVec (toVector, fromVector)
               .multRight (viewpoint .getOrientation ())
               .multRight (this .orientationChaser ._set_destination .getValue ());

            viewpoint .straightenHorizon (userOrientation);

            orientationOffset .assign (viewpoint .getOrientation ()) .inverse () .multRight (userOrientation);

            this .orientationChaser ._set_destination = orientationOffset;
         }
         else
         {
            userOrientation
               .setFromToVec (toVector, fromVector)
               .multRight (viewpoint .getUserOrientation ());

            viewpoint .straightenHorizon (userOrientation);

            orientationOffset .assign (viewpoint .getOrientation ()) .inverse () .multRight (userOrientation);

            this .orientationChaser ._set_value       = viewpoint ._orientationOffset;
            this .orientationChaser ._set_destination = orientationOffset;
         }

         this .disconnect ();
         this .orientationChaser ._value_changed .addInterest ("set_orientationOffset__", this);
      };
   })(),
   disconnect ()
   {
      this .orientationChaser      ._value_changed .removeInterest ("set_orientationOffset__", this);
      this .positionChaser         ._value_changed .removeInterest ("set_positionOffset__",         this)
      this .centerOfRotationChaser ._value_changed .removeInterest ("set_centerOfRotationOffset__", this)
   },
   dispose ()
   {
      this .getBrowser () .getSurface () .off (".LookAtViewer");
      LookAtViewer_$(document) .off (".LookAtViewer" + this .getId ());
   },
});

Object .defineProperties (LookAtViewer,
{
   typeName:
   {
      value: "LookAtViewer",
      enumerable: true,
   },
   fieldDefinitions:
   {
      value: new Base_FieldDefinitionArray ([
         new Base_X3DFieldDefinition (Base_X3DConstants .outputOnly, "isActive", new x_ite_Fields .SFBool ()),
      ]),
      enumerable: true,
   },
});

const LookAtViewer_default_ = LookAtViewer;
;

x_ite_Namespace .add ("LookAtViewer", "x_ite/Browser/Navigation/LookAtViewer", LookAtViewer_default_);
/* harmony default export */ const Navigation_LookAtViewer = (LookAtViewer_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Navigation/X3DNavigationContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/












const
   _activeCollisions   = Symbol (),
   _viewerNode         = Symbol (),
   _headlightContainer = Symbol ();

function getHeadlight (browser)
{
   const headlight = new Lighting_DirectionalLight (browser .getPrivateScene ());

   headlight .setup ();

   const headlightContainer = headlight .getLights () .pop ();

   headlightContainer .set (headlight, null, Numbers_Matrix4 .Identity);
   headlightContainer .dispose = Function .prototype;

   return headlightContainer;
};

function X3DNavigationContext ()
{
   this .addChildObjects (Base_X3DConstants .outputOnly, "activeLayer",          new x_ite_Fields .SFNode (),
                          Base_X3DConstants .outputOnly, "activeNavigationInfo", new x_ite_Fields .SFNode (),
                          Base_X3DConstants .outputOnly, "activeViewpoint",      new x_ite_Fields .SFNode (),
                          Base_X3DConstants .outputOnly, "availableViewers",     new x_ite_Fields .MFString (),
                          Base_X3DConstants .outputOnly, "viewer",               new x_ite_Fields .SFString ("EXAMINE"));

   this [_activeCollisions] = new Set ();
   this [_viewerNode]       = new Navigation_NoneViewer (this .getPrivateScene ());
}

Object .assign (X3DNavigationContext .prototype,
{
   initialize ()
   {
      this ._viewer .addInterest ("set_viewer__", this);

      this .initialized () .addInterest ("set_world__",    this);
      this .shutdown ()    .addInterest ("remove_world__", this);

      this [_headlightContainer] = getHeadlight (this);
      this [_viewerNode] .setup ();
   },
   getHeadlight ()
   {
      return this [_headlightContainer];
   },
   getActiveLayer ()
   {
      return this ._activeLayer .getValue ();
   },
   getActiveNavigationInfo ()
   {
      return this ._activeNavigationInfo .getValue ();
   },
   getActiveViewpoint ()
   {
      return this ._activeViewpoint .getValue ();
   },
   getCurrentViewer ()
   {
      return this ._viewer .getValue ();
   },
   getViewer ()
   {
      return this [_viewerNode];
   },
   addCollision (object)
   {
      this [_activeCollisions] .add (object);
   },
   removeCollision (object)
   {
      this [_activeCollisions] .delete (object);
   },
   getCollisionCount ()
   {
      return this [_activeCollisions] .size;
   },
   remove_world__ ()
   {
      this .getWorld () ._activeLayer .removeInterest ("set_activeLayer__", this);
   },
   set_world__ ()
   {
      this .getWorld () ._activeLayer .addInterest ("set_activeLayer__", this);

      this .set_activeLayer__ ();
   },
   set_activeLayer__ ()
   {
      if (this ._activeLayer .getValue ())
      {
         this ._activeLayer .getValue () .getNavigationInfoStack () .removeInterest ("set_activeNavigationInfo__", this);
         this ._activeLayer .getValue () .getViewpointStack ()      .removeInterest ("set_activeViewpoint__",      this);
      }

      this ._activeLayer = this .getWorld () .getActiveLayer ();

      if (this ._activeLayer .getValue ())
      {
         this ._activeLayer .getValue () .getNavigationInfoStack () .addInterest ("set_activeNavigationInfo__", this);
         this ._activeLayer .getValue () .getViewpointStack ()      .addInterest ("set_activeViewpoint__",      this);
      }

      this .set_activeNavigationInfo__ ();
      this .set_activeViewpoint__ ();
   },
   set_activeNavigationInfo__ ()
   {
      this ._activeNavigationInfo .getValue () ?._viewer .removeFieldInterest (this ._viewer);

      if (this ._activeLayer .getValue ())
      {
         this ._activeNavigationInfo = this ._activeLayer .getValue () .getNavigationInfo ();

         this ._activeNavigationInfo .getValue () ._viewer .addFieldInterest (this ._viewer);

         this ._viewer = this ._activeNavigationInfo .getValue () ._viewer;
      }
      else
      {
         this ._activeNavigationInfo = null;
         this ._viewer               = "NONE";
      }
   },
   set_activeViewpoint__ ()
   {
      if (this ._activeLayer .getValue ())
         this ._activeViewpoint = this ._activeLayer .getValue () .getViewpoint ();
      else
         this ._activeViewpoint = null;
   },
   set_viewer__ (viewer)
   {
      const navigationInfo = this ._activeNavigationInfo .getValue ();

      if (navigationInfo)
         this ._availableViewers = navigationInfo ._availableViewers;
      else
         this ._availableViewers .length = 0;

      // Create viewer node.

      this [_viewerNode] ?.dispose ();

      switch (viewer .getValue ())
      {
         case "EXAMINE":
            this [_viewerNode] = new Navigation_ExamineViewer (this .getPrivateScene (), navigationInfo);
            break;
         case "WALK":
            this [_viewerNode] = new Navigation_WalkViewer (this .getPrivateScene (), navigationInfo);
            break;
         case "FLY":
            this [_viewerNode] = new Navigation_FlyViewer (this .getPrivateScene (), navigationInfo);
            break;
         case "PLANE":
         case "PLANE_create3000.github.io":
         case "PLANE_create3000.de":
            this [_viewerNode] = new Navigation_PlaneViewer (this .getPrivateScene (), navigationInfo);
            break;
         case "NONE":
            this [_viewerNode] = new Navigation_NoneViewer (this .getPrivateScene (), navigationInfo);
            break;
         case "LOOKAT":
            this [_viewerNode] = new Navigation_LookAtViewer (this .getPrivateScene (), navigationInfo);
            break;
         default:
            this [_viewerNode] = new Navigation_ExamineViewer (this .getPrivateScene (), navigationInfo);
            break;
      }

      this [_viewerNode] .setup ();
   },
   dispose ()
   {
      this [_viewerNode] ?.dispose ();
   },
});

const X3DNavigationContext_default_ = X3DNavigationContext;
;

x_ite_Namespace .add ("X3DNavigationContext", "x_ite/Browser/Navigation/X3DNavigationContext", X3DNavigationContext_default_);
/* harmony default export */ const Navigation_X3DNavigationContext = (X3DNavigationContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Networking/X3DNetworkingContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






const
   _baseURL        = Symbol (),
   _loadingDisplay = Symbol (),
   _loadingTotal   = Symbol (),
   X3DNetworkingContext_loadingObjects = Symbol (),
   _loading        = Symbol (),
   _set_loadCount  = Symbol (),
   _defaultScene   = Symbol ();

function getBaseURI (element)
{
   let baseURI = element .prop ("baseURI");

   // Fix for Edge.
   if (baseURI .startsWith ("about:"))
      baseURI = document .baseURI;

   return baseURI;
}

function X3DNetworkingContext ()
{
   this .addChildObjects (Base_X3DConstants .outputOnly, "loadCount", new x_ite_Fields .SFInt32 ());

   this [_baseURL]        = getBaseURI (this .getElement ());
   this [_loadingDisplay] = 0;
   this [_loadingTotal]   = 0;
   this [X3DNetworkingContext_loadingObjects] = new Set ();
   this [_loading]        = false;
}

Object .assign (X3DNetworkingContext .prototype,
{
   initialize ()
   {
      this ._loadCount .addInterest (_set_loadCount, this);
   },
   getProviderURL ()
   {
      return Networking_URLs .getProviderURL ();
   },
   getBaseURL ()
   {
      return this [_baseURL];
   },
   setBaseURL (value)
   {
      const
         base = getBaseURI (this .getElement ()),
         url  = new URL (value, base);

      this [_baseURL] = url .protocol .match (/^(?:data|blob):$/) ? base : url .href;
   },
   getBrowserLoading ()
   {
      return this [_loading];
   },
   setBrowserLoading (value)
   {
      this [_loading] = value;

      if (value)
      {
         if (!this [X3DNetworkingContext_loadingObjects] .has (this))
            this .resetLoadCount ();

         this .getShadow () .find (".x_ite-private-world-info") .remove ();

         if (this .getBrowserOption ("SplashScreen"))
         {
            this .getContextMenu () .hide ();
            this .getCanvas () .hide ();
            this .getSplashScreen () .stop (true, true) .show ();
         }
      }
      else
      {
         if (this .getBrowserOption ("SplashScreen"))
         {
            this .getCanvas () .show ();
            this .getSplashScreen () .stop (true, true) .show () .fadeOut (2000);
         }
      }
   },
   getLoadingObjects ()
   {
      return this [X3DNetworkingContext_loadingObjects];
   },
   addLoadingObject (object)
   {
      if (this [X3DNetworkingContext_loadingObjects] .has (object))
         return;

      ++ this [_loadingTotal];

      this [X3DNetworkingContext_loadingObjects] .add (object);

      this .setLoadCount (this [X3DNetworkingContext_loadingObjects] .size);
      this .setCursor ("DEFAULT");
   },
   removeLoadingObject (object)
   {
      if (!this [X3DNetworkingContext_loadingObjects] .has (object))
         return;

      this [X3DNetworkingContext_loadingObjects] .delete (object);

      this .setLoadCount (this [X3DNetworkingContext_loadingObjects] .size);
      this .setCursor (this .getCursor ());
   },
   getDisplayLoadCount ()
   {
      return [... this [X3DNetworkingContext_loadingObjects]] .reduce ((v, o) => v + !(o .isPrivate ?.() ?? true), 0);
   },
   setLoadCount (value)
   {
      this ._loadCount = value;
   },
   resetLoadCount ()
   {
      this ._loadCount       = 0;
      this [_loadingDisplay] = 0;
      this [_loadingTotal]   = 0;

      this [X3DNetworkingContext_loadingObjects] .clear ();

      for (const object of this .getPrivateScene () .getLoadingObjects ())
         this .addLoadingObject (object);
   },
   [_set_loadCount] ()
   {
      const loadingDisplay = this .getDisplayLoadCount ();

      if (this ._loadCount .getValue () || this [_loading])
      {
         var string = ((loadingDisplay || 1) === 1
            ? locale_gettext ("Loading %1 file")
            : locale_gettext ("Loading %1 files")) .replace ("%1", loadingDisplay || 1);
      }
      else
      {
         var string = locale_gettext("Loading done");
         this .setCursor ("DEFAULT");
      }

      if (this [_loading])
      {
         this .getSplashScreen () .find (".x_ite-private-spinner-text") .text (string);
         this .getSplashScreen () .find (".x_ite-private-progressbar div")
            .css ("width", (100 - 100 * this ._loadCount .getValue () / this [_loadingTotal]) + "%");
      }
      else
      {
         if (loadingDisplay !== this [_loadingDisplay])
            this .getNotification () ._string = string;
      }

      this [_loadingDisplay] = loadingDisplay;
   },
   getDefaultScene ()
   {
      // Inline node's empty scene.

      this [_defaultScene] = this .createScene ();
      this [_defaultScene] .setLive (true);

      this .getDefaultScene = function () { return this [_defaultScene]; };

      Object .defineProperty (this, "getDefaultScene", { enumerable: false });

      return this [_defaultScene];
   },
});

const X3DNetworkingContext_default_ = X3DNetworkingContext;
;

x_ite_Namespace .add ("X3DNetworkingContext", "x_ite/Browser/Networking/X3DNetworkingContext", X3DNetworkingContext_default_);
/* harmony default export */ const Networking_X3DNetworkingContext = (X3DNetworkingContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Picking/X3DPickingContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




const
   _transformSensorNodes = Symbol (),
   _pickSensorNodes      = Symbol (),
   _pickingHierarchy     = Symbol (),
   _pickable             = Symbol (),
   _pickingTime          = Symbol ();

function X3DPickingContext ()
{
   this [_transformSensorNodes] = new Set ();
   this [_pickSensorNodes]      = [ new Set () ];
   this [_pickingHierarchy]     = [ ];
   this [_pickable]             = [ false ];
   this [_pickingTime]          = new Time_StopWatch ();
}

Object .assign (X3DPickingContext .prototype,
{
   addTransformSensor (transformSensorNode)
   {
      this [_transformSensorNodes] .add (transformSensorNode);
      this .enablePicking ();
   },
   removeTransformSensor (transformSensorNode)
   {
      this [_transformSensorNodes] .delete (transformSensorNode);
      this .enablePicking ();
   },
   addPickSensor (pickSensorNode)
   {
      this [_pickSensorNodes] [0] .add (pickSensorNode);
      this .enablePicking ();
   },
   removePickSensor (pickSensorNode)
   {
      this [_pickSensorNodes] [0] .delete (pickSensorNode);
      this .enablePicking ();
   },
   getPickSensors ()
   {
      return this [_pickSensorNodes];
   },
   getPickingHierarchy ()
   {
      return this [_pickingHierarchy];
   },
   getPickable ()
   {
      return this [_pickable];
   },
   enablePicking ()
   {
      if (this [_transformSensorNodes] .size || this [_pickSensorNodes] [0] .size)
         this ._sensorEvents .addInterest ("picking", this);
      else
         this ._sensorEvents .removeInterest ("picking", this);
   },
   picking ()
   {
      this [_pickingTime] .start ();

      this .getWorld () .traverse (Rendering_TraverseType .PICKING);

      for (const transformSensorNode of this [_transformSensorNodes])
      {
         transformSensorNode .process ();
      }

      for (const pickSensorNode of this [_pickSensorNodes] [0])
      {
         pickSensorNode .process ();
      }

      this [_pickingTime] .stop ();
   },
   getPickingTime ()
   {
      return this [_pickingTime];
   },
});

const X3DPickingContext_default_ = X3DPickingContext;
;

x_ite_Namespace .add ("X3DPickingContext", "x_ite/Browser/Picking/X3DPickingContext", X3DPickingContext_default_);
/* harmony default export */ const Picking_X3DPickingContext = (X3DPickingContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/PointingDeviceSensor/PointingDevice.js
/* provided dependency */ var PointingDevice_jquery_mousewheel = __webpack_require__(946);
/* provided dependency */ var PointingDevice_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



typeof PointingDevice_jquery_mousewheel; // import plugin

const CONTEXT_MENU_TIME = 1200;

function PointingDevice (executionContext)
{
   Base_X3DBaseNode .call (this, executionContext);

   this .cursor     = "DEFAULT";
   this .isOver     = false;
   this .motionTime = 0;
}

Object .assign (Object .setPrototypeOf (PointingDevice .prototype, Base_X3DBaseNode .prototype),
{
   initialize ()
   {
      const element = this .getBrowser () .getSurface ();

      //element .on ("mousewheel.PointingDevice", this .mousewheel .bind (this));
      element .on ("mousedown.PointingDevice" + this .getId (), this .mousedown  .bind (this));
      element .on ("mouseup.PointingDevice"   + this .getId (), this .mouseup    .bind (this));
      element .on ("dblclick.PointingDevice"  + this .getId (), this .dblclick   .bind (this));
      element .on ("mousemove.PointingDevice" + this .getId (), this .mousemove  .bind (this));
      element .on ("mouseout.PointingDevice"  + this .getId (), this .onmouseout .bind (this));

      element .on ("touchstart.PointingDevice" + this .getId (), this .touchstart .bind (this));
      element .on ("touchend.PointingDevice"   + this .getId (), this .touchend   .bind (this));
   },
   mousewheel (event)
   {
      // event .preventDefault () must be done in the all viewers.
   },
   mousedown (event)
   {
      const
         browser = this .getBrowser (),
         element = browser .getSurface ();

      browser .getElement () .focus ();

      if (browser .getShiftKey () && browser .getControlKey ())
         return;

      if (event .button === 0)
      {
         const { x, y } = browser .getPointerFromEvent (event);

         element .off ("mousemove.PointingDevice" + this .getId ());

         PointingDevice_$(document)
            .on ("mouseup.PointingDevice"   + this .getId (), this .mouseup   .bind (this))
            .on ("mousemove.PointingDevice" + this .getId (), this .mousemove .bind (this))
            .on ("touchend.PointingDevice"  + this .getId (), this .touchend  .bind (this))
            .on ("touchmove.PointingDevice" + this .getId (), this .touchmove .bind (this));

         if (browser .buttonPressEvent (x, y))
         {
            event .preventDefault ();
            event .stopImmediatePropagation (); // Keeps the rest of the handlers from being executed

            browser .setCursor ("HAND");
            browser .finishedEvents () .addInterest ("onverifymotion", this, x, y);
         }
      }
   },
   mouseup (event)
   {
      event .preventDefault ();

      if (event .button === 0)
      {
         const
            browser = this .getBrowser (),
            element = browser .getSurface ();

         const { x, y } = browser .getPointerFromEvent (event);

         PointingDevice_$(document) .off (".PointingDevice" + this .getId ());
         element .on ("mousemove.PointingDevice" + this .getId (), this .mousemove .bind (this));

         browser .buttonReleaseEvent ();
         browser .setCursor (this .isOver ? "HAND" : "DEFAULT");
         browser .finishedEvents () .addInterest ("onverifymotion", this, x, y);
         browser .addBrowserEvent ();

         this .cursor = "DEFAULT";
      }
   },
   dblclick (event)
   {
      if (this .isOver)
         event .stopImmediatePropagation ();
   },
   mousemove (event)
   {
      event .preventDefault ();

      const browser = this .getBrowser ();

      if (this .motionTime === browser .getCurrentTime ())
         return;

      this .motionTime = browser .getCurrentTime ();

      const { x, y } = browser .getPointerFromEvent (event);

      this .onmotion (x, y);
   },
   touchstart (event)
   {
      const touches = event .originalEvent .touches;

      switch (touches .length)
      {
         case 1:
         {
            // button 0.

            event .button = 0;
            event .pageX  = touches [0] .pageX;
            event .pageY  = touches [0] .pageY;

            this .mousedown (event);

            // Show context menu on long tab.

            const hit = this .getBrowser () .getHit ();

            if (hit .id === 0 || hit .sensors .length === 0)
            {
               this .touchX       = event .pageX;
               this .touchY       = event .pageY;
               this .touchTimeout = setTimeout (this .showContextMenu .bind (this, event), CONTEXT_MENU_TIME);
            }

            break;
         }
         case 2:
         {
            this .touchend (event);
            break;
         }
      }
   },
   touchend (event)
   {
      event .button = 0;

      this .mouseup (event);

      clearTimeout (this .touchTimeout);
   },
   touchmove (event)
   {
      const touches = event .originalEvent .touches;

      switch (touches .length)
      {
         case 1:
         {
            // button 0.

            event .button = 0;
            event .pageX  = touches [0] .pageX;
            event .pageY  = touches [0] .pageY;

            this .mousemove (event);

            if (Math .hypot (this .touchX - event .pageX, this .touchY - event .pageY) > 7)
               clearTimeout (this .touchTimeout);

            break;
         }
      }
   },
   onmotion (x, y)
   {
      const browser = this .getBrowser ();

      if (browser .motionNotifyEvent (x, y))
      {
         if (!this .isOver)
         {
            this .isOver = true;
            this .cursor = browser .getCursor ();

            browser .setCursor ("HAND");
         }
      }
      else
      {
         if (this .isOver)
         {
            this .isOver = false;

            browser .setCursor (this .cursor);
         }
      }
   },
   onmouseout (event)
   {
      this .getBrowser () .leaveNotifyEvent ();
   },
   onverifymotion (x, y)
   {
      // Verify isOver state. This is necessary if an Switch changes on buttonReleaseEvent
      // and the new child has a sensor node inside. This sensor node must be update to
      // reflect the correct isOver state.

      this .getBrowser () .finishedEvents () .removeInterest ("onverifymotion", this);

      this .onmotion (x, y);
   },
   showContextMenu (event)
   {
      this .getBrowser () .getContextMenu () .show (event);
   },
});

Object .defineProperties (PointingDevice,
{
   typeName:
   {
      value: "PointingDevice",
      enumerable: true,
   },
});

const PointingDevice_default_ = PointingDevice;
;

x_ite_Namespace .add ("PointingDevice", "x_ite/Browser/PointingDeviceSensor/PointingDevice", PointingDevice_default_);
/* harmony default export */ const PointingDeviceSensor_PointingDevice = (PointingDevice_default_);
;// CONCATENATED MODULE: ./src/x_ite/Rendering/PointingBuffer.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

function PointingBuffer (browser)
{
   const gl = browser .getContext ();

   this .context = gl;
   this .array   = new Float32Array (4);

   // Create frame buffer.

   this .lastBuffer  = gl .getParameter (gl .FRAMEBUFFER_BINDING);
   this .frameBuffer = gl .createFramebuffer ();

   // Create color buffers.

   this .colorBuffers = [ ];
   this .frameBuffers = [ ];

   for (let i = 0; i < 3; ++ i)
   {
      this .colorBuffers [i] = gl .createRenderbuffer ();
      this .frameBuffers [i] = gl .createFramebuffer ();

      gl .bindRenderbuffer (gl .RENDERBUFFER, this .colorBuffers [i]);
      gl .renderbufferStorage (gl .RENDERBUFFER, gl .RGBA32F, 1, 1);
      gl .bindFramebuffer (gl .FRAMEBUFFER, this .frameBuffer);
      gl .framebufferRenderbuffer (gl .FRAMEBUFFER, gl .COLOR_ATTACHMENT0 + i, gl .RENDERBUFFER, this .colorBuffers [i]);
      gl .bindFramebuffer (gl .FRAMEBUFFER, this .frameBuffers [i]);
      gl .framebufferRenderbuffer (gl .FRAMEBUFFER, gl .COLOR_ATTACHMENT0, gl .RENDERBUFFER, this .colorBuffers [i]);
   }

   gl .bindFramebuffer (gl .FRAMEBUFFER, this .frameBuffer);

   gl .drawBuffers ([
      gl .COLOR_ATTACHMENT0, // gl_FragData [0]
      gl .COLOR_ATTACHMENT1, // gl_FragData [1]
      gl .COLOR_ATTACHMENT2, // gl_FragData [2]
   ]);

   // Create depth buffer.

   if (gl .HAS_FEATURE_DEPTH_TEXTURE)
   {
      this .depthTexture = gl .createTexture ();

      gl .bindTexture (gl .TEXTURE_2D, this .depthTexture);

      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 .texParameteri (gl .TEXTURE_2D, gl .TEXTURE_MAG_FILTER, gl .NEAREST);
      gl .texParameteri (gl .TEXTURE_2D, gl .TEXTURE_MIN_FILTER, gl .NEAREST);

      const internalFormat = gl .getVersion () >= 2 ? gl .DEPTH_COMPONENT24 : gl .DEPTH_COMPONENT;

      gl .texImage2D (gl .TEXTURE_2D, 0, internalFormat, 1, 1, 0, gl .DEPTH_COMPONENT, gl .UNSIGNED_INT, null);
      gl .framebufferTexture2D (gl .FRAMEBUFFER, gl .DEPTH_ATTACHMENT, gl .TEXTURE_2D, this .depthTexture, 0);
   }
   else
   {
      this .depthBuffer = gl .createRenderbuffer ();

      gl .bindRenderbuffer (gl .RENDERBUFFER, this .depthBuffer);
      gl .renderbufferStorage (gl .RENDERBUFFER, gl .DEPTH_COMPONENT16, 1, 1);
      gl .framebufferRenderbuffer (gl .FRAMEBUFFER, gl .DEPTH_ATTACHMENT, gl .RENDERBUFFER, this .depthBuffer);
   }

   const status = gl .checkFramebufferStatus (gl .FRAMEBUFFER) === gl .FRAMEBUFFER_COMPLETE;

   gl .bindFramebuffer (gl .FRAMEBUFFER, this .lastBuffer);

   // Always check that our frame buffer is ok.

   if (!status)
      throw new Error ("Couldn't create frame buffer.");
}

Object .assign (PointingBuffer .prototype,
{
   bind ()
   {
      const gl = this .context;

      this .lastBuffer = gl .getParameter (gl .FRAMEBUFFER_BINDING);

      gl .bindFramebuffer (gl .FRAMEBUFFER, this .frameBuffer);
      gl .clearColor (0, 0, 0, 0);
      gl .clear (gl .COLOR_BUFFER_BIT);
   },
   unbind ()
   {
      const gl = this .context;

      gl .bindFramebuffer (gl .FRAMEBUFFER, this .lastBuffer);
   },
   getHit (hit)
   {
      const { context: gl, array } = this;

      // Id, point

      // gl .readBuffer (gl .COLOR_ATTACHMENT0); // WebGL 2
      gl .bindFramebuffer (gl .FRAMEBUFFER, this .frameBuffers [0]);
      gl .readPixels (0, 0, 1, 1, gl .RGBA, gl .FLOAT, array);

      hit .id = array [3];
      hit .point .set (array [0], array [1], array [2]);

      // Normal

      gl .bindFramebuffer (gl .FRAMEBUFFER, this .frameBuffers [1]);
      gl .readPixels (0, 0, 1, 1, gl .RGBA, gl .FLOAT, array);

      hit .normal .set (array [0], array [1], array [2]);

      // TexCoord

      gl .bindFramebuffer (gl .FRAMEBUFFER, this .frameBuffers [2]);
      gl .readPixels (0, 0, 1, 1, gl .RGBA, gl .FLOAT, array);

      hit .texCoord .set (array [0], array [1], array [2], array [3]);

      // Finish

      gl .bindFramebuffer (gl .FRAMEBUFFER, this .frameBuffer);
   },
   dispose ()
   {
      const gl = this .context;

      gl .deleteFramebuffer (this .frameBuffer);

      for (const framebuffer of this .frameBuffers)
         gl .deleteFramebuffer (framebuffer);

      for (const colorBuffer of this .colorBuffers)
         gl .deleteRenderbuffer (colorBuffer);

      gl .deleteRenderbuffer (this .depthBuffer);
      gl .deleteTexture (this .depthTexture);
   },
});

const PointingBuffer_default_ = PointingBuffer;
;

x_ite_Namespace .add ("PointingBuffer", "x_ite/Rendering/PointingBuffer", PointingBuffer_default_);
/* harmony default export */ const Rendering_PointingBuffer = (PointingBuffer_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/PointingDeviceSensor/X3DPointingDeviceSensorContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/










const
   _pointingDevice            = Symbol (),
   _pointingDeviceSensorNodes = Symbol (),
   _cursorType                = Symbol (),
   _pointer                   = Symbol (),
   _hit                       = Symbol (),
   _overSensors               = Symbol (),
   _activeSensors             = Symbol (),
   _pointingLayer             = Symbol (),
   _pointingTime              = Symbol (),
   _pointingBuffer            = Symbol (),
   _pointingShaders           = Symbol (),
   _id                        = Symbol (),
   _pointingContexts          = Symbol ();

function X3DPointingDeviceSensorContext ()
{
   this [_pointingDevice]            = new PointingDeviceSensor_PointingDevice (this .getPrivateScene ());
   this [_pointingDeviceSensorNodes] = new Set ();
   this [_pointer]                   = new Numbers_Vector2 (0, 0);
   this [_overSensors]               = [ ];
   this [_activeSensors]             = [ ];
   this [_pointingLayer]             = null;
   this [_pointingTime]              = new Time_StopWatch ();
   this [_pointingBuffer]            = new Rendering_PointingBuffer (this);
   this [_pointingShaders]           = new Map ();
   this [_pointingContexts]          = [ ];

   this [_hit] = {
      id: 0,
      pointer: this [_pointer],
      hitRay: null,
      sensors: [ ],
      modelViewMatrix: new Numbers_Matrix4 (),
      point: new Numbers_Vector3 (0, 0, 0),
      normal: new Numbers_Vector3 (0, 0, 0),
      texCoord: new Numbers_Vector4 (0, 0, 0, 0),
      layerNode: null,
      shapeNode: null,
   };
}

Object .assign (X3DPointingDeviceSensorContext .prototype,
{
   initialize ()
   {
      this .setCursor ("DEFAULT");

      this [_pointingDevice] .setup ();
   },
   getPointingTime ()
   {
      return this [_pointingTime];
   },
   addPointingDeviceSensor (node)
   {
      this [_pointingDeviceSensorNodes] .add (node);
   },
   removePointingDeviceSensor (node)
   {
      this [_pointingDeviceSensorNodes] .delete (node);
   },
   setCursor (value)
   {
      const div = this .getSurface ();

      this [_cursorType] = value;

      switch (value)
      {
         case "HAND": // Hand with finger
            div .css ("cursor", "pointer");
            break;
         case "MOVE": // Hand grabbed something
            div .css ("cursor", "move");
            break;
         case "CROSSHAIR":
            div .css ("cursor", "crosshair");
            break;
         default:
         {
            if (this .getDisplayLoadCount ())
               div .css ("cursor", "wait");
            else if (this [_pointingDevice] ?.isOver)
               div .css ("cursor", "pointer");
            else
               div .css ("cursor", "default");
            break;
         }
      }
   },
   getCursor ()
   {
      return this [_cursorType];
   },
   getPointer ()
   {
      return this [_pointer];
   },
   getPointerFromEvent ({ pageX, pageY })
   {
      const
         offset   = this .getSurface () .offset (),
         rect     = this .getSurface () [0] .getBoundingClientRect (),
         viewport = this .getViewport (),
         x        =      (pageX - offset .left) / rect .width   * viewport [2],
         y        = (1 - (pageY - offset .top)  / rect .height) * viewport [3];

      return new Numbers_Vector2 (x, y);
   },
   isPointerInRectangle (rectangle, pointer = this [_pointer])
   {
      return pointer .x >= rectangle .x &&
             pointer .x <= rectangle .x + rectangle .z &&
             pointer .y >= rectangle .y &&
             pointer .y <= rectangle .y + rectangle .w;
   },
   getPointingLayer ()
   {
      return this [_pointingLayer];
   },
   getHit ()
   {
      return this [_hit];
   },
   addPointingShape (pickingContext)
   {
      const id = ++ this [_id];

      this [_pointingContexts] [id] = pickingContext;

      return id;
   },
   buttonPressEvent (x, y)
   {
      if (!this [_pointingDeviceSensorNodes] .size)
         return false;

      if (!this .touch (x, y))
         return false;

      const hit = this [_hit];

      this [_activeSensors] = hit .sensors;
      this [_pointingLayer] = hit .layerNode;

      for (const sensor of this [_activeSensors])
         sensor .set_active__ (true, hit);

      return !! hit .sensors .length;
   },
   buttonReleaseEvent ()
   {
      if (!this [_pointingDeviceSensorNodes] .size)
         return;

      for (const sensor of this [_activeSensors])
         sensor .set_active__ (false, null);

      this [_activeSensors] = Array .prototype;
      this [_pointingLayer] = null;
   },
   motionNotifyEvent (x, y)
   {
      if (!this [_pointingDeviceSensorNodes] .size)
         return false;

      this .touch (x, y);
      this .motion ();

      return !! this [_hit] .sensors .length;
   },
   leaveNotifyEvent ()
   { },
   touch (x, y)
   {
      this [_pointingTime] .start ();

      if (this .getViewer () ._isActive .getValue ())
      {
         this [_pointingTime] .reset ();
         return false;
      }

      // Pick.

      const hit = this [_hit];

      this [_id] = 0;

      this [_pointer] .set (x, y);
      this [_pointingBuffer] .bind ();

      this .getWorld () .traverse (Rendering_TraverseType .POINTER);

      this [_pointingBuffer] .getHit (hit);
      this [_pointingBuffer] .unbind ();

      if (Number .isInteger (hit .id) && hit .id > 0 && hit .id <= this [_id])
      {
         const
            pickingContext  = this [_pointingContexts] [hit .id],
            shapeNode       = pickingContext .shapeNode,
            appearanceNode  = shapeNode .getAppearance (),
            geometryContext = shapeNode .getGeometryContext ();

         hit .hitRay    = pickingContext .renderObject .getHitRay ();
         hit .sensors   = pickingContext .sensors .slice ();
         hit .layerNode = pickingContext .renderObject;
         hit .shapeNode = shapeNode;

         hit .modelViewMatrix .assign (pickingContext .modelViewMatrix);

         // A ParticleSystem has only a geometry context.

         if (geometryContext .hasNormals)
            hit .modelViewMatrix .submatrix .inverse () .transpose () .multVecMatrix (hit .normal) .normalize ();
         else
            hit .normal .assign (Numbers_Vector3 .zAxis);

         appearanceNode .getTextureTransform () .transformPoint (hit .texCoord);
      }
      else
      {
         hit .id        = 0;
         hit .hitRay    = this [_pointingLayer] ? this [_pointingLayer] .getHitRay () : null;
         hit .sensors   = Array .prototype;
         hit .layerNode = this [_pointingLayer];
         hit .shapeNode = null;

         hit .modelViewMatrix .assign (Numbers_Matrix4 .Identity);
      }

      // Picking end.

      this .addBrowserEvent ();
      this [_pointingTime] .stop ();

      return !! hit .id;
   },
   motion ()
   {
      const hit = this [_hit];

      // Set isOver to FALSE for appropriate nodes

      if (hit .id)
      {
         var difference = this [_overSensors] .filter (a => !hit .sensors .find (b => a .node === b .node));
      }
      else
      {
         var difference = this [_overSensors];
      }

      for (const sensor of difference)
         sensor .set_over__ (false, hit);

      // Set isOver to TRUE for appropriate nodes

      if (hit .id)
      {
         this [_overSensors] = hit .sensors;

         for (const sensor of this [_overSensors])
            sensor .set_over__ (true, hit);
      }
      else
      {
         this [_overSensors] = Array .prototype;
      }

      // Forward motion event to active drag sensor nodes

      for (const sensor of this [_activeSensors])
         sensor .set_motion__ (hit);
   },
   getPointingShader (numClipPlanes, shapeNode, humanoidNode)
   {
      const geometryContext = shapeNode .getGeometryContext ();

      let key = "";

      key += numClipPlanes;
      key += ".";
      key += shapeNode .getShapeKey ();
      key += geometryContext .geometryType;
      key += ".";
      key += humanoidNode ?.getHumanoidKey () ?? "";
      key += ".";

      if (geometryContext .geometryType >= 2)
      {
         key += "0.0.0";
      }
      else
      {
         const appearanceNode  = shapeNode .getAppearance ();

         key += appearanceNode .getStyleProperties (geometryContext .geometryType) ? 1 : 0;
         key += ".";
         key += appearanceNode .getTextureBits () .toString (4); // Textures for point and line.
         key += ".";
         key += appearanceNode .getMaterial () .getTextureBits () .toString (4); // Textures for point and line.
      }

      return this [_pointingShaders] .get (key) || this .createPointingShader (key, numClipPlanes, shapeNode, humanoidNode);
   },
   createPointingShader (key, numClipPlanes, shapeNode, humanoidNode)
   {
      const
         appearanceNode  = shapeNode .getAppearance (),
         geometryContext = shapeNode .getGeometryContext (),
         options         = [ ];

      if (numClipPlanes)
      {
         options .push ("X3D_CLIP_PLANES");
         options .push ("X3D_NUM_CLIP_PLANES " + numClipPlanes);
      }

      if (shapeNode .getShapeKey () > 0)
         options .push ("X3D_PARTICLE_SYSTEM");

      options .push (`X3D_GEOMETRY_${geometryContext .geometryType}D`);

      if (appearanceNode .getStyleProperties (geometryContext .geometryType))
         options .push ("X3D_STYLE_PROPERTIES");

      if (humanoidNode)
      {
         options .push ("X3D_SKINNING");
         options .push (`X3D_NUM_JOINT_SETS ${humanoidNode .getNumJoints () / 4}`);
         options .push (`X3D_NUM_DISPLACEMENTS ${humanoidNode .getNumDisplacements ()}`);
      }

      const shaderNode = this .createShader ("PointingShader", "Pointing", "Pointing", options);

      this [_pointingShaders] .set (key, shaderNode);

      return shaderNode;
   },
});

const X3DPointingDeviceSensorContext_default_ = X3DPointingDeviceSensorContext;
;

x_ite_Namespace .add ("X3DPointingDeviceSensorContext", "x_ite/Browser/PointingDeviceSensor/X3DPointingDeviceSensorContext", X3DPointingDeviceSensorContext_default_);
/* harmony default export */ const PointingDeviceSensor_X3DPointingDeviceSensorContext = (X3DPointingDeviceSensorContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Rendering/MultiSampleFrameBuffer.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

function MultiSampleFrameBuffer (browser, width, height, samples, oit)
{
   const gl = browser .getContext ();

   if (gl .getVersion () === 1 || width === 0 || height === 0)
      return Fallback;

   this .context    = gl;
   this .width      = width;
   this .height     = height;
   this .samples    = samples;
   this .oit        = oit;
   this .lastBuffer = [ ];

   // Create frame buffer.

   this .lastBuffer .push (gl .getParameter (gl .FRAMEBUFFER_BINDING));

   this .frameBuffer = gl .createFramebuffer ();

   gl .bindFramebuffer (gl .FRAMEBUFFER, this .frameBuffer);

   // Create color buffer.

   this .colorBuffer = gl .createRenderbuffer ();

   gl .bindRenderbuffer (gl .RENDERBUFFER, this .colorBuffer);

   if (samples && !oit)
      gl .renderbufferStorageMultisample (gl .RENDERBUFFER, samples, gl .RGBA8, width, height);
   else
      gl .renderbufferStorage (gl .RENDERBUFFER, gl .RGBA8, width, height);

   gl .framebufferRenderbuffer (gl .FRAMEBUFFER, gl .COLOR_ATTACHMENT0, gl .RENDERBUFFER, this .colorBuffer);

   // Create depth buffer.

   this .depthBuffer = gl .createRenderbuffer ();

   gl .bindRenderbuffer (gl .RENDERBUFFER, this .depthBuffer);

   if (samples && !oit)
      gl .renderbufferStorageMultisample (gl .RENDERBUFFER, samples, gl .DEPTH_COMPONENT24, width, height);
   else
      gl .renderbufferStorage (gl .RENDERBUFFER, gl .DEPTH_COMPONENT24, width, height);

   gl .framebufferRenderbuffer (gl .FRAMEBUFFER, gl .DEPTH_ATTACHMENT, gl .RENDERBUFFER, this .depthBuffer);

   const status1 = gl .checkFramebufferStatus (gl .FRAMEBUFFER) === gl .FRAMEBUFFER_COMPLETE;

   gl .bindFramebuffer (gl .FRAMEBUFFER, this .lastBuffer .pop ());

   // Always check that our frame buffer is ok.

   if (!status1)
      throw new Error ("Couldn't create frame buffer.");

   if (!oit)
      return;

   // Create oit frame buffer.

   this .lastBuffer .push (gl .getParameter (gl .FRAMEBUFFER_BINDING));

   this .oitFrameBuffer = gl .createFramebuffer ();

   gl .bindFramebuffer (gl .FRAMEBUFFER, this .oitFrameBuffer);

   // Set draw buffers.

   gl .drawBuffers ([
      gl .COLOR_ATTACHMENT0, // gl_FragData [0]
      gl .COLOR_ATTACHMENT1, // gl_FragData [1]
   ]);

   if (samples)
   {
      // Create accum and revealage buffer.

      this .accumRevealageBuffer = gl .createRenderbuffer ();

      gl .bindRenderbuffer (gl .RENDERBUFFER, this .accumRevealageBuffer);
      gl .renderbufferStorageMultisample (gl .RENDERBUFFER, samples, gl .RGBA32F, width, height);
      gl .framebufferRenderbuffer (gl .FRAMEBUFFER, gl .COLOR_ATTACHMENT0, gl .RENDERBUFFER, this .accumRevealageBuffer);

      // Create alpha buffer.

      this .alphaBuffer = gl .createRenderbuffer ();

      gl .bindRenderbuffer (gl .RENDERBUFFER, this .alphaBuffer);
      gl .renderbufferStorageMultisample (gl .RENDERBUFFER, samples, gl .RGBA32F, width, height);
      gl .framebufferRenderbuffer (gl .FRAMEBUFFER, gl .COLOR_ATTACHMENT1, gl .RENDERBUFFER, this .alphaBuffer);

      // Add depth buffer.

      this .oitDepthBuffer = gl .createRenderbuffer ();

      gl .bindRenderbuffer (gl .RENDERBUFFER, this .oitDepthBuffer);
      gl .renderbufferStorageMultisample (gl .RENDERBUFFER, samples, gl .DEPTH_COMPONENT24, width, height);
      gl .framebufferRenderbuffer (gl .FRAMEBUFFER, gl .DEPTH_ATTACHMENT, gl .RENDERBUFFER, this .oitDepthBuffer);

      // Create accum texture buffer.

      this .accumRevealageTextureBuffer = gl .createFramebuffer ();

      gl .bindFramebuffer (gl .FRAMEBUFFER, this .accumRevealageTextureBuffer);

      // Create accum texture.

      this .accumRevealageTexture = gl .createTexture ();

      gl .bindTexture (gl .TEXTURE_2D, this .accumRevealageTexture);
      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 .texParameteri (gl .TEXTURE_2D, gl .TEXTURE_MIN_FILTER, gl .NEAREST);
      gl .texParameteri (gl .TEXTURE_2D, gl .TEXTURE_MAG_FILTER, gl .NEAREST);

      gl .texImage2D (gl .TEXTURE_2D, 0, gl .RGBA32F, width, height, 0, gl .RGBA, gl .FLOAT, null);
      gl .framebufferTexture2D (gl .FRAMEBUFFER, gl .COLOR_ATTACHMENT0, gl .TEXTURE_2D, this .accumRevealageTexture, 0);

      // Create alpha texture buffer.

      this .alphaTextureBuffer = gl .createFramebuffer ();

      gl .bindFramebuffer (gl .FRAMEBUFFER, this .alphaTextureBuffer);

      // Create alpha texture.

      this .alphaTexture = gl .createTexture ();

      gl .bindTexture (gl .TEXTURE_2D, this .alphaTexture);
      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 .texParameteri (gl .TEXTURE_2D, gl .TEXTURE_MIN_FILTER, gl .NEAREST);
      gl .texParameteri (gl .TEXTURE_2D, gl .TEXTURE_MAG_FILTER, gl .NEAREST);

      gl .texImage2D (gl .TEXTURE_2D, 0, gl .RGBA32F, width, height, 0, gl .RGBA, gl .FLOAT, null);
      gl .framebufferTexture2D (gl .FRAMEBUFFER, gl .COLOR_ATTACHMENT0, gl .TEXTURE_2D, this .alphaTexture, 0);
   }
   else
   {
      // Create accum texture.

      this .accumRevealageTexture = gl .createTexture ();

      gl .bindTexture (gl .TEXTURE_2D, this .accumRevealageTexture);
      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 .texParameteri (gl .TEXTURE_2D, gl .TEXTURE_MIN_FILTER, gl .NEAREST);
      gl .texParameteri (gl .TEXTURE_2D, gl .TEXTURE_MAG_FILTER, gl .NEAREST);

      gl .texImage2D (gl .TEXTURE_2D, 0, gl .RGBA32F, width, height, 0, gl .RGBA, gl .FLOAT, null);
      gl .framebufferTexture2D (gl .FRAMEBUFFER, gl .COLOR_ATTACHMENT0, gl .TEXTURE_2D, this .accumRevealageTexture, 0);

      // Create alpha texture.

      this .alphaTexture = gl .createTexture ();

      gl .bindTexture (gl .TEXTURE_2D, this .alphaTexture);
      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 .texParameteri (gl .TEXTURE_2D, gl .TEXTURE_MIN_FILTER, gl .NEAREST);
      gl .texParameteri (gl .TEXTURE_2D, gl .TEXTURE_MAG_FILTER, gl .NEAREST);

      gl .texImage2D (gl .TEXTURE_2D, 0, gl .RGBA32F, width, height, 0, gl .RGBA, gl .FLOAT, null);
      gl .framebufferTexture2D (gl .FRAMEBUFFER, gl .COLOR_ATTACHMENT1, gl .TEXTURE_2D, this .alphaTexture, 0);

      // Add depth buffer.

      this .oitDepthBuffer = gl .createRenderbuffer ();

      gl .bindRenderbuffer (gl .RENDERBUFFER, this .oitDepthBuffer);
      gl .renderbufferStorage (gl .RENDERBUFFER, gl .DEPTH_COMPONENT24, width, height);
      gl .framebufferRenderbuffer (gl .FRAMEBUFFER, gl .DEPTH_ATTACHMENT, gl .RENDERBUFFER, this .oitDepthBuffer);
   }

   const status2 = gl .checkFramebufferStatus (gl .FRAMEBUFFER) === gl .FRAMEBUFFER_COMPLETE;

   gl .bindTexture (gl .TEXTURE_2D, null);
   gl .bindFramebuffer (gl .FRAMEBUFFER, this .lastBuffer .pop ());

   // Always check that our frame buffer is ok.

   if (!status2)
      throw new Error ("Couldn't create frame buffer.");

   // Get compose shader and texture units.

   this .shaderNode = browser .getComposeShader ();
   this .program    = this .shaderNode .getProgram ();

   gl .useProgram (this .program);

   const
      accumRevealageTextureUnit = gl .getUniformLocation (this .program, "x3d_AccumRevealageTexture"),
      alphaTextureUnit          = gl .getUniformLocation (this .program, "x3d_AlphaTexture");

   gl .uniform1i (accumRevealageTextureUnit, 0);
   gl .uniform1i (alphaTextureUnit,          1);

   // Quad for compose pass.

   this .quadArray  = gl .createVertexArray ();
   this .quadBuffer = gl .createBuffer ();

   gl .bindVertexArray (this .quadArray);
   gl .bindBuffer (gl .ARRAY_BUFFER, this .quadBuffer);
   gl .bufferData (gl .ARRAY_BUFFER, new Float32Array ([-1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1]), gl .STATIC_DRAW);
   gl .vertexAttribPointer (0, 2, gl .FLOAT, false, 0, 0);
   gl .enableVertexAttribArray (null);
}

Object .assign (MultiSampleFrameBuffer .prototype,
{
   getWidth ()
   {
      return this .width;
   },
   getHeight ()
   {
      return this .height;
   },
   getSamples ()
   {
      return this .samples;
   },
   getOrderIndependentTransparency ()
   {
      return this .oit;
   },
   bind ()
   {
      const { context: gl, lastBuffer, frameBuffer } = this;

      lastBuffer .push (gl .getParameter (gl .FRAMEBUFFER_BINDING));

      gl .bindFramebuffer (gl .FRAMEBUFFER, frameBuffer);

      gl .clearColor (0, 0, 0, 0);
      gl .clear (gl .COLOR_BUFFER_BIT);
   },
   blit ()
   {
      const { context: gl, width, height, samples, frameBuffer, oit } = this;

      // Reset viewport before blit, otherwise only last layer size is used.
      gl .viewport (0, 0, width, height);
      gl .scissor  (0, 0, width, height);

      gl .bindFramebuffer (gl .READ_FRAMEBUFFER, frameBuffer);
      gl .bindFramebuffer (gl .DRAW_FRAMEBUFFER, null);

      gl .blitFramebuffer (0, 0, width, height,
                           0, 0, width, height,
                           gl .COLOR_BUFFER_BIT, samples && !oit ? gl .LINEAR : gl .NEAREST);
   },
   unbind ()
   {
      const { context: gl, lastBuffer } = this;

      gl .bindFramebuffer (gl .FRAMEBUFFER, lastBuffer .pop ());
   },
   bindForOrderIndependentTransparency ()
   {
      const { context: gl, lastBuffer, oitFrameBuffer } = this;

      lastBuffer .push (gl .getParameter (gl .FRAMEBUFFER_BINDING));

      gl .bindFramebuffer (gl .FRAMEBUFFER, oitFrameBuffer);

      gl .clearColor (0, 0, 0, 1);
      gl .clear (gl .COLOR_BUFFER_BIT);
      gl .blendFuncSeparate (gl .ONE, gl .ONE, gl .ZERO, gl .ONE_MINUS_SRC_ALPHA);
   },
   compose ()
   {
      const { context: gl, width, height, samples, program } = this;

      // TODO: Combining lights and lights with shadows, can cause feedback loop of texture.
      // TODO: VolumeRendering shader is not made for OIT.

      // Reset viewport before blit, otherwise only last layer size is used.
      gl .viewport (0, 0, width, height);
      gl .scissor  (0, 0, width, height);

      if (samples)
      {
         gl .bindFramebuffer (gl .READ_FRAMEBUFFER, this .oitFrameBuffer);

         gl .readBuffer (gl .COLOR_ATTACHMENT0);
         gl .bindFramebuffer (gl .DRAW_FRAMEBUFFER, this .accumRevealageTextureBuffer);

         gl .blitFramebuffer (0, 0, width, height,
                              0, 0, width, height,
                              gl .COLOR_BUFFER_BIT, gl .LINEAR);

         gl .readBuffer (gl .COLOR_ATTACHMENT1);
         gl .bindFramebuffer (gl .DRAW_FRAMEBUFFER, this .alphaTextureBuffer);

         gl .blitFramebuffer (0, 0, width, height,
                              0, 0, width, height,
                              gl .COLOR_BUFFER_BIT, gl .LINEAR);
      }

      gl .useProgram (program);
      gl .activeTexture (gl .TEXTURE0 + 0);
      gl .bindTexture (gl .TEXTURE_2D, this .accumRevealageTexture);
      gl .activeTexture (gl .TEXTURE0 + 1);
      gl .bindTexture (gl .TEXTURE_2D, this .alphaTexture);

      gl .bindFramebuffer (gl .FRAMEBUFFER, this .frameBuffer);
      gl .disable (gl .DEPTH_TEST);
      gl .enable (gl .BLEND);
      gl .blendFunc (gl .ONE, gl .ONE_MINUS_SRC_ALPHA);
      gl .enable (gl .CULL_FACE);
      gl .frontFace (gl .CCW);
      gl .bindVertexArray (this .quadArray);
      gl .drawArrays (gl .TRIANGLES, 0, 6);
      gl .disable (gl .BLEND);
      gl .enable (gl .DEPTH_TEST);
   },
   dispose ()
   {
      const gl = this .context;

      gl .deleteFramebuffer (this .frameBuffer);
      gl .deleteRenderbuffer (this .colorBuffer);
      gl .deleteRenderbuffer (this .depthBuffer);

      gl .deleteFramebuffer (this .oitFrameBuffer);
      gl .deleteFramebuffer (this .accumRevealageTextureBuffer);
      gl .deleteFramebuffer (this .alphaTextureBuffer);
      gl .deleteRenderbuffer (this .oitDepthBuffer);
      gl .deleteRenderbuffer (this .accumRevealageBuffer);
      gl .deleteRenderbuffer (this .alphaBuffer);
      gl .deleteTexture (this .accumRevealageTexture);
      gl .deleteTexture (this .alphaTexture)
      gl .deleteVertexArray (this .quadArray);
      gl .deleteBuffer (this .quadBuffer);
   },
});

const Fallback = {
   getWidth: Function .prototype,
   getHeight: Function .prototype,
   getSamples: Function .prototype,
   getOrderIndependentTransparency: Function .prototype,
   bind: Function .prototype,
   clear: Function .prototype,
   blit: Function .prototype,
   compose: Function .prototype,
   unbind: Function .prototype,
   dispose: Function .prototype,
};

const MultiSampleFrameBuffer_default_ = MultiSampleFrameBuffer;
;

x_ite_Namespace .add ("MultiSampleFrameBuffer", "x_ite/Rendering/MultiSampleFrameBuffer", MultiSampleFrameBuffer_default_);
/* harmony default export */ const Rendering_MultiSampleFrameBuffer = (MultiSampleFrameBuffer_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Rendering/X3DRenderingContext.js
/* provided dependency */ var X3DRenderingContext_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




const
   _viewport      = Symbol (),
   _frameBuffer   = Symbol (),
   _resizer       = Symbol (),
   _localObjects  = Symbol (),
   _composeShader = Symbol (),
   _depthShaders  = Symbol ();

function X3DRenderingContext ()
{
   this [_viewport]     = new Numbers_Vector4 (0, 0, 300, 150);
   this [_frameBuffer]  = new Rendering_MultiSampleFrameBuffer (this, 300, 150, 4);
   this [_localObjects] = [ ]; // shader objects dumpster
   this [_depthShaders] = new Map ();
}

Object .assign (X3DRenderingContext .prototype,
{
   initialize ()
   {
      // Configure context.

      const gl = this .getContext ();

      gl .enable (gl .SCISSOR_TEST);
      gl .enable (gl .DEPTH_TEST);
      gl .depthFunc (gl .LEQUAL);
      gl .clearDepth (1);

      gl .blendFuncSeparate (gl .SRC_ALPHA, gl .ONE_MINUS_SRC_ALPHA, gl .ONE, gl .ONE_MINUS_SRC_ALPHA);
      gl .blendEquationSeparate (gl .FUNC_ADD, gl .FUNC_ADD);

      // Configure viewport.

      X3DRenderingContext_$(document) .on ('webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange', this .onfullscreen .bind (this));

      this [_resizer] = new ResizeObserver (this .reshape .bind (this));
      this [_resizer] .observe (this .getSurface () [0]);

      this .reshape ();
   },
   getRenderer ()
   {
      const gl = this .getContext ();

      if (! navigator .userAgent .match (/Firefox/))
      {
         const dbgRenderInfo = gl .getExtension ("WEBGL_debug_renderer_info");

         if (dbgRenderInfo)
            return gl .getParameter (dbgRenderInfo .UNMASKED_RENDERER_WEBGL);
      }

      return gl .getParameter (gl .RENDERER);
   },
   getVendor ()
   {
      const gl = this .getContext ();

      if (! navigator .userAgent .match (/Firefox/))
      {
         const dbgRenderInfo = gl .getExtension ("WEBGL_debug_renderer_info");

         if (dbgRenderInfo)
            return gl .getParameter (dbgRenderInfo .UNMASKED_VENDOR_WEBGL);
      }

      return gl .getParameter (gl .VENDOR);
   },
   getWebGLVersion ()
   {
      const gl = this .getContext ();

      return gl .getParameter (gl .VERSION);
   },
   getMaxSamples ()
   {
      const gl = this .getContext ();

      return gl .getVersion () > 1 ? gl .getParameter (gl .MAX_SAMPLES) : 0;
   },
   getMaxClipPlanes ()
   {
      return 6;
   },
   getDepthSize ()
   {
      const gl = this .getContext ();

      return gl .getParameter (gl .DEPTH_BITS);
   },
   getColorDepth ()
   {
      const gl = this .getContext ();

      return (gl .getParameter (gl .RED_BITS) +
              gl .getParameter (gl .BLUE_BITS) +
              gl .getParameter (gl .GREEN_BITS) +
              gl .getParameter (gl .ALPHA_BITS));
   },
   getViewport ()
   {
      return this [_viewport];
   },
   getLocalObjects ()
   {
      return this [_localObjects];
   },
   getFrameBuffer ()
   {
      return this [_frameBuffer];
   },
   getComposeShader ()
   {
      if (this [_composeShader])
         return this [_composeShader];

      return this [_composeShader] = this .createShader ("ComposeShader", "Compose", "Compose");
   },
   getDepthShader (numClipPlanes, shapeNode, humanoidNode)
   {
      const geometryContext = shapeNode .getGeometryContext ();

      let key = "";

      key += numClipPlanes;
      key += ".";
      key += shapeNode .getShapeKey ();
      key += geometryContext .geometryType;
      key += ".";
      key += humanoidNode ?.getHumanoidKey () ?? "";
      key += ".";

      if (geometryContext .geometryType >= 2)
      {
         key += "0.0.0";
      }
      else
      {
         const appearanceNode  = shapeNode .getAppearance ();

         key += appearanceNode .getStyleProperties (geometryContext .geometryType) ? 1 : 0;
         key += ".";
         key += appearanceNode .getTextureBits () .toString (4); // Textures for point and line.
         key += ".";
         key += appearanceNode .getMaterial () .getTextureBits () .toString (4); // Textures for point and line.
      }

      return this [_depthShaders] .get (key) || this .createDepthShader (key, numClipPlanes, shapeNode, humanoidNode);
   },
   createDepthShader (key, numClipPlanes, shapeNode, humanoidNode)
   {
      const
         appearanceNode  = shapeNode .getAppearance (),
         geometryContext = shapeNode .getGeometryContext (),
         options         = [ ];

      if (numClipPlanes)
      {
         options .push ("X3D_CLIP_PLANES");
         options .push ("X3D_NUM_CLIP_PLANES " + numClipPlanes);
      }

      if (shapeNode .getShapeKey () > 0)
         options .push ("X3D_PARTICLE_SYSTEM");

      options .push (`X3D_GEOMETRY_${geometryContext .geometryType}D`);

      if (appearanceNode .getStyleProperties (geometryContext .geometryType))
         options .push ("X3D_STYLE_PROPERTIES");

      if (humanoidNode)
      {
         options .push ("X3D_SKINNING");
         options .push (`X3D_NUM_JOINT_SETS ${humanoidNode .getNumJoints () / 4}`);
         options .push (`X3D_NUM_DISPLACEMENTS ${humanoidNode .getNumDisplacements ()}`);
      }

      const shaderNode = this .createShader ("DepthShader", "Depth", "Depth", options);

      this [_depthShaders] .set (key, shaderNode);

      return shaderNode;
   },
   reshape ()
   {
      const
         $canvas      = this .getCanvas (),
         contentScale = this .getRenderingProperty ("ContentScale"),
         samples      = this .getRenderingProperty ("Multisampling"),
         oit          = this .getBrowserOption ("OrderIndependentTransparency"),
         width        = $canvas .width () * contentScale,
         height       = $canvas .height () * contentScale,
         canvas       = $canvas [0];

      canvas .width  = width;
      canvas .height = height;

      this [_viewport] [2] = width;
      this [_viewport] [3] = height;

      if (width   !== this [_frameBuffer] .getWidth ()   ||
          height  !== this [_frameBuffer] .getHeight ()  ||
          samples !== this [_frameBuffer] .getSamples () ||
          oit     !== this [_frameBuffer] .getOrderIndependentTransparency ())
      {
         this [_frameBuffer] .dispose ();
         this [_frameBuffer] = new Rendering_MultiSampleFrameBuffer (this, width, height, samples, oit);
      }

      this .addBrowserEvent ();
   },
   onfullscreen ()
   {
      const element = this .getElement ();

      if (element .fullScreen ())
         element .addClass ("x_ite-fullscreen");
      else
         element .removeClass ("x_ite-fullscreen");
   },
});

const X3DRenderingContext_default_ = X3DRenderingContext;
;

x_ite_Namespace .add ("X3DRenderingContext", "x_ite/Browser/Rendering/X3DRenderingContext", X3DRenderingContext_default_);
/* harmony default export */ const Rendering_X3DRenderingContext = (X3DRenderingContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Scripting/X3DScriptingContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

const _scripts = Symbol ();

function X3DScriptingContext ()
{
   this [_scripts] = [this];
}

Object .assign (X3DScriptingContext .prototype,
{
   isExternal ()
   {
      return this [_scripts] .length === 1;
   },
   getScriptStack ()
   {
      return this [_scripts];
   },
});

const X3DScriptingContext_default_ = X3DScriptingContext;
;

x_ite_Namespace .add ("X3DScriptingContext", "x_ite/Browser/Scripting/X3DScriptingContext", X3DScriptingContext_default_);
/* harmony default export */ const Scripting_X3DScriptingContext = (X3DScriptingContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Shaders/X3DShadersContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






const
   _wireframe      = Symbol (),
   _primitiveModes = Symbol (),
   _shaderNodes    = Symbol ();

function X3DShadersContext ()
{
   this [_wireframe]      = false;
   this [_primitiveModes] = new Map ();
   this [_shaderNodes]    = new Map ();
}

Object .assign (X3DShadersContext .prototype,
{
   initialize ()
   {
      this .setShading (this .getBrowserOptions () .getShading ());
   },
   getShadingLanguageVersion ()
   {
      const gl = this .getContext ();

      return gl .getParameter (gl .SHADING_LANGUAGE_VERSION);
   },
   getMaxVertexUniformVectors ()
   {
      const gl = this .getContext ();

      return gl .getParameter (gl .MAX_VERTEX_UNIFORM_VECTORS);
   },
   getMaxFragmentUniformVectors ()
   {
      const gl = this .getContext ();

      return gl .getParameter (gl .MAX_FRAGMENT_UNIFORM_VECTORS);
   },
   getMaxVertexAttribs ()
   {
      const gl = this .getContext ();

      return gl .getParameter (gl .MAX_VERTEX_ATTRIBS);
   },
   getMaxVaryingVectors ()
   {
      const gl = this .getContext ();

      return gl .getParameter (gl .MAX_VARYING_VECTORS);
   },
   getWireframe ()
   {
      return this [_wireframe];
   },
   getPrimitiveMode (primitiveMode)
   {
      return this [_primitiveModes] .get (primitiveMode);
   },
   getShaders ()
   {
      return this [_shaderNodes];
   },
   setShading (type)
   {
      const gl = this .getContext ();

      switch (type)
      {
         case Core_Shading .POINT:
         {
            this [_wireframe] = false;

            this [_primitiveModes] .set (gl .POINTS,    gl .POINTS);
            this [_primitiveModes] .set (gl .LINES,     gl .POINTS);
            this [_primitiveModes] .set (gl .TRIANGLES, gl .POINTS);
            break;
         }
         case Core_Shading .WIREFRAME:
         {
            this [_wireframe] = true;

            this [_primitiveModes] .set (gl .POINTS,    gl .POINTS);
            this [_primitiveModes] .set (gl .LINES,     gl .LINES);
            this [_primitiveModes] .set (gl .TRIANGLES, gl .LINE_LOOP);
            break;
         }
         default:
         {
            // case Shading .FLAT:
            // case Shading .GOURAUD:
            // case Shading .PHONG:

            this [_wireframe] = false;

            this [_primitiveModes] .set (gl .POINTS,    gl .POINTS);
            this [_primitiveModes] .set (gl .LINES,     gl .LINES);
            this [_primitiveModes] .set (gl .TRIANGLES, gl .TRIANGLES);
            break;
         }
      }
   },
   createShader (name, vs, fs = vs, options = [ ], uniformNames = [ ], transformFeedbackVaryings = [ ])
   {
      if (this .getBrowserOption ("Debug"))
         console .info ("Initializing " + name);

      const
         gl      = this .getContext (),
         version = gl .getVersion ();

      const vertexShader = new Shaders_ShaderPart (this .getPrivateScene ());
      vertexShader ._url .push (encodeURI (vs .startsWith ("data:") ? vs : "data:x-shader/x-vertex," + Shaders_ShaderRegistry .vertex [version] [vs]));
      vertexShader .setPrivate (true);
      vertexShader .setName (name + "Vertex");
      vertexShader .setOptions (options);
      vertexShader .setup ();

      const fragmentShader = new Shaders_ShaderPart (this .getPrivateScene ());
      fragmentShader ._type  = "FRAGMENT";
      fragmentShader ._url .push (encodeURI (fs .startsWith ("data:") ? fs : "data:x-shader/x-fragment," + Shaders_ShaderRegistry .fragment [version] [fs]));
      fragmentShader .setPrivate (true);
      fragmentShader .setName (name + "Fragment");
      fragmentShader .setOptions (options);
      fragmentShader .setup ();

      const shaderNode = new Shaders_ComposedShader (this .getPrivateScene ());
      shaderNode ._language = "GLSL";
      shaderNode ._parts .push (vertexShader);
      shaderNode ._parts .push (fragmentShader);
      shaderNode .setPrivate (true);
      shaderNode .setName (name);
      shaderNode .setUniformNames (uniformNames);
      shaderNode .setTransformFeedbackVaryings (transformFeedbackVaryings);
      shaderNode .setup ();

      return shaderNode;
   },
});

const X3DShadersContext_default_ = X3DShadersContext;
;

x_ite_Namespace .add ("X3DShadersContext", "x_ite/Browser/Shaders/X3DShadersContext", X3DShadersContext_default_);
/* harmony default export */ const Shaders_X3DShadersContext = (X3DShadersContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Shape/X3DShapeContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/









const
   _linetypeTextures          = Symbol (),
   _hatchStyleTextures        = Symbol (),
   _defaultAppearance         = Symbol (),
   _defaultPointProperties    = Symbol (),
   _defaultLineProperties     = Symbol (),
   _defaultMaterial           = Symbol (),
   _lineFillTextureProperties = Symbol (),
   _lineTransformShaderNode   = Symbol (),
   _lineTransformFeedback     = Symbol ();

function X3DShapeContext ()
{
   this [_hatchStyleTextures] = [ ];
}

Object .assign (X3DShapeContext .prototype,
{
   getDefaultAppearance ()
   {
      this [_defaultAppearance] = new Shape_Appearance (this .getPrivateScene ());
      this [_defaultAppearance] .setPrivate (true);
      this [_defaultAppearance] .setup ();

      this .getDefaultAppearance = function () { return this [_defaultAppearance]; };

      Object .defineProperty (this, "getDefaultAppearance", { enumerable: false });

      return this [_defaultAppearance];
   },
   getLineStippleScale ()
   {
      return 1 / (this .getPixelPerPoint () * 32); // 32px
   },
   getDefaultPointProperties ()
   {
      this [_defaultPointProperties] = new Shape_PointProperties (this .getPrivateScene ());
      this [_defaultPointProperties] .setPrivate (true);
      this [_defaultPointProperties] .setup ();

      this .getDefaultPointProperties = function () { return this [_defaultPointProperties]; };

      Object .defineProperty (this, "getDefaultPointProperties", { enumerable: false });

      return this [_defaultPointProperties];
   },
   getDefaultLineProperties ()
   {
      this [_defaultLineProperties] = new Shape_LineProperties (this .getPrivateScene ());
      this [_defaultLineProperties] ._applied = false;
      this [_defaultLineProperties] .setPrivate (true);
      this [_defaultLineProperties] .setup ();

      this .getDefaultLineProperties = function () { return this [_defaultLineProperties]; };

      Object .defineProperty (this, "getDefaultLineProperties", { enumerable: false });

      return this [_defaultLineProperties];
   },
   getDefaultMaterial ()
   {
      this [_defaultMaterial] = new Shape_UnlitMaterial (this .getPrivateScene ());
      this [_defaultMaterial] .setPrivate (true);
      this [_defaultMaterial] .setup ();

      this .getDefaultMaterial = function () { return this [_defaultMaterial]; };

      Object .defineProperty (this, "getDefaultMaterial", { enumerable: false });

      return this [_defaultMaterial];
   },
   getLinetypeTexture ()
   {
      this [_linetypeTextures] = new Texturing_ImageTexture (this .getPrivateScene ());
      this [_linetypeTextures] ._url [0]           = Networking_URLs .getLinetypeURL ();
      this [_linetypeTextures] ._textureProperties = this .getLineFillTextureProperties ();
      this [_linetypeTextures] .setPrivate (true);
      this [_linetypeTextures] .setup ();

      this .getLinetypeTexture = function () { return this [_linetypeTextures]; };

      Object .defineProperty (this, "getLinetypeTexture", { enumerable: false });

      return this [_linetypeTextures];
   },
   getHatchStyleTexture (index)
   {
      let hatchStyleTexture = this [_hatchStyleTextures] [index];

      if (hatchStyleTexture)
         return hatchStyleTexture;

      hatchStyleTexture = this [_hatchStyleTextures] [index] = new Texturing_ImageTexture (this .getPrivateScene ());

      hatchStyleTexture ._url [0]           = Networking_URLs .getHatchingURL (index);
      hatchStyleTexture ._textureProperties = this .getLineFillTextureProperties ();
      hatchStyleTexture .setPrivate (true);
      hatchStyleTexture .setup ();

      return hatchStyleTexture;
   },
   getLineFillTextureProperties ()
   {
      this [_lineFillTextureProperties] = new Texturing_TextureProperties (this .getPrivateScene ());
      this [_lineFillTextureProperties] ._minificationFilter  = "NEAREST_PIXEL";
      this [_lineFillTextureProperties] ._magnificationFilter = "NEAREST_PIXEL";
      this [_lineFillTextureProperties] ._textureCompression  = "DEFAULT";
      this [_lineFillTextureProperties] .setPrivate (true);
      this [_lineFillTextureProperties] .setup ();

      this .getLineFillTextureProperties = function () { return this [_lineFillTextureProperties]; };

      Object .defineProperty (this, "getLineFillTextureProperties", { enumerable: false });

      return this [_lineFillTextureProperties];
   },
   getLineTransformShader ()
   {
      const uniformNames = [
         "viewport",
         "modelViewProjectionMatrix",
         "invModelViewProjectionMatrix",
         "scale",
      ];

      const transformFeedbackVaryings = [
         "coordIndex0", "lineStipple0", "fogDepth0", "color0", "normal0", "vertex0",
         "coordIndex1", "lineStipple1", "fogDepth1", "color1", "normal1", "vertex1",
         "coordIndex2", "lineStipple2", "fogDepth2", "color2", "normal2", "vertex2",
      ];

      this [_lineTransformShaderNode] = this .createShader ("LineTransformShader", "LineTransform", "LineTransform", [ ], uniformNames, transformFeedbackVaryings);

      this .getLineTransformShader = function () { return this [_lineTransformShaderNode]; };

      Object .defineProperty (this, "getLineTransformShader", { enumerable: false });

      return this [_lineTransformShaderNode];
   },
   getLineTransformFeedback ()
   {
      const gl = this .getContext ();

      this [_lineTransformFeedback] = gl .createTransformFeedback ();

      this .getLineTransformFeedback = function () { return this [_lineTransformFeedback]; };

      Object .defineProperty (this, "getLineTransformFeedback", { enumerable: false });

      return this [_lineTransformFeedback];
   },
});

const X3DShapeContext_default_ = X3DShapeContext;
;

x_ite_Namespace .add ("X3DShapeContext", "x_ite/Browser/Shape/X3DShapeContext", X3DShapeContext_default_);
/* harmony default export */ const Shape_X3DShapeContext = (X3DShapeContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Sound/X3DSoundContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




const
   _audioContext        = Symbol (),
   _defaultPeriodicWave = Symbol ();

function X3DSoundContext ()
{
   this [_audioContext] = new AudioContext ();
}

Object .assign (X3DSoundContext .prototype,
{
   initialize ()
   {
      this .startAudioElement (this [_audioContext], "resume");
   },
   getAudioContext ()
   {
      return this [_audioContext];
   },
   getDefaultPeriodicWave ()
   {
      this [_defaultPeriodicWave] = new Sound_PeriodicWave (this .getPrivateScene ());
      this [_defaultPeriodicWave] .setPrivate (true);
      this [_defaultPeriodicWave] .setup ();

      this .getDefaultPeriodicWave = function () { return this [_defaultPeriodicWave]; };

      Object .defineProperty (this, "getDefaultPeriodicWave", { enumerable: false });

      return this [_defaultPeriodicWave];
   },
   startAudioElement (audioElement, functionName = "play")
   {
      const id = `X3DSoundContext-${Base_X3DObject .getId (audioElement)}`;

      const events = [
         "blur",
         "click",
         "contextmenu",
         "dblclick",
         "focus",
         "keydown",
         "keyup",
         "mousedown",
         "mouseup",
         "pointerup",
         "touchend",
      ]
      .map (event => `${event}.${id}`);

      this .getElement () .on (events .join (" "), event =>
      {
         audioElement [functionName] ()
            .then (() => this .getElement () .off (`.${id}`))
            .catch (Function .prototype);
      });
   },
});

const X3DSoundContext_default_ = X3DSoundContext;
;

x_ite_Namespace .add ("X3DSoundContext", "x_ite/Browser/Sound/X3DSoundContext", X3DSoundContext_default_);
/* harmony default export */ const Sound_X3DSoundContext = (X3DSoundContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Texturing/X3DTexturingContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/






const
   _maxTextures              = Symbol (),
   _combinedTextureUnits     = Symbol (),
   _texture2DUnits           = Symbol (),
   _texture3DUnits           = Symbol (),
   _textureCubeUnits         = Symbol (),
   _texture2DUnitIndex       = Symbol (),
   _texture3DUnitIndex       = Symbol (),
   _textureCubeUnitIndex     = Symbol (),
   _defaultTexture2D         = Symbol (),
   _defaultTexture3D         = Symbol (),
   _defaultTextureCube       = Symbol (),
   _defaultTextureProperties = Symbol (),
   _defaultTextureTransform  = Symbol (),
   _defaultTextureCoordinate = Symbol ();

function X3DTexturingContext ()
{
   const
      gl                   = this .getContext (),
      maxTextureImageUnits = gl .getParameter (gl .MAX_TEXTURE_IMAGE_UNITS);

   // console .log (gl .getParameter (gl .MAX_TEXTURE_IMAGE_UNITS))
   // console .log (gl .getParameter (gl .MAX_ARRAY_TEXTURE_LAYERS))

   this [_maxTextures] = maxTextureImageUnits > 8 ? 2 : 1;
}

Object .assign (X3DTexturingContext .prototype,
{
   initialize ()
   {
      const gl = this .getContext ();

      gl .pixelStorei (gl .UNPACK_ALIGNMENT, 1);

      // Get texture Units

      const maxCombinedTextureUnits = gl .getParameter (gl .MAX_COMBINED_TEXTURE_IMAGE_UNITS);

      this [_combinedTextureUnits] = [...Array (maxCombinedTextureUnits) .keys ()] .reverse ();
      this [_texture2DUnits]       = [this [_combinedTextureUnits] .pop ()];
      this [_texture3DUnits]       = [this [_combinedTextureUnits] .pop ()];
      this [_textureCubeUnits]     = [this [_combinedTextureUnits] .pop ()];

      // Default Texture 2D Unit

      const defaultData = new Uint8Array ([ 255, 255, 255, 255 ]);

      this [_defaultTexture2D] = gl .createTexture ();

      gl .activeTexture (gl .TEXTURE0 + this [_texture2DUnits] [0]);
      gl .bindTexture (gl .TEXTURE_2D, this [_defaultTexture2D]);
      gl .texImage2D (gl .TEXTURE_2D, 0, gl .RGBA, 1, 1, 0, gl .RGBA, gl .UNSIGNED_BYTE, defaultData);

      // Default Texture 3D Unit

      if (gl .getVersion () >= 2)
      {
         this [_defaultTexture3D] = gl .createTexture ();

         gl .activeTexture (gl .TEXTURE0 + this [_texture3DUnits] [0]);
         gl .bindTexture (gl .TEXTURE_3D, this [_defaultTexture3D]);
         gl .texImage3D (gl .TEXTURE_3D, 0, gl .RGBA, 1, 1, 1, 0, gl .RGBA, gl .UNSIGNED_BYTE, defaultData);
      }

      // Default Texture Cube Unit

      this [_defaultTextureCube] = gl .createTexture ();

      gl .activeTexture (gl .TEXTURE0 + this [_textureCubeUnits] [0]);
      gl .bindTexture (gl .TEXTURE_CUBE_MAP, this [_defaultTextureCube]);
      gl .texImage2D (gl .TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl .RGBA, 1, 1, 0, gl .RGBA, gl .UNSIGNED_BYTE, defaultData);
      gl .texImage2D (gl .TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl .RGBA, 1, 1, 0, gl .RGBA, gl .UNSIGNED_BYTE, defaultData);
      gl .texImage2D (gl .TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl .RGBA, 1, 1, 0, gl .RGBA, gl .UNSIGNED_BYTE, defaultData);
      gl .texImage2D (gl .TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl .RGBA, 1, 1, 0, gl .RGBA, gl .UNSIGNED_BYTE, defaultData);
      gl .texImage2D (gl .TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl .RGBA, 1, 1, 0, gl .RGBA, gl .UNSIGNED_BYTE, defaultData);
      gl .texImage2D (gl .TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl .RGBA, 1, 1, 0, gl .RGBA, gl .UNSIGNED_BYTE, defaultData);

      // Init texture units.

      this .resetTextureUnits ();

      // Set texture quality.

      this .setTextureQuality (this .getBrowserOptions () .getTextureQuality ());
   },
   getMaxTextures ()
   {
      return this [_maxTextures];
   },
   getMaxTextureTransforms ()
   {
      return 4;
   },
   getMaxTexCoords ()
   {
      return 4;
   },
   getMinTextureSize ()
   {
      return 16;
   },
   getMaxTextureSize ()
   {
      const gl = this .getContext ();

      return gl .getParameter (gl .MAX_TEXTURE_SIZE);
   },
   getMaxCombinedTextureUnits ()
   {
      const gl = this .getContext ();

      return gl .getParameter (gl .MAX_COMBINED_TEXTURE_IMAGE_UNITS)
   },
   popTexture2DUnit ()
   {
      if (this [_texture2DUnitIndex] > 0)
      {
         -- this [_texture2DUnitIndex];

         return this [_texture2DUnits] .pop ();
      }
      else
      {
         return this [_combinedTextureUnits] .pop ();
      }
   },
   pushTexture2DUnit (textureUnit)
   {
      if (textureUnit === undefined)
         return;

      ++ this [_texture2DUnitIndex];

      this [_texture2DUnits] .push (textureUnit);
   },
   getTexture2DUnit ()
   {
      if (this [_texture2DUnitIndex] > 0)
         return this [_texture2DUnits] [-- this [_texture2DUnitIndex]];

      const textureUnit = this [_combinedTextureUnits] .pop ();

      if (textureUnit !== undefined)
         this [_texture2DUnits] .push (textureUnit);

      return textureUnit;
   },
   getTexture3DUnit ()
   {
      if (this [_texture3DUnitIndex] > 0)
         return this [_texture3DUnits] [-- this [_texture3DUnitIndex]];

      const textureUnit = this [_combinedTextureUnits] .pop ();

      if (textureUnit !== undefined)
         this [_texture3DUnits] .push (textureUnit);

      return textureUnit;
   },
   getTextureCubeUnit ()
   {
      if (this [_textureCubeUnitIndex] > 0)
         return this [_textureCubeUnits] [-- this [_textureCubeUnitIndex]];

      const textureUnit = this [_combinedTextureUnits] .pop ();

      if (textureUnit !== undefined)
         this [_textureCubeUnits] .push (textureUnit);

      return textureUnit;
   },
   getTextureUnit (textureType)
   {
      switch (textureType)
      {
         case 2: return this .getTexture2DUnit ();
         case 3: return this .getTexture3DUnit ();
         case 4: return this .getTextureCubeUnit ();
      }
   },
   resetTextureUnits ()
   {
      this [_texture2DUnitIndex]   = this [_texture2DUnits]   .length;
      this [_texture3DUnitIndex]   = this [_texture3DUnits]   .length;
      this [_textureCubeUnitIndex] = this [_textureCubeUnits] .length;
   },
   getDefaultTexture2DUnit ()
   {
      return this [_texture2DUnits] [0];
   },
   getDefaultTexture3DUnit ()
   {
      return this [_texture3DUnits] [0];
   },
   getDefaultTextureCubeUnit ()
   {
      return this [_textureCubeUnits] [0];
   },
   getTextureMemory ()
   {
      return NaN;
   },
   getDefaultTextureProperties ()
   {
      this [_defaultTextureProperties] = new Texturing_TextureProperties (this .getPrivateScene ());
      this [_defaultTextureProperties] ._magnificationFilter = "NICEST";
      this [_defaultTextureProperties] ._minificationFilter  = "NEAREST_PIXEL_AVG_MIPMAP";
      this [_defaultTextureProperties] ._generateMipMaps     = true;
      this [_defaultTextureProperties] ._textureCompression  = "NICEST";

      this [_defaultTextureProperties] .setup ();

      this .getDefaultTextureProperties = function () { return this [_defaultTextureProperties]; };

      Object .defineProperty (this, "getDefaultTextureProperties", { enumerable: false });

      return this [_defaultTextureProperties];
   },
   getDefaultTextureTransform ()
   {
      this [_defaultTextureTransform] = new Texturing_TextureTransform (this .getPrivateScene ());
      this [_defaultTextureTransform] .setPrivate (true);
      this [_defaultTextureTransform] .setup ();

      this .getDefaultTextureTransform = function () { return this [_defaultTextureTransform]; };

      Object .defineProperty (this, "getDefaultTextureTransform", { enumerable: false });

      return this [_defaultTextureTransform];
   },
   getDefaultTextureCoordinate ()
   {
      this [_defaultTextureCoordinate] = new Texturing_TextureCoordinate (this .getPrivateScene ());
      this [_defaultTextureCoordinate] .setPrivate (true);
      this [_defaultTextureCoordinate] .setup ();

      this .getDefaultTextureCoordinate = function () { return this [_defaultTextureCoordinate]; };

      Object .defineProperty (this, "getDefaultTextureCoordinate", { enumerable: false });

      return this [_defaultTextureCoordinate];
   },
   setTextureQuality (textureQuality)
   {
      const textureProperties = this .getDefaultTextureProperties ();

      switch (textureQuality)
      {
         case Core_TextureQuality .LOW:
         {
            textureProperties ._magnificationFilter = "AVG_PIXEL";
            textureProperties ._minificationFilter  = "AVG_PIXEL";
            textureProperties ._textureCompression  = "FASTEST";
            textureProperties ._generateMipMaps     = true;

            //glHint (GL_GENERATE_MIPMAP_HINT,        GL_FASTEST);
            //glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
            break;
         }
         case Core_TextureQuality .MEDIUM:
         {
            textureProperties ._magnificationFilter = "NICEST";
            textureProperties ._minificationFilter  = "NEAREST_PIXEL_AVG_MIPMAP";
            textureProperties ._textureCompression  = "NICEST";
            textureProperties ._generateMipMaps     = true;

            //glHint (GL_GENERATE_MIPMAP_HINT,        GL_FASTEST);
            //glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
            break;
         }
         case Core_TextureQuality .HIGH:
         {
            textureProperties ._magnificationFilter = "NICEST";
            textureProperties ._minificationFilter  = "NICEST";
            textureProperties ._textureCompression  = "NICEST";
            textureProperties ._generateMipMaps     = true;

            //glHint (GL_GENERATE_MIPMAP_HINT,        GL_NICEST);
            //glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
            break;
         }
      }
   },
});

const X3DTexturingContext_default_ = X3DTexturingContext;
;

x_ite_Namespace .add ("X3DTexturingContext", "x_ite/Browser/Texturing/X3DTexturingContext", X3DTexturingContext_default_);
/* harmony default export */ const Texturing_X3DTexturingContext = (X3DTexturingContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/Time/X3DTimeContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



const
   _currentTime      = Symbol (),
   _currentFrameRate = Symbol (),
   _currentPosition  = Symbol (),
   _currentSpeed     = Symbol ();

function X3DTimeContext ()
{
   this [_currentTime]      = Date .now () / 1000;
   this [_currentFrameRate] = 60;
   this [_currentPosition]  = new Numbers_Vector3 (0, 0, 0);
   this [_currentSpeed]     = 0;
}

Object .assign (X3DTimeContext .prototype,
{
   getCurrentTime ()
   {
      return this [_currentTime];
   },
   getCurrentFrameRate ()
   {
      return this [_currentFrameRate];
   },
   getCurrentSpeed ()
   {
      return this [_currentSpeed];
   },
   advanceTime: (() =>
   {
      const lastPosition = new Numbers_Vector3 (0, 0, 0);

      return function ()
      {
         const
            time     = Date .now () / 1000,
            interval = time - this [_currentTime];

         this [_currentTime]      = time;
         this [_currentFrameRate] = interval ? 1 / interval : 60;

         if (this .getWorld () && this .getActiveLayer ())
         {
            const cameraSpaceMatrix = this .getActiveLayer () .getViewpoint () .getCameraSpaceMatrix ();

            lastPosition .assign (this [_currentPosition]);
            this [_currentPosition] .set (cameraSpaceMatrix [12], cameraSpaceMatrix [13], cameraSpaceMatrix [14]);

            this [_currentSpeed] = lastPosition .subtract (this [_currentPosition]) .magnitude () * this [_currentFrameRate];
         }
         else
         {
            this [_currentSpeed] = 0;
         }
      };
   })(),
});

const X3DTimeContext_default_ = X3DTimeContext;
;

x_ite_Namespace .add ("X3DTimeContext", "x_ite/Browser/Time/X3DTimeContext", X3DTimeContext_default_);
/* harmony default export */ const Time_X3DTimeContext = (X3DTimeContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Routing/X3DRoutingContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

const
   _taintedFields     = Symbol (),
   _taintedFieldsTemp = Symbol (),
   _taintedNodes      = Symbol (),
   _taintedNodesTemp  = Symbol ();

function X3DRoutingContext ()
{
   this [_taintedFields]     = [ ];
   this [_taintedFieldsTemp] = [ ];
   this [_taintedNodes]      = [ ];
   this [_taintedNodesTemp]  = [ ];
}

Object .assign (X3DRoutingContext .prototype,
{
   initialize () { },
   addTaintedField (field, event)
   {
      this [_taintedFields] .push (field, event);
   },
   addTaintedNode (node)
   {
      this [_taintedNodes] .push (node);
   },
   [Symbol .for ("X_ITE.X3DRoutingContext.processEvents")] ()
   {
      do
      {
         // Process field events
         do
         {
            const taintedFields = this [_taintedFields];

            // Swap tainted fields.
            this [_taintedFields]         = this [_taintedFieldsTemp];
            this [_taintedFields] .length = 0;

            for (let i = 0, length = taintedFields .length; i < length; i += 2)
               taintedFields [i] .processEvent (taintedFields [i + 1]);

            // Don't know why this must be done after the for loop, otherwise a fatal error could be thrown.
            this [_taintedFieldsTemp] = taintedFields;
         }
         while (this [_taintedFields] .length);

         // Process node events
         do
         {
            const taintedNodes = this [_taintedNodes];

            // Swap tainted nodes.
            this [_taintedNodes]         = this [_taintedNodesTemp];
            this [_taintedNodes] .length = 0;

            for (const taintedNode of taintedNodes)
               taintedNode .processEvent ();

            // Don't know why this must be done after the for loop, otherwise a fatal error could be thrown.
            this [_taintedNodesTemp] = taintedNodes;
         }
         while (! this [_taintedFields] .length && this [_taintedNodes] .length);
      }
      while (this [_taintedFields] .length);
   },
   dispose () { },
});

const X3DRoutingContext_default_ = X3DRoutingContext;
;

x_ite_Namespace .add ("X3DRoutingContext", "x_ite/Routing/X3DRoutingContext", X3DRoutingContext_default_);
/* harmony default export */ const Routing_X3DRoutingContext = (X3DRoutingContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Configuration/AbstractNodesArray.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/




function AbstractNodesArray (values = [ ])
{
   return Base_X3DInfoArray .call (this, Array .from (values, value => [value .typeName, value]), Function);
}

Object .assign (Object .setPrototypeOf (AbstractNodesArray .prototype, Base_X3DInfoArray .prototype),
{
   add (typeName, AbstractNode)
   {
      Base_X3DConstants .addNode (AbstractNode);

      Base_X3DInfoArray .prototype .add .call (this, typeName, AbstractNode);
   },
});

for (const key of Object .keys (AbstractNodesArray .prototype))
   Object .defineProperty (AbstractNodesArray .prototype, key, { enumerable: false });

Object .defineProperties (AbstractNodesArray,
{
   typeName:
   {
      value: "AbstractNodesArray",
      enumerable: true,
   },
});

const AbstractNodesArray_default_ = AbstractNodesArray;
;

x_ite_Namespace .add ("AbstractNodesArray", "x_ite/Configuration/AbstractNodesArray", AbstractNodesArray_default_);
/* harmony default export */ const Configuration_AbstractNodesArray = (AbstractNodesArray_default_);
;// CONCATENATED MODULE: ./src/x_ite/Configuration/AbstractNodes.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



const AbstractNodes_default_ = new Configuration_AbstractNodesArray ();
;

x_ite_Namespace .add ("AbstractNodes", "x_ite/Configuration/AbstractNodes", AbstractNodes_default_);
/* harmony default export */ const AbstractNodes = (AbstractNodes_default_);
;// CONCATENATED MODULE: ./src/x_ite/Configuration/ConcreteNodesArray.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function ConcreteNodesArray (values = [ ])
{
   return Base_X3DInfoArray .call (this, Array .from (values, value => [value .typeName, value]), Function);
}

Object .assign (Object .setPrototypeOf (ConcreteNodesArray .prototype, Base_X3DInfoArray .prototype),
{
   add (typeName, ConcreteNode)
   {
      Base_X3DConstants .addNode (ConcreteNode);
      Parser_HTMLSupport .addConcreteNode (ConcreteNode);

      Base_X3DInfoArray .prototype .add .call (this, typeName, ConcreteNode);
   },
   update (oldTypeName, typeName, ConcreteNode)
   {
      Base_X3DConstants .addNode (ConcreteNode);
      Parser_HTMLSupport .addConcreteNode (ConcreteNode);

      Base_X3DInfoArray .prototype .update .call (this, oldTypeName, typeName, ConcreteNode);
   },
});

for (const key of Object .keys (ConcreteNodesArray .prototype))
   Object .defineProperty (ConcreteNodesArray .prototype, key, { enumerable: false });

Object .defineProperties (ConcreteNodesArray,
{
   typeName:
   {
      value: "ConcreteNodesArray",
      enumerable: true,
   },
});

const ConcreteNodesArray_default_ = ConcreteNodesArray;
;

x_ite_Namespace .add ("ConcreteNodesArray", "x_ite/Configuration/ConcreteNodesArray", ConcreteNodesArray_default_);
/* harmony default export */ const Configuration_ConcreteNodesArray = (ConcreteNodesArray_default_);
;// CONCATENATED MODULE: ./src/x_ite/Configuration/ConcreteNodes.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



const ConcreteNodes_default_ = new Configuration_ConcreteNodesArray ();
;

x_ite_Namespace .add ("ConcreteNodes", "x_ite/Configuration/ConcreteNodes", ConcreteNodes_default_);
/* harmony default export */ const ConcreteNodes = (ConcreteNodes_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/X3DBrowserContext.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





























const
   _world           = Symbol (),
   _changedTime     = Symbol (),
   _limitFrameRate  = Symbol (),
   _traverse        = Symbol (),
   _renderCallback  = Symbol (),
   _previousTime    = Symbol (),
   _systemTime      = Symbol (),
   _browserTime     = Symbol (),
   _cameraTime      = Symbol (),
   _collisionTime   = Symbol (),
   _displayTime     = Symbol (),
   _processEvents   = Symbol .for ("X_ITE.X3DRoutingContext.processEvents");

const
   browsers        = new Set (),
   browserContexts = [ ];

function X3DBrowserContext (element)
{
   Base_X3DBaseNode                    .call (this, this);
   Routing_X3DRoutingContext              .call (this);
   Scripting_X3DScriptingContext            .call (this);
   Core_X3DCoreContext                 .call (this, element);
   Networking_X3DNetworkingContext           .call (this);
   Texturing_X3DTexturingContext            .call (this);
   Shaders_X3DShadersContext              .call (this);
   Rendering_X3DRenderingContext            .call (this);
   Shape_X3DShapeContext                .call (this);
   Grouping_X3DGroupingContext             .call (this);
   Geometry3D_X3DGeometry3DContext           .call (this);
   PointingDeviceSensor_X3DPointingDeviceSensorContext .call (this);
   Navigation_X3DNavigationContext           .call (this);
   Layering_X3DLayeringContext             .call (this);
   EnvironmentalEffects_X3DEnvironmentalEffectsContext .call (this);
   Lighting_X3DLightingContext             .call (this);
   Picking_X3DPickingContext              .call (this);
   Sound_X3DSoundContext                .call (this);
   Time_X3DTimeContext                 .call (this);

   browsers .add (this);

   for (const browserContext of browserContexts)
      browserContext .call (this);

   this .addChildObjects (Base_X3DConstants .outputOnly, "initialized",    new Fields_SFTime (),
                          Base_X3DConstants .outputOnly, "shutdown",       new Fields_SFTime (),
                          Base_X3DConstants .outputOnly, "prepareEvents",  new Fields_SFTime (),
                          Base_X3DConstants .outputOnly, "timeEvents",     new Fields_SFTime (),
                          Base_X3DConstants .outputOnly, "sensorEvents",   new Fields_SFTime (),
                          Base_X3DConstants .outputOnly, "displayEvents",  new Fields_SFTime (),
                          Base_X3DConstants .outputOnly, "finishedEvents", new Fields_SFTime ());

   this [_changedTime]    = 0;
   this [_previousTime]   = 0;
   this [_renderCallback] = this [_traverse] .bind (this);
   this [_systemTime]     = new Time_StopWatch ();
   this [_browserTime]    = new Time_StopWatch ();
   this [_cameraTime]     = new Time_StopWatch ();
   this [_collisionTime]  = new Time_StopWatch ();
   this [_displayTime]    = new Time_StopWatch ();
};

Object .assign (Object .setPrototypeOf (X3DBrowserContext .prototype, Base_X3DBaseNode .prototype),
   Core_X3DCoreContext .prototype,
   EnvironmentalEffects_X3DEnvironmentalEffectsContext .prototype,
   Geometry3D_X3DGeometry3DContext .prototype,
   Grouping_X3DGroupingContext .prototype,
   Layering_X3DLayeringContext .prototype,
   Lighting_X3DLightingContext .prototype,
   Navigation_X3DNavigationContext .prototype,
   Networking_X3DNetworkingContext .prototype,
   Picking_X3DPickingContext .prototype,
   PointingDeviceSensor_X3DPointingDeviceSensorContext .prototype,
   Rendering_X3DRenderingContext .prototype,
   Routing_X3DRoutingContext .prototype,
   Scripting_X3DScriptingContext .prototype,
   Shaders_X3DShadersContext .prototype,
   Shape_X3DShapeContext .prototype,
   Sound_X3DSoundContext .prototype,
   Texturing_X3DTexturingContext .prototype,
   Time_X3DTimeContext .prototype,
{
   initialize ()
   {
      Base_X3DBaseNode                    .prototype .initialize ?.call (this);
      Routing_X3DRoutingContext              .prototype .initialize ?.call (this);
      Scripting_X3DScriptingContext            .prototype .initialize ?.call (this);
      Core_X3DCoreContext                 .prototype .initialize ?.call (this);
      Networking_X3DNetworkingContext           .prototype .initialize ?.call (this);
      Texturing_X3DTexturingContext            .prototype .initialize ?.call (this);
      Shaders_X3DShadersContext              .prototype .initialize ?.call (this);
      Rendering_X3DRenderingContext            .prototype .initialize ?.call (this);
      Shape_X3DShapeContext                .prototype .initialize ?.call (this);
      Grouping_X3DGroupingContext             .prototype .initialize ?.call (this);
      Geometry3D_X3DGeometry3DContext           .prototype .initialize ?.call (this);
      PointingDeviceSensor_X3DPointingDeviceSensorContext .prototype .initialize ?.call (this);
      Navigation_X3DNavigationContext           .prototype .initialize ?.call (this);
      Layering_X3DLayeringContext             .prototype .initialize ?.call (this);
      EnvironmentalEffects_X3DEnvironmentalEffectsContext .prototype .initialize ?.call (this);
      Lighting_X3DLightingContext             .prototype .initialize ?.call (this);
      Picking_X3DPickingContext              .prototype .initialize ?.call (this);
      Sound_X3DSoundContext                .prototype .initialize ?.call (this);
      Time_X3DTimeContext                 .prototype .initialize ?.call (this);

      for (const browserContext of browserContexts)
         browserContext .prototype .initialize ?.call (this);
   },
   initialized ()
   {
      return this ._initialized;
   },
   shutdown ()
   {
      return this ._shutdown;
   },
   prepareEvents ()
   {
      return this ._prepareEvents;
   },
   timeEvents ()
   {
      return this ._timeEvents;
   },
   sensorEvents ()
   {
      return this ._sensorEvents;
   },
   displayEvents ()
   {
      return this ._displayEvents;
   },
   finishedEvents ()
   {
      return this ._finishedEvents;
   },
   getBrowser ()
   {
      return this;
   },
   getWorld ()
   {
      return this [_world];
   },
   getExecutionContext ()
   {
      return this [_world] .getExecutionContext ();
   },
   setExecutionContext (executionContext)
   {
      this [_world] = new Execution_X3DWorld (executionContext);
      this [_world] .setup ();
   },
   addBrowserEvent ()
   {
      if (this [_changedTime] === this .getCurrentTime ())
         return;

      this [_changedTime] = this .getCurrentTime ();

      requestAnimationFrame (this [_renderCallback]);
   },
   [_limitFrameRate] (now)
   {
      if (now === this [_previousTime])
      {
         requestAnimationFrame (this [_renderCallback]);

         return true;
      }
      else
      {
         this [_previousTime] = now;

         return false;
      }
   },
   [_traverse] (now)
   {
      // Limit frame rate.

      if (this [_limitFrameRate] (now))
         return;

      // Start

      this [_systemTime] .stop ();
      this [_browserTime] .start ();

      // time

      this .advanceTime ();

      // Events

      this .addTaintedField (this ._prepareEvents);
      this [_processEvents] ();

      this .addTaintedField (this ._timeEvents);
      this [_processEvents] ();

      // Camera

      this [_cameraTime] .start ();
      this [_world] .traverse (Rendering_TraverseType .CAMERA);
      this [_cameraTime] .stop ();

      // Collision

      this [_collisionTime] .start ();

      if (this .getCollisionCount ())
         this [_world] .traverse (Rendering_TraverseType .COLLISION);

      this [_collisionTime] .stop ();

      // Events

      this .addTaintedField (this ._sensorEvents);
      this [_processEvents] ();

      // Display

      this [_displayTime] .start ()

      this .addTaintedField (this ._displayEvents);
      this [_processEvents] ();

      this .getFrameBuffer () .bind ();

      this [_world] .traverse (Rendering_TraverseType .DISPLAY);

      this .addTaintedField (this ._finishedEvents);
      this [_processEvents] ();

      this .getFrameBuffer () .blit ();
      this .getFrameBuffer () .unbind ();

      this [_displayTime] .stop ();

      // Finish

      this [_browserTime] .stop ();
      this [_systemTime] .start ();
   },
   getSystemTime ()
   {
      return this [_systemTime];
   },
   getBrowserTime ()
   {
      return this [_browserTime];
   },
   getCameraTime ()
   {
      return this [_cameraTime];
   },
   getCollisionTime ()
   {
      return this [_collisionTime];
   },
   getDisplayTime ()
   {
      return this [_displayTime];
   },
   dispose ()
   {
      browsers .delete (this);

      for (const browserContext of browserContexts)
         browserContext .prototype .dispose ?.call (this);

      Time_X3DTimeContext                 .prototype .dispose ?.call (this);
      Sound_X3DSoundContext                .prototype .dispose ?.call (this);
      Picking_X3DPickingContext              .prototype .dispose ?.call (this);
      Lighting_X3DLightingContext             .prototype .dispose ?.call (this);
      EnvironmentalEffects_X3DEnvironmentalEffectsContext .prototype .dispose ?.call (this);
      Layering_X3DLayeringContext             .prototype .dispose ?.call (this);
      Navigation_X3DNavigationContext           .prototype .dispose ?.call (this);
      PointingDeviceSensor_X3DPointingDeviceSensorContext .prototype .dispose ?.call (this);
      Geometry3D_X3DGeometry3DContext           .prototype .dispose ?.call (this);
      Grouping_X3DGroupingContext             .prototype .dispose ?.call (this);
      Shape_X3DShapeContext                .prototype .dispose ?.call (this);
      Rendering_X3DRenderingContext            .prototype .dispose ?.call (this);
      Shaders_X3DShadersContext              .prototype .dispose ?.call (this);
      Texturing_X3DTexturingContext            .prototype .dispose ?.call (this);
      Networking_X3DNetworkingContext           .prototype .dispose ?.call (this);
      Core_X3DCoreContext                 .prototype .dispose ?.call (this);
      Scripting_X3DScriptingContext            .prototype .dispose ?.call (this);
      Routing_X3DRoutingContext              .prototype .dispose ?.call (this);
      Base_X3DBaseNode                    .prototype .dispose ?.call (this);
   },
});

for (const key of Object .keys (X3DBrowserContext .prototype))
   Object .defineProperty (X3DBrowserContext .prototype, key, { enumerable: false });

Object .assign (X3DBrowserContext,
{
   addComponent ({ name, concreteNodes, abstractNodes, browserContext, external })
   {
      if (concreteNodes)
      {
         for (const ConcreteNode of concreteNodes)
            ConcreteNodes .add (ConcreteNode .typeName, ConcreteNode);
      }

      if (abstractNodes)
      {
         for (const AbstractNode of abstractNodes)
            AbstractNodes .add (AbstractNode .typeName, AbstractNode);
      }

      if (browserContext)
      {
         browserContexts .push (browserContext);

         const keys = Object .keys (browserContext .prototype)
            .filter (k => !k .match (/^(?:initialize|dispose)$/))
            .concat (Object .getOwnPropertySymbols (browserContext .prototype));

         for (const key of keys)
         {
            Object .defineProperty (X3DBrowserContext .prototype, key,
            {
               value: browserContext .prototype [key],
               writable: true,
            });
         }
      }

      for (const browser of browsers)
      {
         if (concreteNodes)
         {
            for (const ConcreteNode of concreteNodes)
               browser .addConcreteNode (ConcreteNode);
         }

         if (abstractNodes)
         {
            for (const AbstractNode of abstractNodes)
               browser .addAbstractNode (AbstractNode);
         }

         if (browserContext)
         {
            browserContext .call (browser);
            browserContext .prototype .initialize ?.call (browser);

            // Process events from context creation. This will setup nodes like
            // geometry option nodes before any node is created.
            browser [_processEvents] ();
         }
      }

      if (external && DEVELOPMENT)
         console .info (`Done loading external component '${name}'.`);
   },
});

const X3DBrowserContext_default_ = X3DBrowserContext;
;

x_ite_Namespace .add ("X3DBrowserContext", "x_ite/Browser/X3DBrowserContext", X3DBrowserContext_default_);
/* harmony default export */ const Browser_X3DBrowserContext = (X3DBrowserContext_default_);
;// CONCATENATED MODULE: ./src/x_ite/Components.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





















let external = false;

const Components =
{
   add ({ name, concreteNodes, abstractNodes, browserContext })
   {
      Browser_X3DBrowserContext .addComponent ({ name, concreteNodes, abstractNodes, browserContext, external });
   },
};

Components .add (Core);
Components .add (EnvironmentalEffects);
Components .add (EnvironmentalSensor);
Components .add (Followers);
Components .add (Geometry3D);
Components .add (Grouping);
Components .add (Interpolation);
Components .add (Layering);
Components .add (Lighting);
Components .add (Navigation);
Components .add (Networking);
Components .add (PointingDeviceSensor);
Components .add (Rendering);
Components .add (Shaders);
Components .add (Components_Shape);
Components .add (Components_Sound);
Components .add (Texturing);
Components .add (Time);

external = true;

const Components_default_ = Components;
;

x_ite_Namespace .add ("Components", "x_ite/Components", Components_default_);
/* harmony default export */ const x_ite_Components = ((/* unused pure expression or super */ null && (Components_default_)));
;// CONCATENATED MODULE: ./src/x_ite/Browser/DOMIntegration.js
/* provided dependency */ var DOMIntegration_$ = __webpack_require__(659);
/*******************************************************************************
 * MIT License
 *
 * Copyright (c) 2016 Andreas Plesch
 * taken from https://github.com/andreasplesch/x_ite_dom.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 ******************************************************************************/





class DOMIntegration
{
	constructor (browser)
	{
		this .browser        = browser;
		this .rootElement    = undefined;
		this .canvasObserver = new MutationObserver (() => this .processCanvasMutation (browser));

		this .canvasObserver .observe (browser .getElement () [0], {
			childList: true,
		});

		this .processCanvasMutation (browser)
	}

	processCanvasMutation (browser)
	{
		this .processRootElement (browser, browser .getElement () .children ("X3D") .get (-1));
	}

	async processRootElement (browser, rootElement)
	{
		try
		{
			if (rootElement === this .rootElement)
				return;

			this .rootElement = rootElement;

			if (rootElement)
			{
				// Display splash screen.

				browser .setBrowserLoading (true);
				browser .addLoadingObject (this);

				// Now also attached node property to each node element.

				const scene = browser .createScene ();

				this .parser = new Parser_XMLParser (scene);

				this .parser .setInput (rootElement);

				await new Promise (this .parser .parseIntoScene .bind (this .parser));

				browser .replaceWorld (scene);

				// Create an observer instance.

				this .observer = new MutationObserver (mutations =>
				{
					for (const mutation of mutations)
						this .processMutation (mutation);
				});

				// Start observing, also catches inlined Inline elements.

				this .observer .observe (rootElement, {
					attributes: true,
					childList: true,
					characterData: false,
					subtree: true,
					attributeOldValue: true,
				});

				// Add Inline elements from initial scene, and connect to node events.

				this .processInlineElements (rootElement);
				this .addEventDispatchersAll (rootElement);

				browser .removeLoadingObject (this);
			}
			else
			{
				browser .replaceWorld (null);
			}
		}
		catch (error)
		{
			console .error ("Error importing document:", error);
		}
	}

	processMutation (mutation)
	{
		switch (mutation .type)
		{
			case "attributes":
			{
				this .processAttribute (mutation, mutation .target);
				break;
			}
			case "childList":
			{
				for (const node of mutation .addedNodes)
					this .processAddedNode (node);

				for (const node of mutation .removedNodes)
					this .processRemovedNode (node);

				break;
			}
		}
	}

	processAttribute (mutation, element)
	{
		const
			parser = this .parser,
			node   = DOMIntegration_$.data (element, "node");

		if (node)
		{
			const
				attributeName = mutation .attributeName,
				attribute     = element .attributes .getNamedItem (attributeName);

			parser .nodeAttribute (attribute, node);
		}
		else
		{
			// Is an attribute of non-node child such as fieldValue (or ROUTE).

			const
				parentNode = element .parentNode,
			 	node       = DOMIntegration_$.data (parentNode, "node");

			if (node)
			{
				parser .pushExecutionContext (node .getExecutionContext ());
				parser .pushParent (node);
				parser .childElement (element);
				parser .popParent ();
				parser .popExecutionContext ();
			}
		}
	}

	processAddedNode (element)
	{
		// Only process element nodes.

		if (element .nodeType !== Node .ELEMENT_NODE)
			return;

		if (element .nodeName === "X3D")
			return;

		if (DOMIntegration_$.data (element, "node"))
			return;

		const
			parentNode = element .parentNode,
			parser     = this .parser;

		if (parentNode .nodeName .match (/^(?:Scene|SCENE)$/))
		{
			// Root scene or Inline scene.

			const scene = DOMIntegration_$.data (parentNode, "node");

			parser .pushExecutionContext (scene);
			parser .childElement (element);
			parser .popExecutionContext ();
		}
		else if (DOMIntegration_$.data (parentNode, "node"))
		{
			// Use parent's scene if non-root, works for Inline.

			const
				node             = DOMIntegration_$.data (parentNode, "node"),
				executionContext = node .getExecutionContext ();

			parser .pushExecutionContext (executionContext);
			parser .pushParent (node);
			parser .childElement (element);
			parser .popParent ();
			parser .popExecutionContext ();
		}
		else
		{
			const scene = this .browser .currentScene;

			parser .pushExecutionContext (scene);
			parser .childElement (element);
			parser .popExecutionContext ();
		}

		// Now after creating nodes need to look again for Inline elements.

		this .processInlineElements (element);

		// Then attach event dispatchers.

		this .addEventDispatchers (element);
		this .addEventDispatchersAll (element);
	}

	processRemovedNode (element)
	{
		// Works also for root nodes, as it has to be, since scene .rootNodes is effectively a MFNode in x-ite.
		// Also removes ROUTE elements.

		const node = DOMIntegration_$.data (element, "node");

		if (!node)
			return;

		node .dispose ();

		DOMIntegration_$.data (element, "node", null);
	}

	processInlineElements (element)
	{
		if (element .nodeName .match (/^(?:Inline|INLINE)$/))
			this .processInlineElement (element);

		for (const inlineElement of element .querySelectorAll ("Inline"))
			this .processInlineElement (inlineElement);
	}

	processInlineElement (element)
	{
		const node = DOMIntegration_$.data (element, "node");

		if (!node)
			return;

		node ._loadState .addInterest ("appendInlineChildElement", this, element);

		this .appendInlineChildElement (element);
	}

	appendInlineChildElement (element)
	{
		const node = DOMIntegration_$.data (element, "node");

		switch (node .checkLoadState ())
		{
			case Base_X3DConstants .NOT_STARTED_STATE:
			case Base_X3DConstants .FAILED_STATE:
			{
				// Remove all child nodes.

				while (element .firstChild)
					element .removeChild (element .lastChild);

				break;
			}
			case Base_X3DConstants .COMPLETE_STATE:
			{
				// Remove all child nodes.

				while (element .firstChild)
					element .removeChild (element .lastChild);

				// Add scene as child node of Inline element.

				const X3DElement = DOMIntegration_$.data (node .getInternalScene (), "X3D");

				if (X3DElement)
					element .appendChild (X3DElement);

				// Add Inline elements, and connect to node events.

				this .processInlineElements (X3DElement);
				this .addEventDispatchersAll (X3DElement);

				break;
			}
		}

		switch (node .checkLoadState ())
		{
			case Base_X3DConstants .COMPLETE_STATE:
			{
				const event = new CustomEvent ("load",
				{
					detail: { node: Fields_SFNodeCache .get (node) },
				});

				element .dispatchEvent (event);
				break;
			}
			case Base_X3DConstants .FAILED_STATE:
			{
				const event = new CustomEvent ("error",
				{
					detail: { node: Fields_SFNodeCache .get (node) },
				});

				element .dispatchEvent (event);
				break;
			}
		}
	}

	addEventDispatchersAll (element)
	{
		const childElements = element .querySelectorAll ("*");

		for (const childElement of childElements)
			this .addEventDispatchers (childElement);
	}

	addEventDispatchers (element)
	{
		// Check for USE nodes; they do not emit events.

		if (element .nodeName === "ROUTE")
			return;

		const node = DOMIntegration_$.data (element, "node");

		if (!node)
			return;

		for (const field of node .getPredefinedFields ())
			this .bindFieldCallback (field, element);

		for (const field of node .getUserDefinedFields ())
			this .bindFieldCallback (field, element);
	}

	bindFieldCallback (field, element)
	{
		if (!field .isOutput ())
			return;

		field .addInterest ("fieldCallback", this, element);
	}

	fieldCallback (element, field)
	{
		const node = DOMIntegration_$.data (element, "node");

		if (!node)
			return;

		const event = new CustomEvent (field .getName (),
		{
			detail: {
				node: Fields_SFNodeCache .get (node),
				value: field .valueOf (),
			},
		});

		element .dispatchEvent (event);
	}
};

const DOMIntegration_default_ = DOMIntegration;
;

x_ite_Namespace .add ("DOMIntegration", "x_ite/Browser/DOMIntegration", DOMIntegration_default_);
/* harmony default export */ const Browser_DOMIntegration = (DOMIntegration_default_);
;// CONCATENATED MODULE: ./src/x_ite/Configuration/ProfileInfo.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



function ProfileInfo (name, title, providerURL, components)
{
   Object .defineProperties (this,
   {
      name: { value: name, enumerable: true },
      title: { value: title, enumerable: true },
      providerURL: { value: providerURL, enumerable: true },
      components: { value: components, enumerable: true },
   });
}

Object .assign (Object .setPrototypeOf (ProfileInfo .prototype, Base_X3DObject .prototype),
{
   toVRMLStream (generator)
   {
      generator .string += generator .Indent ();
      generator .string += "PROFILE";
      generator .string += generator .Space ();
      generator .string += this .name;
   },
   toXMLStream (generator)
   {
      generator .string += this .name;
   },
   toJSONStream (generator)
   {
      generator .string += this .name;
   },
});

for (const key of Object .keys (ProfileInfo .prototype))
   Object .defineProperty (ProfileInfo .prototype, key, { enumerable: false });

Object .defineProperties (ProfileInfo,
{
   typeName:
   {
      value: "ProfileInfo",
      enumerable: true,
   },
});

Object .defineProperties (ProfileInfo .prototype,
{
   providerUrl: // legacy
   {
      get: function () { return this .providerURL; },
   },
});

const ProfileInfo_default_ = ProfileInfo;
;

x_ite_Namespace .add ("ProfileInfo", "x_ite/Configuration/ProfileInfo", ProfileInfo_default_);
/* harmony default export */ const Configuration_ProfileInfo = (ProfileInfo_default_);
;// CONCATENATED MODULE: ./src/x_ite/Configuration/ProfileInfoArray.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





function ProfileInfoArray (values = [ ])
{
   return Base_X3DInfoArray .call (this, Array .from (values, value => [value .name, value]), Configuration_ProfileInfo);
}

Object .assign (Object .setPrototypeOf (ProfileInfoArray .prototype, Base_X3DInfoArray .prototype),
{
   add (name, { title, providerURL, components })
   {
      Base_X3DInfoArray .prototype .add .call (this, name, new Configuration_ProfileInfo (name, title, providerURL, new Configuration_ComponentInfoArray (components)));
   },
});

for (const key of Object .keys (ProfileInfoArray .prototype))
   Object .defineProperty (ProfileInfoArray .prototype, key, { enumerable: false });

Object .defineProperties (ProfileInfoArray,
{
   typeName:
   {
      value: "ProfileInfoArray",
      enumerable: true,
   },
});

const ProfileInfoArray_default_ = ProfileInfoArray;
;

x_ite_Namespace .add ("ProfileInfoArray", "x_ite/Configuration/ProfileInfoArray", ProfileInfoArray_default_);
/* harmony default export */ const Configuration_ProfileInfoArray = (ProfileInfoArray_default_);
;// CONCATENATED MODULE: ./src/x_ite/Configuration/SupportedComponents.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



const SupportedComponents = new Configuration_ComponentInfoArray ([ ]);

SupportedComponents .add ("Annotation",
{
   title: "Annotation",
   level: 2,
   external: true,
});

SupportedComponents .add ("CADGeometry",
{
   title: "CAD geometry",
   level: 2,
   external: true,
});

SupportedComponents .add ("Core",
{
   title: "Core",
   level: 2,
});

SupportedComponents .add ("CubeMapTexturing",
{
   title: "Cube map environmental texturing",
   level: 3,
   external: true,
});

SupportedComponents .add ("DIS",
{
   title: "Distributed interactive simulation",
   level: 2,
   external: true,
});

SupportedComponents .add ("EnvironmentalEffects",
{
   title: "Environmental effects",
   level: 4,
});

SupportedComponents .add ("EnvironmentalSensor",
{
   title: "Environmental sensor",
   level: 3,
});

SupportedComponents .add ("EventUtilities",
{
   title: "Event utilities",
   level: 1,
   external: true,
});

SupportedComponents .add ("Followers",
{
   title: "Followers",
   level: 1,
});

SupportedComponents .add ("Geometry2D",
{
   title: "Geometry2D",
   level: 2,
   external: true,
});

SupportedComponents .add ("Geometry3D",
{
   title: "Geometry3D",
   level: 4,
});

SupportedComponents .add ("Geospatial",
{
   title: "Geospatial",
   level: 2,
   external: true,
});

SupportedComponents .add ("Grouping",
{
   title: "Grouping",
   level: 3,
});

SupportedComponents .add ("HAnim",
{
   title: "Humanoid animation (HAnim)",
   level: 3,
   external: true,
});

SupportedComponents .alias ("H-Anim", SupportedComponents .get ("HAnim"));

SupportedComponents .add ("Interpolation",
{
   title: "Interpolation",
   level: 5,
});

SupportedComponents .add ("KeyDeviceSensor",
{
   title: "Key device sensor",
   level: 2,
   external: true,
});

SupportedComponents .add ("Layering",
{
   title: "Layering",
   level: 1,
});

SupportedComponents .add ("Layout",
{
   title: "Layout",
   level: 2,
   external: true,
   dependencies: ["Text"],
});

SupportedComponents .add ("Lighting",
{
   title: "Lighting",
   level: 3,
});

SupportedComponents .add ("Navigation",
{
   title: "Navigation",
   level: 3,
});

SupportedComponents .add ("Networking",
{
   title: "Networking",
   level: 4,
});

SupportedComponents .add ("NURBS",
{
   title: "NURBS",
   level: 4,
   external: true,
});

SupportedComponents .add ("ParticleSystems",
{
   title: "Particle systems",
   level: 3,
   external: true,
});

SupportedComponents .add ("Picking",
{
   title: "Picking",
   level: 3,
   external: true,
   dependencies: ["RigidBodyPhysics"],
});

SupportedComponents .add ("PointingDeviceSensor",
{
   title: "Pointing device sensor",
   level: 1,
});

SupportedComponents .add ("Shaders",
{
   title: "Programmable shaders",
   level: 1,
});

SupportedComponents .add ("TextureProjector",
{
   title: "Texture Projector",
   level: 2,
   external: true,
});

SupportedComponents .alias ("ProjectiveTextureMapping", SupportedComponents .get ("TextureProjector"));

SupportedComponents .add ("Rendering",
{
   title: "Rendering",
   level: 5,
});

SupportedComponents .add ("RigidBodyPhysics",
{
   title: "Rigid body physics",
   level: 2,
   external: true,
});

SupportedComponents .add ("Scripting",
{
   title: "Scripting",
   level: 1,
   external: true,
});

SupportedComponents .add ("Shape",
{
   title: "Shape",
   level: 4,
});

SupportedComponents .add ("Sound",
{
   title: "Sound",
   level: 3,
});

SupportedComponents .add ("Text",
{
   title: "Text",
   level: 1,
   external: true,
});

SupportedComponents .add ("Texturing",
{
   title: "Texturing",
   level: 4,
});

SupportedComponents .add ("Texturing3D",
{
   title: "Texturing3D",
   level: 2,
   external: true,
});

SupportedComponents .add ("Time",
{
   title: "Time",
   level: 2,
});

SupportedComponents .add ("VolumeRendering",
{
   title: "Volume rendering",
   level: 4,
   external: true,
   dependencies: ["CADGeometry", "Texturing3D"],
});

SupportedComponents .add ("X_ITE",
{
   title: "X_ITE",
   level: 1,
   external: true,
});

const SupportedComponents_default_ = SupportedComponents;
;

x_ite_Namespace .add ("SupportedComponents", "x_ite/Configuration/SupportedComponents", SupportedComponents_default_);
/* harmony default export */ const Configuration_SupportedComponents = (SupportedComponents_default_);
;// CONCATENATED MODULE: ./src/x_ite/Configuration/SupportedProfiles.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





const SupportedProfiles = new Configuration_ProfileInfoArray ();

SupportedProfiles .add ("CADInterchange",
{
   title: "Computer-Aided Design (CAD) interchange",
   providerURL: Networking_URLs .getProviderURL (),
   components: [
      Configuration_SupportedComponents .get ("CADGeometry"),
      Configuration_SupportedComponents .get ("Core"),
      Configuration_SupportedComponents .get ("Grouping"),
      Configuration_SupportedComponents .get ("Lighting"),
      Configuration_SupportedComponents .get ("Navigation"),
      Configuration_SupportedComponents .get ("Networking"),
      Configuration_SupportedComponents .get ("Rendering"),
      Configuration_SupportedComponents .get ("Shaders"),
      Configuration_SupportedComponents .get ("Shape"),
      Configuration_SupportedComponents .get ("Texturing"),
   ],
});

SupportedProfiles .add ("Core",
{
   title: "Core",
   providerURL: Networking_URLs .getProviderURL (),
   components: [
      Configuration_SupportedComponents .get ("Core"),
   ],
});

SupportedProfiles .add ("Full",
{
   title: "Full",
   providerURL: Networking_URLs .getProviderURL (),
   components: [
      //SupportedComponents .get ("Annotation"),
      Configuration_SupportedComponents .get ("CADGeometry"),
      Configuration_SupportedComponents .get ("Core"),
      Configuration_SupportedComponents .get ("CubeMapTexturing"),
      Configuration_SupportedComponents .get ("DIS"),
      Configuration_SupportedComponents .get ("EnvironmentalEffects"),
      Configuration_SupportedComponents .get ("EnvironmentalSensor"),
      Configuration_SupportedComponents .get ("EventUtilities"),
      Configuration_SupportedComponents .get ("Followers"),
      Configuration_SupportedComponents .get ("Geometry2D"),
      Configuration_SupportedComponents .get ("Geometry3D"),
      Configuration_SupportedComponents .get ("Geospatial"),
      Configuration_SupportedComponents .get ("Grouping"),
      Configuration_SupportedComponents .get ("HAnim"),
      Configuration_SupportedComponents .get ("Interpolation"),
      Configuration_SupportedComponents .get ("KeyDeviceSensor"),
      Configuration_SupportedComponents .get ("Layering"),
      Configuration_SupportedComponents .get ("Layout"),
      Configuration_SupportedComponents .get ("Lighting"),
      Configuration_SupportedComponents .get ("Navigation"),
      Configuration_SupportedComponents .get ("Networking"),
      Configuration_SupportedComponents .get ("NURBS"),
      Configuration_SupportedComponents .get ("ParticleSystems"),
      Configuration_SupportedComponents .get ("Picking"),
      Configuration_SupportedComponents .get ("PointingDeviceSensor"),
      Configuration_SupportedComponents .get ("TextureProjector"),
      Configuration_SupportedComponents .get ("Rendering"),
      Configuration_SupportedComponents .get ("RigidBodyPhysics"),
      Configuration_SupportedComponents .get ("Scripting"),
      Configuration_SupportedComponents .get ("Shaders"),
      Configuration_SupportedComponents .get ("Shape"),
      Configuration_SupportedComponents .get ("Sound"),
      Configuration_SupportedComponents .get ("Text"),
      Configuration_SupportedComponents .get ("Texturing"),
      Configuration_SupportedComponents .get ("Texturing3D"),
      Configuration_SupportedComponents .get ("Time"),
      Configuration_SupportedComponents .get ("VolumeRendering"),
   ],
});

SupportedProfiles .add ("Immersive",
{
   title: "Immersive",
   providerURL: Networking_URLs .getProviderURL (),
   components: [
      Configuration_SupportedComponents .get ("Core"),
      Configuration_SupportedComponents .get ("EnvironmentalEffects"),
      Configuration_SupportedComponents .get ("EnvironmentalSensor"),
      Configuration_SupportedComponents .get ("EventUtilities"),
      Configuration_SupportedComponents .get ("Geometry2D"),
      Configuration_SupportedComponents .get ("Geometry3D"),
      Configuration_SupportedComponents .get ("Grouping"),
      Configuration_SupportedComponents .get ("Interpolation"),
      Configuration_SupportedComponents .get ("KeyDeviceSensor"),
      Configuration_SupportedComponents .get ("Lighting"),
      Configuration_SupportedComponents .get ("Navigation"),
      Configuration_SupportedComponents .get ("Networking"),
      Configuration_SupportedComponents .get ("PointingDeviceSensor"),
      Configuration_SupportedComponents .get ("Rendering"),
      Configuration_SupportedComponents .get ("Scripting"),
      Configuration_SupportedComponents .get ("Shape"),
      Configuration_SupportedComponents .get ("Sound"),
      Configuration_SupportedComponents .get ("Text"),
      Configuration_SupportedComponents .get ("Texturing"),
      Configuration_SupportedComponents .get ("Time"),
   ],
});

SupportedProfiles .add ("Interactive",
{
   title: "Interactive",
   providerURL: Networking_URLs .getProviderURL (),
   components: [
      Configuration_SupportedComponents .get ("Core"),
      Configuration_SupportedComponents .get ("EnvironmentalEffects"),
      Configuration_SupportedComponents .get ("EnvironmentalSensor"),
      Configuration_SupportedComponents .get ("EventUtilities"),
      Configuration_SupportedComponents .get ("Geometry3D"),
      Configuration_SupportedComponents .get ("Grouping"),
      Configuration_SupportedComponents .get ("Interpolation"),
      Configuration_SupportedComponents .get ("KeyDeviceSensor"),
      Configuration_SupportedComponents .get ("Lighting"),
      Configuration_SupportedComponents .get ("Navigation"),
      Configuration_SupportedComponents .get ("Networking"),
      Configuration_SupportedComponents .get ("PointingDeviceSensor"),
      Configuration_SupportedComponents .get ("Rendering"),
      Configuration_SupportedComponents .get ("Shape"),
      Configuration_SupportedComponents .get ("Texturing"),
      Configuration_SupportedComponents .get ("Time"),
   ],
});

SupportedProfiles .add ("Interchange",
{
   title: "Interchange",
   providerURL: Networking_URLs .getProviderURL (),
   components: [
      Configuration_SupportedComponents .get ("Core"),
      Configuration_SupportedComponents .get ("EnvironmentalEffects"),
      Configuration_SupportedComponents .get ("Geometry3D"),
      Configuration_SupportedComponents .get ("Grouping"),
      Configuration_SupportedComponents .get ("Interpolation"),
      Configuration_SupportedComponents .get ("Lighting"),
      Configuration_SupportedComponents .get ("Navigation"),
      Configuration_SupportedComponents .get ("Networking"),
      Configuration_SupportedComponents .get ("Rendering"),
      Configuration_SupportedComponents .get ("Shape"),
      Configuration_SupportedComponents .get ("Texturing"),
      Configuration_SupportedComponents .get ("Time"),
   ],
});

SupportedProfiles .add ("MedicalInterchange",
{
   title: "Medical interchange",
   providerURL: Networking_URLs .getProviderURL (),
   components: [
      Configuration_SupportedComponents .get ("Core"),
      Configuration_SupportedComponents .get ("EnvironmentalEffects"),
      Configuration_SupportedComponents .get ("EventUtilities"),
      Configuration_SupportedComponents .get ("Geometry2D"),
      Configuration_SupportedComponents .get ("Geometry3D"),
      Configuration_SupportedComponents .get ("Grouping"),
      Configuration_SupportedComponents .get ("Interpolation"),
      Configuration_SupportedComponents .get ("Lighting"),
      Configuration_SupportedComponents .get ("Navigation"),
      Configuration_SupportedComponents .get ("Networking"),
      Configuration_SupportedComponents .get ("Rendering"),
      Configuration_SupportedComponents .get ("Shape"),
      Configuration_SupportedComponents .get ("Text"),
      Configuration_SupportedComponents .get ("Texturing"),
      Configuration_SupportedComponents .get ("Texturing3D"),
      Configuration_SupportedComponents .get ("Time"),
      Configuration_SupportedComponents .get ("VolumeRendering"),
   ],
});

SupportedProfiles .add ("MPEG-4",
{
   title: "MPEG-4 interactive",
   providerURL: Networking_URLs .getProviderURL (),
   components: [
      Configuration_SupportedComponents .get ("Core"),
      Configuration_SupportedComponents .get ("EnvironmentalEffects"),
      Configuration_SupportedComponents .get ("EnvironmentalSensor"),
      Configuration_SupportedComponents .get ("Geometry3D"),
      Configuration_SupportedComponents .get ("Grouping"),
      Configuration_SupportedComponents .get ("Interpolation"),
      Configuration_SupportedComponents .get ("Lighting"),
      Configuration_SupportedComponents .get ("Navigation"),
      Configuration_SupportedComponents .get ("Networking"),
      Configuration_SupportedComponents .get ("PointingDeviceSensor"),
      Configuration_SupportedComponents .get ("Rendering"),
      Configuration_SupportedComponents .get ("Shape"),
      Configuration_SupportedComponents .get ("Texturing"),
      Configuration_SupportedComponents .get ("Time"),
   ],
});

const SupportedProfiles_default_ = SupportedProfiles;
;

x_ite_Namespace .add ("SupportedProfiles", "x_ite/Configuration/SupportedProfiles", SupportedProfiles_default_);
/* harmony default export */ const Configuration_SupportedProfiles = (SupportedProfiles_default_);
;// CONCATENATED MODULE: ./src/x_ite/Browser/X3DBrowser.js
/* provided dependency */ var X3DBrowser_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/


























const
   _DOMIntegration      = Symbol (),
   _supportedProfiles   = Symbol (),
   _supportedComponents = Symbol (),
   _concreteNodes       = Symbol (),
   _abstractNodes       = Symbol (),
   _reject              = Symbol (),
   _fileLoader          = Symbol (),
   _browserCallbacks    = Symbol (),
   _console             = Symbol (),
   X3DBrowser_processEvents       = Symbol .for ("X_ITE.X3DRoutingContext.processEvents");

function X3DBrowser (element)
{
   element = X3DBrowser_$(element);

   if (element .prop ("browser"))
      throw new Error ("Couldn't create browser, element has already a browser.");

   Browser_X3DBrowserContext .call (this, element);

   this .addType (Base_X3DConstants .X3DBrowser);

   this [_supportedProfiles]   = Configuration_SupportedProfiles .copy ();
   this [_supportedComponents] = Configuration_SupportedComponents .copy ();
   this [_concreteNodes]       = ConcreteNodes .copy ();
   this [_abstractNodes]       = AbstractNodes .copy ();
   this [_console]             = document .getElementsByClassName ("x_ite-console");

   this [_browserCallbacks] = new Map ([
      [Base_X3DConstants .CONNECTION_ERROR,  new Map ()],
      [Base_X3DConstants .BROWSER_EVENT,     new Map ()],
      [Base_X3DConstants .INITIALIZED_EVENT, new Map ()],
      [Base_X3DConstants .SHUTDOWN_EVENT,    new Map ()],
      [Base_X3DConstants .INITIALIZED_ERROR, new Map ()],
   ]);

   this .setup ();
};

Object .assign (Object .setPrototypeOf (X3DBrowser .prototype, Browser_X3DBrowserContext .prototype),
{
   initialize ()
   {
      Browser_X3DBrowserContext .prototype .initialize .call (this);

      this .replaceWorld (this .createScene ())
         .catch (DEVELOPMENT ? error => console .error (error) : Function .prototype);

      this [_DOMIntegration] = new Browser_DOMIntegration (this);

      Browser_Legacy .browser (this);

      // Process events from context creation. This will setup nodes like
      // geometry option nodes before any node is created.
      this [X3DBrowser_processEvents] .call (this);

      // Print welcome message.

      if (this .getInstanceId () > 1)
         return;

      if (!this .getBrowserOption ("Debug"))
         return;

      this .print (this .getWelcomeMessage ());
   },
   getWelcomeMessage ()
   {
      return `Welcome to ${this .name} X3D Browser v${this .version}:\n` +
             `   Current Graphics Renderer\n` +
             `      Name: ${this .getVendor ()} ${this .getRenderer ()}\n` +
             `      WebGL version: ${this .getWebGLVersion ()}\n` +
             `      Shading language: ${this .getShadingLanguageVersion ()}\n` +
             `   Rendering Properties\n` +
             `      Antialiased: ${this .getRenderingProperty ("Antialiased")}\n` +
             `      Max samples: ${this .getMaxSamples ()}\n` +
             `      Depth size: ${this .getDepthSize ()} bits\n` +
             `      Color depth: ${this .getColorDepth ()} bits\n` +
             `      Max clip planes per shape: ${this .getMaxClipPlanes ()}\n` +
             `      Max lights per shape: ${this .getMaxLights ()}\n` +
             `      Max multi textures per shape: ${this .getMaxTextures ()}\n` +
             `      Texture units: ${this .getMaxCombinedTextureUnits ()}\n` +
             `      Max texture size: ${this .getMaxTextureSize ()} × ${this .getMaxTextureSize ()} pixels\n` +
             `      Texture memory: ${this .getTextureMemory ()}\n` +
             `      Max vertex uniform vectors: ${this .getMaxVertexUniformVectors ()}\n` +
             `      Max fragment uniform vectors: ${this .getMaxFragmentUniformVectors ()}\n` +
             `      Max vertex attribs: ${this .getMaxVertexAttribs ()}\n` +
             `      Max varying vectors: ${this .getMaxVaryingVectors ()}\n`;
   },
   getName ()
   {
      return "X_ITE";
   },
   getVersion ()
   {
      return VERSION;
   },
   getDescription ()
   {
      return this .getNotification () ._string .getValue ()
   },
   setDescription (value)
   {
      this .getNotification () ._string = value;
   },
   getWorldURL ()
   {
      return this .currentScene .worldURL;
   },
   getProfile (name)
   {
      name = String (name);

      const profile = this [_supportedProfiles] .get (name);

      if (profile)
         return profile;

      throw Error (`Profile '${name}' is not supported.`);
   },
   addSupportedProfile: function (profile)
   {
      this [_supportedProfiles] .add (profile .name, profile);
   },
   updateSupportedProfile: function (profile)
   {
      this [_supportedProfiles] .update (profile .name, profile .name, profile);
   },
   removeSupportedProfile (name)
   {
      return this [_supportedProfiles] .remove (String (name));
   },
   getSupportedProfile (name)
   {
      const profile = this [_supportedProfiles] .get (String (name));

      if (profile)
         return profile;

      throw new Error (`Supported profile '${name}' does not exists.`);
   },
   getSupportedProfiles ()
   {
      return this [_supportedProfiles];
   },
   getComponent (name, level)
   {
      name   = String (name);
      level |= 0;

      const component = this [_supportedComponents] .get (name);

      if (component)
      {
         return new Configuration_ComponentInfo (component .name,
            Math_Algorithm .clamp (level || component .level, 1, component .level),
            component .title,
            component .providerURL,
            component .external,
            component .dependencies);
      }

      throw Error (`Component '${name}' at level '${level}' is not supported.`);
   },
   addSupportedComponent (component)
   {
      this [_supportedComponents] .add (component .name, component);
   },
   updateSupportedComponent (component)
   {
      this [_supportedComponents] .update (component .name, component .name, component);
   },
   removeSupportedComponent (name)
   {
      this [_supportedComponents] .remove (String (name));
   },
   getSupportedComponent (name)
   {
      const component = this [_supportedComponents] .get (String (name));

      if (component)
         return component;

      throw new Error (`Supported component '${name}' does not exists.`);
   },
   getSupportedComponents ()
   {
      return this [_supportedComponents];
   },
   loadComponents: (() =>
   {
      function loadComponents (components, seen)
      {
         return Promise .all (components .map (component => loadComponent .call (this, component, seen)))
      }

      async function loadComponent ({ name, providerURL, external, dependencies }, seen)
      {
         if (seen .has (name)) return; seen .add (name);

         await loadComponents .call (this, dependencies .map (name => this [_supportedComponents] .get (name)), seen);

         if (!external)
            return;

         switch (x_ite_Features .ENVIRONMENT)
         {
            case "NODE":
            {
               __webpack_require__.g .require (__webpack_require__.g .require ("url") .fileURLToPath (providerURL))
               break;
            }
            case "BROWSER":
            case "MODULE":
            {
               await import (/* webpackIgnore: true */ providerURL);
               break;
            }
         }
      }

      return function (... args)
      {
         const component = [ ];

         for (const arg of args)
         {
            if (arg instanceof Configuration_ProfileInfo)
               component .push (... arg .components);

            else if (arg instanceof Configuration_ComponentInfoArray)
               component .push (... arg);

            else if (arg instanceof Configuration_ComponentInfo)
               component .push (arg);

            else if (typeof arg === "string")
               component .push (this [_supportedComponents] .get (arg))
         }

         // Load array of component names.
         return loadComponents .call (this, component, new Set ());
      };
   })(),
   addConcreteNode (ConcreteNode)
   {
      this [_concreteNodes] .add (ConcreteNode .typeName, ConcreteNode);
   },
   updateConcreteNode (ConcreteNode)
   {
      this [_concreteNodes] .update (ConcreteNode .typeName, ConcreteNode .typeName, ConcreteNode);
   },
   removeConcreteNode (typeName)
   {
      this [_concreteNodes] .remove (String (typeName));
   },
   getConcreteNode (typeName)
   {
      const concreteNode = this [_concreteNodes] .get (String (typeName));

      if (concreteNode)
         return concreteNode;

      throw new Error (`Concrete node '${typeName}' does not exists.`);
   },
   getConcreteNodes ()
   {
      return this [_concreteNodes];
   },
   addAbstractNode (AbstractNode)
   {
      this [_abstractNodes] .add (AbstractNode .typeName, AbstractNode);
   },
   updateAbstractNode (AbstractNode)
   {
      this [_abstractNodes] .update (AbstractNode .typeName, AbstractNode .typeName, AbstractNode);
   },
   removeAbstractNode (typeName)
   {
      this [_abstractNodes] .remove (String (typeName));
   },
   getAbstractNode (typeName)
   {
      const abstractNode = this [_abstractNodes] .get (String (typeName));

      if (abstractNode)
         return abstractNode;

      throw new Error (`Abstract node '${typeName}' does not exists.`);
   },
   getAbstractNodes ()
   {
      return this [_abstractNodes];
   },
   createScene (profile, ... components)
   {
      const scene = new Execution_X3DScene (this);

      if (arguments .length)
      {
         if (!(profile instanceof Configuration_ProfileInfo))
            throw new Error ("Couldn't create scene: profile must be of type ProfileInfo.");

         scene .setProfile (profile);

         for (const component of components)
         {
            if (!(component instanceof Configuration_ComponentInfo))
               throw new Error ("Couldn't create scene: component must be of type ComponentInfo.");

            scene .addComponent (component);
         }
      }

      scene .setup ();

      return scene;
   },
   replaceWorld (scene)
   {
      return new Promise ((resolve, reject) =>
      {
         this [_fileLoader] ?.abort ();

         this [_reject] ?.("Replacing world aborted.");
         this [_reject] = reject;

         // Remove world.

         if (this .initialized () .getValue ())
         {
            this .getExecutionContext () .setLive (false);
            this .shutdown () .processInterests ();
            this .callBrowserCallbacks (Base_X3DConstants .SHUTDOWN_EVENT);
            this .callBrowserEventHandler ("shutdown");
         }

         // Replace world.

         if (scene instanceof x_ite_Fields .MFNode)
         {
            // VRML version of replaceWorld has a MFNode value as argument.

            const rootNodes = scene;

            scene = this .createScene ();

            for (const node of rootNodes .filter (node => node))
               scene .getLive () .addInterest ("setLive", node .getValue () .getExecutionContext ());

            scene .setRootNodes (rootNodes);
         }

         if (!(scene instanceof Execution_X3DScene))
            scene = this .createScene ();

         // Detach scene from parent.

         scene .getExecutionContext () .getLive () .removeInterest ("setLive", scene);
         scene .setExecutionContext (scene);

         // Replace.

         this .setDescription ("");
         this .setBrowserLoading (true);
         this ._loadCount .addInterest ("checkLoadCount", this, resolve);

         for (const object of scene .getLoadingObjects ())
            this .addLoadingObject (object);

         this .setExecutionContext (scene);
         this .getWorld () .bindBindables ();

         scene .setLive (this .isLive ());
      });
   },
   checkLoadCount (resolve, loadCount)
   {
      if (loadCount .getValue ())
         return;

      loadCount .removeInterest ("checkLoadCount", this);
      this .setBrowserLoading (false);
      this .initialized () .set (this .getCurrentTime ());
      this .initialized () .processInterests ();
      this .callBrowserCallbacks (Base_X3DConstants .INITIALIZED_EVENT);
      this .callBrowserEventHandler ("initialized load");
      resolve ();
   },
   createVrmlFromString (vrmlSyntax)
   {
      const
         external     = this .isExternal (),
         currentScene = this .currentScene,
         worldURL     = external ? this .getBaseURL () : currentScene .getWorldURL (),
         fileLoader   = new InputOutput_FileLoader (this .getWorld ()),
         scene        = fileLoader .createX3DFromString (worldURL, `#VRML V2.0 utf8\n\n${vrmlSyntax}`);

      if (!external)
      {
         currentScene .getLive () .addInterest ("setLive", scene);
         scene .setExecutionContext (currentScene);
         scene .setLive (currentScene .isLive ());
      }

      return scene .rootNodes;
   },
   createX3DFromString: async function (x3dSyntax)
   {
      x3dSyntax = String (x3dSyntax);

      const
         external     = this .isExternal (),
         currentScene = this .currentScene,
         worldURL     = external ? this .getBaseURL () : currentScene .getWorldURL (),
         fileLoader   = new InputOutput_FileLoader (this .getWorld ());

      const scene = await new Promise ((resolve, reject) =>
      {
         fileLoader .createX3DFromString (worldURL, x3dSyntax, resolve, reject);
      });

      if (!external)
      {
         currentScene .getLive () .addInterest ("setLive", scene);
         scene .setExecutionContext (currentScene);
         scene .setLive (currentScene .isLive ());
      }

      return scene;
   },
   createVrmlFromURL (url, node, event)
   {
      node  = Base_X3DCast (Base_X3DConstants .X3DNode, node, false);
      event = String (event);

      if (!(url instanceof x_ite_Fields .MFString))
         throw new Error ("Browser.createVrmlFromURL: url must be of type MFString.");

      if (!node)
         throw new Error ("Browser.createVrmlFromURL: node must be of type X3DNode.");

      const field = node .getField (event);

      if (!field .isInput ())
         throw new Error (`Browser.createVrmlFromURL: event named '${event}' must be a input field.`);

      if (field .getType () !== Base_X3DConstants .MFNode)
         throw new Error (`Browser.createVrmlFromURL: event named '${event}' must be of type MFNode.`);

      const
         currentScene = this .currentScene,
         external     = this .isExternal (),
         fileLoader   = new InputOutput_FileLoader (this .getWorld ());

      this .addLoadingObject (fileLoader);

      fileLoader .createX3DFromURL (url, null, (scene) =>
      {
         this .removeLoadingObject (fileLoader);

         if (scene)
         {
            // Handle getLive for script scenes here:

            if (!external)
            {
               currentScene .getLive () .addInterest ("setLive", scene);
               scene .setExecutionContext (currentScene);
               scene .setLive (currentScene .isLive ());
            }

            // Wait until scene is completely loaded, scene ._loadCount must be 0.
            field .setValue (scene .rootNodes);
         }
      });
   },
   createX3DFromURL (url, node, event)
   {
      if (arguments .length === 3)
         return this .createVrmlFromURL (url, node, event);

      // arguments .length === 1

      if (!(url instanceof x_ite_Fields .MFString))
         throw new Error ("Browser.createX3DFromURL: url must be of type MFString.");

      return new Promise ((resolve, reject) =>
      {
         const
            currentScene = this .currentScene,
            external     = this .isExternal (),
            fileLoader   = new InputOutput_FileLoader (this .getWorld ());

         this .addLoadingObject (fileLoader);

         fileLoader .createX3DFromURL (url, null, (scene) =>
         {
            this .removeLoadingObject (fileLoader);

            if (scene)
            {
               if (!external)
               {
                  currentScene .getLive () .addInterest ("setLive", scene);
                  scene .setExecutionContext (currentScene);
                  scene .setLive (currentScene .isLive ());
               }

               resolve (scene);
            }
            else
            {
               reject (new Error ("Couldn't load X3D file."));
            }
         })
      });
   },
   loadURL (url, parameter = new x_ite_Fields .MFString ())
   {
      return new Promise ((resolve, reject) =>
      {
         if (!(url instanceof x_ite_Fields .MFString))
            throw new Error ("Browser.loadURL: url must be of type MFString.");

         if (!(parameter instanceof x_ite_Fields .MFString))
            throw new Error ("Browser.loadURL: parameter must be of type MFString.");

         // Start loading.

         const fileLoader = new InputOutput_FileLoader (this .getWorld ());

         fileLoader .createX3DFromURL (url, parameter, (scene) =>
         {
            if (this [_fileLoader] !== fileLoader)
            {
               reject (new Error ("Loading of X3D file aborted."));
            }
            else
            {
               if (!this .getBrowserOption ("SplashScreen"))
                  this .getCanvas () .show ();

               if (scene)
               {
                  this .addLoadingObject (this); // Prevent resetLoadCount.
                  this .replaceWorld (scene) .then (resolve) .catch (reject);
                  this .removeLoadingObject (this);
                  this .removeLoadingObject (fileLoader);
               }
               else
               {
                  this .callBrowserCallbacks (Base_X3DConstants .CONNECTION_ERROR);
                  this .callBrowserEventHandler ("error");

                  setTimeout (() =>
                  {
                     this .getSplashScreen ()
                        .find (".x_ite-private-spinner-text")
                        .text (locale_gettext ("Failed loading world."));
                  });

                  reject (new Error ("Couldn't load X3D file."));
               }
            }
         },
         (fragment) =>
         {
            fileLoader .ready = true;

            this .changeViewpoint (fragment);
            this .removeLoadingObject (fileLoader);

            resolve ();
         },
         (url, target) =>
         {
            fileLoader .ready = true;

            if (target)
               window .open (url, target);
            else
               location = url;

            this .removeLoadingObject (fileLoader);

            resolve ();
         });

         if (!fileLoader .ready)
         {
            this [_fileLoader] ?.abort ();

            this .setBrowserLoading (true);
            this .addLoadingObject (this [_fileLoader] = fileLoader);
         }
      });
   },
   addBrowserListener (callback, object)
   {
      // The string describes the name of the callback function to be called within the current ECMAScript context.
   },
   removeBrowserListener (callback)
   {
      // The string describes the name of the callback function to be called within the current ECMAScript context.
   },
   addBrowserCallback (... args)
   {
      switch (args .length)
      {
         case 2:
         {
            const [key, object] = args;

            this [_browserCallbacks] .forEach (map => map .set (key, object));
            break;
         }
         case 3:
         {
            const [key, event, object] = args;

            this [_browserCallbacks] .get (event) .set (key, object);
            break;
         }
      }
   },
   removeBrowserCallback (key, event)
   {
      if (arguments .length === 2)
         this [_browserCallbacks] .get (event) .delete (key);
      else
         this [_browserCallbacks] .forEach (map => map .delete (key));
   },
   getBrowserCallbacks (event)
   {
      if (arguments .length === 1)
         return this [_browserCallbacks] .get (event);
      else
         return new Map ([... this [_browserCallbacks]] .flatMap (([event, map]) => [... map]));
   },
   callBrowserCallbacks: (() =>
   {
      const values = [ ];

      return function (event)
      {
         const browserCallbacks = this [_browserCallbacks] .get (event);

         if (browserCallbacks .size)
         {
            for (const callback of Utility_MapUtilities .values (values, browserCallbacks))
               callback (event);
         }
      };
   })(),
   importDocument (dom)
   {
      const
         currentScene = this .currentScene,
         scene        = this .createScene (),
         external     = this .isExternal ();

      if (!external)
      {
         currentScene .getLive () .addInterest ("setLive", scene);
         scene .setExecutionContext (currentScene);
         scene .setLive (currentScene .isLive ());
      }

      const parser = new Parser_XMLParser (scene);

      parser .setInput (dom)

      return new Promise (parser .parseIntoScene .bind (parser));
   },
   importJS (json)
   {
      const
         currentScene = this .currentScene,
         scene        = this .createScene (),
         external     = this .isExternal ();

      if (!external)
      {
         currentScene .getLive () .addInterest ("setLive", scene);
         scene .setExecutionContext (currentScene);
         scene .setLive (currentScene .isLive ());
      }

      const parser = new Parser_JSONParser (scene);

      parser .setInput (json);

      return new Promise (parser .parseIntoScene .bind (parser));
   },
   getBrowserProperty (name)
   {
      return this .getBrowserProperties () .getField (name) .getValue ();
   },
   setBrowserOption (name, value)
   {
      this .getBrowserOptions () .getField (name) .setValue (value);
   },
   getBrowserOption (name)
   {
      return this .getBrowserOptions () .getField (name) .getValue ();
   },
   getRenderingProperty (name)
   {
      return this .getRenderingProperties () .getField (name) .getValue ();
   },
   viewAll (layerNode, transitionTime = 1)
   {
      if (arguments .length === 1 && typeof layerNode === "number")
         transitionTime = layerNode;

      layerNode = Base_X3DCast (Base_X3DConstants .X3DLayerNode, layerNode) ?? this .getActiveLayer ();

      if (!layerNode)
         return;

      layerNode .viewAll (transitionTime, 1, this .getBrowserOption ("StraightenHorizon"));
   },
   firstViewpoint (layerNode)
   {
      layerNode = Base_X3DCast (Base_X3DConstants .X3DLayerNode, layerNode) ?? this .getActiveLayer ();

      const viewpoints = layerNode .getUserViewpoints ();

      if (viewpoints .length)
         this .bindViewpoint (layerNode, viewpoints [0]);
   },
   previousViewpoint (layerNode)
   {
      layerNode = Base_X3DCast (Base_X3DConstants .X3DLayerNode, layerNode) ?? this .getActiveLayer ();

      if (!layerNode)
         return;

      const viewpoints = layerNode .getUserViewpoints ();

      if (viewpoints .length === 0)
         return;

      for (var i = 0, length = viewpoints .length; i < length; ++ i)
      {
         if (viewpoints [i] ._isBound .getValue ())
            break;
      }

      if (i < viewpoints .length)
      {
         if (i === 0)
            this .bindViewpoint (layerNode, viewpoints .at (-1));

         else
            this .bindViewpoint (layerNode, viewpoints [i - 1]);
      }
      else
         this .bindViewpoint (layerNode, viewpoints .at (-1));
   },
   nextViewpoint (layerNode)
   {
      layerNode = Base_X3DCast (Base_X3DConstants .X3DLayerNode, layerNode) ?? this .getActiveLayer ();

      if (!layerNode)
         return;

      const viewpoints = layerNode .getUserViewpoints ();

      if (viewpoints .length === 0)
         return;

      for (var i = 0, length = viewpoints .length; i < length; ++ i)
      {
         if (viewpoints [i] ._isBound .getValue ())
            break;
      }

      if (i < viewpoints .length)
      {
         if (i === viewpoints .length - 1)
            this .bindViewpoint (layerNode, viewpoints [0]);

         else
            this .bindViewpoint (layerNode, viewpoints [i + 1]);
      }
      else
         this .bindViewpoint (layerNode, viewpoints [0]);
   },
   lastViewpoint (layerNode)
   {
      layerNode = Base_X3DCast (Base_X3DConstants .X3DLayerNode, layerNode) ?? this .getActiveLayer ();

      if (!layerNode)
         return;

      const viewpoints = layerNode .getUserViewpoints ();

      if (viewpoints .length)
         this .bindViewpoint (layerNode, viewpoints .at (-1));
   },
   changeViewpoint (layerNode, name)
   {
      if (arguments .length === 1)
      {
         name      = String (layerNode);
         layerNode = this .getActiveLayer ();
      }

      layerNode = Base_X3DCast (Base_X3DConstants .X3DLayerNode, layerNode) ?? this .getActiveLayer ();

      if (!layerNode)
         return;

      for (const viewpointNode of layerNode .getViewpoints () .get ())
      {
         if (viewpointNode .getName () !== name)
            continue;

         this .bindViewpoint (layerNode, viewpointNode);
         break;
      }
   },
   bindViewpoint (layerNode, viewpointNode)
   {
      layerNode     = Base_X3DCast (Base_X3DConstants .X3DLayerNode,     layerNode);
      viewpointNode = Base_X3DCast (Base_X3DConstants .X3DViewpointNode, viewpointNode);

      if (!layerNode)
         throw new Error ("Browser.bindViewpoint: layerNode must be of type X3DLayerNode.")

      if (!viewpointNode)
         throw new Error ("Browser.bindViewpoint: viewpointNode must be of type X3DViewpointNode.")

      viewpointNode .setVRMLTransition (true);

      viewpointNode ._set_bind = true;
   },
   addRoute (fromNode, fromEventOut, toNode, toEventIn)
   {
      this .currentScene .addRoute (fromNode, fromEventOut, toNode, toEventIn);
   },
   deleteRoute (fromNode, fromEventOut, toNode, toEventIn)
   {
      try
      {
         const route = this .currentScene .getRoute (fromNode, fromEventOut, toNode, toEventIn);

         if (route)
            this .currentScene .deleteRoute (route);
      }
      catch (error)
      {
         console .error (error);
      }
   },
   beginUpdate ()
   {
      this .setLive (true);
      this .getExecutionContext () .setLive (true);
      this .advanceTime ();
      this .addBrowserEvent ();
   },
   endUpdate ()
   {
      this .setLive (false);
      this .getExecutionContext () .setLive (false);
   },
   print (... args)
   {
      const string = args .join (" ");

      console .log (string);

      for (const element of this [_console])
         element .append (document .createTextNode (string));
   },
   println (... args)
   {
      const string = args .join (" ");

      console .log (string);

      for (const element of this [_console])
         element .append (document .createTextNode (`${string}\n`));
   },
   toVRMLStream (generator)
   {
      this .currentScene .toVRMLStream (generator);
   },
   toXMLStream (generator)
   {
      this .currentScene .toXMLStream (generator);
   },
   toJSONStream (generator)
   {
      this .currentScene .toJSONStream (generator);
   },
});

for (const key of Object .keys (X3DBrowser .prototype))
   Object .defineProperty (X3DBrowser .prototype, key, { enumerable: false });

Object .defineProperties (X3DBrowser .prototype,
{
   name:
   {
      get: X3DBrowser .prototype .getName,
      enumerable: true,
   },
   version:
   {
      value: VERSION,
      enumerable: true,
   },
   providerURL:
   {
      get: X3DBrowser .prototype .getProviderURL,
      enumerable: true,
   },
   providerUrl: // legacy
   {
      get: X3DBrowser .prototype .getProviderURL,
      enumerable: false,
   },
   currentFrameRate:
   {
      get: X3DBrowser .prototype .getCurrentFrameRate,
      enumerable: true,
   },
   currentSpeed:
   {
      get: X3DBrowser .prototype .getCurrentSpeed,
      enumerable: true,
   },
   description:
   {
      get: X3DBrowser .prototype .getDescription,
      set: X3DBrowser .prototype .setDescription,
      enumerable: true,
   },
   baseURL:
   {
      get: X3DBrowser .prototype .getBaseURL,
      set: X3DBrowser .prototype .setBaseURL,
      enumerable: true,
   },
   currentScene:
   {
      get ()
      {
         return this .getScriptStack () .at (-1) .getExecutionContext ();
      },
      enumerable: true,
   },
   supportedProfiles:
   {
      get ()
      {
         return this [_supportedProfiles];
      },
      enumerable: true,
   },
   supportedComponents:
   {
      get ()
      {
         return this [_supportedComponents];
      },
      enumerable: true,
   },
   concreteNodes:
   {
      get ()
      {
         return this [_concreteNodes];
      },
      enumerable: true,
   },
   abstractNodes:
   {
      get ()
      {
         return this [_abstractNodes];
      },
      enumerable: true,
   },
});

Object .defineProperties (X3DBrowser,
{
   typeName:
   {
      value: "X3DBrowser",
      enumerable: true,
   },
});

Base_X3DConstants .addNode (X3DBrowser);

const X3DBrowser_default_ = X3DBrowser;
;

x_ite_Namespace .add ("X3DBrowser", "x_ite/Browser/X3DBrowser", X3DBrowser_default_);
/* harmony default export */ const Browser_X3DBrowser = (X3DBrowser_default_);
;// CONCATENATED MODULE: ./src/x_ite/X3DCanvasElement.js
/* provided dependency */ var X3DCanvasElement_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/



class X3DCanvasElement extends HTMLElement
{
   constructor ()
   {
      try
      {
         super ();

         new Browser_X3DBrowser (this)
      }
      catch (error)
      {
         console .error (error);

         X3DCanvasElement_$(this .shadowRoot)
            .append (X3DCanvasElement_$("<slot></slot>"))
            .children (".x_ite-private-browser") .remove ();
      }
   }

   connectedCallback ()
   {
      this .browser ?.connectedCallback ();
   }

   static get observedAttributes ()
   {
      return [
         "antialiased",
         "baseURL",
         "baseurl",
         "cache",
         "contentScale",
         "contentscale",
         "contextMenu",
         "contextmenu",
         "debug",
         "multisampling",
         "notifications",
         "oninitialized",
         "onshutdown",
         "orderIndependentTransparency",
         "orderindependenttransparency",
         "splashScreen",
         "splashscreen",
         "src",
         "timings",
         "update",
         "url",
      ];
   }

   attributeChangedCallback (name, oldValue, newValue)
   {
      this .browser ?.attributeChangedCallback (name, oldValue, newValue);
   }

   captureStream (... args)
   {
      return this .browser ?.getCanvas () [0] .captureStream (... args);
   }

   toBlob (... args)
   {
      return this .browser ?.getCanvas () [0] .toBlob (... args);
   }

   toDataURL (... args)
   {
      return this .browser ?.getCanvas () [0] .toDataURL (... args);
   }
}

// IE fix.
document .createElement ("X3DCanvas");

const X3DCanvasElement_default_ = X3DCanvasElement;
;

x_ite_Namespace .add ("X3DCanvasElement", "x_ite/X3DCanvasElement", X3DCanvasElement_default_);
/* harmony default export */ const x_ite_X3DCanvasElement = (X3DCanvasElement_default_);
;// CONCATENATED MODULE: ./src/lib/jquery.js
/* provided dependency */ var jquery_$ = __webpack_require__(659);
/* provided dependency */ var pako = __webpack_require__(822);
Object .assign (jquery_$,
{
   decodeText (input)
   {
      if (typeof input === "string")
         return input;

      return new TextDecoder () .decode (input);
   },
   ungzip (arrayBuffer)
   {
      try
      {
         return pako .ungzip (arrayBuffer, { to: "raw" }) .buffer;
      }
      catch (exception)
      {
         return arrayBuffer;
      }
   },
   toLowerCaseFirst (string)
   {
      return string [0] .toLowerCase () + string .slice (1);
   },
   try (callback, logError = false)
   {
      try
      {
         return callback ();
      }
      catch (error)
      {
         if (logError)
            console .error (error .message);
      }
   },
   enum (object, property, defaultValue)
   {
      return object .hasOwnProperty (property) ? object [property] : defaultValue;
   },
});

// // decorator: @iffe fn (... args) { return function () { }; }
// function iife (target, key, descriptor)
// {
//    descriptor .value = descriptor .value ();
//
//    return descriptor;
// }
//
// class C {
//   @iffe fn (... args) { return function () { }; }
// }

Object .assign (jquery_$.fn,
{
   isInViewport ()
   {
      const
         $this          = jquery_$(this),
         $window        = jquery_$(window),
         elementTop     = $this .offset () .top,
         elementBottom  = elementTop + $this .outerHeight (),
         viewportTop    = $window .scrollTop (),
         viewportBottom = viewportTop + $window .height ();

      return elementBottom > viewportTop && elementTop < viewportBottom;
   },
});

const jquery_default_ = jquery_$;
;

x_ite_Namespace .add ("jquery", "lib/jquery", jquery_default_);
/* harmony default export */ const jquery = ((/* unused pure expression or super */ null && (jquery_default_)));
;// CONCATENATED MODULE: ./src/lib/libtess.js
/* provided dependency */ var libtess_libtess = __webpack_require__(793);
const libtess_default_ = libtess_libtess;
;

x_ite_Namespace .add ("libtess", "lib/libtess", libtess_default_);
/* harmony default export */ const lib_libtess = ((/* unused pure expression or super */ null && (libtess_default_)));
;// CONCATENATED MODULE: ./src/x_ite/X3D.js
/* provided dependency */ var X3D_$ = __webpack_require__(659);
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





































const
   callbacks = X3D_$.Deferred (),
   fallbacks = X3D_$.Deferred ();

let initialized = false;

/**
 *
 * @param {function?} callback
 * @param {function?} fallback
 * @returns {Promise<void>} Promise
 */
function X3D (callback, fallback)
{
   return new Promise ((resolve, reject) =>
   {
      if (typeof callback === "function")
         callbacks .done (callback);

      if (typeof fallback === "function")
         fallbacks .done (fallback);

      callbacks .done (resolve);
      fallbacks .done (reject);

      if (initialized)
         return;

      initialized = true;

      X3D_$(() =>
      {
         try
         {
            Browser_Legacy .elements (X3D_$("X3DCanvas"), Browser_X3DBrowser);

            if ([... X3D_$("x3d-canvas")] .every (canvas => canvas .browser))
               callbacks .resolve ();
            else
               fallbacks .resolve (new Error ("Couldn't create browser."));
         }
         catch (error)
         {
            Browser_Legacy .error (X3D_$("X3DCanvas"), error);
            fallbacks .resolve (error);
         }
      });
   });
}

Object .assign (X3D, x_ite_Namespace, x_ite_Namespace .Fields,
{
   require (id)
   {
      if (!x_ite_Namespace .has (id))
         throw new Error (`Unknown module '${id}'.`);

      return x_ite_Namespace .get (id);
   },
   noConflict: (() =>
   {
      const
         _had = window .hasOwnProperty ("X3D"),
         _X3D = window .X3D;

      return function ()
      {
         if (window .X3D === X3D)
         {
            if (_had)
               window .X3D = _X3D;
            else
               delete window .X3D;
         }

         return X3D;
      };
   })(),
   getBrowser (element)
   {
      return X3D_$(element || "x3d-canvas, X3DCanvas") .prop ("browser");
   },
   createBrowser (url, parameter)
   {
      const element = document .createElement ("x3d-canvas");

      if (arguments .length)
         element .browser .loadURL (url, parameter);

      return element;
   },
});

Object .assign (X3D,
{
   X3DConstants:                Base_X3DConstants,
   X3DBrowser:                  Browser_X3DBrowser,
   X3DExecutionContext:         Execution_X3DExecutionContext,
   X3DScene:                    Execution_X3DScene,
   ComponentInfo:               Configuration_ComponentInfo,
   ComponentInfoArray:          Configuration_ComponentInfoArray,
   ProfileInfo:                 Configuration_ProfileInfo,
   ProfileInfoArray:            Configuration_ProfileInfoArray,
   ConcreteNodesArray:          Configuration_ConcreteNodesArray,          // non-standard
   AbstractNodesArray:          Configuration_AbstractNodesArray,          // non-standard
   UnitInfo:                    Configuration_UnitInfo,
   UnitInfoArray:               Configuration_UnitInfoArray,
   NamedNodesArray:             Execution_NamedNodesArray,             // non-standard
   ImportedNodesArray:          Execution_ImportedNodesArray,          // non-standard
   X3DImportedNode:             Execution_X3DImportedNode,             // non-standard
   ExportedNodesArray:          Execution_ExportedNodesArray,          // non-standard
   X3DExportedNode:             Execution_X3DExportedNode,             // non-standard
   ExternProtoDeclarationArray: Prototype_ExternProtoDeclarationArray,
   ProtoDeclarationArray:       Prototype_ProtoDeclarationArray,
   X3DExternProtoDeclaration:   Prototype_X3DExternProtoDeclaration,
   X3DProtoDeclaration:         Prototype_X3DProtoDeclaration,
   X3DProtoDeclarationNode:     Prototype_X3DProtoDeclarationNode,     // non-standard
   RouteArray:                  Routing_RouteArray,
   X3DRoute:                    Routing_X3DRoute,

   X3DBaseNode:                 Base_X3DBaseNode,                 // non-standard

   X3DFieldDefinition:          Base_X3DFieldDefinition,
   FieldDefinitionArray:        Base_FieldDefinitionArray,

   X3DField:                    Base_X3DField,
   X3DArrayField:               Base_X3DArrayField,

   SFColor:                     x_ite_Fields .SFColor,
   SFColorRGBA:                 x_ite_Fields .SFColorRGBA,
   SFImage:                     x_ite_Fields .SFImage,
   SFMatrix3d:                  x_ite_Fields .SFMatrix3d,
   SFMatrix3f:                  x_ite_Fields .SFMatrix3f,
   SFMatrix4d:                  x_ite_Fields .SFMatrix4d,
   SFMatrix4f:                  x_ite_Fields .SFMatrix4f,
   SFNode:                      x_ite_Fields .SFNode,
   SFRotation:                  x_ite_Fields .SFRotation,
   SFVec2d:                     x_ite_Fields .SFVec2d,
   SFVec2f:                     x_ite_Fields .SFVec2f,
   SFVec3d:                     x_ite_Fields .SFVec3d,
   SFVec3f:                     x_ite_Fields .SFVec3f,
   SFVec4d:                     x_ite_Fields .SFVec4d,
   SFVec4f:                     x_ite_Fields .SFVec4f,
   VrmlMatrix:                  x_ite_Fields .VrmlMatrix,

   MFBool:                      x_ite_Fields .MFBool,
   MFColor:                     x_ite_Fields .MFColor,
   MFColorRGBA:                 x_ite_Fields .MFColorRGBA,
   MFDouble:                    x_ite_Fields .MFDouble,
   MFFloat:                     x_ite_Fields .MFFloat,
   MFImage:                     x_ite_Fields .MFImage,
   MFInt32:                     x_ite_Fields .MFInt32,
   MFMatrix3d:                  x_ite_Fields .MFMatrix3d,
   MFMatrix3f:                  x_ite_Fields .MFMatrix3f,
   MFMatrix4d:                  x_ite_Fields .MFMatrix4d,
   MFMatrix4f:                  x_ite_Fields .MFMatrix4f,
   MFNode:                      x_ite_Fields .MFNode,
   MFRotation:                  x_ite_Fields .MFRotation,
   MFString:                    x_ite_Fields .MFString,
   MFTime:                      x_ite_Fields .MFTime,
   MFVec2d:                     x_ite_Fields .MFVec2d,
   MFVec2f:                     x_ite_Fields .MFVec2f,
   MFVec3d:                     x_ite_Fields .MFVec3d,
   MFVec3f:                     x_ite_Fields .MFVec3f,
   MFVec4d:                     x_ite_Fields .MFVec4d,
   MFVec4f:                     x_ite_Fields .MFVec4f,
});

/* harmony default export */ const x_ite_X3D = (X3D);

;// CONCATENATED MODULE: ./src/shim.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/

(() =>
{
   // Added at February 2022
   // https://github.com/tc39/proposal-relative-indexing-method#polyfill

   function at (n)
   {
      // ToInteger() abstract op
      n = Math.trunc(n) || 0;
      // Allow negative indexing from the end
      if (n < 0) n += this.length;
      // OOB access is guaranteed to return undefined
      if (n < 0 || n >= this.length) return undefined;
      // Otherwise, this is just normal property access
      return this[n];
   }

   const TypedArray = Reflect .getPrototypeOf (Int8Array);
   for (const C of [Array, String, TypedArray])
   {
      if (C .prototype .at === undefined)
      {
         Object .defineProperty (C .prototype, "at",
         {
            value: at,
            writable: true,
            enumerable: false,
            configurable: true,
         });
      }
   }
})();

const shim_default_ = undefined;
;

x_ite_Namespace .add ("shim", "shim", shim_default_);
/* harmony default export */ const shim = ((/* unused pure expression or super */ null && (shim_default_)));
;// CONCATENATED MODULE: ./src/x_ite.js
/*******************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011 - 2022.
 *
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 *
 * The copyright notice above does not evidence any actual of intended
 * publication of such source code, and is an unpublished work by create3000.
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 * create3000.
 *
 * No permission is granted to copy, distribute, or create derivative works from
 * the contents of this software, in whole or in part, without the prior written
 * permission of create3000.
 *
 * NON-MILITARY USE ONLY
 *
 * All create3000 software are effectively free software with a non-military use
 * restriction. It is free. Well commented source is provided. You may reuse the
 * source in any way you please with the exception anything that uses it must be
 * marked to indicate is contains 'non-military use only' components.
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2011 - 2022, Holger Seelig <holger.seelig@yahoo.de>.
 *
 * This file is part of the X_ITE Project.
 *
 * X_ITE is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 only, as published by the
 * Free Software Foundation.
 *
 * X_ITE is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 * details (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with X_ITE.  If not, see <https://www.gnu.org/licenses/gpl.html> for a
 * copy of the GPLv3 License.
 *
 * For Silvio, Joy and Adi.
 *
 ******************************************************************************/





// Assign X3D to global namespace.

window [Symbol .for ("X_ITE.X3D-8.12.5")] = x_ite_X3D;

customElements .define ("x3d-canvas", x_ite_X3DCanvasElement);

x_ite_X3D ();

const x_ite_default_ = x_ite_X3D;
;

x_ite_Namespace .add ("x_ite", "x_ite", x_ite_default_);
/* harmony default export */ const x_ite = (x_ite_default_);
})();

var __webpack_exports__default = __webpack_exports__.Z;
export { __webpack_exports__default as default };
