diff --git a/browser/index.html b/browser/index.html new file mode 100644 index 0000000..eb03468 --- /dev/null +++ b/browser/index.html @@ -0,0 +1,95 @@ + + + + Tyria 2D + + + + +
+ + + + + + + + + + + diff --git a/browser/index.js b/browser/index.js new file mode 100644 index 0000000..111aefd --- /dev/null +++ b/browser/index.js @@ -0,0 +1,888 @@ +(function () { + 'use strict'; + + window.onload = () => { + /// T3D + let _lr; + let _context; + let _fileId; + let _fileList; + let _audioSource; + let _audioContext; + + /// THREE + let _scene; + let _camera; + let _renderer; + let _models = []; + let _controls; + + $(function () { + /* + SET MAIN UP GRID + */ + const pstyle = "border: 1px solid #dfdfdf; padding: 0;"; + $("#layout").w2layout({ + name: "layout", + panels: [ + { + type: "left", + size: 570, + resizable: true, + style: pstyle + "margin:0", + }, + { + type: "main", + style: pstyle + " background-color: transparent;", + toolbar: { + style: "background-color:#eaeaea; height:40px", + items: [ + { + type: "html", + id: "fileIdToolbar", + html: + '
' + + " File ID:" + + ' ' + + ' " + + "
", + }, + { + type: "html", + id: "contextToolbar", + html: '
', + }, + ], + onClick: function (event) { + this.owner.content("main", event); + }, + }, + }, + ], + onResize: onCanvasResize, + }); + + $("#fileIdInputBtn").click(function () { + viewFileByFileId($("#fileIdInput").val()); + }); + + /// Grid inside main left + $().w2layout({ + name: "leftLayout", + panels: [ + { + type: "left", + size: 150, + resizable: true, + style: pstyle, + content: "left", + }, + { + type: "main", + size: 420, + resizable: true, + style: pstyle, + content: "right", + }, + ], + }); + w2ui["layout"].content("left", w2ui["leftLayout"]); + + /* + SIDEBAR + */ + w2ui["leftLayout"].content( + "left", + $().w2sidebar({ + name: "sidebar", + img: null, + nodes: [{ id: "All", text: "All", img: "icon-folder", group: false }], + onClick: onFilterClick, + }) + ); + + /* + SET UP FILE BROWSER + */ + w2ui["leftLayout"].content( + "main", + $().w2grid({ + name: "grid", + show: { + toolbar: true, + footer: true, + }, + columns: [ + { + field: "recid", + caption: "MFT index", + size: "80px", + sortable: true, + resizable: true, + searchable: "int", + }, + { + field: "baseIds", + caption: "BaseId list", + size: "100%", + sortable: true, + resizable: true, + searchable: true, + }, + { + field: "type", + caption: "Type", + size: "100px", + resizable: true, + sortable: true, + }, + { + field: "fileSize", + caption: "Pack Size", + size: "85px", + resizable: true, + sortable: true, + }, + ], + onClick: function (event) { + viewFileByMFT(event.recid); + }, + }) + ); + + /* + SET UP FILE VIEW 'WINDOW' + */ + $(w2ui["layout"].el("main")) + .append($("

")) + .append($("
")) + .append($("
" + "
" + "
")) + .append( + $("
" + "
" + "
").hide() + ) + .append( + $( + "
" + "
" + "
" + ).hide() + ) + .append($("
" + "
" + "
").hide()) + .append($("
" + "
" + "
").hide()) + .append( + $("
" + "
" + "
").hide() + ); + + $("#fileTabs").w2tabs({ + name: "fileTabs", + active: "tabRaw", + tabs: [ + { + id: "tabRaw", + caption: "Raw", + disabled: true, + onClick: function () { + $(".fileTab").hide(); + $("#fileTabsRaw").show(); + }, + }, + { + id: "tabPF", + caption: "Pack File", + disabled: true, + onClick: function () { + $(".fileTab").hide(); + $("#fileTabsPack").show(); + }, + }, + { + id: "tabTexture", + caption: "Texture", + disabled: true, + onClick: function () { + $(".fileTab").hide(); + $("#fileTabsTexture").show(); + }, + }, + { + id: "tabString", + caption: "String", + disabled: true, + onClick: function () { + $(".fileTab").hide(); + $("#fileTabsString").show(); + }, + }, + { + id: "tabModel", + caption: "Model", + disabled: true, + onClick: function () { + $(".fileTab").hide(); + $("#fileTabsModel").show(); + }, + }, + { + id: "tabSound", + caption: "Sound", + disabled: true, + onClick: function () { + $(".fileTab").hide(); + $("#fileTabsSound").show(); + }, + }, + ], + }); + + /// Set up grid for strings view + ///Create grid + $("#stringOutput").w2grid({ + name: "stringGrid", + selectType: "cell", + show: { + toolbar: true, + footer: true, + }, + columns: [ + { field: "recid", caption: "Row #", size: "60px" }, + { field: "value", caption: "Text", size: "100%" }, + ], + }); + + /* + SET UP TREE 3D SCENE + */ + setupScene(); + + /// Ask for file + w2popup.open({ + speed: 0, + title: "Load A GW2 dat", + modal: true, + showClose: false, + body: + '
' + + '
' + + '' + + "
", + }); + + $("#filePickerPop").change(function (evt) { + _lr = T3D.getLocalReader(evt.target.files[0], onReaderCreated, "./static/t3dworker.js"); + }); + + /// Overwrite progress logger + T3D.Logger.logFunctions[T3D.Logger.TYPE_PROGRESS] = function () { + $("#filePickerPop").prop("disabled", true); + $("#fileLoadProgress").html("Indexing .dat file (first visit only)
" + arguments[1] + "%

"); + }; + }); + + function onReaderCreated() { + T3D.getFileListAsync( + _lr, + function (files) { + /// Store fileList globally + _fileList = files; + + const packNode = { + id: "packGroup", + text: "Pack Files", + img: "icon-folder", + group: false, + nodes: [], + }; + + const textureNode = { + id: "textureGroup", + text: "Texture files", + img: "icon-folder", + group: false, + nodes: [], + }; + + const unsortedNode = { + id: "unsortedGroup", + text: "Unsorted", + img: "icon-folder", + group: false, + nodes: [], + }; + + /// Build sidebar nodes + for (const fileType in _fileList) { + if (Object.getOwnPropertyNames(_fileList).includes(fileType)) { + let node = { id: fileType, img: "icon-folder", group: false }; + //let isPack = false; + if (fileType.startsWith("TEXTURE")) { + node = { + id: fileType, + img: "icon-folder", + group: false, + text: fileType, + }; + textureNode.nodes.push(node); + } else if (fileType === "BINARIES") { + node.text = "Binaries"; + w2ui.sidebar.add(node); + } else if (fileType === "STRINGS") { + node.text = "Strings"; + w2ui.sidebar.add(node); + } else if (fileType.startsWith("PF")) { + node = { + id: fileType, + img: "icon-folder", + group: false, + text: fileType, + }; + packNode.nodes.push(node); + } else if (fileType === "UNKNOWN") { + node.text = "Unknown"; + w2ui.sidebar.add(node); + } else { + node = { + id: fileType, + img: "icon-folder", + group: false, + text: fileType, + }; + unsortedNode.nodes.push(node); + } + } + } + + if (packNode.nodes.length > 0) { + w2ui.sidebar.add(packNode); + } + + if (textureNode.nodes.length > 0) { + w2ui.sidebar.add(textureNode); + } + + if (unsortedNode.nodes.length > 0) { + w2ui.sidebar.add(unsortedNode); + } + + /// Close the pop + w2popup.close(); + + /// Select the "All" category + w2ui.sidebar.click("All"); + } /// End getFileListAsync callback + ); + } + + function onFilterClick(evt) { + /// No filter if clicked group was "All" + if (evt.target === "All") { + showFileGroup(); + } + + /// Other events are fine to just pass + else { + showFileGroup([evt.target]); + } + } + + function showFileGroup(fileTypeFilter) { + w2ui.grid.records = []; + + const reverseTable = _lr.getReverseIndex(); + + for (const fileType in _fileList) { + /// Only show types we've asked for + if (fileTypeFilter && fileTypeFilter.indexOf(fileType) < 0) { + /// Special case for "packGroup" + /// Should let trough all pack types + /// Should NOT let trought any non-pack types + /// i.e. Strings, Binaries etc + if (fileTypeFilter.indexOf("packGroup") >= 0) { + if (!fileType.startsWith("PF")) { + continue; + } + } else if (fileTypeFilter.indexOf("textureGroup") >= 0) { + if (!fileType.startsWith("TEXTURE")) { + continue; + } + } else { + continue; + } + } + + if (Object.keys(_fileList).includes(fileType)) { + const fileArr = _fileList[fileType]; + fileArr.forEach( + function (mftIndex) { + const meta = _lr.getFileMeta(mftIndex); + + const baseIds = reverseTable[mftIndex]; + const fileSize = meta ? meta.size : ""; + + if (fileSize > 0 && mftIndex > 15) { + w2ui["grid"].records.push({ + recid: mftIndex, /// MFT index + baseIds: baseIds, + type: fileType, + fileSize: fileSize, + }); + } + + mftIndex++; + } /// End for each mft in this file type + ); + } /// End if _fileList[filetype] + } /// End for each fileType key in _fileList object + + /// Update file grid + w2ui.grid.refresh(); + } + + function viewFileByMFT(mftIdx) { + const reverseTable = _lr.getReverseIndex(); + + const baseId = reverseTable[mftIdx] ? reverseTable[mftIdx][0] : ""; + + viewFileByFileId(baseId); + } + + function viewFileByFileId(fileId) { + /// Clean outputs + $(".tabOutput").html(""); + $("#fileTitle").html(""); + + /// Clean context toolbar + $("#contextToolbar").html(""); + + /// Disable tabs + w2ui.fileTabs.disable("tabRaw"); + w2ui.fileTabs.disable("tabPF"); + w2ui.fileTabs.disable("tabTexture"); + w2ui.fileTabs.disable("tabString"); + w2ui.fileTabs.disable("tabModel"); + w2ui.fileTabs.disable("tabSound"); + + /// Remove old models from the scene + if (_models) { + _models.forEach(function (mdl) { + _scene.remove(mdl); + }); + } + + /// Make sure _context is clean + _context = {}; + + /// Run the basic DataRenderer, handles all sorts of files for us. + T3D.runRenderer(T3D.DataRenderer, _lr, { id: fileId }, _context, onBasicRendererDone); + } + + function onBasicRendererDone() { + /// Read render output from _context VO + const fileId = (_fileId = T3D.getContextValue(_context, T3D.DataRenderer, "fileId")); + + const rawData = T3D.getContextValue(_context, T3D.DataRenderer, "rawData"); + + const raw = T3D.getContextValue(_context, T3D.DataRenderer, "rawString"); + + const packfile = T3D.getContextValue(_context, T3D.DataRenderer, "file"); + + const image = T3D.getContextValue(_context, T3D.DataRenderer, "image"); + + const fcc = raw.substring(0, 4); + + /// Update main header to show filename + + const fileName = fileId + (image || !packfile ? "." + fcc : "." + packfile.header.type); + $("#fileTitle").html(fileName); + + /// Update raw view and enable tab + w2ui.fileTabs.enable("tabRaw"); + + $("#contextToolbar").append( + $("").click(function () { + const blob = new Blob([rawData], { type: "octet/stream" }); + saveData(blob, fileName + ".raw"); + }) + ); + + $("#rawOutput").append($("
").text(raw)); + + const ui8aRawData = new Uint8Array(rawData); + + /// Texture file + if (image) { + /// Select texture tab + w2ui.fileTabs.enable("tabTexture"); + w2ui.fileTabs.click("tabTexture"); + + /// Display bitmap on canvas + const canvas = $(""); + canvas[0].width = image.width; + canvas[0].height = image.height; + const ctx = canvas[0].getContext("2d"); + const uica = new Uint8ClampedArray(image.data); + const imagedata = new ImageData(uica, image.width, image.height); + ctx.putImageData(imagedata, 0, 0); + + $("#textureOutput").append(canvas); + } + + // PNG texture + else if ( + ui8aRawData.length > 4 && + ui8aRawData[0] === 137 && + ui8aRawData[1] === 80 && // P + ui8aRawData[2] === 78 && // N + ui8aRawData[3] === 71 // G + ) { + /// Select texture tab + w2ui.fileTabs.enable("tabTexture"); + w2ui.fileTabs.click("tabTexture"); + + const canvas = $(""); + const pngBlob = new Blob([rawData], { type: "image/png" }); + const url = URL.createObjectURL(pngBlob); + const img = new Image(); + img.onload = function () { + canvas[0].width = img.width; + canvas[0].height = img.height; + const ctx = canvas[0].getContext("2d"); + ctx.drawImage(this, 0, 0); + URL.revokeObjectURL(url); + }; + img.src = url; + $("#textureOutput").append(canvas); + $("#contextToolbar") + .show() + .append( + $("").click(function () { + const blob = new Blob([rawData], { type: "octet/stream" }); + saveData(blob, fileId + ".png"); + }) + ); + } + + // RIFF texture + else if ( + ui8aRawData.length > 4 && + ui8aRawData[0] === 82 && // R + ui8aRawData[1] === 73 && // I + ui8aRawData[2] === 70 && // F + ui8aRawData[3] === 70 // F + ) { + /// Select texture tab + w2ui.fileTabs.enable("tabTexture"); + w2ui.fileTabs.click("tabTexture"); + + const canvas = $(""); + const riffBlob = new Blob([rawData], { type: "image/webp" }); + const url = URL.createObjectURL(riffBlob); + const img = new Image(); + img.onload = function () { + canvas[0].width = img.width; + canvas[0].height = img.height; + const ctx = canvas[0].getContext("2d"); + ctx.drawImage(this, 0, 0); + URL.revokeObjectURL(url); + }; + img.src = url; + $("#textureOutput").append(canvas); + $("#contextToolbar") + .show() + .append( + $("").click(function () { + const blob = new Blob([rawData], { type: "octet/stream" }); + saveData(blob, fileId + ".riff"); + }) + ); + } + + /// PF Pack file + else if (packfile) { + /// Always render the pack file chunk data + displayPackFile(); + + /// Enable corresponding tab + w2ui.fileTabs.enable("tabPF"); + + /// If the pack file was a model, render it! + if (packfile.header.type === "MODL") { + /// Render model + renderFileModel(fileId); + } else if (packfile.header.type === "ASND") { + /// Get a chunk, this is really the job of a renderer but whatevs + const chunk = packfile.getChunk("ASND"); + + /// Enable and select sound tab + w2ui.fileTabs.enable("tabSound"); + w2ui.fileTabs.click("tabSound"); + + /// Print some random data about this sound + $("#soundOutput").html( + "Length: " + chunk.data.length + " seconds
" + "Size: " + chunk.data.audioData.length + " bytes" + ); + + /// Extract sound data + + const soundUintArray = chunk.data.audioData; + + $("#contextToolbar") + .show() + .append( + $("").click(function () { + const blob = new Blob([soundUintArray], { type: "octet/stream" }); + saveData(blob, fileName + ".mp3"); + }) + ) + .append( + $("").click(function () { + if (!_audioContext) { + _audioContext = new AudioContext(); + } + + /// Stop previous sound + try { + _audioSource.stop(); + } catch (e) { + console.error(e); + } + + /// Create new buffer for current sound + _audioSource = _audioContext.createBufferSource(); + _audioSource.connect(_audioContext.destination); + + /// Decode and start playing + _audioContext.decodeAudioData(soundUintArray.buffer, function (res) { + _audioSource.buffer = res; + _audioSource.start(); + }); + }) + ) + .append( + $("").click(function () { + try { + _audioSource.stop(); + } catch (e) { + console.error(e); + } + }) + ); + } else { + /// Select PF tab + w2ui.fileTabs.click("tabPF"); + } + } else if (fcc === "strs") { + showFileString(fileId); + } + + /// Else just show raw view + else { + w2ui.fileTabs.click("tabRaw"); + } + } + + function displayPackFile() { + //let fileId = T3D.getContextValue(_context, T3D.DataRenderer, "fileId"); + const packfile = T3D.getContextValue(_context, T3D.DataRenderer, "file"); + + $("#packOutput").html(""); + $("#packOutput").append($("

Chunks

")); + + packfile.chunks.forEach(function (chunk) { + const field = $("
"); + const legend = $("" + chunk.header.type + ""); + + const logButton = $(""); + logButton.click(function () { + T3D.Logger.log(T3D.Logger.TYPE_MESSAGE, "Logging", chunk.header.type, "chunk"); + T3D.Logger.log(T3D.Logger.TYPE_MESSAGE, chunk.data); + }); + + field.append(legend); + field.append($("

Size:" + chunk.header.chunkDataSize + "

")); + field.append(logButton); + + $("#packOutput").append(field); + $("#packOutput").show(); + }); + } + + function showFileString(fileId) { + /// Make sure output is clean + _context = {}; + + /// Run single renderer + T3D.runRenderer(T3D.StringRenderer, _lr, { id: fileId }, _context, onRendererDoneString); + } + + function onRendererDoneString() { + /// Read data from renderer + const strings = T3D.getContextValue(_context, T3D.StringRenderer, "strings", []); + + w2ui.stringGrid.records = strings; + + w2ui.stringGrid.buffered = w2ui.stringGrid.records.length; + w2ui.stringGrid.total = w2ui.stringGrid.buffered; + w2ui.stringGrid.refresh(); + + /// Select this view + w2ui.fileTabs.enable("tabString"); + w2ui.fileTabs.click("tabString"); + } + + function renderFileModel(fileId) { + const packfile = T3D.getContextValue(_context, T3D.DataRenderer, "file"); + const hasModel = packfile.chunks.find((chunk) => chunk.header.type === "MODL"); + + /// Make sure output is clean + _context = {}; + + if (hasModel) { + /// Run single renderer + T3D.runRenderer(T3D.SingleModelRenderer, _lr, { id: fileId }, _context, onRendererDoneModel); + } else { + w2ui.fileTabs.click("tabPF"); + } + } + + function onRendererDoneModel() { + /// Enable and select model tab + w2ui.fileTabs.enable("tabModel"); + w2ui.fileTabs.click("tabModel"); + $("#modelOutput").show(); + + /// Re-fit canvas + onCanvasResize(); + + /// Add context toolbar export button + $("#contextToolbar").append($("").click(exportScene)); + + /// Read the new models + _models = T3D.getContextValue(_context, T3D.SingleModelRenderer, "meshes", []); + + /// Keeping track of the biggest model for later + let biggestMdl = null; + + /// Add all models to the scene + _models.forEach(function (model) { + /// Find the biggest model for camera focus/fitting + if (!biggestMdl || biggestMdl.boundingSphere.radius < model.boundingSphere.radius) { + biggestMdl = model; + } + + _scene.add(model); + }); + + /// Reset any zoom and transaltion/rotation done when viewing earlier models. + _controls.reset(); + + /// Focus camera to the bigest model, doesn't work great. + let dist = + biggestMdl && biggestMdl.boundingSphere ? biggestMdl.boundingSphere.radius / Math.tan((Math.PI * 60) / 360) : 100; + dist = 1.2 * Math.max(100, dist); + dist = Math.min(1000, dist); + _camera.position.zoom = 1; + _camera.position.x = dist * Math.sqrt(2); + _camera.position.y = 50; + _camera.position.z = 0; + + if (biggestMdl) _camera.lookAt(biggestMdl.position); + } + + /// Exports current model as an .obj file with a .mtl refering .png textures. + function exportScene() { + /// Get last loaded fileId + const fileId = _fileId; + + /// Run T3D hacked version of OBJExporter + const result = new THREE.OBJExporter().parse(_scene, fileId); + + /// Download obj + const blob = new Blob([result], { type: "octet/stream" }); + saveData(blob, "export." + fileId + ".obj"); + } + + /// Utility for downloading files to client + const saveData = (function () { + const a = document.createElement("a"); + document.body.appendChild(a); + a.style = "display: none"; + return function (blob, fileName) { + const url = window.URL.createObjectURL(blob); + a.href = url; + a.download = fileName; + a.click(); + window.URL.revokeObjectURL(url); + }; + })(); + + /// Setting up a scene, Tree.js standard stuff... + function setupScene() { + const canvasWidth = $("#modelOutput").width(); + const canvasHeight = $("#modelOutput").height(); + const canvasClearColor = 0x342920; // For happy rendering, always use Van Dyke Brown. + const fov = 60; + const aspect = 1; + const near = 0.1; + const far = 500000; + + _camera = new THREE.PerspectiveCamera(fov, aspect, near, far); + + _scene = new THREE.Scene(); + + /// This scene has one ambient light source and three directional lights + const ambientLight = new THREE.AmbientLight(0x555555); + _scene.add(ambientLight); + + const directionalLight1 = new THREE.DirectionalLight(0xffffff, 0.8); + directionalLight1.position.set(0, 0, 1); + _scene.add(directionalLight1); + + const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.8); + directionalLight2.position.set(1, 0, 0); + _scene.add(directionalLight2); + + const directionalLight3 = new THREE.DirectionalLight(0xffffff, 0.8); + directionalLight3.position.set(0, 1, 0); + _scene.add(directionalLight3); + + /// Standard THREE renderer with AA + _renderer = new THREE.WebGLRenderer({ antialiasing: true }); + $("#modelOutput")[0].appendChild(_renderer.domElement); + + _renderer.setSize(canvasWidth, canvasHeight); + _renderer.setClearColor(canvasClearColor); + + /// Add THREE orbit controls, for simple orbiting, panning and zooming + _controls = new THREE.OrbitControls(_camera, _renderer.domElement); + _controls.enableZoom = true; + + /// Sems w2ui delays resizing :/ + $(window).resize(function () { + setTimeout(onCanvasResize, 10); + }); + + /// Note: constant continous rendering from page load event, not very opt. + render(); + } + + function onCanvasResize() { + const sceneWidth = $("#modelOutput").width(); + const sceneHeight = $("#modelOutput").height(); + + if (!sceneHeight || !sceneWidth) return; + + _camera.aspect = sceneWidth / sceneHeight; + + _renderer.setSize(sceneWidth, sceneHeight); + + _camera.updateProjectionMatrix(); + } + + /// Render loop, no game logic, just rendering. + function render() { + window.requestAnimationFrame(render); + _renderer.render(_scene, _camera); + } + }; + +})(); +//# sourceMappingURL=index.js.map diff --git a/browser/index.js.map b/browser/index.js.map new file mode 100644 index 0000000..c2c610a --- /dev/null +++ b/browser/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sources":["../src/index.js"],"sourcesContent":["window.onload = () => {\n /// T3D\n let _lr;\n let _context;\n let _fileId;\n let _fileList;\n let _audioSource;\n let _audioContext;\n\n /// THREE\n let _scene;\n let _camera;\n let _renderer;\n let _models = [];\n let _controls;\n\n $(function () {\n /*\n SET MAIN UP GRID\n */\n const pstyle = \"border: 1px solid #dfdfdf; padding: 0;\";\n $(\"#layout\").w2layout({\n name: \"layout\",\n panels: [\n {\n type: \"left\",\n size: 570,\n resizable: true,\n style: pstyle + \"margin:0\",\n },\n {\n type: \"main\",\n style: pstyle + \" background-color: transparent;\",\n toolbar: {\n style: \"background-color:#eaeaea; height:40px\",\n items: [\n {\n type: \"html\",\n id: \"fileIdToolbar\",\n html:\n '
' +\n \" File ID:\" +\n ' ' +\n ' \" +\n \"
\",\n },\n {\n type: \"html\",\n id: \"contextToolbar\",\n html: '
',\n },\n ],\n onClick: function (event) {\n this.owner.content(\"main\", event);\n },\n },\n },\n ],\n onResize: onCanvasResize,\n });\n\n $(\"#fileIdInputBtn\").click(function () {\n viewFileByFileId($(\"#fileIdInput\").val());\n });\n\n /// Grid inside main left\n $().w2layout({\n name: \"leftLayout\",\n panels: [\n {\n type: \"left\",\n size: 150,\n resizable: true,\n style: pstyle,\n content: \"left\",\n },\n {\n type: \"main\",\n size: 420,\n resizable: true,\n style: pstyle,\n content: \"right\",\n },\n ],\n });\n w2ui[\"layout\"].content(\"left\", w2ui[\"leftLayout\"]);\n\n /*\n SIDEBAR\n */\n w2ui[\"leftLayout\"].content(\n \"left\",\n $().w2sidebar({\n name: \"sidebar\",\n img: null,\n nodes: [{ id: \"All\", text: \"All\", img: \"icon-folder\", group: false }],\n onClick: onFilterClick,\n })\n );\n\n /*\n SET UP FILE BROWSER\n */\n w2ui[\"leftLayout\"].content(\n \"main\",\n $().w2grid({\n name: \"grid\",\n show: {\n toolbar: true,\n footer: true,\n },\n columns: [\n {\n field: \"recid\",\n caption: \"MFT index\",\n size: \"80px\",\n sortable: true,\n resizable: true,\n searchable: \"int\",\n },\n {\n field: \"baseIds\",\n caption: \"BaseId list\",\n size: \"100%\",\n sortable: true,\n resizable: true,\n searchable: true,\n },\n {\n field: \"type\",\n caption: \"Type\",\n size: \"100px\",\n resizable: true,\n sortable: true,\n },\n {\n field: \"fileSize\",\n caption: \"Pack Size\",\n size: \"85px\",\n resizable: true,\n sortable: true,\n },\n ],\n onClick: function (event) {\n viewFileByMFT(event.recid);\n },\n })\n );\n\n /*\n SET UP FILE VIEW 'WINDOW'\n */\n $(w2ui[\"layout\"].el(\"main\"))\n .append($(\"

\"))\n .append($(\"
\"))\n .append($(\"
\" + \"
\" + \"
\"))\n .append(\n $(\"
\" + \"
\" + \"
\").hide()\n )\n .append(\n $(\n \"
\" + \"
\" + \"
\"\n ).hide()\n )\n .append($(\"
\" + \"
\" + \"
\").hide())\n .append($(\"
\" + \"
\" + \"
\").hide())\n .append(\n $(\"
\" + \"
\" + \"
\").hide()\n );\n\n $(\"#fileTabs\").w2tabs({\n name: \"fileTabs\",\n active: \"tabRaw\",\n tabs: [\n {\n id: \"tabRaw\",\n caption: \"Raw\",\n disabled: true,\n onClick: function () {\n $(\".fileTab\").hide();\n $(\"#fileTabsRaw\").show();\n },\n },\n {\n id: \"tabPF\",\n caption: \"Pack File\",\n disabled: true,\n onClick: function () {\n $(\".fileTab\").hide();\n $(\"#fileTabsPack\").show();\n },\n },\n {\n id: \"tabTexture\",\n caption: \"Texture\",\n disabled: true,\n onClick: function () {\n $(\".fileTab\").hide();\n $(\"#fileTabsTexture\").show();\n },\n },\n {\n id: \"tabString\",\n caption: \"String\",\n disabled: true,\n onClick: function () {\n $(\".fileTab\").hide();\n $(\"#fileTabsString\").show();\n },\n },\n {\n id: \"tabModel\",\n caption: \"Model\",\n disabled: true,\n onClick: function () {\n $(\".fileTab\").hide();\n $(\"#fileTabsModel\").show();\n },\n },\n {\n id: \"tabSound\",\n caption: \"Sound\",\n disabled: true,\n onClick: function () {\n $(\".fileTab\").hide();\n $(\"#fileTabsSound\").show();\n },\n },\n ],\n });\n\n /// Set up grid for strings view\n ///Create grid\n $(\"#stringOutput\").w2grid({\n name: \"stringGrid\",\n selectType: \"cell\",\n show: {\n toolbar: true,\n footer: true,\n },\n columns: [\n { field: \"recid\", caption: \"Row #\", size: \"60px\" },\n { field: \"value\", caption: \"Text\", size: \"100%\" },\n ],\n });\n\n /*\n SET UP TREE 3D SCENE\n */\n setupScene();\n\n /// Ask for file\n w2popup.open({\n speed: 0,\n title: \"Load A GW2 dat\",\n modal: true,\n showClose: false,\n body:\n '
' +\n '
' +\n '' +\n \"
\",\n });\n\n $(\"#filePickerPop\").change(function (evt) {\n _lr = T3D.getLocalReader(evt.target.files[0], onReaderCreated, \"./static/t3dworker.js\");\n });\n\n /// Overwrite progress logger\n T3D.Logger.logFunctions[T3D.Logger.TYPE_PROGRESS] = function () {\n $(\"#filePickerPop\").prop(\"disabled\", true);\n $(\"#fileLoadProgress\").html(\"Indexing .dat file (first visit only)
\" + arguments[1] + \"%

\");\n };\n });\n\n function onReaderCreated() {\n T3D.getFileListAsync(\n _lr,\n function (files) {\n /// Store fileList globally\n _fileList = files;\n\n const packNode = {\n id: \"packGroup\",\n text: \"Pack Files\",\n img: \"icon-folder\",\n group: false,\n nodes: [],\n };\n\n const textureNode = {\n id: \"textureGroup\",\n text: \"Texture files\",\n img: \"icon-folder\",\n group: false,\n nodes: [],\n };\n\n const unsortedNode = {\n id: \"unsortedGroup\",\n text: \"Unsorted\",\n img: \"icon-folder\",\n group: false,\n nodes: [],\n };\n\n /// Build sidebar nodes\n for (const fileType in _fileList) {\n if (Object.getOwnPropertyNames(_fileList).includes(fileType)) {\n let node = { id: fileType, img: \"icon-folder\", group: false };\n //let isPack = false;\n if (fileType.startsWith(\"TEXTURE\")) {\n node = {\n id: fileType,\n img: \"icon-folder\",\n group: false,\n text: fileType,\n };\n textureNode.nodes.push(node);\n } else if (fileType === \"BINARIES\") {\n node.text = \"Binaries\";\n w2ui.sidebar.add(node);\n } else if (fileType === \"STRINGS\") {\n node.text = \"Strings\";\n w2ui.sidebar.add(node);\n } else if (fileType.startsWith(\"PF\")) {\n node = {\n id: fileType,\n img: \"icon-folder\",\n group: false,\n text: fileType,\n };\n packNode.nodes.push(node);\n } else if (fileType === \"UNKNOWN\") {\n node.text = \"Unknown\";\n w2ui.sidebar.add(node);\n } else {\n node = {\n id: fileType,\n img: \"icon-folder\",\n group: false,\n text: fileType,\n };\n unsortedNode.nodes.push(node);\n }\n }\n }\n\n if (packNode.nodes.length > 0) {\n w2ui.sidebar.add(packNode);\n }\n\n if (textureNode.nodes.length > 0) {\n w2ui.sidebar.add(textureNode);\n }\n\n if (unsortedNode.nodes.length > 0) {\n w2ui.sidebar.add(unsortedNode);\n }\n\n /// Close the pop\n w2popup.close();\n\n /// Select the \"All\" category\n w2ui.sidebar.click(\"All\");\n } /// End getFileListAsync callback\n );\n }\n\n function onFilterClick(evt) {\n /// No filter if clicked group was \"All\"\n if (evt.target === \"All\") {\n showFileGroup();\n }\n\n /// Other events are fine to just pass\n else {\n showFileGroup([evt.target]);\n }\n }\n\n function showFileGroup(fileTypeFilter) {\n w2ui.grid.records = [];\n\n const reverseTable = _lr.getReverseIndex();\n\n for (const fileType in _fileList) {\n /// Only show types we've asked for\n if (fileTypeFilter && fileTypeFilter.indexOf(fileType) < 0) {\n /// Special case for \"packGroup\"\n /// Should let trough all pack types\n /// Should NOT let trought any non-pack types\n /// i.e. Strings, Binaries etc\n if (fileTypeFilter.indexOf(\"packGroup\") >= 0) {\n if (!fileType.startsWith(\"PF\")) {\n continue;\n }\n } else if (fileTypeFilter.indexOf(\"textureGroup\") >= 0) {\n if (!fileType.startsWith(\"TEXTURE\")) {\n continue;\n }\n } else {\n continue;\n }\n }\n\n if (Object.keys(_fileList).includes(fileType)) {\n const fileArr = _fileList[fileType];\n fileArr.forEach(\n function (mftIndex) {\n const meta = _lr.getFileMeta(mftIndex);\n\n const baseIds = reverseTable[mftIndex];\n const fileSize = meta ? meta.size : \"\";\n\n if (fileSize > 0 && mftIndex > 15) {\n w2ui[\"grid\"].records.push({\n recid: mftIndex, /// MFT index\n baseIds: baseIds,\n type: fileType,\n fileSize: fileSize,\n });\n }\n\n mftIndex++;\n } /// End for each mft in this file type\n );\n } /// End if _fileList[filetype]\n } /// End for each fileType key in _fileList object\n\n /// Update file grid\n w2ui.grid.refresh();\n }\n\n function viewFileByMFT(mftIdx) {\n const reverseTable = _lr.getReverseIndex();\n\n const baseId = reverseTable[mftIdx] ? reverseTable[mftIdx][0] : \"\";\n\n viewFileByFileId(baseId);\n }\n\n function viewFileByFileId(fileId) {\n /// Clean outputs\n $(\".tabOutput\").html(\"\");\n $(\"#fileTitle\").html(\"\");\n\n /// Clean context toolbar\n $(\"#contextToolbar\").html(\"\");\n\n /// Disable tabs\n w2ui.fileTabs.disable(\"tabRaw\");\n w2ui.fileTabs.disable(\"tabPF\");\n w2ui.fileTabs.disable(\"tabTexture\");\n w2ui.fileTabs.disable(\"tabString\");\n w2ui.fileTabs.disable(\"tabModel\");\n w2ui.fileTabs.disable(\"tabSound\");\n\n /// Remove old models from the scene\n if (_models) {\n _models.forEach(function (mdl) {\n _scene.remove(mdl);\n });\n }\n\n /// Make sure _context is clean\n _context = {};\n\n /// Run the basic DataRenderer, handles all sorts of files for us.\n T3D.runRenderer(T3D.DataRenderer, _lr, { id: fileId }, _context, onBasicRendererDone);\n }\n\n function onBasicRendererDone() {\n /// Read render output from _context VO\n const fileId = (_fileId = T3D.getContextValue(_context, T3D.DataRenderer, \"fileId\"));\n\n const rawData = T3D.getContextValue(_context, T3D.DataRenderer, \"rawData\");\n\n const raw = T3D.getContextValue(_context, T3D.DataRenderer, \"rawString\");\n\n const packfile = T3D.getContextValue(_context, T3D.DataRenderer, \"file\");\n\n const image = T3D.getContextValue(_context, T3D.DataRenderer, \"image\");\n\n const fcc = raw.substring(0, 4);\n\n /// Update main header to show filename\n\n const fileName = fileId + (image || !packfile ? \".\" + fcc : \".\" + packfile.header.type);\n $(\"#fileTitle\").html(fileName);\n\n /// Update raw view and enable tab\n w2ui.fileTabs.enable(\"tabRaw\");\n\n $(\"#contextToolbar\").append(\n $(\"\").click(function () {\n const blob = new Blob([rawData], { type: \"octet/stream\" });\n saveData(blob, fileName + \".raw\");\n })\n );\n\n $(\"#rawOutput\").append($(\"
\").text(raw));\n\n const ui8aRawData = new Uint8Array(rawData);\n\n /// Texture file\n if (image) {\n /// Select texture tab\n w2ui.fileTabs.enable(\"tabTexture\");\n w2ui.fileTabs.click(\"tabTexture\");\n\n /// Display bitmap on canvas\n const canvas = $(\"\");\n canvas[0].width = image.width;\n canvas[0].height = image.height;\n const ctx = canvas[0].getContext(\"2d\");\n const uica = new Uint8ClampedArray(image.data);\n const imagedata = new ImageData(uica, image.width, image.height);\n ctx.putImageData(imagedata, 0, 0);\n\n $(\"#textureOutput\").append(canvas);\n }\n\n // PNG texture\n else if (\n ui8aRawData.length > 4 &&\n ui8aRawData[0] === 137 &&\n ui8aRawData[1] === 80 && // P\n ui8aRawData[2] === 78 && // N\n ui8aRawData[3] === 71 // G\n ) {\n /// Select texture tab\n w2ui.fileTabs.enable(\"tabTexture\");\n w2ui.fileTabs.click(\"tabTexture\");\n\n const canvas = $(\"\");\n const pngBlob = new Blob([rawData], { type: \"image/png\" });\n const url = URL.createObjectURL(pngBlob);\n const img = new Image();\n img.onload = function () {\n canvas[0].width = img.width;\n canvas[0].height = img.height;\n const ctx = canvas[0].getContext(\"2d\");\n ctx.drawImage(this, 0, 0);\n URL.revokeObjectURL(url);\n };\n img.src = url;\n $(\"#textureOutput\").append(canvas);\n $(\"#contextToolbar\")\n .show()\n .append(\n $(\"\").click(function () {\n const blob = new Blob([rawData], { type: \"octet/stream\" });\n saveData(blob, fileId + \".png\");\n })\n );\n }\n\n // RIFF texture\n else if (\n ui8aRawData.length > 4 &&\n ui8aRawData[0] === 82 && // R\n ui8aRawData[1] === 73 && // I\n ui8aRawData[2] === 70 && // F\n ui8aRawData[3] === 70 // F\n ) {\n /// Select texture tab\n w2ui.fileTabs.enable(\"tabTexture\");\n w2ui.fileTabs.click(\"tabTexture\");\n\n const canvas = $(\"\");\n const riffBlob = new Blob([rawData], { type: \"image/webp\" });\n const url = URL.createObjectURL(riffBlob);\n const img = new Image();\n img.onload = function () {\n canvas[0].width = img.width;\n canvas[0].height = img.height;\n const ctx = canvas[0].getContext(\"2d\");\n ctx.drawImage(this, 0, 0);\n URL.revokeObjectURL(url);\n };\n img.src = url;\n $(\"#textureOutput\").append(canvas);\n $(\"#contextToolbar\")\n .show()\n .append(\n $(\"\").click(function () {\n const blob = new Blob([rawData], { type: \"octet/stream\" });\n saveData(blob, fileId + \".riff\");\n })\n );\n }\n\n /// PF Pack file\n else if (packfile) {\n /// Always render the pack file chunk data\n displayPackFile();\n\n /// Enable corresponding tab\n w2ui.fileTabs.enable(\"tabPF\");\n\n /// If the pack file was a model, render it!\n if (packfile.header.type === \"MODL\") {\n /// Render model\n renderFileModel(fileId);\n } else if (packfile.header.type === \"ASND\") {\n /// Get a chunk, this is really the job of a renderer but whatevs\n const chunk = packfile.getChunk(\"ASND\");\n\n /// Enable and select sound tab\n w2ui.fileTabs.enable(\"tabSound\");\n w2ui.fileTabs.click(\"tabSound\");\n\n /// Print some random data about this sound\n $(\"#soundOutput\").html(\n \"Length: \" + chunk.data.length + \" seconds
\" + \"Size: \" + chunk.data.audioData.length + \" bytes\"\n );\n\n /// Extract sound data\n\n const soundUintArray = chunk.data.audioData;\n\n $(\"#contextToolbar\")\n .show()\n .append(\n $(\"\").click(function () {\n const blob = new Blob([soundUintArray], { type: \"octet/stream\" });\n saveData(blob, fileName + \".mp3\");\n })\n )\n .append(\n $(\"\").click(function () {\n if (!_audioContext) {\n _audioContext = new AudioContext();\n }\n\n /// Stop previous sound\n try {\n _audioSource.stop();\n } catch (e) {\n console.error(e);\n }\n\n /// Create new buffer for current sound\n _audioSource = _audioContext.createBufferSource();\n _audioSource.connect(_audioContext.destination);\n\n /// Decode and start playing\n _audioContext.decodeAudioData(soundUintArray.buffer, function (res) {\n _audioSource.buffer = res;\n _audioSource.start();\n });\n })\n )\n .append(\n $(\"\").click(function () {\n try {\n _audioSource.stop();\n } catch (e) {\n console.error(e);\n }\n })\n );\n } else {\n /// Select PF tab\n w2ui.fileTabs.click(\"tabPF\");\n }\n } else if (fcc === \"strs\") {\n showFileString(fileId);\n }\n\n /// Else just show raw view\n else {\n w2ui.fileTabs.click(\"tabRaw\");\n }\n }\n\n function displayPackFile() {\n //let fileId = T3D.getContextValue(_context, T3D.DataRenderer, \"fileId\");\n const packfile = T3D.getContextValue(_context, T3D.DataRenderer, \"file\");\n\n $(\"#packOutput\").html(\"\");\n $(\"#packOutput\").append($(\"

Chunks

\"));\n\n packfile.chunks.forEach(function (chunk) {\n const field = $(\"
\");\n const legend = $(\"\" + chunk.header.type + \"\");\n\n const logButton = $(\"\");\n logButton.click(function () {\n T3D.Logger.log(T3D.Logger.TYPE_MESSAGE, \"Logging\", chunk.header.type, \"chunk\");\n T3D.Logger.log(T3D.Logger.TYPE_MESSAGE, chunk.data);\n });\n\n field.append(legend);\n field.append($(\"

Size:\" + chunk.header.chunkDataSize + \"

\"));\n field.append(logButton);\n\n $(\"#packOutput\").append(field);\n $(\"#packOutput\").show();\n });\n }\n\n function showFileString(fileId) {\n /// Make sure output is clean\n _context = {};\n\n /// Run single renderer\n T3D.runRenderer(T3D.StringRenderer, _lr, { id: fileId }, _context, onRendererDoneString);\n }\n\n function onRendererDoneString() {\n /// Read data from renderer\n const strings = T3D.getContextValue(_context, T3D.StringRenderer, \"strings\", []);\n\n w2ui.stringGrid.records = strings;\n\n w2ui.stringGrid.buffered = w2ui.stringGrid.records.length;\n w2ui.stringGrid.total = w2ui.stringGrid.buffered;\n w2ui.stringGrid.refresh();\n\n /// Select this view\n w2ui.fileTabs.enable(\"tabString\");\n w2ui.fileTabs.click(\"tabString\");\n }\n\n function renderFileModel(fileId) {\n const packfile = T3D.getContextValue(_context, T3D.DataRenderer, \"file\");\n const hasModel = packfile.chunks.find((chunk) => chunk.header.type === \"MODL\");\n\n /// Make sure output is clean\n _context = {};\n\n if (hasModel) {\n /// Run single renderer\n T3D.runRenderer(T3D.SingleModelRenderer, _lr, { id: fileId }, _context, onRendererDoneModel);\n } else {\n w2ui.fileTabs.click(\"tabPF\");\n }\n }\n\n function onRendererDoneModel() {\n /// Enable and select model tab\n w2ui.fileTabs.enable(\"tabModel\");\n w2ui.fileTabs.click(\"tabModel\");\n $(\"#modelOutput\").show();\n\n /// Re-fit canvas\n onCanvasResize();\n\n /// Add context toolbar export button\n $(\"#contextToolbar\").append($(\"\").click(exportScene));\n\n /// Read the new models\n _models = T3D.getContextValue(_context, T3D.SingleModelRenderer, \"meshes\", []);\n\n /// Keeping track of the biggest model for later\n let biggestMdl = null;\n\n /// Add all models to the scene\n _models.forEach(function (model) {\n /// Find the biggest model for camera focus/fitting\n if (!biggestMdl || biggestMdl.boundingSphere.radius < model.boundingSphere.radius) {\n biggestMdl = model;\n }\n\n _scene.add(model);\n });\n\n /// Reset any zoom and transaltion/rotation done when viewing earlier models.\n _controls.reset();\n\n /// Focus camera to the bigest model, doesn't work great.\n let dist =\n biggestMdl && biggestMdl.boundingSphere ? biggestMdl.boundingSphere.radius / Math.tan((Math.PI * 60) / 360) : 100;\n dist = 1.2 * Math.max(100, dist);\n dist = Math.min(1000, dist);\n _camera.position.zoom = 1;\n _camera.position.x = dist * Math.sqrt(2);\n _camera.position.y = 50;\n _camera.position.z = 0;\n\n if (biggestMdl) _camera.lookAt(biggestMdl.position);\n }\n\n /// Exports current model as an .obj file with a .mtl refering .png textures.\n function exportScene() {\n /// Get last loaded fileId\n const fileId = _fileId;\n\n /// Run T3D hacked version of OBJExporter\n const result = new THREE.OBJExporter().parse(_scene, fileId);\n\n /// Download obj\n const blob = new Blob([result], { type: \"octet/stream\" });\n saveData(blob, \"export.\" + fileId + \".obj\");\n }\n\n /// Utility for downloading files to client\n const saveData = (function () {\n const a = document.createElement(\"a\");\n document.body.appendChild(a);\n a.style = \"display: none\";\n return function (blob, fileName) {\n const url = window.URL.createObjectURL(blob);\n a.href = url;\n a.download = fileName;\n a.click();\n window.URL.revokeObjectURL(url);\n };\n })();\n\n /// Setting up a scene, Tree.js standard stuff...\n function setupScene() {\n const canvasWidth = $(\"#modelOutput\").width();\n const canvasHeight = $(\"#modelOutput\").height();\n const canvasClearColor = 0x342920; // For happy rendering, always use Van Dyke Brown.\n const fov = 60;\n const aspect = 1;\n const near = 0.1;\n const far = 500000;\n\n _camera = new THREE.PerspectiveCamera(fov, aspect, near, far);\n\n _scene = new THREE.Scene();\n\n /// This scene has one ambient light source and three directional lights\n const ambientLight = new THREE.AmbientLight(0x555555);\n _scene.add(ambientLight);\n\n const directionalLight1 = new THREE.DirectionalLight(0xffffff, 0.8);\n directionalLight1.position.set(0, 0, 1);\n _scene.add(directionalLight1);\n\n const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.8);\n directionalLight2.position.set(1, 0, 0);\n _scene.add(directionalLight2);\n\n const directionalLight3 = new THREE.DirectionalLight(0xffffff, 0.8);\n directionalLight3.position.set(0, 1, 0);\n _scene.add(directionalLight3);\n\n /// Standard THREE renderer with AA\n _renderer = new THREE.WebGLRenderer({ antialiasing: true });\n $(\"#modelOutput\")[0].appendChild(_renderer.domElement);\n\n _renderer.setSize(canvasWidth, canvasHeight);\n _renderer.setClearColor(canvasClearColor);\n\n /// Add THREE orbit controls, for simple orbiting, panning and zooming\n _controls = new THREE.OrbitControls(_camera, _renderer.domElement);\n _controls.enableZoom = true;\n\n /// Sems w2ui delays resizing :/\n $(window).resize(function () {\n setTimeout(onCanvasResize, 10);\n });\n\n /// Note: constant continous rendering from page load event, not very opt.\n render();\n }\n\n function onCanvasResize() {\n const sceneWidth = $(\"#modelOutput\").width();\n const sceneHeight = $(\"#modelOutput\").height();\n\n if (!sceneHeight || !sceneWidth) return;\n\n _camera.aspect = sceneWidth / sceneHeight;\n\n _renderer.setSize(sceneWidth, sceneHeight);\n\n _camera.updateProjectionMatrix();\n }\n\n /// Render loop, no game logic, just rendering.\n function render() {\n window.requestAnimationFrame(render);\n _renderer.render(_scene, _camera);\n }\n};\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/browser/static/FlyControls.js b/browser/static/FlyControls.js new file mode 100644 index 0000000..253d987 --- /dev/null +++ b/browser/static/FlyControls.js @@ -0,0 +1,307 @@ +THREE.FlyControls = function ( object, domElement ) { + + if ( domElement === undefined ) { + + console.warn( 'THREE.FlyControls: The second parameter "domElement" is now mandatory.' ); + domElement = document; + + } + + this.object = object; + this.domElement = domElement; + + if ( domElement ) this.domElement.setAttribute( 'tabindex', - 1 ); + + // API + + this.movementSpeed = 1.0; + this.rollSpeed = 0.005; + + this.dragToLook = false; + this.autoForward = false; + + // disable default target object behavior + + // internals + + var scope = this; + var changeEvent = { type: "change" }; + var EPS = 0.000001; + + this.tmpQuaternion = new THREE.Quaternion(); + + this.mouseStatus = 0; + + this.moveState = { up: 0, down: 0, left: 0, right: 0, forward: 0, back: 0, pitchUp: 0, pitchDown: 0, yawLeft: 0, yawRight: 0, rollLeft: 0, rollRight: 0 }; + this.moveVector = new THREE.Vector3( 0, 0, 0 ); + this.rotationVector = new THREE.Vector3( 0, 0, 0 ); + + this.keydown = function ( event ) { + + if ( event.altKey ) { + + return; + + } + + //event.preventDefault(); + + switch ( event.keyCode ) { + + case 16: /* shift */ this.movementSpeedMultiplier = .1; break; + + case 87: /*W*/ this.moveState.forward = 1; break; + case 83: /*S*/ this.moveState.back = 1; break; + + case 65: /*A*/ this.moveState.left = 1; break; + case 68: /*D*/ this.moveState.right = 1; break; + + case 82: /*R*/ this.moveState.up = 1; break; + case 70: /*F*/ this.moveState.down = 1; break; + + case 38: /*up*/ this.moveState.pitchUp = 1; break; + case 40: /*down*/ this.moveState.pitchDown = 1; break; + + case 37: /*left*/ this.moveState.yawLeft = 1; break; + case 39: /*right*/ this.moveState.yawRight = 1; break; + + case 81: /*Q*/ this.moveState.rollLeft = 1; break; + case 69: /*E*/ this.moveState.rollRight = 1; break; + + } + + this.updateMovementVector(); + this.updateRotationVector(); + + }; + + this.keyup = function ( event ) { + + switch ( event.keyCode ) { + + case 16: /* shift */ this.movementSpeedMultiplier = 1; break; + + case 87: /*W*/ this.moveState.forward = 0; break; + case 83: /*S*/ this.moveState.back = 0; break; + + case 65: /*A*/ this.moveState.left = 0; break; + case 68: /*D*/ this.moveState.right = 0; break; + + case 82: /*R*/ this.moveState.up = 0; break; + case 70: /*F*/ this.moveState.down = 0; break; + + case 38: /*up*/ this.moveState.pitchUp = 0; break; + case 40: /*down*/ this.moveState.pitchDown = 0; break; + + case 37: /*left*/ this.moveState.yawLeft = 0; break; + case 39: /*right*/ this.moveState.yawRight = 0; break; + + case 81: /*Q*/ this.moveState.rollLeft = 0; break; + case 69: /*E*/ this.moveState.rollRight = 0; break; + + } + + this.updateMovementVector(); + this.updateRotationVector(); + + }; + + this.mousedown = function ( event ) { + + if ( this.domElement !== document ) { + + this.domElement.focus(); + + } + + event.preventDefault(); + event.stopPropagation(); + + if ( this.dragToLook ) { + + this.mouseStatus ++; + + } else { + + switch ( event.button ) { + + case 0: this.moveState.forward = 1; break; + case 2: this.moveState.back = 1; break; + + } + + this.updateMovementVector(); + + } + + }; + + this.mousemove = function ( event ) { + + if ( ! this.dragToLook || this.mouseStatus > 0 ) { + + var container = this.getContainerDimensions(); + var halfWidth = container.size[ 0 ] / 2; + var halfHeight = container.size[ 1 ] / 2; + + this.moveState.yawLeft = - ( ( event.pageX - container.offset[ 0 ] ) - halfWidth ) / halfWidth; + this.moveState.pitchDown = ( ( event.pageY - container.offset[ 1 ] ) - halfHeight ) / halfHeight; + + this.updateRotationVector(); + + } + + }; + + this.mouseup = function ( event ) { + + event.preventDefault(); + event.stopPropagation(); + + if ( this.dragToLook ) { + + this.mouseStatus --; + + this.moveState.yawLeft = this.moveState.pitchDown = 0; + + } else { + + switch ( event.button ) { + + case 0: this.moveState.forward = 0; break; + case 2: this.moveState.back = 0; break; + + } + + this.updateMovementVector(); + + } + + this.updateRotationVector(); + + }; + + this.update = function () { + + var lastQuaternion = new THREE.Quaternion(); + var lastPosition = new THREE.Vector3(); + + return function ( delta ) { + + var moveMult = delta * scope.movementSpeed; + var rotMult = delta * scope.rollSpeed; + + scope.object.translateX( scope.moveVector.x * moveMult ); + scope.object.translateY( scope.moveVector.y * moveMult ); + scope.object.translateZ( scope.moveVector.z * moveMult ); + + scope.tmpQuaternion.set( scope.rotationVector.x * rotMult, scope.rotationVector.y * rotMult, scope.rotationVector.z * rotMult, 1 ).normalize(); + scope.object.quaternion.multiply( scope.tmpQuaternion ); + + if ( + lastPosition.distanceToSquared( scope.object.position ) > EPS || + 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS + ) { + + scope.dispatchEvent( changeEvent ); + lastQuaternion.copy( scope.object.quaternion ); + lastPosition.copy( scope.object.position ); + + } + + }; + + }(); + + this.updateMovementVector = function () { + + var forward = ( this.moveState.forward || ( this.autoForward && ! this.moveState.back ) ) ? 1 : 0; + + this.moveVector.x = ( - this.moveState.left + this.moveState.right ); + this.moveVector.y = ( - this.moveState.down + this.moveState.up ); + this.moveVector.z = ( - forward + this.moveState.back ); + + //console.log( 'move:', [ this.moveVector.x, this.moveVector.y, this.moveVector.z ] ); + + }; + + this.updateRotationVector = function () { + + this.rotationVector.x = ( - this.moveState.pitchDown + this.moveState.pitchUp ); + this.rotationVector.y = ( - this.moveState.yawRight + this.moveState.yawLeft ); + this.rotationVector.z = ( - this.moveState.rollRight + this.moveState.rollLeft ); + + //console.log( 'rotate:', [ this.rotationVector.x, this.rotationVector.y, this.rotationVector.z ] ); + + }; + + this.getContainerDimensions = function () { + + if ( this.domElement != document ) { + + return { + size: [ this.domElement.offsetWidth, this.domElement.offsetHeight ], + offset: [ this.domElement.offsetLeft, this.domElement.offsetTop ] + }; + + } else { + + return { + size: [ window.innerWidth, window.innerHeight ], + offset: [ 0, 0 ] + }; + + } + + }; + + function bind( scope, fn ) { + + return function () { + + fn.apply( scope, arguments ); + + }; + + } + + function contextmenu( event ) { + + event.preventDefault(); + + } + + this.dispose = function () { + + this.domElement.removeEventListener( 'contextmenu', contextmenu, false ); + this.domElement.removeEventListener( 'mousedown', _mousedown, false ); + this.domElement.removeEventListener( 'mousemove', _mousemove, false ); + this.domElement.removeEventListener( 'mouseup', _mouseup, false ); + + window.removeEventListener( 'keydown', _keydown, false ); + window.removeEventListener( 'keyup', _keyup, false ); + + }; + + var _mousemove = bind( this, this.mousemove ); + var _mousedown = bind( this, this.mousedown ); + var _mouseup = bind( this, this.mouseup ); + var _keydown = bind( this, this.keydown ); + var _keyup = bind( this, this.keyup ); + + this.domElement.addEventListener( 'contextmenu', contextmenu, false ); + + this.domElement.addEventListener( 'mousemove', _mousemove, false ); + this.domElement.addEventListener( 'mousedown', _mousedown, false ); + this.domElement.addEventListener( 'mouseup', _mouseup, false ); + + window.addEventListener( 'keydown', _keydown, false ); + window.addEventListener( 'keyup', _keyup, false ); + + this.updateMovementVector(); + this.updateRotationVector(); + +}; + +THREE.FlyControls.prototype = Object.create( THREE.EventDispatcher.prototype ); +THREE.FlyControls.prototype.constructor = THREE.FlyControls; diff --git a/browser/static/OBJExporter.js b/browser/static/OBJExporter.js new file mode 100644 index 0000000..ba1cb26 --- /dev/null +++ b/browser/static/OBJExporter.js @@ -0,0 +1,328 @@ +THREE.OBJExporter = function () {}; + +THREE.OBJExporter.prototype = { + + constructor: THREE.OBJExporter, + + parse: function ( object ) { + + var output = ''; + + var indexVertex = 0; + var indexVertexUvs = 0; + var indexNormals = 0; + + var vertex = new THREE.Vector3(); + var color = new THREE.Color(); + var normal = new THREE.Vector3(); + var uv = new THREE.Vector2(); + + var i, j, k, l, m, face = []; + + var parseMesh = function ( mesh ) { + + var nbVertex = 0; + var nbNormals = 0; + var nbVertexUvs = 0; + + var geometry = mesh.geometry; + + var normalMatrixWorld = new THREE.Matrix3(); + + if ( geometry instanceof THREE.Geometry ) { + + geometry = new THREE.BufferGeometry().setFromObject( mesh ); + + } + + if ( geometry instanceof THREE.BufferGeometry ) { + + // shortcuts + var vertices = geometry.getAttribute( 'position' ); + var normals = geometry.getAttribute( 'normal' ); + var uvs = geometry.getAttribute( 'uv' ); + var indices = geometry.getIndex(); + + // name of the mesh object + output += 'o ' + mesh.name + '\n'; + + // name of the mesh material + if ( mesh.material && mesh.material.name ) { + + output += 'usemtl ' + mesh.material.name + '\n'; + + } + + // vertices + + if ( vertices !== undefined ) { + + for ( i = 0, l = vertices.count; i < l; i ++, nbVertex ++ ) { + + vertex.x = vertices.getX( i ); + vertex.y = vertices.getY( i ); + vertex.z = vertices.getZ( i ); + + // transform the vertex to world space + vertex.applyMatrix4( mesh.matrixWorld ); + + // transform the vertex to export format + output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'; + + } + + } + + // uvs + + if ( uvs !== undefined ) { + + for ( i = 0, l = uvs.count; i < l; i ++, nbVertexUvs ++ ) { + + uv.x = uvs.getX( i ); + uv.y = uvs.getY( i ); + + // transform the uv to export format + output += 'vt ' + uv.x + ' ' + uv.y + '\n'; + + } + + } + + // normals + + if ( normals !== undefined ) { + + normalMatrixWorld.getNormalMatrix( mesh.matrixWorld ); + + for ( i = 0, l = normals.count; i < l; i ++, nbNormals ++ ) { + + normal.x = normals.getX( i ); + normal.y = normals.getY( i ); + normal.z = normals.getZ( i ); + + // transform the normal to world space + normal.applyMatrix3( normalMatrixWorld ).normalize(); + + // transform the normal to export format + output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n'; + + } + + } + + // faces + + if ( indices !== null ) { + + for ( i = 0, l = indices.count; i < l; i += 3 ) { + + for ( m = 0; m < 3; m ++ ) { + + j = indices.getX( i + m ) + 1; + + face[ m ] = ( indexVertex + j ) + ( normals || uvs ? '/' + ( uvs ? ( indexVertexUvs + j ) : '' ) + ( normals ? '/' + ( indexNormals + j ) : '' ) : '' ); + + } + + // transform the face to export format + output += 'f ' + face.join( ' ' ) + "\n"; + + } + + } else { + + for ( i = 0, l = vertices.count; i < l; i += 3 ) { + + for ( m = 0; m < 3; m ++ ) { + + j = i + m + 1; + + face[ m ] = ( indexVertex + j ) + ( normals || uvs ? '/' + ( uvs ? ( indexVertexUvs + j ) : '' ) + ( normals ? '/' + ( indexNormals + j ) : '' ) : '' ); + + } + + // transform the face to export format + output += 'f ' + face.join( ' ' ) + "\n"; + + } + + } + + } else { + + console.warn( 'THREE.OBJExporter.parseMesh(): geometry type unsupported', geometry ); + + } + + // update index + indexVertex += nbVertex; + indexVertexUvs += nbVertexUvs; + indexNormals += nbNormals; + + }; + + var parseLine = function ( line ) { + + var nbVertex = 0; + + var geometry = line.geometry; + var type = line.type; + + if ( geometry instanceof THREE.Geometry ) { + + geometry = new THREE.BufferGeometry().setFromObject( line ); + + } + + if ( geometry instanceof THREE.BufferGeometry ) { + + // shortcuts + var vertices = geometry.getAttribute( 'position' ); + + // name of the line object + output += 'o ' + line.name + '\n'; + + if ( vertices !== undefined ) { + + for ( i = 0, l = vertices.count; i < l; i ++, nbVertex ++ ) { + + vertex.x = vertices.getX( i ); + vertex.y = vertices.getY( i ); + vertex.z = vertices.getZ( i ); + + // transform the vertex to world space + vertex.applyMatrix4( line.matrixWorld ); + + // transform the vertex to export format + output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'; + + } + + } + + if ( type === 'Line' ) { + + output += 'l '; + + for ( j = 1, l = vertices.count; j <= l; j ++ ) { + + output += ( indexVertex + j ) + ' '; + + } + + output += '\n'; + + } + + if ( type === 'LineSegments' ) { + + for ( j = 1, k = j + 1, l = vertices.count; j < l; j += 2, k = j + 1 ) { + + output += 'l ' + ( indexVertex + j ) + ' ' + ( indexVertex + k ) + '\n'; + + } + + } + + } else { + + console.warn( 'THREE.OBJExporter.parseLine(): geometry type unsupported', geometry ); + + } + + // update index + indexVertex += nbVertex; + + }; + + var parsePoints = function ( points ) { + + var nbVertex = 0; + + var geometry = points.geometry; + + if ( geometry instanceof THREE.Geometry ) { + + geometry = new THREE.BufferGeometry().setFromObject( points ); + + } + + if ( geometry instanceof THREE.BufferGeometry ) { + + var vertices = geometry.getAttribute( 'position' ); + var colors = geometry.getAttribute( 'color' ); + + output += 'o ' + points.name + '\n'; + + if ( vertices !== undefined ) { + + for ( i = 0, l = vertices.count; i < l; i ++, nbVertex ++ ) { + + vertex.fromBufferAttribute( vertices, i ); + vertex.applyMatrix4( points.matrixWorld ); + + output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z; + + if ( colors !== undefined ) { + + color.fromBufferAttribute( colors, i ); + + output += ' ' + color.r + ' ' + color.g + ' ' + color.b; + + } + + output += '\n'; + + } + + } + + output += 'p '; + + for ( j = 1, l = vertices.count; j <= l; j ++ ) { + + output += ( indexVertex + j ) + ' '; + + } + + output += '\n'; + + } else { + + console.warn( 'THREE.OBJExporter.parsePoints(): geometry type unsupported', geometry ); + + } + + // update index + indexVertex += nbVertex; + + }; + + object.traverse( function ( child ) { + + if ( child instanceof THREE.Mesh ) { + + parseMesh( child ); + + } + + if ( child instanceof THREE.Line ) { + + parseLine( child ); + + } + + if ( child instanceof THREE.Points ) { + + parsePoints( child ); + + } + + } ); + + return output; + + } + +}; diff --git a/browser/static/OrbitControls.js b/browser/static/OrbitControls.js new file mode 100644 index 0000000..97b9396 --- /dev/null +++ b/browser/static/OrbitControls.js @@ -0,0 +1,1207 @@ +// This set of controls performs orbiting, dollying (zooming), and panning. +// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). +// +// Orbit - left mouse / touch: one-finger move +// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish +// Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move + +THREE.OrbitControls = function ( object, domElement ) { + + if ( domElement === undefined ) console.warn( 'THREE.OrbitControls: The second parameter "domElement" is now mandatory.' ); + if ( domElement === document ) console.error( 'THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.' ); + + this.object = object; + this.domElement = domElement; + + // Set to false to disable this control + this.enabled = true; + + // "target" sets the location of focus, where the object orbits around + this.target = new THREE.Vector3(); + + // How far you can dolly in and out ( PerspectiveCamera only ) + this.minDistance = 0; + this.maxDistance = Infinity; + + // How far you can zoom in and out ( OrthographicCamera only ) + this.minZoom = 0; + this.maxZoom = Infinity; + + // How far you can orbit vertically, upper and lower limits. + // Range is 0 to Math.PI radians. + this.minPolarAngle = 0; // radians + this.maxPolarAngle = Math.PI; // radians + + // How far you can orbit horizontally, upper and lower limits. + // If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI ) + this.minAzimuthAngle = - Infinity; // radians + this.maxAzimuthAngle = Infinity; // radians + + // Set to true to enable damping (inertia) + // If damping is enabled, you must call controls.update() in your animation loop + this.enableDamping = false; + this.dampingFactor = 0.05; + + // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. + // Set to false to disable zooming + this.enableZoom = true; + this.zoomSpeed = 1.0; + + // Set to false to disable rotating + this.enableRotate = true; + this.rotateSpeed = 1.0; + + // Set to false to disable panning + this.enablePan = true; + this.panSpeed = 1.0; + this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up + this.keyPanSpeed = 7.0; // pixels moved per arrow key push + + // Set to true to automatically rotate around the target + // If auto-rotate is enabled, you must call controls.update() in your animation loop + this.autoRotate = false; + this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 + + // Set to false to disable use of the keys + this.enableKeys = true; + + // The four arrow keys + this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; + + // Mouse buttons + this.mouseButtons = { LEFT: THREE.MOUSE.ROTATE, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.PAN }; + + // Touch fingers + this.touches = { ONE: THREE.TOUCH.ROTATE, TWO: THREE.TOUCH.DOLLY_PAN }; + + // for reset + this.target0 = this.target.clone(); + this.position0 = this.object.position.clone(); + this.zoom0 = this.object.zoom; + + // + // public methods + // + + this.getPolarAngle = function () { + + return spherical.phi; + + }; + + this.getAzimuthalAngle = function () { + + return spherical.theta; + + }; + + this.saveState = function () { + + scope.target0.copy( scope.target ); + scope.position0.copy( scope.object.position ); + scope.zoom0 = scope.object.zoom; + + }; + + this.reset = function () { + + scope.target.copy( scope.target0 ); + scope.object.position.copy( scope.position0 ); + scope.object.zoom = scope.zoom0; + + scope.object.updateProjectionMatrix(); + scope.dispatchEvent( changeEvent ); + + scope.update(); + + state = STATE.NONE; + + }; + + // this method is exposed, but perhaps it would be better if we can make it private... + this.update = function () { + + var offset = new THREE.Vector3(); + + // so camera.up is the orbit axis + var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) ); + var quatInverse = quat.clone().invert(); + + var lastPosition = new THREE.Vector3(); + var lastQuaternion = new THREE.Quaternion(); + + var twoPI = 2 * Math.PI; + + return function update() { + + var position = scope.object.position; + + offset.copy( position ).sub( scope.target ); + + // rotate offset to "y-axis-is-up" space + offset.applyQuaternion( quat ); + + // angle from z-axis around y-axis + spherical.setFromVector3( offset ); + + if ( scope.autoRotate && state === STATE.NONE ) { + + rotateLeft( getAutoRotationAngle() ); + + } + + if ( scope.enableDamping ) { + + spherical.theta += sphericalDelta.theta * scope.dampingFactor; + spherical.phi += sphericalDelta.phi * scope.dampingFactor; + + } else { + + spherical.theta += sphericalDelta.theta; + spherical.phi += sphericalDelta.phi; + + } + + // restrict theta to be between desired limits + + var min = scope.minAzimuthAngle; + var max = scope.maxAzimuthAngle; + + if ( isFinite( min ) && isFinite( max ) ) { + + if ( min < - Math.PI ) min += twoPI; else if ( min > Math.PI ) min -= twoPI; + + if ( max < - Math.PI ) max += twoPI; else if ( max > Math.PI ) max -= twoPI; + + if ( min <= max ) { + + spherical.theta = Math.max( min, Math.min( max, spherical.theta ) ); + + } else { + + spherical.theta = ( spherical.theta > ( min + max ) / 2 ) ? + Math.max( min, spherical.theta ) : + Math.min( max, spherical.theta ); + + } + + } + + // restrict phi to be between desired limits + spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) ); + + spherical.makeSafe(); + + + spherical.radius *= scale; + + // restrict radius to be between desired limits + spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) ); + + // move target to panned location + + if ( scope.enableDamping === true ) { + + scope.target.addScaledVector( panOffset, scope.dampingFactor ); + + } else { + + scope.target.add( panOffset ); + + } + + offset.setFromSpherical( spherical ); + + // rotate offset back to "camera-up-vector-is-up" space + offset.applyQuaternion( quatInverse ); + + position.copy( scope.target ).add( offset ); + + scope.object.lookAt( scope.target ); + + if ( scope.enableDamping === true ) { + + sphericalDelta.theta *= ( 1 - scope.dampingFactor ); + sphericalDelta.phi *= ( 1 - scope.dampingFactor ); + + panOffset.multiplyScalar( 1 - scope.dampingFactor ); + + } else { + + sphericalDelta.set( 0, 0, 0 ); + + panOffset.set( 0, 0, 0 ); + + } + + scale = 1; + + // update condition is: + // min(camera displacement, camera rotation in radians)^2 > EPS + // using small-angle approximation cos(x/2) = 1 - x^2 / 8 + + if ( zoomChanged || + lastPosition.distanceToSquared( scope.object.position ) > EPS || + 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) { + + scope.dispatchEvent( changeEvent ); + + lastPosition.copy( scope.object.position ); + lastQuaternion.copy( scope.object.quaternion ); + zoomChanged = false; + + return true; + + } + + return false; + + }; + + }(); + + this.dispose = function () { + + scope.domElement.removeEventListener( 'contextmenu', onContextMenu, false ); + + scope.domElement.removeEventListener( 'pointerdown', onPointerDown, false ); + scope.domElement.removeEventListener( 'wheel', onMouseWheel, false ); + + scope.domElement.removeEventListener( 'touchstart', onTouchStart, false ); + scope.domElement.removeEventListener( 'touchend', onTouchEnd, false ); + scope.domElement.removeEventListener( 'touchmove', onTouchMove, false ); + + scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove, false ); + scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp, false ); + + scope.domElement.removeEventListener( 'keydown', onKeyDown, false ); + + //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here? + + }; + + // + // internals + // + + var scope = this; + + var changeEvent = { type: 'change' }; + var startEvent = { type: 'start' }; + var endEvent = { type: 'end' }; + + var STATE = { + NONE: - 1, + ROTATE: 0, + DOLLY: 1, + PAN: 2, + TOUCH_ROTATE: 3, + TOUCH_PAN: 4, + TOUCH_DOLLY_PAN: 5, + TOUCH_DOLLY_ROTATE: 6 + }; + + var state = STATE.NONE; + + var EPS = 0.000001; + + // current position in spherical coordinates + var spherical = new THREE.Spherical(); + var sphericalDelta = new THREE.Spherical(); + + var scale = 1; + var panOffset = new THREE.Vector3(); + var zoomChanged = false; + + var rotateStart = new THREE.Vector2(); + var rotateEnd = new THREE.Vector2(); + var rotateDelta = new THREE.Vector2(); + + var panStart = new THREE.Vector2(); + var panEnd = new THREE.Vector2(); + var panDelta = new THREE.Vector2(); + + var dollyStart = new THREE.Vector2(); + var dollyEnd = new THREE.Vector2(); + var dollyDelta = new THREE.Vector2(); + + function getAutoRotationAngle() { + + return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; + + } + + function getZoomScale() { + + return Math.pow( 0.95, scope.zoomSpeed ); + + } + + function rotateLeft( angle ) { + + sphericalDelta.theta -= angle; + + } + + function rotateUp( angle ) { + + sphericalDelta.phi -= angle; + + } + + var panLeft = function () { + + var v = new THREE.Vector3(); + + return function panLeft( distance, objectMatrix ) { + + v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix + v.multiplyScalar( - distance ); + + panOffset.add( v ); + + }; + + }(); + + var panUp = function () { + + var v = new THREE.Vector3(); + + return function panUp( distance, objectMatrix ) { + + if ( scope.screenSpacePanning === true ) { + + v.setFromMatrixColumn( objectMatrix, 1 ); + + } else { + + v.setFromMatrixColumn( objectMatrix, 0 ); + v.crossVectors( scope.object.up, v ); + + } + + v.multiplyScalar( distance ); + + panOffset.add( v ); + + }; + + }(); + + // deltaX and deltaY are in pixels; right and down are positive + var pan = function () { + + var offset = new THREE.Vector3(); + + return function pan( deltaX, deltaY ) { + + var element = scope.domElement; + + if ( scope.object.isPerspectiveCamera ) { + + // perspective + var position = scope.object.position; + offset.copy( position ).sub( scope.target ); + var targetDistance = offset.length(); + + // half of the fov is center to top of screen + targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 ); + + // we use only clientHeight here so aspect ratio does not distort speed + panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix ); + panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix ); + + } else if ( scope.object.isOrthographicCamera ) { + + // orthographic + panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix ); + panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix ); + + } else { + + // camera neither orthographic nor perspective + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' ); + scope.enablePan = false; + + } + + }; + + }(); + + function dollyOut( dollyScale ) { + + if ( scope.object.isPerspectiveCamera ) { + + scale /= dollyScale; + + } else if ( scope.object.isOrthographicCamera ) { + + scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) ); + scope.object.updateProjectionMatrix(); + zoomChanged = true; + + } else { + + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); + scope.enableZoom = false; + + } + + } + + function dollyIn( dollyScale ) { + + if ( scope.object.isPerspectiveCamera ) { + + scale *= dollyScale; + + } else if ( scope.object.isOrthographicCamera ) { + + scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) ); + scope.object.updateProjectionMatrix(); + zoomChanged = true; + + } else { + + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); + scope.enableZoom = false; + + } + + } + + // + // event callbacks - update the object state + // + + function handleMouseDownRotate( event ) { + + rotateStart.set( event.clientX, event.clientY ); + + } + + function handleMouseDownDolly( event ) { + + dollyStart.set( event.clientX, event.clientY ); + + } + + function handleMouseDownPan( event ) { + + panStart.set( event.clientX, event.clientY ); + + } + + function handleMouseMoveRotate( event ) { + + rotateEnd.set( event.clientX, event.clientY ); + + rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); + + var element = scope.domElement; + + rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height + + rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); + + rotateStart.copy( rotateEnd ); + + scope.update(); + + } + + function handleMouseMoveDolly( event ) { + + dollyEnd.set( event.clientX, event.clientY ); + + dollyDelta.subVectors( dollyEnd, dollyStart ); + + if ( dollyDelta.y > 0 ) { + + dollyOut( getZoomScale() ); + + } else if ( dollyDelta.y < 0 ) { + + dollyIn( getZoomScale() ); + + } + + dollyStart.copy( dollyEnd ); + + scope.update(); + + } + + function handleMouseMovePan( event ) { + + panEnd.set( event.clientX, event.clientY ); + + panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); + + pan( panDelta.x, panDelta.y ); + + panStart.copy( panEnd ); + + scope.update(); + + } + + function handleMouseUp( /*event*/ ) { + + // no-op + + } + + function handleMouseWheel( event ) { + + if ( event.deltaY < 0 ) { + + dollyIn( getZoomScale() ); + + } else if ( event.deltaY > 0 ) { + + dollyOut( getZoomScale() ); + + } + + scope.update(); + + } + + function handleKeyDown( event ) { + + var needsUpdate = false; + + switch ( event.keyCode ) { + + case scope.keys.UP: + pan( 0, scope.keyPanSpeed ); + needsUpdate = true; + break; + + case scope.keys.BOTTOM: + pan( 0, - scope.keyPanSpeed ); + needsUpdate = true; + break; + + case scope.keys.LEFT: + pan( scope.keyPanSpeed, 0 ); + needsUpdate = true; + break; + + case scope.keys.RIGHT: + pan( - scope.keyPanSpeed, 0 ); + needsUpdate = true; + break; + + } + + if ( needsUpdate ) { + + // prevent the browser from scrolling on cursor keys + event.preventDefault(); + + scope.update(); + + } + + + } + + function handleTouchStartRotate( event ) { + + if ( event.touches.length == 1 ) { + + rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + + rotateStart.set( x, y ); + + } + + } + + function handleTouchStartPan( event ) { + + if ( event.touches.length == 1 ) { + + panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + + panStart.set( x, y ); + + } + + } + + function handleTouchStartDolly( event ) { + + var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; + var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + + var distance = Math.sqrt( dx * dx + dy * dy ); + + dollyStart.set( 0, distance ); + + } + + function handleTouchStartDollyPan( event ) { + + if ( scope.enableZoom ) handleTouchStartDolly( event ); + + if ( scope.enablePan ) handleTouchStartPan( event ); + + } + + function handleTouchStartDollyRotate( event ) { + + if ( scope.enableZoom ) handleTouchStartDolly( event ); + + if ( scope.enableRotate ) handleTouchStartRotate( event ); + + } + + function handleTouchMoveRotate( event ) { + + if ( event.touches.length == 1 ) { + + rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + + rotateEnd.set( x, y ); + + } + + rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); + + var element = scope.domElement; + + rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height + + rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); + + rotateStart.copy( rotateEnd ); + + } + + function handleTouchMovePan( event ) { + + if ( event.touches.length == 1 ) { + + panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + + panEnd.set( x, y ); + + } + + panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); + + pan( panDelta.x, panDelta.y ); + + panStart.copy( panEnd ); + + } + + function handleTouchMoveDolly( event ) { + + var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; + var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + + var distance = Math.sqrt( dx * dx + dy * dy ); + + dollyEnd.set( 0, distance ); + + dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) ); + + dollyOut( dollyDelta.y ); + + dollyStart.copy( dollyEnd ); + + } + + function handleTouchMoveDollyPan( event ) { + + if ( scope.enableZoom ) handleTouchMoveDolly( event ); + + if ( scope.enablePan ) handleTouchMovePan( event ); + + } + + function handleTouchMoveDollyRotate( event ) { + + if ( scope.enableZoom ) handleTouchMoveDolly( event ); + + if ( scope.enableRotate ) handleTouchMoveRotate( event ); + + } + + function handleTouchEnd( /*event*/ ) { + + // no-op + + } + + // + // event handlers - FSM: listen for events and reset state + // + + function onPointerDown( event ) { + + if ( scope.enabled === false ) return; + + switch ( event.pointerType ) { + + case 'mouse': + case 'pen': + onMouseDown( event ); + break; + + // TODO touch + + } + + } + + function onPointerMove( event ) { + + if ( scope.enabled === false ) return; + + switch ( event.pointerType ) { + + case 'mouse': + case 'pen': + onMouseMove( event ); + break; + + // TODO touch + + } + + } + + function onPointerUp( event ) { + + switch ( event.pointerType ) { + + case 'mouse': + case 'pen': + onMouseUp( event ); + break; + + // TODO touch + + } + + } + + function onMouseDown( event ) { + + // Prevent the browser from scrolling. + event.preventDefault(); + + // Manually set the focus since calling preventDefault above + // prevents the browser from setting it automatically. + + scope.domElement.focus ? scope.domElement.focus() : window.focus(); + + var mouseAction; + + switch ( event.button ) { + + case 0: + + mouseAction = scope.mouseButtons.LEFT; + break; + + case 1: + + mouseAction = scope.mouseButtons.MIDDLE; + break; + + case 2: + + mouseAction = scope.mouseButtons.RIGHT; + break; + + default: + + mouseAction = - 1; + + } + + switch ( mouseAction ) { + + case THREE.MOUSE.DOLLY: + + if ( scope.enableZoom === false ) return; + + handleMouseDownDolly( event ); + + state = STATE.DOLLY; + + break; + + case THREE.MOUSE.ROTATE: + + if ( event.ctrlKey || event.metaKey || event.shiftKey ) { + + if ( scope.enablePan === false ) return; + + handleMouseDownPan( event ); + + state = STATE.PAN; + + } else { + + if ( scope.enableRotate === false ) return; + + handleMouseDownRotate( event ); + + state = STATE.ROTATE; + + } + + break; + + case THREE.MOUSE.PAN: + + if ( event.ctrlKey || event.metaKey || event.shiftKey ) { + + if ( scope.enableRotate === false ) return; + + handleMouseDownRotate( event ); + + state = STATE.ROTATE; + + } else { + + if ( scope.enablePan === false ) return; + + handleMouseDownPan( event ); + + state = STATE.PAN; + + } + + break; + + default: + + state = STATE.NONE; + + } + + if ( state !== STATE.NONE ) { + + scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove, false ); + scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp, false ); + + scope.dispatchEvent( startEvent ); + + } + + } + + function onMouseMove( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); + + switch ( state ) { + + case STATE.ROTATE: + + if ( scope.enableRotate === false ) return; + + handleMouseMoveRotate( event ); + + break; + + case STATE.DOLLY: + + if ( scope.enableZoom === false ) return; + + handleMouseMoveDolly( event ); + + break; + + case STATE.PAN: + + if ( scope.enablePan === false ) return; + + handleMouseMovePan( event ); + + break; + + } + + } + + function onMouseUp( event ) { + + scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove, false ); + scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp, false ); + + if ( scope.enabled === false ) return; + + handleMouseUp( event ); + + scope.dispatchEvent( endEvent ); + + state = STATE.NONE; + + } + + function onMouseWheel( event ) { + + if ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return; + + event.preventDefault(); + event.stopPropagation(); + + scope.dispatchEvent( startEvent ); + + handleMouseWheel( event ); + + scope.dispatchEvent( endEvent ); + + } + + function onKeyDown( event ) { + + if ( scope.enabled === false || scope.enableKeys === false || scope.enablePan === false ) return; + + handleKeyDown( event ); + + } + + function onTouchStart( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); // prevent scrolling + + switch ( event.touches.length ) { + + case 1: + + switch ( scope.touches.ONE ) { + + case THREE.TOUCH.ROTATE: + + if ( scope.enableRotate === false ) return; + + handleTouchStartRotate( event ); + + state = STATE.TOUCH_ROTATE; + + break; + + case THREE.TOUCH.PAN: + + if ( scope.enablePan === false ) return; + + handleTouchStartPan( event ); + + state = STATE.TOUCH_PAN; + + break; + + default: + + state = STATE.NONE; + + } + + break; + + case 2: + + switch ( scope.touches.TWO ) { + + case THREE.TOUCH.DOLLY_PAN: + + if ( scope.enableZoom === false && scope.enablePan === false ) return; + + handleTouchStartDollyPan( event ); + + state = STATE.TOUCH_DOLLY_PAN; + + break; + + case THREE.TOUCH.DOLLY_ROTATE: + + if ( scope.enableZoom === false && scope.enableRotate === false ) return; + + handleTouchStartDollyRotate( event ); + + state = STATE.TOUCH_DOLLY_ROTATE; + + break; + + default: + + state = STATE.NONE; + + } + + break; + + default: + + state = STATE.NONE; + + } + + if ( state !== STATE.NONE ) { + + scope.dispatchEvent( startEvent ); + + } + + } + + function onTouchMove( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); // prevent scrolling + event.stopPropagation(); + + switch ( state ) { + + case STATE.TOUCH_ROTATE: + + if ( scope.enableRotate === false ) return; + + handleTouchMoveRotate( event ); + + scope.update(); + + break; + + case STATE.TOUCH_PAN: + + if ( scope.enablePan === false ) return; + + handleTouchMovePan( event ); + + scope.update(); + + break; + + case STATE.TOUCH_DOLLY_PAN: + + if ( scope.enableZoom === false && scope.enablePan === false ) return; + + handleTouchMoveDollyPan( event ); + + scope.update(); + + break; + + case STATE.TOUCH_DOLLY_ROTATE: + + if ( scope.enableZoom === false && scope.enableRotate === false ) return; + + handleTouchMoveDollyRotate( event ); + + scope.update(); + + break; + + default: + + state = STATE.NONE; + + } + + } + + function onTouchEnd( event ) { + + if ( scope.enabled === false ) return; + + handleTouchEnd( event ); + + scope.dispatchEvent( endEvent ); + + state = STATE.NONE; + + } + + function onContextMenu( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); + + } + + // + + scope.domElement.addEventListener( 'contextmenu', onContextMenu, false ); + + scope.domElement.addEventListener( 'pointerdown', onPointerDown, false ); + scope.domElement.addEventListener( 'wheel', onMouseWheel, false ); + + scope.domElement.addEventListener( 'touchstart', onTouchStart, false ); + scope.domElement.addEventListener( 'touchend', onTouchEnd, false ); + scope.domElement.addEventListener( 'touchmove', onTouchMove, false ); + + scope.domElement.addEventListener( 'keydown', onKeyDown, false ); + + // force an update at start + + this.update(); + +}; + +THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype ); +THREE.OrbitControls.prototype.constructor = THREE.OrbitControls; + + +// This set of controls performs orbiting, dollying (zooming), and panning. +// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). +// This is very similar to OrbitControls, another set of touch behavior +// +// Orbit - right mouse, or left mouse + ctrl/meta/shiftKey / touch: two-finger rotate +// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish +// Pan - left mouse, or arrow keys / touch: one-finger move + +THREE.MapControls = function ( object, domElement ) { + + THREE.OrbitControls.call( this, object, domElement ); + + this.screenSpacePanning = false; // pan orthogonal to world-space direction camera.up + + this.mouseButtons.LEFT = THREE.MOUSE.PAN; + this.mouseButtons.RIGHT = THREE.MOUSE.ROTATE; + + this.touches.ONE = THREE.TOUCH.PAN; + this.touches.TWO = THREE.TOUCH.DOLLY_ROTATE; + +}; + +THREE.MapControls.prototype = Object.create( THREE.EventDispatcher.prototype ); +THREE.MapControls.prototype.constructor = THREE.MapControls; diff --git a/browser/static/PointerLockControls.js b/browser/static/PointerLockControls.js new file mode 100644 index 0000000..282d60d --- /dev/null +++ b/browser/static/PointerLockControls.js @@ -0,0 +1,156 @@ +THREE.PointerLockControls = function ( camera, domElement ) { + + if ( domElement === undefined ) { + + console.warn( 'THREE.PointerLockControls: The second parameter "domElement" is now mandatory.' ); + domElement = document.body; + + } + + this.domElement = domElement; + this.isLocked = false; + + // Set to constrain the pitch of the camera + // Range is 0 to Math.PI radians + this.minPolarAngle = 0; // radians + this.maxPolarAngle = Math.PI; // radians + + // + // internals + // + + var scope = this; + + var changeEvent = { type: 'change' }; + var lockEvent = { type: 'lock' }; + var unlockEvent = { type: 'unlock' }; + + var euler = new THREE.Euler( 0, 0, 0, 'YXZ' ); + + var PI_2 = Math.PI / 2; + + var vec = new THREE.Vector3(); + + function onMouseMove( event ) { + + if ( scope.isLocked === false ) return; + + var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; + var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; + + euler.setFromQuaternion( camera.quaternion ); + + euler.y -= movementX * 0.002; + euler.x -= movementY * 0.002; + + euler.x = Math.max( PI_2 - scope.maxPolarAngle, Math.min( PI_2 - scope.minPolarAngle, euler.x ) ); + + camera.quaternion.setFromEuler( euler ); + + scope.dispatchEvent( changeEvent ); + + } + + function onPointerlockChange() { + + if ( scope.domElement.ownerDocument.pointerLockElement === scope.domElement ) { + + scope.dispatchEvent( lockEvent ); + + scope.isLocked = true; + + } else { + + scope.dispatchEvent( unlockEvent ); + + scope.isLocked = false; + + } + + } + + function onPointerlockError() { + + console.error( 'THREE.PointerLockControls: Unable to use Pointer Lock API' ); + + } + + this.connect = function () { + + scope.domElement.ownerDocument.addEventListener( 'mousemove', onMouseMove, false ); + scope.domElement.ownerDocument.addEventListener( 'pointerlockchange', onPointerlockChange, false ); + scope.domElement.ownerDocument.addEventListener( 'pointerlockerror', onPointerlockError, false ); + + }; + + this.disconnect = function () { + + scope.domElement.ownerDocument.removeEventListener( 'mousemove', onMouseMove, false ); + scope.domElement.ownerDocument.removeEventListener( 'pointerlockchange', onPointerlockChange, false ); + scope.domElement.ownerDocument.removeEventListener( 'pointerlockerror', onPointerlockError, false ); + + }; + + this.dispose = function () { + + this.disconnect(); + + }; + + this.getObject = function () { // retaining this method for backward compatibility + + return camera; + + }; + + this.getDirection = function () { + + var direction = new THREE.Vector3( 0, 0, - 1 ); + + return function ( v ) { + + return v.copy( direction ).applyQuaternion( camera.quaternion ); + + }; + + }(); + + this.moveForward = function ( distance ) { + + // move forward parallel to the xz-plane + // assumes camera.up is y-up + + vec.setFromMatrixColumn( camera.matrix, 0 ); + + vec.crossVectors( camera.up, vec ); + + camera.position.addScaledVector( vec, distance ); + + }; + + this.moveRight = function ( distance ) { + + vec.setFromMatrixColumn( camera.matrix, 0 ); + + camera.position.addScaledVector( vec, distance ); + + }; + + this.lock = function () { + + this.domElement.requestPointerLock(); + + }; + + this.unlock = function () { + + scope.domElement.ownerDocument.exitPointerLock(); + + }; + + this.connect(); + +}; + +THREE.PointerLockControls.prototype = Object.create( THREE.EventDispatcher.prototype ); +THREE.PointerLockControls.prototype.constructor = THREE.PointerLockControls; diff --git a/browser/static/T3D.js b/browser/static/T3D.js new file mode 100644 index 0000000..2a85d29 --- /dev/null +++ b/browser/static/T3D.js @@ -0,0 +1,4271 @@ +/* +Copyright © 2024 T3D project contributors. + +This file is part of the T3D Library. + +T3D Library is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +T3D Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the T3D Library. If not, see . +*/ + +var T3D = (function (t3dParser) { + 'use strict'; + + /// Indexed DB versioning + const DB_VERSION = 4; + /** + * This class handles offline storage of the .dat indexes and files metadata + * @class PersistantStore + */ + class PersistantStore { + _dbConnection; + constructor() { + // They may be multiple connection request issued at the same time, but it's actually okay since + // as soon as they are registered, the not-used ones will get garbage collected + this._dbConnection = undefined; + this._getConnection(); + } + /** + * Initialize the IndexedDB connection and manages version changes. + * + * @async + * @private + * @returns {Promise} Promise to the Database connection + */ + _getConnection() { + const self = this; + return new Promise((resolve, reject) => { + if (self._dbConnection) + resolve(self._dbConnection); + // Let us open our database + const request = window.indexedDB.open("Tyria3DLibrary", DB_VERSION); + /// onblocked is fired when the db needs an upgrade but an older version is opened in another tab + request.onblocked = () => { + T3D.Logger.log(T3D.Logger.TYPE_ERROR, "The T3D persistant database cannot be upgraded while the app is opened somewhere else."); + }; + /// fired when the database needs to be upgraded (or the first time) + request.onupgradeneeded = (event) => { + // Probably bugged + //@ts-ignore + const db = event.target.result; + const currentVersion = event.oldVersion; + if (currentVersion < 2) { + db.createObjectStore("listings", { + autoIncrement: true, + }); + } + if (currentVersion < 3) { + const storeListing = event.currentTarget.transaction.objectStore("listings"); + storeListing.createIndex("filename", "filename", { unique: false }); + } + }; + request.onsuccess = (event) => { + self._dbConnection = event.target.result; + //@ts-ignore + self.isReady = true; + resolve(self._dbConnection); + }; + request.onerror = () => { + T3D.Logger.log(T3D.Logger.TYPE_ERROR, "The T3D persistant database could not be opened."); + reject(); + }; + }); + } + /** + * Add or update a listing into the database + * + * @async + * @param {number|undefined} id This ID doesn't really matter, it's just the index of the object in the database, can be undefined + * @param {Array} listing + * @param {string} fileName .dat file name, allows to have multiple listings for different .dat files. + * @param {boolean} isComplete Keep back the information if that was the last update on the current scan or not. + * @returns {Promise} On success, the number is the object key in the database + */ + putListing(id, listing, fileName, isComplete) { + const self = this; + return new Promise((resolve, reject) => { + self._getConnection().then((db) => { + const store = db.transaction(["listings"], "readwrite").objectStore("listings"); + const request = id + ? store.put({ array: listing, filename: fileName, complete: isComplete }, id) + : store.put({ array: listing, name: fileName }); + request.onsuccess = () => { + resolve(request.result); + }; + request.onerror = () => { + reject(); + }; + }); + }); + } + /** + * Returns the last valid listing in the database + * + * @async + * @param {string} fileName .dat file name, allows to have multiple listings for different .dat files. + * @returns {Promise<{array: Array, key: number, complete: boolean}>} + * array: the last listing + * key: the index of the last listing in the database + */ + getLastListing(fileName) { + const self = this; + return new Promise((resolve) => { + self._getConnection().then((db) => { + const listingsStore = db.transaction(["listings"], "readonly").objectStore("listings").index("filename"); + listingsStore.openCursor(IDBKeyRange.only(fileName), "prev").onsuccess = (event) => { + const cursor = event.target.result; + if (!cursor) + resolve({ array: [], key: undefined, complete: true }); + else { + resolve({ + array: cursor.value.array, + key: cursor.primaryKey, + complete: cursor.value.complete, + }); + } + }; + }); + }); + } + } + + /** + * Organized thread pool of extractors + */ + class DataReader { + settings; + _workerPool; + _workerLoad; + _inflateCallbacks; + constructor(settings) { + this.settings = settings; + this._workerPool = []; + this._workerLoad = []; + this._inflateCallbacks = []; + for (let i = 0; i < settings.workersNb; i++) { + this._startWorker(settings.workerPath); + } + } + inflate(buffer, size, mftId, isImage, capLength) { + return new Promise((resolve, reject) => { + const arrayBuffer = buffer; + // If no capLength then inflate the whole file + if (!capLength || capLength < 0) { + capLength = 0; + } + // Buffer length size check + if (arrayBuffer.byteLength < 12) { + T3D.Logger.log(T3D.Logger.TYPE_WARNING, `not inflating, length is too short (${arrayBuffer.byteLength})`, mftId); + reject(new Error("Couldn't inflate " + mftId + " (mftId)")); + return; + } + // Register the callback + if (this._inflateCallbacks[mftId]) { + this._inflateCallbacks[mftId].push({ + resolve: resolve, + reject: reject, + }); + /// No need to make another call, just wait for callback event to fire. + return; + } + else { + this._inflateCallbacks[mftId] = [{ resolve: resolve, reject: reject }]; + } + // Add the load to the worker + const workerId = this._getBestWorkerIndex(); + this._workerLoad[workerId] += 1; + this._workerPool[workerId].postMessage([mftId, arrayBuffer, isImage === true, capLength]); + }); + } + // Initialization function for creating a new worker (thread) + _startWorker(path) { + const self = this; + const worker = new Worker(path); + const selfWorkerId = this._workerPool.push(worker) - 1; + if (this._workerLoad.push(0) !== selfWorkerId + 1) { + throw new Error("WorkerLoad and WorkerPool don't have the same length"); + } + worker.onmessage = function (message_event) { + let mftId; + // Remove load + self._workerLoad[selfWorkerId] -= 1; + // If error + if (typeof message_event.data === "string") { + T3D.Logger.log(T3D.Logger.TYPE_WARNING, "Inflater threw an error", message_event.data); + mftId = parseInt(message_event.data.split(":")[0]); + for (const callback of self._inflateCallbacks[mftId]) { + callback.reject(); + } + } + else { + mftId = message_event.data[0]; + // On success + if (self._inflateCallbacks[mftId]) { + for (const callback of self._inflateCallbacks[mftId]) { + const data = message_event.data; + // Array buffer, dxtType, imageWidth, imageHeight + callback.resolve({ + buffer: data[1], + dxtType: data[2], + imageWidth: data[3], + imageHeight: data[4], + }); + } + // Remove triggered listeners + self._inflateCallbacks[mftId] = null; + } + // Unknown error + else { + T3D.Logger.log(T3D.Logger.TYPE_ERROR, "Inflater threw an error", message_event.data); + } + } + }; + } + // Get the worker with the less load + _getBestWorkerIndex() { + return this._workerLoad.indexOf(Math.min(...this._workerLoad)); + } + } + + const mapMap = { + /** + * @property maps + * @type {Array.<{name: String, maps: Array.<{fileName: String, name: String}>}>} + */ + maps: [ + { + name: "Core - Ascalon [Regrown]", + maps: [ + { fileName: "131944.data", name: "(City) Black Citadel" }, + { fileName: "196585.data", name: "(City) Black Citadel [MapRegrownCitadel]" }, + { fileName: "1968107.data", name: "(City) Black Citadel" }, + { fileName: "126118.data", name: "(1-15) Plains of Ashford" }, + { fileName: "188591.data", name: "(1-15) Plains of Ashford [MapRegrownAshford]" }, + { fileName: "127888.data", name: "(15-25) Diessa Plateau" }, + { fileName: "190490.data", name: "(15-25) Diessa Plateau [MapRegrownRange]" }, + { fileName: "283574.data", name: "(30-40) Fields of Ruin [MapRegrownHawke]" }, + { fileName: "282668.data", name: "(40-50) Iron Marches [MapRegrownGullet]" }, + { fileName: "280025.data", name: "(50-60) Blazeridge Steppes [MapRegrownBrand]" }, + { fileName: "281313.data", name: "(60-70) Fireheart Rise [MapRegrownFlame]" }, + ], + }, + { + name: "Core - Kryta [Valley]", + maps: [ + { fileName: "128151.data", name: "(City) Divinity's Reach" }, + { fileName: "191265.data", name: "(City) Divinity's Reach [MapValleyDivinity]" }, + { fileName: "1968748.data", name: "(City) Divinity's Reach" }, + { fileName: "129524.data", name: "(1-15) Queensdale" }, + { fileName: "192711.data", name: "(1-15) Queensdale [MapValleyHill]" }, + { fileName: "130970.data", name: "(15-25) Kessex Hills" }, + { fileName: "194288.data", name: "(15-25) Kessex Hills [MapValleyWilderness]" }, + { fileName: "861815.data", name: "(15-25) Kessex Hills [MapValleyWildernessFortSalma]" }, + { fileName: "2737234.data", name: "(15-25) Kessex Hills [MapValleyWildernessTower]" }, + { fileName: "289176.data", name: "(25-35) Gendarran Fields, Vigil Headquarters [MapValleySettlement]" }, + { fileName: "191000.data", name: "(City) Lion's Arch [MapValleyArch]" }, + { fileName: "1796999.data", name: "(City) Lion's Arch [MapValleyArchKiel]" }, + { fileName: "1968576.data", name: "(City) Lion's Arch" }, + { fileName: "287870.data", name: "(35-45) Harathi Hinterlands [MapValleyHeadland]" }, + { fileName: "286945.data", name: "(45-55) Bloodtide Coast [MapValleyCoast]" }, + { fileName: "295005.data", name: "(45-55) Chantry of Secrets [MapValleyWhisper]" }, + { fileName: "520479.data", name: "(80) Southsun Cove, Crab Toss, Southsun Survival [MapEventValleyLost]" }, + ], + }, + { + name: "Core - Shiverpeak Mountains [Alpine]", + maps: [ + { fileName: "132434.data", name: "(City) Hoelbrak, Keg Brawl" }, + { fileName: "197122.data", name: "(City) Hoelbrak, Keg Brawl [MapAlpineHall]" }, + { fileName: "1966018.data", name: "(City) Hoelbrak, Keg Brawl" }, + { fileName: "125199.data", name: "(1-15) Wayfarer Foothills" }, + { fileName: "187611.data", name: "(1-15) Wayfarer Foothills [MapAlpineSnowline]" }, + { fileName: "124093.data", name: "(15-25) Snowden Drifts" }, + { fileName: "186397.data", name: "(15-25) Snowden Drifts [MapAlpinePowder]" }, + { fileName: "277587.data", name: "(25-40) Lornar's Pass, The Durmand Priory [MapAlpineSlope]" }, + { fileName: "275155.data", name: "(40-50) Dredgehaunt Cliffs [MapAlpineCrest]" }, + { fileName: "278717.data", name: "(50-60) Timberline Falls [MapAlpineTimberland]" }, + { fileName: "846866.data", name: "(50-60) Timberline Falls" }, + { fileName: "276252.data", name: "(70-80) Frostgorge Sound [MapAlpineGlacier]" }, + { fileName: "295282.data", name: "(HoM) Eye of the North [MapAlpineMonument]" }, + ], + }, + { + name: "Core - Tarnished Coast [Wetland]", + maps: [ + { fileName: "198272.data", name: "(City) Rata Sum [MapWetlandComplex]" }, + { fileName: "1968896.data", name: "(City) Rata Sum" }, + { fileName: "198076.data", name: "(City) The Grove [MapWetlandGrove]" }, + { fileName: "1969341.data", name: "(City) The Grove" }, + { fileName: "195149.data", name: "(1-15) Caledon Forest [MapWetlandBayou]" }, + { fileName: "195493.data", name: "(1-15) Metrica Province [MapWetlandRiverside]" }, + { fileName: "293307.data", name: "(15-25) Brisban Wildlands [MapWetlandGrotto]" }, + { fileName: "292254.data", name: "(55-65) Sparkfly Fen [MapWetlandGlade]" }, + { fileName: "291064.data", name: "(60-70) Mount Maelstrom [MapWetlandCape]" }, + ], + }, + { + name: "Core - Ruins of Orr [Risen]", + maps: [ + { fileName: "284829.data", name: "(70-75) Straits of Devastation [MapRisenBeachhead]" }, + { fileName: "285089.data", name: "(75-80) Malchor's Leap [MapRisenCliff]" }, + { fileName: "285634.data", name: "(80) Cursed Shore [MapRisenShore]" }, + ], + }, + { + name: "Core - Personal Story", + maps: [ + { + fileName: "295962.data", + name: "(20-60) A Vision of Darkness, A Light in the Darkness [MapWetlandDestiny]", + }, + { fileName: "1019669.data", name: "(40-60) Old Lion's Arch [MapValleyArchOrig]" }, + { fileName: "294938.data", name: "(60) Claw Island [MapValleyClaw]" }, + { + fileName: "1018612.data", + name: "(70) Forging the Pact [MapAlpineTimberlandBeforeConcordiaVines]", + }, + { + fileName: "295179.data", + name: "(80) Temple of the Forgotten God [MapRisenBeachheadAbaddon]", + }, + { fileName: "473765.data", name: "(80) Victory or Death [MapRisenDragonStory]" }, + ], + }, + { + name: "Core - Dungeon", + maps: [ + { fileName: "126840.data", name: "(30-35) Ascalonian Catacombs" }, + { fileName: "189364.data", name: "(30-35) Ascalonian Catacombs [MapRegrownCatacomb]" }, + { fileName: "287214.data", name: "(40-45) Caudecus's Manor [MapValleyEstate]" }, + { fileName: "291284.data", name: "(50) Twilight Arbor [MapWetlandGarden]" }, + { fileName: "645968.data", name: "(55-80) Twilight Arbor [MapWetlandGardenRepeat]" }, + { fileName: "275474.data", name: "(60-65) Sorrow's Embrace [MapAlpineFurnace]" }, + { fileName: "284039.data", name: "(70-75) Citadel of Flame [MapRegrownShaman]" }, + { fileName: "276520.data", name: "(76-80) Honor of the Waves [MapAlpineIceberg]" }, + { fileName: "293606.data", name: "(78-80) Crucible of Eternity [MapWetlandWeapon]" }, + { fileName: "473930.data", name: "(80) The Ruined City of Arah [MapRisenDragonRepeat]" }, + ], + }, + { + name: "(LW1) Living World Season 1: Scarlet's War - (SM) Strike Mission", + maps: [ + { + fileName: "2771534.data", + name: "(Lounge) Memory of Old Lion's Arch [MapValleyArchProbed]", + }, + { fileName: "568778.data", name: "(LW1.E1) Cragstead [MapAlpineEnclave]" }, + { fileName: "580061.data", name: "(LW1.E1) Molten Furnace [MapFlameFrost]" }, + { + fileName: "2690992.data", + name: "(LW1.E2) Memorials on the Pyre, The Scene of the Crime [MapValleyArchDragon]", + }, + { fileName: "595722.data", name: "(LW1.E2) Aetherblade Retreat [MapValleyArchDungeon]" }, + { fileName: "2711089.data", name: "(LW1.E3) Scarlet's Playhouse [MapJubileeArena-2]" }, + { + fileName: "672138.data", + name: "(LW1.E4) The Nightmare Unveiled [MapValleyWildernessKraitTowerInstance]", + }, + { fileName: "679089.data", name: "(LW1.E4) The Tower of Nightmares [MapValleyWildernessKraitTowerInterior]" }, + { + fileName: "2469960.data", + name: "(LW1.E5) The Twisted Marionette [MapAlpineSlopeMarionette]", + }, + { fileName: "2770873.data", name: "(LW1.E5) The Battle For Lion's Arch [MapValleyArch2]" }, + { + fileName: "2773298.data", + name: "(LW1.E5) North Evacuation Camp [MapValleySettlementFeb2014]", + }, + { fileName: "814803.data", name: "(LW1.E5) Lion's Arch: Honored Guests [MapValleyArch3]" }, + { fileName: "2771205.data", name: "(SM) Old Lion's Court [MapValleyArch2Strike]" }, + ], + }, + { + name: "(LW2) Living World Season 2: Glint's Prophecy", + maps: [ + { fileName: "836211.data", name: "(LW2.E1, LW2.E2, LW2.E4) Dry Top [MapDryTop]" }, + { fileName: "861770.data", name: "(LW2.E1, LW2.E2, LW2.E4) Dry Top [MapDryTopE2]" }, + { fileName: "909361.data", name: "(LW2.E5, LW2.E6, LW2.E7, LW2.E8) The Silverwastes [MapSandCastle]" }, + { fileName: "996202.data", name: "(LW2.E5, LW2.E6, LW2.E7, LW2.E8) The Silverwastes [MapSandcastleToFleet]" }, + { fileName: "908730.data", name: "(LW2.E5.4) Hidden Arcana [MapSandGrain]" }, + { + fileName: "922320.data", + name: "(LW2.E7.2) Meeting the Asura [MapWetlandRiversideAsuraFirstContact]", + }, + ], + }, + { + name: "(X1) Guild Wars 2: Heart of Thorns (HoT) - (Z) Zone - Maguuma Jungle [Jungle]", + maps: [ + { fileName: "969663.data", name: "(Z.1) Verdant Brink [MapJungleFleet]" }, + { fileName: "1263739.data", name: "(Z.2) Auric Basin [MapJungleGold]" }, + { fileName: "1264291.data", name: "(Z.3) Tangled Depths [MapJungleRoots]" }, + { fileName: "1262310.data", name: "(Z.4) Dragon's Stand [MapJungleArmy]" }, + { fileName: "1262460.data", name: "(X1.16) Hearts and Minds [MapJungleArmyNightmare]" }, + ], + }, + { + name: "(LW3) Living World Season 3: Glint's Legacy", + maps: [ + { fileName: "1472635.data", name: "(LW3.E1) Bloodstone Fen [MapJungleBloodstone]" }, + { fileName: "1498071.data", name: "(LW3.E2.1) Taimi's Game [MapHoloRoom]" }, + { fileName: "1498578.data", name: "(LW3.E2) Ember Bay [MapFireIsland]" }, + { fileName: "1605211.data", name: "(LW3.E3) Bitterfrost Frontier [MapAlpineTundra]" }, + { fileName: "1646520.data", name: "(LW3.E4) Lake Doric [MapValleyPort]" }, + { fileName: "1645474.data", name: "(LW3.E4.6) Confessor's End [MapValleyEstatePort]" }, + { fileName: "1682493.data", name: "(LW3.E5) Draconis Mons [MapLavaLamp]" }, + { fileName: "1682763.data", name: "(LW3.E5.5) Heart of the Volcano [MapLavaLampInstance2]" }, + { fileName: "1734839.data", name: "(LW3.E6.1) White Mantle Hideout [MapS0E6AspectHunt]" }, + { fileName: "1735440.data", name: "(LW3.E6.2) Shining Blade Headquarters [MapValleyBlade]" }, + { fileName: "1735346.data", name: "(LW3.E6) Siren's Landing [MapReclaimed]" }, + ], + }, + { + name: "(X2) Guild Wars 2: Path of Fire (PoF) - (Z) Zone - Crystal Desert [Desert]", + maps: [ + { fileName: "1794574.data", name: "(Z.1) Crystal Oasis [MapDesertOasis]" }, + { fileName: "1833034.data", name: "(Z.2) Desert Highlands [MapDesertHighlands]" }, + { + fileName: "1840368.data", + name: "(X2.7, X2.OS) Facing the Truth: The Sanctum, The Dark Library [MapDesertSanctum]", + }, + { fileName: "1840103.data", name: "(Z.3) Elon Riverlands [MapDesertRiver]" }, + { + fileName: "1833726.data", + name: "(X2.8, X2.9) The Way Forward, The Departing [MapDesertMists]", + }, + { fileName: "1842533.data", name: "(Z.4) The Desolation [MapDesertTorment]" }, + { fileName: "1839188.data", name: "(Z.5) Domain of Vabbi [MapDesertPalace]" }, + ], + }, + { + name: "(LW4) Living World Season 4: Rise of Kralkatorrik", + maps: [ + { + fileName: "1903523.data", + name: "(LW4.E1.1) Eye of the Brandstorm [MapDesertOasisInstanceS4E1]", + }, + { fileName: "1902235.data", name: "(LW4.E1) Domain of Istan [MapDesertJewel]" }, + { fileName: "1901428.data", name: "(LW4.E1.6) Fahranur, the First City [MapDesertCity]" }, + { + fileName: "1954984.data", + name: "(LW4.E2.1) Tracking the Scientist [MapDesertArchipelago_Chapter1]", + }, + { + fileName: "1955224.data", + name: "(LW4.E2.2) The Test Subject [MapDesertArchipelago_Chapter2]", + }, + { fileName: "1957526.data", name: "(LW4.E2) Sandswept Isles [MapDesertArchipelagoLargeMap]" }, + { fileName: "1955471.data", name: "(LW4.E2.5) The Charge [MapDesertArchipelago_Chapter5]" }, + { fileName: "1955642.data", name: "(LW4.E2.5) ??? [MapDesertArchipelago_Chapter5Boss_1]" }, + { fileName: "1955915.data", name: "(LW4.E2.5) ??? [MapDesertArchipelago_Chapter5Boss_2]" }, + { fileName: "1956140.data", name: "(LW4.E2.5) ??? [MapDesertArchipelago_Chapter5Boss_3]" }, + { fileName: "1956245.data", name: "(LW4.E2.5) ERROR: SIGNAL LOST [MapDesertArchipelago_Chapter5Boss_4]" }, + { fileName: "2005467.data", name: "(LW4.E3.1) Seized [MapDesertOasisS4E3]" }, + { fileName: "2004704.data", name: "(LW4.E3) Domain of Kourna [MapDesertMoon]" }, + { fileName: "2044320.data", name: "(LW4.E4) Jahai Bluffs, Sun's Refuge [MapDesertBluffs]" }, + { fileName: "2044502.data", name: "(LW4.E4.5) Storm Tracking [MapDesertBluffsCh5]" }, + { fileName: "2093791.data", name: "(LW4.E5.1) Scion & Champion [MapThe_Begining]" }, + { fileName: "2092435.data", name: "(LW4.E5) Thunderhead Peaks [MapAlpineKeep]" }, + { fileName: "2092812.data", name: "(LW4.E5.3) The Crystal Blooms [MapAlpineKeepInstance]" }, + { + fileName: "2093450.data", + name: "(LW4.E5.5) The Crystal Dragon [MapAlpineKeepInstanceKralk]", + }, + { fileName: "2124612.data", name: "(LW4.PP) Mists Rift [MapBrandedMistfight]" }, + { fileName: "2146312.data", name: "(LW4.E6.1) The End [MapDesertDragonfallCh01]" }, + { fileName: "2146346.data", name: "(LW4.E6.1) Dragonflight [MapDesertDragonfallCh02]" }, + { fileName: "2146125.data", name: "(LW4.E6) Dragonfall [MapDesertDragonfall]" }, + { fileName: "2146510.data", name: "(LW4.E6.5) Descent [MapDesertDragonfallFinalInstance]" }, + { fileName: "2146376.data", name: "(LW4.E6.5) Epilogue [MapDesertDragonfallEpilogue]" }, + ], + }, + { + name: "(LW5) Living World Season 5: The Icebrood Saga (IBS) - (SM) Strike Mission, (DRM) Dragon Response Missions", + maps: [ + { fileName: "2203371.data", name: "(LW5.E0, SM.1) Grothmar Valley, Shiverpeaks Pass [MapRegrownBlood]" }, + { fileName: "2251232.data", name: "(LW5.E1, LW5.E2) Bjora Marches [MapBjoraMarchesCombined]" }, + { fileName: "2224355.data", name: "(SM.2) Voice of the Fallen and Claw of the Fallen [MapKodanBNB]" }, + { fileName: "2224381.data", name: "(SM.3) Fraenir of Jormag [Mapshamanbnb]" }, + { fileName: "2224406.data", name: "(SM.4) Boneskinner [MapWendigoBNB]" }, + { fileName: "2249817.data", name: "(LW5.E2.5) Voice in the Deep [MapAlpineMarchesEp2FinalInstance]" }, + { fileName: "2251486.data", name: "(SM.5) Whisper of Jormag [MapWhisperofJormag]" }, + { fileName: "2251447.data", name: "(Lobby) Eye of the North [MapAlpineMonumentDragon]" }, + { fileName: "2272807.data", name: "(LW5.VotP.1, SM.6) Forging Steel [MapAlpineClimb]" }, + { fileName: "2273128.data", name: "(LW5.VotP.2) Darkrime Delves [MapAlpineDelves]" }, + { fileName: "2298865.data", name: "(LW5.E3) Drizzlewood Coast [MapAlpineCascades]" }, + { fileName: "2318029.data", name: "(LW5.E3, LW5.E4) Drizzlewood Coast [MapAlpineCascades02]" }, + { fileName: "2299088.data", name: "(SM.7) Cold War [MapAlpineCascadesStrike]" }, + { fileName: "2369582.data", name: "(LW5.E5.1) Primordus Rising [MapWetlandComplexE5Story]" }, + { + fileName: "2370614.data", + name: "(LW5.E5.3, DRM.1) Metrica Province [MapWetlandRiversideS5E5]", + }, + { + fileName: "2370017.data", + name: "(LW5.E5.3, DRM.2) Brisban Wildlands [MapWetlandGrottoS5E5]", + }, + { + fileName: "2369116.data", + name: "(LW5.E5.3, DRM.3) Gendarran Fields [MapValleySettlementS5E5]", + }, + { fileName: "2366776.data", name: "(LW5.E5.4, DRM.4) Fields of Ruin [MapRegrownHawkeS5E5]" }, + { + fileName: "2364032.data", + name: "(LW5.E5.4, DRM.5) Thunderhead Peaks [MapAlpineKeepS5E5]", + }, + { fileName: "2368400.data", name: "(LW5.E5.5, DRM.6) Lake Doric [MapValleyPortS5E5]" }, + { fileName: "2365787.data", name: "(LW5.E5.5, DRM.7) Snowden Drifts [MapAlpinePowderS5E5]" }, + { fileName: "2369398.data", name: "(LW5.E5.6, DRM.8) Caledon Forest [MapWetlandBayouS5E5]" }, + { fileName: "2414140.data", name: "(LW5.E5.7) Wildfire [MapLavaLampInstance_S5E5]" }, + { fileName: "2367211.data", name: "(LW5.E5.8, DRM.9) Bloodtide Coast [MapValleyCoastS5E5]" }, + { fileName: "2366368.data", name: "(LW5.E5.9, DRM.10) Fireheart Rise [MapRegrownFlameS5E5]" }, + { fileName: "2434582.data", name: "(LW5.E5) Dragonstorm [MapDragonFight]" }, + { fileName: "2434675.data", name: "(LW5.E5.11) Champion's End [MapDragonFightStoryInstance]" }, + ], + }, + { + name: "(X3) Guild Wars 2: End of Dragons (EoD) - (Z) Zone, (SM) Strike Mission - Cantha [Cantha]", + maps: [ + { fileName: "2669133.data", name: "(Lounge) Thousand Seas Pavilion [MapMTXLounge]" }, + { fileName: "2639738.data", name: "(X3.1) Old Friends [MapAlpineSlopeX03]" }, + { fileName: "2639795.data", name: "(X3.1) Aetherblade Armada [MapCanthaArmada]" }, + { fileName: "2647516.data", name: "(Z.1) Seitung Province [MapCanthaShingJea]" }, + { fileName: "2649141.data", name: "(SM.1) Aetherblade Hideout [MapMaiTrin]" }, + { fileName: "2645519.data", name: "(Z.2) New Kaineng City [MapCanthaKaineng]" }, + { fileName: "2645805.data", name: "(X3.7) Deepest Secrets: Yong Reactor [MapCanthaKainengCH5Reactor]" }, + { fileName: "2640407.data", name: "(Lobby) Arborstone [MapCanthaArborstone]" }, + { fileName: "2641850.data", name: "(Z.3) The Echovald Wilds [MapCanthaEchovald]" }, + { + fileName: "2642769.data", + name: "(SM.2) Xunlai Jade Junkyard [MapCanthaEchovaldStrikeMissions]", + }, + { fileName: "2646104.data", name: "(SM.3) Kaineng Overlook [MapCanthaKainengMinSecStrike]" }, + { fileName: "2644196.data", name: "(Z.4) Dragon's End [MapCanthaJadeSea]" }, + { fileName: "2702043.data", name: "(SM.4) Harvest Temple [MapCanthaJadeSeaStrikeMission]" }, + { fileName: "3012212.data", name: "(Z.5) Gyala Delve [MapCanthaDeep]" }, + { fileName: "3043972.data", name: "(Z.5) Gyala Delve [MapCanthaDeepQR2]" }, + { + fileName: "3100947.data", + name: "(X3.18) Forward [MapCanthaShingJeaExpac4AureneInstance]", + }, + ], + }, + { + name: "(X4) Guild Wars 2: Secrets of the Obscure (SotO) - (Z) Zone, (SM) Strike Mission - Skies of Tyria [Sky]", + maps: [ + { + fileName: "3134712.data", + name: "(X4.1) Commander without a Cause: Gendarran Fields [MapValleySettlementExpac4StealthMission]", + }, + { fileName: "3134778.data", name: "(Z.1) Skywatch Archipelago [MapSkyRise]" }, + { + fileName: "3135285.data", + name: "(SM.1) Cosmic Observatory [MapSkyRiseStrikeObservatory]", + }, + { fileName: "3135660.data", name: "(Lobby) The Wizard's Tower [MapSkyTower]" }, + { fileName: "3135805.data", name: "(Z.2) Amnytas [MapSkySpire]" }, + { fileName: "3136072.data", name: "(SM.2) Temple of Febe [MapCerusArena]" }, + { fileName: "3193573.data", name: "(?) Convergences [MapBountyIslands]" }, + { fileName: "3194054.data", name: "(Z.3) Inner Nayos [MapDream]" }, + { fileName: "3264516.data", name: "(Z.3) Inner Nayos [MapDream2]" }, + { fileName: "3316196.data", name: "(Z.3) Inner Nayos [MapDream3]" }, + ], + }, + { + name: "(GH) Guild Halls", + maps: [ + { fileName: "1255378.data", name: "(GH.1-2) Gilded Hollow [MapGuildCavern]" }, + { fileName: "1256064.data", name: "(GH.1-2) Lost Precipice [MapGuildHeights]" }, + { fileName: "1843274.data", name: "(GH.3) Windswept Haven [MapGuildPyramid]" }, + { fileName: "2648082.data", name: "(GH.4) Isle of Reflection [MapGuildIsle]" }, + ], + }, + { + name: "Cooperative - (FotM) Fractals of the Mists", + maps: [ + { fileName: "1733961.data", name: "(Lounge) Mistlock Sanctuary [MapInfiniteCosmicVIPLounge]" }, + { fileName: "1498016.data", name: "(FotM.0) Mistlock Observatory [MapInfiniteHub]" }, + { fileName: "519839.data", name: "(FotM.0-9) Fractals of the Mists [MapInfiniteIslands]" }, + { fileName: "2187042.data", name: "(FotM.0-9) Aquatic Ruins [MapInfiniteUnderwater]" }, + { fileName: "1426653.data", name: "(FotM.0-9) Cliffside [MapInfiniteCliffside]" }, + { fileName: "1472382.data", name: "(FotM.0-9) Snowblind [MapInfiniteSnowblind]" }, + { fileName: "1472406.data", name: "(FotM.0-9) Swampland [MapInfiniteSwamp]" }, + { + fileName: "1498798.data", + name: "(FotM.10-14) Aetherblade, Captain Mai Trin Boss [MapValleyArchDungeonUpdated02]", + }, + { + fileName: "1905739.data", + name: "(FotM.10-14) Molten Furnace, Molten Boss [MapFlameFrostFractalExtended]", + }, + { fileName: "697450.data", name: "(FotM.10-14) Thaumanova Reactor [MapInfiniteReactor]" }, + { fileName: "1472361.data", name: "(FotM.15) Chaos Isles [MapInfiniteChaos]" }, + { fileName: "1605344.data", name: "(FotM.16) Nightmare [MapInfiniteToxic]" }, + { fileName: "1733857.data", name: "(FotM.17) Shattered Observatory [MapInfiniteCosmic]" }, + { fileName: "1905889.data", name: "(FotM.18) Twilight Oasis [MapInfiniteMordant]" }, + { fileName: "2005713.data", name: "(FotM.19) Deepstone [MapInfiniteLabyrinth]" }, + { fileName: "2094098.data", name: "(FotM.20) Siren's Reef [MapInfiniteCove]" }, + { fileName: "2333932.data", name: "(FotM.21) Sunqua Peak [MapFractalElementalIslands]" }, + { fileName: "3100195.data", name: "(FotM.22) Silent Surf [MapLuxonFractal]" }, + { fileName: "3317434.data", name: "(FotM.23) Lonely Tower [MapSkyRiseFractalEparch]" }, + ], + }, + { + name: "Cooperative - (R) Raids", + maps: [ + { + fileName: "1427048.data", + name: "(Lobby, R.0) Lion's Arch Aerodrome, Special Forces Training Area [MapValleyArchRaidLobby]", + }, + { fileName: "1151420.data", name: "(R.1) Spirit Vale [MapRaidJungle01]" }, + { fileName: "1383309.data", name: "(R.2) Salvation Pass [MapE1R2]" }, + { fileName: "1454070.data", name: "(R.3) Stronghold of the Faithful [MapE1R3]" }, + { fileName: "1645215.data", name: "(R.4) Bastion of the Penitent [MapE1R4]" }, + { fileName: "1906329.data", name: "(R.5) Hall of Chains [MapE1R5]" }, + { fileName: "2045250.data", name: "(R.6) Mythwright Gambit [MapE2R2]" }, + { fileName: "2157962.data", name: "(R.7) The Key of Ahdashim [MapE2R3]" }, + ], + }, + { + name: "Competitive - Player vs. Player (PvP) - (CQ) Conquest, (MB) Murderball, (SH) Stronghold, (TDM) Team Deathmatch", + maps: [ + { fileName: "132570.data", name: "(Lobby) Heart of the Mists" }, + { fileName: "197249.data", name: "(Lobby) Heart of the Mists [MapPvPLobby]" }, + { fileName: "1713939.data", name: "(Lobby) Heart of the Mists [Mappvplobbyrework_cats]" }, + { fileName: "1734729.data", name: "(Lobby) Heart of the Mists [Mappvplobbyrework_catsMoreRoom]" }, + { fileName: "2129692.data", name: "(Lobby) Heart of the Mists [MapPvPLobby1016rework]" }, + { fileName: "132710.data", name: "(CQ.1-4) Battle of Khylo" }, + { fileName: "197402.data", name: "(CQ.1-4) Battle of Kyhlo [MapPvPConquestSiege]" }, + { fileName: "1644708.data", name: "(CQ.1-4) Battle of Khylo [MapPvPConquestSiege2]" }, + { fileName: "1666233.data", name: "(CQ.1-4) Battle of Khylo [MapPvPConquestSiege3]" }, + { fileName: "132837.data", name: "(CQ.1-4) Forest of Niflhel" }, + { fileName: "197545.data", name: "(CQ.1-4) Forest of Niflhel [MapPvPConquestForest]" }, + { fileName: "376916.data", name: "(CQ.1-4) Legacy of the Foefire [MapPvPConquestGuild]" }, + { fileName: "467374.data", name: "(CQ.1-4) Raid on the Capricorn" }, + { fileName: "520609.data", name: "(CQ.5) Temple of the Silent Storm [MapPvPConquestDojo]" }, + { fileName: "556199.data", name: "(CQ.6) Spirit Watch" }, + { fileName: "1473061.data", name: "(CQ.6) Spirit Watch [MapPVPConquestSpirit2]" }, + { fileName: "579383.data", name: "(CQ.7) Skyhammer" }, + { fileName: "677968.data", name: "(CQ.7) Skyhammer" }, + { fileName: "1426736.data", name: "(CQ.7) Skyhammer [MapPvPConquestCannonCapture]" }, + { fileName: "1934470.data", name: "(CQ.7) Skyhammer [MapPvPConquestCannonCapture2]" }, + { fileName: "1472979.data", name: "(CQ.8) Revenge of the Capricorn [MapPvPConquestCoastReturn]" }, + { fileName: "1644624.data", name: "(CQ.8) Revenge of the Capricorn [MapPvPConquestCoastReturnshrunk]" }, + { fileName: "1498174.data", name: "(CQ.9) Eternal Coliseum [MapPVPConquestArenaGods2]" }, + { fileName: "1704155.data", name: "(CQ.9) Eternal Coliseum [MapPVPConquestArenaGods4]" }, + { fileName: "2128880.data", name: "(CQ.9) Eternal Coliseum [MapPVPConquestArenaGodsTheme]" }, + { fileName: "2065760.data", name: "(CQ.10) Djinn's Dominion [Mapdesertconq]" }, + { fileName: "2128938.data", name: "(CQ.10) Djinn's Dominion [MapDesertConqWallMid]" }, + { fileName: "2175965.data", name: "(CQ.10) Djinn's Dominion [MapDesertConqWallMid2]" }, + { fileName: "791564.data", name: "(MB, TDM.2) Courtyard [MapDMCourtyard]" }, + { fileName: "1713054.data", name: "(MB, TDM.2) Courtyard [MapDMCourtyard2]" }, + { fileName: "870987.data", name: "(SH) Battle of Champion's Dusk [MapPvPStrongholdCity]" }, + { fileName: "871093.data", name: "(SH) Battle of Champion's Dusk [MapPvPStrongholdCityMercs]" }, + { fileName: "1712986.data", name: "(TDM.1) Hall of the Mists [MapHallway2v2]" }, + { fileName: "1712945.data", name: "(TDM.3) Asura Arena [Mapasura2v2]" }, + { fileName: "2187125.data", name: "(TDM.4) Auric Span [MapJungle2v2]" }, + ], + }, + { + name: "Competitive - World vs. World (WvW) - (MW) Mist War, (EotM) Edge of the Mists", + maps: [ + { fileName: "2113077.data", name: "(Lounge) Armistice Bastion [MapWvwLounge]" }, + { fileName: "131235.data", name: "(MW) Eternal Battlegrounds, Obsidian Sanctum" }, + { fileName: "195806.data", name: "(MW) Eternal Battlegrounds, Obsidian Sanctum [MapWvWCenter]" }, + { fileName: "1798709.data", name: "(MW) Eternal Battlegrounds, Obsidian Sanctum [MapWvWCenterGliding]" }, + { fileName: "1885693.data", name: "(MW) Eternal Battlegrounds, Obsidian Sanctum [MapWvWCenter4]" }, + { + fileName: "2263889.data", + name: "(MW) Eternal Battlegrounds, Obsidian Sanctum [MapWvWCenterWallChange10_19]", + }, + { fileName: "131574.data", name: "(MW) Alpine Borderlands" }, + { fileName: "641501.data", name: "(MW) Alpine Borderlands [MapWvWRedHomeLake01]" }, + { fileName: "1799855.data", name: "(MW) Alpine Borderlands [MapWvWRedHomeLake01gliding]" }, + { fileName: "1918037.data", name: "(MW) Alpine Borderlands [MapWvWRedHomeLake02]" }, + { fileName: "1427803.data", name: "(MW) Desert Borderlands [MapWvWDesertHomeUpdate]" }, + { fileName: "1647236.data", name: "(MW) Desert Borderlands [MapWvWDesertHomeUpdateMIDrework]" }, + { fileName: "1799442.data", name: "(MW) Desert Borderlands [MapWvWDesertHome4]" }, + { fileName: "2112733.data", name: "(MW) Desert Borderlands [MapWvWDesertHome]" }, + { fileName: "736241.data", name: "(EotM) Edge of the Mists [MapWvWIslands]" }, + ], + }, + { + name: "Festival - (LNY) Lunar New Year", + maps: [ + { fileName: "1625212.data", name: "(City) Divinity's Reach [MapValleyDivinityLNY]" }, + { fileName: "595582.data", name: "(LNY) Dragon Ball Arena [MapDragonBall]" }, + ], + }, + { + name: "Festival - (SAB) Super Adventure Festival - Super Adventure Box [SAB]", + maps: [ + { fileName: "1666365.data", name: "(City) Rata Sum [MapWetlandComplexSAB]" }, + { fileName: "569756.data", name: "(SAB) Super Adventure Box" }, + { fileName: "636133.data", name: "(Lobby) Hub [MapSABHub]" }, + { fileName: "635555.data", name: "(SAB.1) World 1 [MapSABWorld1]" }, + { fileName: "635960.data", name: "(SAB.2) World 2 [MapSABWorld2]" }, + { fileName: "3024941.data", name: "(SAB.3) World 3 [MapSABWorld3-0]" }, + { fileName: "3281398.data", name: "(SAB.3) World 3 [MapSABWorld3-1]" }, + ], + }, + { + name: "Festival - (DB) Dragon Bash", + maps: [{ fileName: "2164993.data", name: "(City) Hoelbrak [MapAlpineHallDragonBash]" }], + }, + { + name: "Festival - (FotFW) Festival of the Four Winds", + maps: [ + { fileName: "606255.data", name: "(FotFW) Labyrinthine Cliffs [MapEvenKiteCity]" }, + { fileName: "605983.data", name: "(FotFW) Sanctum Sprint [MapEvenTriathlonKiteCity]" }, + { fileName: "617120.data", name: "(FotFW) Aspect Arena [MapEvenPVPKiteCity]" }, + { fileName: "622681.data", name: "(FotFW) The Crown Pavilion [MapJubileeArena]" }, + ], + }, + { + name: "Festival - (HW) Halloween - Mad King's Realm [MadKing]", + maps: [ + { fileName: "1869665.data", name: "(City) Lion's Arch [MapValleyArchKielHalloween]" }, + { fileName: "506670.data", name: "(HW) Mad King's Labyrinth, Lunatic Inquisition [MapMadKingMaze]" }, + { fileName: "662436.data", name: "(HW) Mad King's Labyrinth, Lunatic Inquisition [MapMadKingMaze2013]" }, + { fileName: "2499169.data", name: "(HW) Mad King's Labyrinth, Lunatic Inquisition [MapMadKingMaze2021]" }, + { fileName: "506739.data", name: "(HW) Mad King's Clock Tower [MapMadKingTower]" }, + { fileName: "506539.data", name: "(HW) Mad King's Raceway, Reaper's Rumble [MapMadKingField]" }, + { fileName: "506592.data", name: "(HW) Ascent to Madness [MapMadKingBoss]" }, + ], + }, + { + name: "Festival - (WD) Wintersday - (SM) Strike Mission - Wintersday Celebration [Wintersday]", + maps: [ + { + fileName: "705746.data", + name: "(City) Divinity's Reach [MapWintersDayValleyDivinity2013]", + }, + { fileName: "1917775.data", name: "(City) Divinity's Reach [MapValleyDivinityholiday]" }, + { fileName: "529718.data", name: "(WD) Bell Choir Ensemble, Snowball Mayhem [MapWintersdaySnowGlobe]" }, + { fileName: "529896.data", name: "(WD) Tixx's Infinirarium, Toypocalypse [MapWintersdayAirship]" }, + { fileName: "529945.data", name: "(WD) Winter Wonderland [MapWintersdayFrostyland]" }, + { fileName: "2076921.data", name: "(SM) Secret Lair of the Snowmen [MapFrozenTyrant]" }, + ], + }, + { + name: "Miscellaneous", + maps: [ + { fileName: "122695.data", name: "(((Empty Plane)))" }, + { fileName: "129834.data", name: "Lake Doric" }, + { fileName: "132853.data", name: "(((Empty Box)))" }, + { fileName: "184799.data", name: "[MapDummy]" }, + { fileName: "193081.data", name: "Lake Doric [MapValleyReach]" }, + { fileName: "197562.data", name: "[MapPvPBlackBox]" }, + { fileName: "606030.data", name: "Basket Brawl [MapBasketBrawl]" }, + { fileName: "875614.data", name: "[MapTutorialChina]" }, + { fileName: "969964.data", name: "Verdant Brink [MapRootsAfterShip]" }, + { fileName: "1255516.data", name: "[MapGuildColiseum]" }, + { fileName: "1255634.data", name: "(((Unknown Town)))" }, + { fileName: "1282201.data", name: "(((WvW)))" }, + { fileName: "1498193.data", name: "[MapPvPConquestTemp]" }, + { fileName: "1513556.data", name: "[MapPvPInfection2]" }, + { fileName: "1513607.data", name: "[MapPvPConquestTest_01]" }, + { fileName: "1513620.data", name: "[MapPvPConquestTest_02]" }, + { fileName: "1513675.data", name: "[MapPvPConquestTest_04]" }, + { fileName: "1956299.data", name: "[MapDesertArchipelago_Instance]" }, + { fileName: "2204239.data", name: " [MapRegrownBloodCinematic]" }, + { fileName: "2224545.data", name: "Jaga Moraine [MapAlpinemoraine]" }, + { fileName: "2224624.data", name: "[MapAlpineMoraineFinalInstance]" }, + { fileName: "2257438.data", name: "[MapTest]" }, + { fileName: "2649061.data", name: " [MapRegrownBlood_CinematicEOD]" }, + { fileName: "2644298.data", name: "[MapJadeSeaWhirlpool]" }, + { fileName: "2689589.data", name: " [MapDesertHighlandsE3]" }, + ], + }, + ], + }; + + /** + * Parse the beginning of a file to find its type + * + * @memberof FileTypes + */ + function getFileType(buffer) { + const dataView = new DataView(buffer); + const first4 = String.fromCharCode(dataView.getUint8(0), dataView.getUint8(1), dataView.getUint8(2), dataView.getUint8(3)); + // Parse textures + switch (first4) { + case "ATEC": + return "TEXTURE_ATEC"; + case "ATEP": + return "TEXTURE_ATEP"; + case "ATET": + return "TEXTURE_ATET"; + case "ATEU": + return "TEXTURE_ATEU"; + case "ATEX": + return "TEXTURE_ATEX"; + case "ATTX": + return "TEXTURE_ATTX"; + } + if (first4.indexOf("DDS") === 0) + return "TEXTURE_DDS"; + if (first4.indexOf("PNG") === 1) + return "TEXTURE_PNG"; + if (first4.indexOf("RIFF") === 0) + return "TEXTURE_RIFF"; + if (first4.indexOf("YUI") === 0) + return "TEXT_YUI"; + // PackFiles + if (first4.indexOf("PF") === 0) { + const file = new t3dParser.FileParser(buffer, true); /// true for "plz no load chunkz" + return "PF_" + file.header.type; + } + // Binaries + if (first4.indexOf("MZ") === 0) + return "BINARIES"; + // Strings + if (first4.indexOf("strs") === 0) + return "STRINGS"; + // Raw asnd chunk (without pack file) + if (first4.indexOf("asnd") === 0) + return "CHUNK_ASND"; + // TODO: parse all buffers and if all bytes are valid unicode symbols then + // return TEXT_UNKNOWN; + // Unknown + return "UNKNOWN"; + } + + var FileTypes = /*#__PURE__*/Object.freeze({ + __proto__: null, + getFileType: getFileType + }); + + /** + * A statefull class that handles reading and inflating data from a local GW2 dat file. + */ + class LocalReader { + settings; + dataReader; + persistantStore; + file; + indexTable; + fileMetaTable; + persistantData = []; + _fileTypeCache; + constructor(settings) { + this.settings = settings; + this.dataReader = new DataReader(settings); + this.file = undefined; + this.indexTable = []; + this.fileMetaTable = []; + if (settings.noIndexedDB !== false) { + this.persistantStore = new PersistantStore(); + } + } + /** + * Asynchronously loads the archive by parsing its file index and header. + */ + async openArchive(file) { + const { metaTable, indexTable } = await t3dParser.ArchiveParser.readArchive(file); + this.fileMetaTable = metaTable; + this.indexTable = indexTable; + this.file = file; + } + /** + * Gets MFT index by baseId + */ + getFileIndex(baseId) { + return this.indexTable[baseId]; + } + /** + * Returns the metadata of a file stored in the archive + */ + getFileMeta(mftId) { + return this.fileMetaTable[mftId]; + } + /** + * Fetch a file and uncompress it if needed / required. + */ + async readFile(mftId, isImage, raw, fileLength, extractLength) { + if (!this.file) + throw new Error("No file loaded"); + //let buffer, dxtType, imageWidth, imageHeight; + const meta = this.getFileMeta(mftId); + if (!meta) + throw new Error("Unexistant file"); + // Slice up the data + const buffer = await t3dParser.ParsingUtils.sliceFile(this.file, Number(meta.offset), fileLength || meta.size); + // If needed we decompress, if not we keep raw + if (raw || meta.compressed) { + let data = { + buffer: undefined, + dxtType: undefined, + imageWidth: undefined, + imageHeight: undefined, + }; + await this.dataReader + .inflate(buffer, buffer.byteLength, mftId, isImage, extractLength || 0) + .then((result) => { + data = result; + }) + .catch(() => { + data = { + buffer: undefined, + dxtType: undefined, + imageWidth: undefined, + imageHeight: undefined, + }; + }); + return data; + } + else + return { buffer }; + } + /** + * Scans asynchronously the types of all the files listed in the archive. + * Uses persistant store to cache and speed up a rescan. + */ + async readFileList( + // This is a way for platforms not supporting indexDB to provide their own persistant storage. + oldFileList) { + if (!this.file) + throw new Error("No file loaded"); + const self = this; + let persistantList = oldFileList || []; + let persistantId; + // Load previously saved data + if (this.persistantStore) { + const lastListing = await this.persistantStore.getLastListing(this.file.name); + persistantList = lastListing.array; + // If the last scan was not completed then we will just update it.. + if (!lastListing.complete) { + persistantId = lastListing.key; + } + } + // Create a list of all the baseIds we need to inspect + const iterateList = Object.keys(self.indexTable).map((i) => Number(i)); + for (const index in persistantList) { + if (!(index in self.indexTable)) + iterateList.push(index); + } + // Spawn the decompression tasks + const taskArray = []; + for (let i = 0; i < 1; i++) { + taskArray[i] = Promise.resolve({ task: i }); + } + // Helps us to know when we need to update the persistant store + let persistantNeedsUpdate = false; + // Iterate through the array + for (const index in iterateList) { + const baseId = iterateList[index]; + // First use a synchronous function to know if we need to scan the file + const result = this._needsScan(baseId, persistantList); + if (result.scan === true) { + const taskId = (await Promise.race(taskArray)).task; + taskArray[taskId] = this._readFileType(baseId).then((scanResult) => { + // Put the result into our persistant storage + persistantList[baseId] = { + baseId: baseId, + size: scanResult.size, + crc: scanResult.crc, + fileType: scanResult.fileType, + }; + return { task: taskId }; + }); + } + if (result.change === "removed") { + // Update the persistant storage + delete persistantList[baseId]; + } + // Handle persistant storage update + if (result.change !== "none") + persistantNeedsUpdate = true; + // Tasks to do only every % + if (index % Math.floor(iterateList.length / 100) === 0) { + // Print progress + T3D.Logger.log(T3D.Logger.TYPE_PROGRESS, "Finding types", index / Math.floor(iterateList.length / 100)); + // Update the persistant storage if needed + if (self.persistantStore && persistantNeedsUpdate) { + persistantNeedsUpdate = false; + self.persistantStore + .putListing(persistantId, persistantList, self.file.name, false) + .then((res) => (persistantId = res)); + } + } + } + await Promise.all(taskArray).then(() => { + // Finally update the listing as complete + if (self.persistantStore) { + self.persistantStore.putListing(persistantId, persistantList, self.file.name, true); + } + }); + this.persistantData = persistantList; + return this.getFileList(); + } + /** + * Cheap version of the readFileList which will only scan files registered in the mapFileList + * This helps us being sure that we only return files that contain a mapc chunk when using + * the getMapList function + */ + async readMapList() { + const fileList = mapMap.maps.reduce((maps, category) => { + return maps.concat(category.maps.map((entry) => entry.fileName)); + }, []); + const temporaryStore = []; + for (const fileName of fileList) { + const baseId = fileName.split(".data")[0]; + if (this.indexTable[baseId]) { + const scanResult = await this._readFileType(baseId); + temporaryStore[baseId] = { + baseId: Number(baseId), + size: scanResult.size, + crc: scanResult.crc, + fileType: scanResult.fileType, + }; + } + } + // Fill the store without saving it to disk + this.persistantData = temporaryStore; + } + /** + * Returns a list of all the maps with their name and category. + * Uncategorized maps are available only if readFileList have been used before. + */ + async getMapList() { + const self = this; + const mapArray = []; + // If the archive hasn't been completely scanned we do a partial scan for the map files. + // It should be fast + if (this.persistantData.length === 0) { + await this.readMapList(); + } + // Filter the maps out of all our files + const reversedIndex = this.getReverseIndex(); + const maps = this.persistantData + .filter((file) => file.fileType === "PF_mapc") + .filter((id) => id.baseId === reversedIndex[self.getFileIndex(id.baseId)][0]); + for (const map of maps) { + let found = false; + // Try to see if we already have some informations on this map + for (const category of mapMap.maps) { + const fileMap = category.maps.find((item) => Number(item.fileName.split(".data")[0]) === map.baseId); + if (fileMap) { + mapArray.push({ + name: fileMap.name, + category: category.name, + baseId: map.baseId, + categoryIndex: mapMap.maps.indexOf(category), + }); + found = true; + break; + } + } + // If not we register it as Uncategorized + if (!found) { + mapArray.push({ + name: map.baseId.toString(), + category: "Uncategorized", + baseId: map.baseId, + categoryIndex: 99999, + }); + } + } + mapArray.sort((a, b) => a.category.localeCompare(b.category)); + return mapArray; + } + /** + * Return the meta table with extra information such as an array of baseIds and the file types. + * The filetype is available only if readFileList have been used before of course. + */ + getFileList() { + const typeList = this.persistantData ? this.persistantData.map((i) => i.fileType) : []; + const reverseBaseIdList = this.getReverseIndex(); + const fileList = this.fileMetaTable.map((meta, mftId) => { + const baseIds = reverseBaseIdList[mftId] ? reverseBaseIdList[mftId] : []; + const type = reverseBaseIdList[mftId] ? typeList[baseIds[0]] : "Non-Registered"; + return { + mftId: mftId, + baseIdList: baseIds, + size: meta.size, + crc: meta.crc, + fileType: type, + }; + }); + fileList[0] = { + mftId: 0, + baseIdList: [], + size: 0, + crc: 0, + fileType: "Non-Registered", + }; + return fileList; + } + /** + * @returns {Array>} + */ + getReverseIndex() { + return this.indexTable.reduce((reversed, mftId, baseId) => { + if (mftId in reversed) + reversed[mftId].push(baseId); + else + reversed[mftId] = [baseId]; + return reversed; + }, []); + } + // Callback wrapper + /** + * Reads data from a file in the dat. + * If `raw` is true, any infation is skipped and raw data is returned. + */ + loadFile(baseId, callback, isImage, raw) { + const mftId = this.getFileIndex(baseId); + if (mftId <= 0) + return callback(null); + this.readFile(mftId, isImage, raw).then((result) => { + if (result.buffer === undefined) + return callback(null); + callback(result.buffer, result.dxtType, result.imageWidth, result.imageHeight); + }); + } + // Private + _needsScan(baseId, persistantData) { + if (baseId <= 0) + return { change: "none", scan: false }; + const mftId = this.getFileIndex(baseId); + const metaData = this.getFileMeta(mftId); + // Nothing interesting + if (metaData === undefined && !(baseId in persistantData)) { + return { change: "none", scan: false }; + } + // If the file have been deleted + else if (metaData === undefined) { + return { change: "removed", scan: false }; + } + // If the file is new + else if (!(baseId in persistantData)) { + return { change: "added", scan: true }; + } + // If the size or crc don't match + else if (metaData.size !== persistantData[baseId].size || metaData.crc !== persistantData[baseId].crc) { + return { change: "modified", scan: true }; + } + // If everything is the same + else { + return { change: "none", scan: false }; + } + } + async _readFileType(baseId) { + if (!this._fileTypeCache) + this._fileTypeCache = []; + const mftId = this.getFileIndex(baseId); + const metaData = this.getFileMeta(mftId); + let fileType; + if (this._fileTypeCache[baseId] !== undefined) { + fileType = this._fileTypeCache[baseId]; + } + else { + const fileBuffer = (await this.readFile(mftId, false, false, Math.min(metaData.size, 1000), 32)).buffer; + if (fileBuffer === undefined) + return undefined; + fileType = getFileType(fileBuffer); + } + return { fileType: fileType, crc: metaData.crc, size: metaData.size }; + } + } + + /** + * Base class for data interpretors a.k.a. 'Renderers' + * + * Renderers are classes that collect and interpret data from the dat file. + * + * A {{#crossLink "LocalReader"}}{{/crossLink}} instance is used for accessing data from the dat. + * + * A {{#crossLink "Logger"}}{{/crossLink}} is used for posting progress output or error messages. + * + * The generated data, be it strings, numbers or meshes are put into a value object structure called + * the 'context'. The context can store data generated by multiple renderers and makes sure each + * renderer type, or class has it's own value object within the context. This enables one renderer + * to read data written by another renderer wihtout having to worry about overwriting existing data + * within the context. Keep in mind that you will have to manually pass and clean the conext object! + * + * A clean context object should just be the empty javasript object : {}. + * + * When a Renderer is done it will fire the callback and any view interrested in retrieving the generated + * data from the context can read it using + * {{#crossLink "T3D/getContextValue:method"}}{{/crossLink}}. + * + * + * + * + * @class DataRenderer + * @constructor + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class DataRenderer { + localReader; + settings; + context; + rendererName; + static rendererName = "DataRenderer"; + logger; + constructor(localReader, settings, context, logger_, rendererName = "DataRenderer") { + this.localReader = localReader; + this.settings = settings; + this.context = context; + this.rendererName = rendererName; + /// Just storing parameters + if (!settings) { + settings = {}; + } + this.context[rendererName] = {}; + if (!logger_) { + this.logger = T3D.Logger; + } + else { + this.logger = logger_; + } + } + /** + * Gets the output value object for a specified class within the context. + * + * @param {Class} otherClass The class to fetch the output value object for. + * If not specified the class of this instance will be used. + * @return {Object} The output value object for this class within the context. + */ + getOutput(otherClass) { + return this.context[otherClass ? otherClass.rendererName : this.rendererName]; + } + /** + * Basic rendering of unknown files. Output fileds generated: + * + * - *fileId* The fileId passed in the settings parameter when constructing this instance. + * + * - *rawData* An ArrayBuffer containg the infalted binary data of the loaded file. + * + * - *rawString* A string representation of the rawData + * + * - *image* A value object witht he fields 'width', 'height' and 'data' describing a RGBA bitmap + * image. Only set if the loaded file was a texture. + * + * - *file* A FileParser representation of the loaded file. Only set if the loaded file was a Pack File. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + const self = this; + this.localReader.loadFile(this.settings.id, function (inflatedData) { + /// Set fileId so callers can identify this VO + self.getOutput().fileId = self.settings.id; + /// Share inflated data + self.getOutput().rawData = inflatedData; + /// Construct raw string + const uarr = new Uint8Array(inflatedData); + const rawStrings = []; + const chunksize = 0xffff; + const len = Math.min(uarr.length, 10000); + // There is a maximum stack size. We cannot call String.fromCharCode with as many arguments as we want + for (let i = 0; i * chunksize < len; i++) { + //@ts-ignore + rawStrings.push(String.fromCharCode.apply(null, uarr.subarray(i * chunksize, (i + 1) * chunksize))); + } + if (len < uarr.length) { + rawStrings.push("T3D Ignored the last " + (uarr.length - len) + " bytes when generating this raw output"); + } + self.getOutput().rawString = rawStrings.join(); + /// Check if this is an PF or ATEX file + // Binareis are MZ + const dataView = new DataView(inflatedData); + const first4 = String.fromCharCode(dataView.getUint8(0), dataView.getUint8(1), dataView.getUint8(2), dataView.getUint8(3)); + /// Do special stuff for different fcc signatures + /// + /// fourcc != fcc::ATEX && fourcc != fcc::ATEC && fourcc != fcc::ATEP && + /// fourcc != fcc::ATET && fourcc != fcc::ATEU && fourcc != fcc::ATTX) + /// + if (first4 === "ATEX" || + first4 === "ATEC" || + first4 === "ATEP" || + first4 === "ATET" || + first4 === "ATEU" || + first4 === "ATTX") { + /// TODO: MOVE TO GW2 texture file!! + /// Load file using LocalReader. + self.localReader.loadFile(self.settings.id, function (inflatedData, dxtType, imageWidth, imageHeigth) { + /// Create image using returned data. + const image = { + data: new Uint8Array(inflatedData), + width: imageWidth, + height: imageHeigth, + }; + self.getOutput().image = image; + callback(); + }, true); + } + else if (first4.indexOf("PF") === 0) { + self.getOutput().file = new t3dParser.FileParser(inflatedData); + callback(); + } + else { + self.getOutput().file = null; + callback(); + } + }); + } + } + + /* + guid 1683952224941671000 is fucked up floor in SAB HUB + materialFilename for that mesh is 564821, shared with lots of stuff + lod 1 and 2 are both 0 + material flags is 2056 + */ + /** + * Builds a custom vertex shader for a given number of uv cannels. + * WIP not implemented yet! + * + * @memberof MaterialUtils + * @param {Number} numUv Number of UV channels used by this shader + * @return {String} Genereted vertex shader source + */ + function buildVS(numUv) { + let vdefs = ""; + let adefs = ""; + let reads = ""; + for (let i = 0; i < numUv; i++) { + vdefs += "varying vec2 vUv_" + (i + 1) + ";\n"; + /// uv and uv2 are defined by THREE + if (i > 1) + adefs += "attribute vec2 uv" + (i + 1) + ";\n"; + reads += "vUv_" + (i + 1) + " = uv" + (i > 0 ? i + 1 : "") + ";\n"; + } + return (adefs + + vdefs + + "void main()\n" + + "{\n" + + reads + + "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n" + + "gl_Position = projectionMatrix * mvPosition;\n" + + "}"); + } + /** + * Generate a texture of a specified color, used to be part of THREEjs + * + * @memberof MaterialUtils + * @param {Number} width + * @param {Number} height + * @param {THREE.Color} color + * @returns {THREE.DataTexture} + */ + function generateDataTexture(width, height, color) { + // create a buffer with color data + const size = width * height; + const data = new Uint8Array(4 * size); + const r = Math.floor(color.r * 255); + const g = Math.floor(color.g * 255); + const b = Math.floor(color.b * 255); + const a = 255; + for (let i = 0; i < size; i++) { + const stride = i * 4; + data[stride] = r; + data[stride + 1] = g; + data[stride + 2] = b; + data[stride + 3] = a; + } + // used the buffer to create a DataTexture + return new THREE.DataTexture(data, width, height, THREE.RGBAFormat); + } + /** + * Builds a custom pixel shader for a given number of uv cannels. + * WIP not implemented yet! + * + * @memberof MaterialUtils + * @param {Array} textures THREE textures + * @param {Number} numUv Number of UV channels used by this shader + * @param {Number} alphaTest Texture see-trough alpha treshold + * @param {any} lightMap TODO + * @returns {string} + */ + function buildPS(textures, numUv, alphaTest, lightMap) { + const t1uv = "vUv_" + (textures[0].uvIdx + 1); + let discard = ""; + if (alphaTest) { + discard = " if (c1.a < 0.5) \n" + " discard;\n"; + } + /// Color from 1st text or lighted by 2nd? + let writeColor = "gl_FragColor = c1;\n"; + if (lightMap) { + const texIdx = 0; + // var t2uv = "vUv_4";//+(3-textures[texIdx].uvIdx+1); + const t2uv = "vUv_1"; // + (textures[texIdx].uvIdx+1); + // console.log("t2uv",t2uv); + writeColor = " vec4 c2 = texture2D( texture" + (texIdx + 1) + ", " + t2uv + " );\n" + " gl_FragColor = c2;\n"; + // " gl_FragColor = vec4(c2.rgb * c1.r/.5, c2.a);\n"; + } + let uniforms = ""; + textures.forEach(function (t, idx) { + uniforms += "uniform sampler2D texture" + (idx + 1) + ";\n"; + }); + /* uniforms += "uniform sampler2D texture1;\n"; + if(lightMap) + uniforms += "uniform sampler2D texture2;\n"; */ + let varyings = ""; + for (let i = 0; i < numUv; i++) { + varyings += "varying vec2 vUv_" + (i + 1) + ";\n"; + } + return (uniforms + + varyings + + "void main( void ) {\n" + + " vec4 c1 = texture2D( texture1, " + + t1uv + + " );\n" + + discard + + writeColor + + "}"); + } + /** + * WIP, concept for generatin materials to render multi UV chanelled meshes. + * + * @memberof MaterialUtils + * @param {Array} textures THREE texture + * @param {Number} numUV Number of UV channels used by this shader + * @param {Number} alphaTest Texture see-trough alpha treshold + * @return {THREE.ShaderMaterial} Generated shader + */ + function getUVMat(textures, numUV, alphaTest) { + let lightMap = false; + const uniforms = {}; + textures.forEach(function (t, idx) { + uniforms["texture" + idx] = { type: "t", value: t }; + }); + if (textures.length > 1) { + lightMap = true; + } + const attributes = {}; + for (let i = 2; i < numUV; i++) { + attributes["uv" + (i + 1)] = { type: "v2", value: [] }; + } + const vs = buildVS(numUV); + return new THREE.ShaderMaterial({ + uniforms: uniforms, + vertexShader: vs, + fragmentShader: buildPS(textures, numUV, alphaTest, lightMap), + // @ts-ignore + attributes: attributes, + side: THREE.FrontSide, + }); + } + /** + * Builds a THREE texture from a ModelMaterialData by reading settings and + * loading any required data from the localReader. Uses sharedTextures for + * texture caching. + * + * This method is full of guesses and estimations, and could be improved on + * a lot, allowing rendering of multi UV channeled materials, or special + * materials like custom color chanelled gear. + * + * @memberof MaterialUtils + * @param {ModelMaterialData} material + * @param {FileParser} materialFile A FileParser instance, must be of type AMAT + * @param {LocalReader} localReader The LocalReader to load the file contents from. + * @param {Object} sharedTextures Value Object for keeping the texture cache + * @return {THREE.Material} A THREE Material with the generated contents and settings. + */ + function getMaterial(material, materialFile, localReader, sharedTextures) { + if (!materialFile) + return; + const dxChunk = materialFile.getChunk("dx9s"); + let grChunk = materialFile.getChunk("grmt"); + if (!dxChunk) { + return getSimpleMaterial(material, materialFile, localReader, sharedTextures); + } + /// Append all textures to the custom material + const finalTextures = []; + // Some materials don't use textures.. + if (material && material.textures.length && dxChunk.data.techniques.length > 0) { + /// TODO: check for flags! + /// + /// techinques[] -> passes[] -> effects[] -> samplerIndex[] + /// + // console.log("num effects",dxChunk.data.techniques[0].passes[0].effects.length); + // if(grChunk.data.flags!=76) + // return; + /// 3 teqs : high medium low GRAPHICS LEVEL SETTINGS + /// 1 passes DON'T CARE + /// 15 effects Each effect has a pixel shader HOW?? + /// 1 or 2 sampler indices USE ALL! (Multi material) + const effects = dxChunk.data.techniques[0].passes[0].effects; + // var effect = effects[10]; + const effect = effects[0]; + //let shader = dxChunk.data.shaders[effect.pixelShader]; + /* effects.forEach(function (eff) { + if(eff.samplerIndex.length > effect.samplerIndex.length) + effect = eff; + }); */ + // var samplerIdx = effect.samplerIndex[0]; + const samplerTextures = []; + let textureToken; // UINT64 + let samplerTex; + for (let i = 0; i < effect.samplerIndex.length; i++) { + const samplerIdx = effect.samplerIndex[i]; + const sampler = dxChunk.data.samplers[samplerIdx]; + /// SHOULD NEVER HAPPEN, hide mesh! + if (!sampler) + continue; // return; + textureToken = sampler && Number(grChunk.data.texTokens[sampler.textureIndex]); + if (!textureToken) + textureToken = 0; + /* else + textureToken =textureToken.val; */ + /// Find the texture reffered by this sampler + samplerTex = null; + material.textures.forEach(function (tex /*, index*/) { + /// Seems like only 1st part of token is used... + if (!samplerTex && Number(tex.token) === textureToken) { + // console.log("TEX match",tex.token, textureToken) + samplerTex = tex; + } + }); + /// Add this sampler's texture to the collection of all textures + if (samplerTex) { + samplerTextures.push(samplerTex); + } + else { + /// FALLBACK, just guess what texture we should use + if (sampler) { + samplerTextures.push(material.textures[sampler.textureIndex]); + } + else if (material.textures.length > 0) { + samplerTextures.push(material.textures[0]); + } + else { + return; + } + } + } /// END for each sampler index in effect + /// We now have all textures + // console.log("textures from sampler", samplerTextures); + /// Fallback to using whatever texture there is. + if (samplerTextures.length <= 0) { + return; + // mainTex = material.textures[0]; + } + // console.log("num samplers ",samplerTextures.length); + samplerTextures.forEach(function (texture, idx) { + if (!texture) + return; + /// Set texture "URL" + const texURL = texture && texture.filename; + /// Load texture from RAM or local reader: + finalTextures[idx] = getTexture(texURL, localReader, sharedTextures); + if (finalTextures[idx]) { + finalTextures[idx].uvIdx = texture.uvPSInputIndex; + } + }); + } /// End if material and texture + let finalMaterial; + /// Create custom shader material if there are textures + if (finalTextures) { + // TODO: make this work! + // eslint-disable-next-line no-constant-condition, no-constant-binary-expression + { + let ft; + let nt; + material.textures.forEach(function (t) { + // Flag for diffuse map + if (!ft && Number(t.token) === 1733499172) + ft = t; + // Flag for normal map + if (!nt && Number(t.token) === 404146670) + nt = t; + }); + if (!ft || ft.filename <= 0) + return; + finalMaterial = new THREE.MeshPhongMaterial({ + side: THREE.FrontSide, + map: getTexture(ft.filename, localReader, sharedTextures), + }); + if (nt) { + const normalMap = getTexture(nt.filename, localReader, sharedTextures); + normalMap.flipY = true; + finalMaterial.normalMap = normalMap; + } + finalMaterial.textureFilename = ft.filename; + if (grChunk.data.flags !== 16460) { + // console.log("Setting alpha flag for ",grChunk.data.flags) + finalMaterial.alphaTest = 0.05; + } + } + } + /// Fallback material is monocolored red + else { + finalMaterial = new THREE.MeshBasicMaterial({ + side: THREE.FrontSide, + color: 0xff0000, + flatShading: true, + }); + } + finalMaterial.needsUpdate = true; + /// Set material props + /// disable for now in order for custom shaders not to fuck up + if (material) { + const alphaMask0 = 0x0001; // + 0x0100 + 0x0200; + const alphaMask1 = 0x0010; + const alphaMask2 = 0x0100 + 0x0200; + //let alphaMask2b = 0x0200; + grChunk = materialFile.getChunk("grmt"); + // Enable alpha test for transparent flags + if (material.materialFlags & alphaMask0 || + material.materialFlags & alphaMask1 || + material.materialFlags & alphaMask2 // && solidColor != null + ) ; + /// GRCHUNK -> DATA -> FLAGS + /// HAS LIGHT - TEX - ? - EMISSIVE16460 + /// + /// 56533 LOD FOR TOMBSTONE? + // 16460 0100 0000 0100 1100 "standard" stuff rendering OK in SAB (no alpha test) + // + // 16452(SAB) 0100 0000 0100 0100 yellow numbers in sab signs + // 16448(SAB) 0100 0000 0100 0000 faces on rocks, cloudmen, skybox portal images, holes in walls, floor plates... + // no lighting?? + // + // 8268 0010 0000 0100 1100 + // 3392 0000 1101 0100 0000 Moto machine light bulbs + // 2380 0000 1001 0100 1100 + // 2368 0000 1001 0100 0000 Fountain water with rings, portal border and circular "light" + // 332 0000 0001 0100 1100 + // 324 0000 0001 0100 0100 Moto face sprites + // + // 320(SAB) 0000 0001 0100 0000 portal textures (normal maps ish) + // + // 76 0000 0000 0100 1100 LOTS OF STUFF + // Tree leaves, ground, hills, some roofs, flags, street lights + // sheild textures, some fences, water tops, waterfall + // + // IN KHYLO "everything with alpha" + // + // + // 68 0000 0000 0100 0100 Some flowers (lo res?) fountain edges foam + // + // 64(SAB) 0000 0000 0100 0000 clouds, sun iamge + const lightMask = 8; + const knownFileFlags = [24652, 16460, 16452, 16448, 8268, 3392, 2380, 2368, 332, 324, 320, 76, 68, 64]; + if (knownFileFlags.indexOf(grChunk.data.flags) < 0) { + T3D.Logger.log(T3D.Logger.TYPE_WARNING, "unknown GR flag", grChunk.data.flags); + } + if (!(grChunk.data.flags & lightMask)) { + // debugger; + // console.log("no light"); + finalMaterial = new THREE.MeshBasicMaterial({ + side: THREE.FrontSide, + map: finalMaterial.map, + }); + } + if (grChunk.data.flags !== 16460) { + finalMaterial.alphaTest = 0.05; + } + } /// End if material + return finalMaterial; + } + function getSimpleMaterial(material, materialFile, localReader, sharedTextures) { + if (!materialFile) + return; + const grChunk = materialFile.getChunk("grmt"); + let ft; + let nt; + material.textures.forEach(function (t) { + console.log(t); + // Flag for diffuse map + if (!ft && Number(t.token) === 1733499172) + ft = t; + if (!ft && t.token === 27219515885689124n) + ft = t; + // Flag for normal map + if (!nt && Number(t.token) === 404146670) + nt = t; + if (!nt && t.token === 850610087184878n) + nt = t; + }); + console.log(ft); + if (!ft || ft.filename <= 0) { + return; + } + const finalMaterial = new THREE.MeshPhongMaterial({ + side: THREE.FrontSide, + map: getTexture(ft.filename, localReader, sharedTextures), + }); + if (nt) { + const normalMap = getTexture(nt.filename, localReader, sharedTextures); + normalMap.flipY = true; + finalMaterial.normalMap = normalMap; + } + finalMaterial.textureFilename = ft.filename; + if (grChunk.data.flags !== 16460) { + finalMaterial.alphaTest = 0.05; + } + finalMaterial.needsUpdate = true; + return finalMaterial; + } + /** + * Load image data into a THREE.Texture from a texture file in the .dat file, using a LocalReader. + * Any loaded tetures are added to sharedTextures, allowing for texture caching and fewer reads. + * + * @memberof MaterialUtils + * @param {Number} texURL The fileId or baseId of the file to load image data from. + * @param {LocalReader} localReader The LocalReader to load the file contents from. + * @param {Object} sharedTextures Value Object for keeping the texture cache + * @return {THREE.Texture} A texture that will be populated by the file data when it is loaded. + */ + function getTexture(texURL, localReader, sharedTextures) { + let finalTexture; + /// Read texture from shared array of loaded textures + /// or read it from URL and add to shared ones! + if (texURL && sharedTextures[texURL]) { + /// Just read from already loaded textures. + finalTexture = sharedTextures[texURL]; + } + else if (texURL) { + /// Load and add to shared array. + finalTexture = loadLocalTexture(localReader, texURL); + /// Set standard texture functionality. + finalTexture.wrapT = THREE.RepeatWrapping; + finalTexture.wrapS = THREE.RepeatWrapping; + finalTexture.flipY = false; + sharedTextures[texURL] = finalTexture; + } + return finalTexture; + } + /** + * Load image data into a THREE.Texture from a texture file in the .dat file, using a LocalReader. + * If you're loading multiple textures, make sure to use + * {{#crossLink "MaterialUtils/getTexture"}}{{/crossLink}} that allows you to cache textures. + * + * @memberof MaterialUtils + * @param {LocalReader} localReader - The LocalReader to load the file contents from. + * @param {Number} fileId - The fileId or baseId of the file to load image data from. + * @param {Number} mapping - What THREE mapping the returned texture will use, not implemented. + + * @return {THREE.Texture} A texture that will be populated by the file data when it is loaded. + */ + function loadLocalTexture(localReader, fileId, mapping, defaultColor, onerror) { + if (defaultColor === undefined) { + defaultColor = Math.floor(0xffffff * Math.random()); + } + /// Temporary texture that will be returned by the function. + /// Color is randomized in order to differentiate different textures during loading. + const texture = generateDataTexture(1, // Width + 1, // Height + new THREE.Color(defaultColor) // Color + ); + // Threejs r71 is using these settings by default, r72+ changed it + texture.minFilter = THREE.LinearMipMapLinearFilter; + texture.magFilter = THREE.LinearFilter; + texture.generateMipmaps = true; + texture.flipY = true; + /// Only allow non-zero fileId, otherwise jsut return static texture + if (parseInt(String(fileId)) <= 0) { + if (onerror) + onerror(); + return texture; + } + /// Load file using LocalReader. + localReader.loadFile(fileId, function (inflatedData, dxtType, imageWidth, imageHeigth) { + /// Require infalted data to be returned. + if (!inflatedData) { + if (onerror) + onerror(); + return; + } + /// Create image using returned data. + const image = { + data: new Uint8Array(inflatedData), + width: imageWidth, + height: imageHeigth, + }; + /// Use RGBA for all textures for now... + /// TODO: don't use alpha for some formats! + texture.format = + //eslint-disable-next-line no-constant-condition + dxtType === 3 || dxtType === 5 || true ? THREE.RGBAFormat : THREE.RGBFormat; + /// Update texture with the loaded image. + //@ts-ignore + texture.image = image; + texture.needsUpdate = true; + }, true); + /// Return texture with temporary content. + return texture; + } + + var MaterialUtils = /*#__PURE__*/Object.freeze({ + __proto__: null, + buildPS: buildPS, + buildVS: buildVS, + generateDataTexture: generateDataTexture, + getMaterial: getMaterial, + getSimpleMaterial: getSimpleMaterial, + getTexture: getTexture, + getUVMat: getUVMat, + loadLocalTexture: loadLocalTexture + }); + + /** + * + * A renderer that generates some of the environment objects of a map. + * + * @class EnvironmentRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "mapFile", a FileParser. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class EnvironmentRenderer extends DataRenderer { + static rendererName = "EnvironmentRenderer"; + mapFile; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "EnvironmentRenderer"); + this.mapFile = this.settings.mapFile; + } + getMat(tex) { + return new THREE.MeshBasicMaterial({ + map: tex, + side: THREE.BackSide, + fog: false, + depthWrite: false, + }); + } + loadTextureWithFallback(targetMatIndices, materialArray, filename, fallbackFilename, hazeColorAsInt) { + const self = this; + function writeMat(mat) { + targetMatIndices.forEach(function (i) { + materialArray[i] = mat; + }); + } + function loadFallback() { + const mat = self.getMat(new THREE.TextureLoader().load(fallbackFilename)); + writeMat(mat); + } + function errorCallback() { + setTimeout(loadFallback, 1); + } + const mat = self.getMat(loadLocalTexture(this.localReader, filename, undefined, hazeColorAsInt, errorCallback)); + writeMat(mat); + } + getHazeColor(environmentChunkData) { + const hazes = environmentChunkData && environmentChunkData.dataGlobal.haze; + if (!hazes || hazes.length <= 0) { + return [190, 160, 60]; + } + else { + return hazes[0].farColor; + } + } + parseLights(environmentChunkData) { + const self = this; + /// Set up output array + self.getOutput().lights = []; + const lights = environmentChunkData + ? environmentChunkData.dataGlobal.lighting + : [ + { + lights: [], + backlightIntensity: 1.0, + backlightColor: [255, 255, 255], + }, + ]; + let ambientLight; + // var light = lights[0]; + // + let hasLight = false; + lights.forEach(function (light /*, idx*/) { + if (hasLight) + return; + /// Directional lights + // eslint-disable-next-line @typescript-eslint/no-unused-vars + let sumDirLightIntensity = 0; + light.lights.forEach(function (dirLightData /*, idx*/) { + hasLight = true; + const color = new THREE.Color(dirLightData.color[2] / 255.0, dirLightData.color[1] / 255.0, dirLightData.color[0] / 255.0); + const directionalLight = new THREE.DirectionalLight(color.getHex(), dirLightData.intensity); + directionalLight.position + .set(-dirLightData.direction[0], dirLightData.direction[2], dirLightData.direction[1]) + .normalize(); + sumDirLightIntensity += dirLightData.intensity; + self.getOutput().lights.push(directionalLight); + }); // END for each directional light in light + /// Add some random directional lighting if there was no, in order to se SOME depth on models + if (!light.lights || light.lights.length === 0) { + const directions = [ + [0, 1, 0, 0.3], + [1, 2, 1, 0.3], + [-1, -2, -1, 0.3], + ]; + directions.forEach(function (lightDir) { + const color = new THREE.Color(1, 1, 1); + const intensity = lightDir[3]; + const directionalLight = new THREE.DirectionalLight(color.getHex(), intensity); + directionalLight.position.set(lightDir[0], lightDir[1], lightDir[2]).normalize(); + sumDirLightIntensity += intensity; + self.getOutput().lights.push(directionalLight); + }); + } + /// Ambient light + // light.backlightIntensity /= sumDirLightIntensity +light.backlightIntensity; + // light.backlightIntensity = light.backlightIntensity; + const color = new THREE.Color((light.backlightIntensity * (255.0 - light.backlightColor[2])) / 255.0, (light.backlightIntensity * (255.0 - light.backlightColor[1])) / 255.0, (light.backlightIntensity * (255.0 - light.backlightColor[0])) / 255.0); + ambientLight = new THREE.AmbientLight(color); + }); // END for each light in lighting + let ambientTotal = 0; + if (ambientLight) { + ambientTotal = ambientLight.color.r + ambientLight.color.g + ambientLight.color.b; + this.getOutput().lights.push(ambientLight); + } + /// Parsing done, set hasLight flag and return + this.getOutput().hasLight = hasLight || ambientTotal > 0; + } + parseSkybox(environmentChunkData, parameterChunkData, hazeColorAsInt) { + /// set up output array + this.getOutput().skyCubeTexture = null; + this.getOutput().skyBox = null; + /// Grab sky texture. + /// index 0 and 1 day + /// index 2 and 3 evening + let skyModeTex = environmentChunkData && environmentChunkData.dataGlobal.skyModeTex[0]; + /// Fallback skyboxfrom dat. + if (!skyModeTex) { + skyModeTex = { + texPathNE: 187554, + texPathSW: 187556, + texPathT: 187558, + }; + } + /// Calculate bounds + const bounds = parameterChunkData.rect; + Math.abs(bounds[0] - bounds[2]); + Math.abs(bounds[1] - bounds[3]); + const materialArray = []; + /// Load skybox textures, fallback to hosted png files. + this.loadTextureWithFallback([1, 4], materialArray, skyModeTex.texPathNE + 1, "img/193068.png", hazeColorAsInt); + this.loadTextureWithFallback([0, 5], materialArray, skyModeTex.texPathSW + 1, "img/193070.png", hazeColorAsInt); + this.loadTextureWithFallback([2], materialArray, skyModeTex.texPathT + 1, "img/193072.png", hazeColorAsInt); + materialArray[3] = new THREE.MeshBasicMaterial({ visible: false }); + /// Create skybox geometry + const boxSize = 1024; // boundSide * 2; + const skyGeometry = new THREE.BoxGeometry(boxSize, boxSize / 2, boxSize); // Width Height Depth + /// Ugly way of fixing UV maps for the skybox (I think) + skyGeometry.faceVertexUvs[0].forEach((vecs, idx) => { + const face = Math.floor(idx / 2); + // PX NX + // PY NY + // PZ NZ + /// PX - WEST NX - EAST + if (face === 0 || face === 1) { + vecs.forEach((vec2) => { + vec2.x = 1 - vec2.x; + vec2.y /= 2.0; + vec2.y += 0.5; + }); + } + /// NZ - SOUTH PZ - NORTH + else if (face === 5 || face === 4) { + vecs.forEach((vec2) => { + vec2.y /= -2.0; + vec2.y += 0.5; + }); + } + else { + vecs.forEach((vec2) => { + vec2.x = 1 - vec2.x; + }); + } + }); + skyGeometry.uvsNeedUpdate = true; + /// Generate final skybox + const skyBox = new THREE.Mesh(skyGeometry, materialArray); + /// Put horizon in camera center + // skyBox.translateY(-(boxSize / 8)); + // skyBox.translateY( -environmentChunk.data.dataGlobal.sky.verticalOffset ); + /// Write to output + this.getOutput().skyBox = skyBox; + } + /** + * Output fileds generated: + * + * - *hazeColor* Array of RGBA values describing the global haze color of the map. + * - *lights* An array of THREE.DirectionalLight and THREE.AmbientLight objects. + * - *hasLight* Boolean is false if no directional lights were added to "lights". + * - *skyBox* A textured THREE.Mesh skybox. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + if (!this.mapFile) { + throw new Error("No map file available for EnvironmentRenderer"); + } + const environmentChunkData = this.mapFile.getChunk("env").data; + const parameterChunkData = this.mapFile.getChunk("parm").data; + /// Set renderer clear color from environment haze + const hazeColor = this.getHazeColor(environmentChunkData); + const hazeColorAsInt = hazeColor[2] * 256 * 256 + hazeColor[1] * 256 + hazeColor[0]; + this.getOutput().hazeColor = hazeColor; + /// Add directional lights to output. Also write hasLight flag + this.parseLights(environmentChunkData); + /// Generate skybox + this.parseSkybox(environmentChunkData, parameterChunkData, hazeColorAsInt); + /// All parsing is synchronous, just fire callback + callback(); + } + } + + /** + * + * A renderer that generates meshes describing the collisions of a map. + * + * @class HavokRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "mapFile", a FileParser. If "visible" is specified and true, the generated meshes will be textured + * with a MeshNormalMaterial, otherwise they will not be visible. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class HavokRenderer extends DataRenderer { + static rendererName = "HavokRenderer"; + mapFile; + lastP; + seed; + meshes; + geometries; + animations; + havokChunkData; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "HavokRenderer"); + this.mapFile = this.settings.mapFile; + this.lastP = -1; + this.seed = 1; + this.meshes = []; + } + /** + * TODO + * + * @param {Function} callback [description] + * @async + */ + renderModels(models, title, callback) { + let mat; + if (this.settings && this.settings.visible) { + mat = new THREE.MeshNormalMaterial({ side: THREE.DoubleSide }); + } + else if (this.settings && this.settings.export) { + mat = new THREE.MeshBasicMaterial({ visible: true }); + } + else { + mat = new THREE.MeshBasicMaterial({ visible: false }); + } + this.parseAllModels(models, mat, title, 200, 0, callback); + } + /** + * TODO + * + * @param {*} animation [description] + * @param {*} collisions [description] + * @return {*} [description] + */ + getCollisionsForAnimation(animation, collisions) { + const ret = []; + for (let i = 0; i < animation.collisionIndices.length; i++) { + const index = animation.collisionIndices[i]; + const collision = collisions[index]; + collision.index = index; + ret.push(collision); + } + return ret; + } + /** + * TODO + * + * @param {*} models [description] + * @param {*} mat [description] + * @param {*} title [description] + * @param {*} chunkSize [description] + * @param {*} offset [description] + * @return {*} callback [description] + * @async + */ + parseAllModels(models, mat, title, chunkSize, offset, callback) { + let i = offset; + for (; i < offset + chunkSize && i < models.length; i++) { + const p = Math.round((i * 100) / models.length); + if (p !== this.lastP) { + this.logger.log(T3D.Logger.TYPE_PROGRESS, "Loading Collision Models (" + title + ")", p); + this.lastP = p; + } + /// Get animation object + const animation = this.animationFromGeomIndex(models[i].geometryIndex, this.geometries, this.animations); + const collisions = this.getCollisionsForAnimation(animation, this.havokChunkData.collisions); + for (let j = 0; j < collisions.length; j++) { + const collision = collisions[j]; + this.renderMesh(collision, models[i], mat); + } + } + if (i < models.length) { + setTimeout(this.parseAllModels.bind(this, models, mat, title, chunkSize, offset + chunkSize, callback), 10 /* time in ms to next call */); + } + else { + callback(); + } + } + /** + * TODO + * + * @param {*} propGeomIndex [description] + * @param {*} geometries [description] + * @param {*} animations [description] + * @return {*} [description] + */ + animationFromGeomIndex(propGeomIndex, geometries, animations) { + // geometries is just list of all geometries.animations[end] for now + const l = geometries[propGeomIndex].animations.length; + return animations[geometries[propGeomIndex].animations[l - 1]]; + // return animations[ geometries[propGeomIndex].animations[0] ]; + } + /** + * TODO + * + * @param {*} collision [description] + * @param {*} model [description] + * @param {*} mat [description] + * @return {*} [description] + */ + renderMesh(collision, model, mat) { + const pos = model.translate; + const rot = model.rotate; + const scale = 32 * model.scale; + /// Generate mesh + const mesh = this.parseHavokMesh(collision, mat); + /// Position mesh + /// "x","float32","z","float32","y","float32" + mesh.position.set(pos[0], -pos[2], -pos[1]); + /// Scale mesh + if (scale) + mesh.scale.set(scale, scale, scale); + /// Rotate mesh + if (rot) { + mesh.rotation.order = "ZXY"; + // ["x","float32","z","float32","y","float32"], + mesh.rotation.set(rot[0], -rot[2], -rot[1]); + } + /// Add mesh to scene and collisions + this.getOutput().meshes.push(mesh); + } + /** + * TODO + * + * @return {*} [description] + */ + seedRandom() { + const x = Math.sin(this.seed++) * 10000; + return x - Math.floor(x); + } + /** + * TODO + * + * @param {*} collision [description] + * @param {*} mat [description] + * @return {*} [description] + */ + parseHavokMesh(collision, mat) { + const index = collision.index; + if (!this.meshes[index]) { + const geom = new THREE.Geometry(); + /// Pass vertices + for (let i = 0; i < collision.vertices.length; i++) { + const v = collision.vertices[i]; + // "x","float32","z","float32","y","float32"] + geom.vertices.push(new THREE.Vector3(v[0], v[2], -v[1])); + } + /// Pass faces + for (let i = 0; i < collision.indices.length; i += 3) { + const f1 = collision.indices[i]; + const f2 = collision.indices[i + 1]; + const f3 = collision.indices[i + 2]; + if (f1 <= collision.vertices.length && f2 <= collision.vertices.length && f3 <= collision.vertices.length) { + geom.faces.push(new THREE.Face3(f1, f2, f3)); + } + else { + this.logger.log(T3D.Logger.TYPE_ERROR, "Errorus index in havok model geometry."); + } + } + /// Prepare geometry and pass new mesh + geom.computeFaceNormals(); + // geom.computeVertexNormals(); + this.meshes[index] = new THREE.Mesh(geom, mat); + return this.meshes[index]; + } + else { + return this.meshes[index].clone(); + } + } + /** + * Output fileds generated: + * + * - *boundingBox* Array of values describing the bounding box of all collision. + * - *meshes* An array of THREE.Mesh objects visualizing all collision in the map. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + const self = this; + // TODO:The design of this method pretty much requires one instance + // of the class per parallel async render. Should probably fix this + // at some point... + /// Get required chunks + this.havokChunkData = this.mapFile.getChunk("havk").data; + /// Set static bounds to the bounds of the havk models + this.getOutput().boundingBox = this.havokChunkData.boundsMax; + /// Clear old meshes + this.meshes = []; + /// Set up output array + this.getOutput().meshes = []; + /// Grab model raw data from the chunk. + /// Add missing scale value to obs models. + const propModels = this.havokChunkData.propModels; + const zoneModels = this.havokChunkData.zoneModels; + const obsModels = this.havokChunkData.obsModels; + obsModels.forEach(function (mdl) { + mdl.scale = 1; + }); + /// Store geoms and animations from the file in hte instance so we don't + /// have to pass them arround too much. (fix this later) + this.geometries = this.havokChunkData.geometries; + this.animations = this.havokChunkData.animations; + /// Render "prop", "zone" and "obs" models in that order. + const renderZoneModelsCB = function () { + self.renderModels(obsModels, "obs", callback); + }; + const renderPropModelsCB = function () { + self.renderModels(zoneModels, "zone", renderZoneModelsCB); + }; + self.renderModels(propModels, "prop", renderPropModelsCB); + } + } + + const base32Max = Math.pow(2, 32); + /** + * Collection Math and sorting methods + * @namespace MathUtils + */ + /** + * Takes an integer and calculates what the 16 bit float + * representation of the binary data used to read the integer is. + * + * @memberof MathUtils + * @param {Number} h Integer value + * @return {Number} Float value + */ + function f16(h) { + const s = (h & 0x8000) >> 15; + const e = (h & 0x7c00) >> 10; + const f = h & 0x03ff; + if (e === 0) { + return (s ? -1 : 1) * Math.pow(2, -14) * (f / Math.pow(2, 10)); + } + else if (e === 0x1f) { + return f ? NaN : (s ? -1 : 1) * Infinity; + } + return (s ? -1 : 1) * Math.pow(2, e - 15) * (1 + f / Math.pow(2, 10)); + } + /** + * Calculates the number of binary ones present in the data used to + * generate the input integer. + * + * @memberof MathUtils + * @param {Number} bits Integer + * @return {Number} Number of binary ones in the data + */ + function popcount(bits) { + const SK5 = 0x55555555; + const SK3 = 0x33333333; + const SKF0 = 0x0f0f0f0f; + // let SKFF = 0xff00ff + bits -= (bits >> 1) & SK5; + bits = (bits & SK3) + ((bits >> 2) & SK3); + bits = (bits & SKF0) + ((bits >> 4) & SKF0); + bits += bits >> 8; + return (bits + (bits >> 15)) & 63; + } + /** + * Calculates the 64 bit integer value of two 32 bit integers. Only works up to + * the limit of the javascript Number maximum value. + * + * @memberof MathUtils + * @param {Number[]} arr Input integers, length should be 2. + * @return {Number} 64 bit representation of the two integers. + */ + function arr32To64(arr) { + /// Re-read as uint64 (still little endian) + /// Warn: this will not work for ~50+ bit longs cus all JS numbers are 64 bit floats... + return base32Max * arr[1] + arr[0]; + } + /** + * Sorts an array and returns unique values only. + * + * @memberof MathUtils + * @param {Array} arr_in Input array + * @param {Function} comparator A comparator function between the objects in arr_in + * @return {Array} Sorted and unique value. + */ + function sort_unique(arr_in, comparator) { + const arr = Array.prototype.sort.call(arr_in, comparator); + const u = {}; + const a = []; + for (let i = 0, l = arr.length; i < l; ++i) { + // eslint-disable-next-line no-prototype-builtins + if (u.hasOwnProperty(arr[i])) { + continue; + } + a.push(arr[i]); + //@ts-ignore + u[arr[i]] = 1; + } + return a; + } + + var MathUtils = /*#__PURE__*/Object.freeze({ + __proto__: null, + arr32To64: arr32To64, + f16: f16, + popcount: popcount, + sort_unique: sort_unique + }); + + // TODO: Remove this local cache!! + const matFiles = {}; + /** + * Object describing the meaning of the bits in fvf integers. + * @property fvfFormat + * @private + * @type {Object} + */ + const fvfFormat = { + Position: 0x00000001 /** < 12 bytes. Position as three 32-bit floats in the order x, y, z. */, + Weights: 0x00000002 /** < 4 bytes. Contains bone weights. */, + Group: 0x00000004 /** < 4 bytes. Related to bone weights. */, + Normal: 0x00000008 /** < 12 bytes. Normal as three 32-bit floats in the order x, y, z. */, + Color: 0x00000010 /** < 4 bytes. Vertex color. */, + Tangent: 0x00000020 /** < 12 bytes. Tangent as three 32-bit floats in the order x, y, z. */, + Bitangent: 0x00000040 /** < 12 bytes. Bitangent as three 32-bit floats in the order x, y, z. */, + TangentFrame: 0x00000080 /** < 12 bytes. */, + UV32Mask: 0x0000ff00 /** < 8 bytes for each set bit. Contains UV-coords as two 32-bit floats in the order u, v. */, + UV16Mask: 0x00ff0000 /** < 4 bytes for each set bit. Contains UV-coords as two 16-bit floats in the order u, v. */, + Unknown1: 0x01000000 /** < 48 bytes. Unknown data. */, + Unknown2: 0x02000000 /** < 4 bytes. Unknown data. */, + Unknown3: 0x04000000 /** < 4 bytes. Unknown data. */, + Unknown4: 0x08000000 /** < 16 bytes. Unknown data. */, + PositionCompressed: 0x10000000 /** < 6 bytes. Position as three 16-bit floats in the order x, y, z. */, + Unknown5: 0x20000000 /** < 12 bytes. Unknown data. **/, + }; + /** + * Collection of methods used for generating THREE meshes from Guild Wars 2 data formats. + * @namespace RenderUtils + */ + /** + * Creates a mesh representing a single plane. + * + * @memberof RenderUtils + * @param {Object} rect An object with x1,x2,y1 and y2 properties. + * @param {Number} yPos Vertical position of the rectangle. + * @param {THREE.Material} material Mesh material to apply. + * @param {Number} dy Mesh height. + * @return {THREE.Mesh} The generated mesh. + */ + function renderRect(rect, yPos, material, dy) { + const dx = rect.x1 - rect.x2; + const dz = rect.y1 - rect.y2; + if (!dy) + dy = 1; + const cx = (rect.x1 + rect.x2) / 2; + const cz = (rect.y1 + rect.y2) / 2; + const cy = yPos; + const geometry = new THREE.BoxGeometry(dx, dy, dz); + material = + material || + new THREE.MeshBasicMaterial({ + color: 0xff0000, + wireframe: true, + }); + const plane = new THREE.Mesh(geometry, material); + //@ts-ignore + plane.overdraw = true; + plane.position.x = cx; + plane.position.y = cy; + plane.position.z = cz; + return plane; + } + /** + * Returns a THREE representation of the data contained by a GW2 model file. + * The data is read using a LocalReader reference into the GW2 .dat. + * + * @memberof RenderUtils + * @param {LocalReader} localReader The LocalReader to load the file contents from. + * @param {Object} chunk Model GEOM chunk. + * @param {Object} modelDataChunk Model MODL chunk. + * @param {Object} sharedTextures Value Object for keeping the texture cache. + * @param {boolean} showUnmaterialed If false does not render any models with missing materials. + * + * @return {Array} Each geometry in the model file represented by a textured THREE.Mesh object + */ + function renderGeomChunk(localReader, chunk, modelDataChunk, sharedTextures, showUnmaterialed) { + const rawMeshes = chunk.data.meshes; + const meshes = []; + const mats = modelDataChunk.data.permutations[0].materials; + rawMeshes.forEach(function (rawMesh) { + const rawGeom = rawMesh.geometry; + const fvf = rawGeom.verts.mesh.fvf; // rawGeom.fvf; + const numVerts = rawGeom.verts.vertexCount; // rawGeom.vertexCount; + const rawVerts = rawGeom.verts.mesh.vertices; // rawGeom.vertices + const indices = rawGeom.indices.indices; + const geom = new THREE.BufferGeometry(); + const vertsDataView = new DataView(rawVerts.buffer); + // Dirty step length for now: + const stride = rawVerts.length / numVerts; + // Each vertex + // DO UV as well + const vertices = new Float32Array(numVerts * 3); + const uvs = []; + /// Calculate the distance to the first pair of UV data from the + /// start of the vertex entry + /// + const distToNormals = + //@ts-ignore + !!(fvf & fvfFormat.Position) * 12 + !!(fvf & fvfFormat.Weights) * 4 + !!(fvf & fvfFormat.Group) * 4; + //@ts-ignore + const distToTangent = distToNormals + !!(fvf & fvfFormat.Normal) * 12 + !!(fvf & fvfFormat.Color) * 4; + //@ts-ignore + const distToBittangent = distToTangent + !!(fvf & fvfFormat.Tangent) * 12; + //@ts-ignore + const distToTangentFrame = distToBittangent + !!(fvf & fvfFormat.Bitangent) * 12; + //@ts-ignore + const distToUV = distToTangentFrame + !!(fvf & fvfFormat.TangentFrame) * 12; + /// Check if the UV is 32 bit float or 16 bit float. + const uv32Flag = (fvf & fvfFormat.UV32Mask) >> 8; + const uv16Flag = (fvf & fvfFormat.UV16Mask) >> 16; + const isUV32 = !!uv32Flag; + const hasUV = !!uv16Flag || !!uv32Flag; + /// Popcount (count the number of binary 1's) in the UV flag + /// to get the number of UV pairs used in this vertex format. + const masked = isUV32 ? uv32Flag : uv16Flag; + let numUV = popcount(masked); + numUV = Math.min(numUV, 1.0); + /// Create typed UV arrays + if (hasUV) { + for (let i = 0; i < numUV; i++) { + uvs[i] = new Float32Array(numVerts * 2); + } + } + /// Read data from each vertex data entry + for (let i = 0; i < numVerts; i++) { + /// Go to vertex memory position + let cursor = i * stride; + /// Read position data + /// (we just hope all meshes has 32 bit position...) + const x = vertsDataView.getFloat32(cursor, true); + const z = vertsDataView.getFloat32(cursor + 4, true); + const y = vertsDataView.getFloat32(cursor + 8, true); + /// Write position data, transformed to Tyria3D coordinate system. + vertices[i * 3 + 0] = x; // - c.x; + vertices[i * 3 + 1] = -y; // + c.y; + vertices[i * 3 + 2] = -z; // + c.z; + /// Read data at UV position + if (hasUV) { + for (let uvIdx = 0; uvIdx < numUV; uvIdx++) { + cursor = i * stride + distToUV + uvIdx * (isUV32 ? 8 : 4); + /// Add one UV pair: + let u, v; + if (isUV32) { + u = vertsDataView.getFloat32(cursor, true); + v = vertsDataView.getFloat32(cursor + 4, true); + } + else { + u = f16(vertsDataView.getUint16(cursor, true)); + v = f16(vertsDataView.getUint16(cursor + 2, true)); + } + /// Push to correct UV array + uvs[uvIdx][i * 2 + 0] = u; + uvs[uvIdx][i * 2 + 1] = v; + } + } /// End if has UV + } /// End each vertex + /// Each face descripbed in indices + const faces = new Uint16Array(indices.length); + for (let i = 0; i < indices.length; i += 3) { + // This is ONE face + faces[i + 0] = indices[i + 2]; + faces[i + 1] = indices[i + 1]; + faces[i + 2] = indices[i + 0]; + } // End each index aka "face" + /// Add position, index and uv props to buffered geometry + geom.setAttribute("position", new THREE.BufferAttribute(vertices, 3)); + // geom.setAttribute( 'index', new THREE.BufferAttribute( faces, 1) ); + geom.setIndex(new THREE.BufferAttribute(faces, 1)); + { + /// Calculate normals + geom.computeVertexNormals(); + } + if (hasUV) { + for (let uvIdx = 0; uvIdx < numUV; uvIdx++) { + /// Names are "uv", "uv2", "uv3", ... , "uvN" + const uvName = "uv" + (uvIdx > 0 ? uvIdx + 1 : ""); + /// Set "custom" attribute uvN + geom.setAttribute(uvName, new THREE.BufferAttribute(uvs[uvIdx], 2)); + /// Flag for update + geom.attributes[uvName].needsUpdate = true; + } + /// Not needed anymore? + //@ts-ignore + geom.uvsNeedUpdate = true; + } + /// Tell geometry to update its UVs and buffers + //@ts-ignore + geom.buffersNeedUpdate = true; + /// DONE READING VERTEX DATA + /// Get material used for this mesh + const matIdx = rawMesh.materialIndex; + const mat = mats[matIdx]; + let materialFile = null; + if (mat && matFiles[mat.filename]) { + materialFile = matFiles[mat.filename]; + } + console.log(`material file:`, materialFile); + let finalMaterial = getMaterial(mat, materialFile, localReader, sharedTextures); + /// IF we could not find a material abort OR use a wireframe placeholder. + if (!finalMaterial) { + if (showUnmaterialed) { + finalMaterial = new THREE.MeshLambertMaterial({ + color: 0x5bb1e8, + wireframe: false, + side: THREE.DoubleSide, + }); + } + else { + return; + } + } + /// Create the final mesh from the BufferedGeometry and MeshBasicMaterial + const finalMesh = new THREE.Mesh(geom, finalMaterial); + /// Set material info on the returned mesh + if (mat) { + finalMesh.materialFlags = mat.materialFlags; + finalMesh.materialFilename = mat.filename; + } + finalMesh.materialName = rawMesh.materialName; + /// Use materialFilename, materialName, and material.textureFilename in order to build export + /// Set lod info on the returned mesh + finalMesh.numLods = rawMesh.geometry.lods.length; + finalMesh.lodOverride = modelDataChunk.data.lodOverride; + /// Set flag and UV info on the returned mehs + finalMesh.flags = rawMesh.flags; + finalMesh.numUV = numUV; + /// Add mesh to returned Array + meshes.push(finalMesh); + }); /// End rawMeshes for Each + return meshes; + } + /** + * Merge multiple meshes together and return an instancedMesh for it + * @param {Array} meshes Three Meshes to be merged into a single mesh + * @param {Number} size Size of the instanced mesh + * @param {Number} filterFlags When undefined, it will render all LODs. When using 0, only show most detailed LOD + * @returns {Mesh} a Three instanced mesh + */ + function getInstancedMesh(meshes, size, filterFlags) { + const meshMaterials = []; + const mergedGeometry = new THREE.Geometry(); + meshes.forEach((mesh, index) => { + // If filterFlags is set, we ignore any mesh without the correct flag + if (filterFlags !== undefined && mesh.flags !== filterFlags) { + return; + } + meshMaterials.push(mesh.material); + // It's only possible to merge geometries of the same type + const meshGeometry = new THREE.Geometry().fromBufferGeometry(mesh.geometry); + mergedGeometry.merge(meshGeometry, mesh.matrix, index); + }); + const finalMesh = new THREE.InstancedMesh(mergedGeometry, meshMaterials, size); + finalMesh.updateMatrix(); + finalMesh.matrixAutoUpdate = false; + return finalMesh; + } + /** + * Loads mesh array from Model file and sends as argument to callback. + * + * @memberof RenderUtils + * @async + * @param {Number} filename Name of the model file to load data from. + * @param {Array} solidColor RGBA array of 4 integers + * @param {LocalReader} localReader The LocalReader to load the file contents from. + * @param {Object} sharedTextures Value Object for keeping the texture cache. + * @param {boolean} showUnmaterialed If false does not render any models with missing materials. + + * @param {Function} callback Fired once all meshes have been loaded. + * two arguments are passed to the callback function. + * + * The first argument is an Array with each textured THREE.Mesh objects. + * + * The second argument is the bounding spehere of this model file. + * + */ + function loadMeshFromModelFile(filename, solidColor, localReader, sharedTextures, showUnmaterialed, callback) { + // Short handles prop attributes + const finalMeshes = []; + /// Load file + localReader.loadFile(filename, function (inflatedData) { + try { + if (!inflatedData) { + throw "Could not find MFT entry for " + filename; + } + const modelFile = new t3dParser.FileParser(inflatedData); + // MODL for materials -> textures + const modelDataChunk = modelFile.getChunk("modl"); + // GEOM for geometry + const geometryDataChunk = modelFile.getChunk("geom"); + /// Hacky fix for not being able to adjust for position + const boundingSphere = modelDataChunk.data.boundingSphere; + const bsc = boundingSphere.center; + if (bsc) { + boundingSphere.radius += Math.sqrt(bsc[0] * bsc[0] + Math.sqrt(bsc[1] * bsc[1] + bsc[2] * bsc[2])); + } + /// Load all material files + const allMats = modelDataChunk.data.permutations[0].materials; + function loadMaterialIndex(mIdx, matCallback) { + if (mIdx >= allMats.length) { + matCallback(); + return; + } + const mat = allMats[mIdx]; + /// Skip if file is loaded + if (matFiles[mat.filename]) { + loadMaterialIndex(mIdx + 1, matCallback); + return; + } + localReader.loadFile(mat.filename, function (inflatedData) { + if (inflatedData) { + const materialFile = new t3dParser.FileParser(inflatedData); + matFiles[mat.filename] = materialFile; + } + loadMaterialIndex(mIdx + 1, matCallback); + }); + } + loadMaterialIndex(0, function () { + /// Create meshes + const meshes = renderGeomChunk(localReader, geometryDataChunk, modelDataChunk, sharedTextures, showUnmaterialed); + // Build mesh group + meshes.forEach(function (mesh) { + /// Material flags + const knownflags = [ + /* + 1-5 + Has Tex? IDK Light? Alpha? + + 5-8 + 0 0 IDK Water? + + 9-12 + Has Tex? 0 Alpha? Alpha? + + 13 + IDK KEV + */ + 0, // 0 0000 0000 0000 Ground / Wall splashes + 8, // 0 0000 0000 1000 Broken Khylo roof DDS + 9, // 0 0000 0000 1001 Tree leaves + 520, // 0 0010 0000 1000 Some LOD modules, fires, smoke, inside of tents (some DSS textures) + 2056, // 0 1000 0000 1000 Solid objects, also broken animations + /// Solids here are unhappy, or are they? could be animations etc + 2057, // 0 1000 0000 1001 Windmill sails, bushes, trees, but also a statue and a few pieces of wall + 2060, // 0 1000 0000 1100 A few solid objects, like wooden barricades, one(!) painting + 2061, // 0 1000 0000 1101 A few bushes, two paintings + 2312, // 0 1001 0000 1000 Opaque Clock tower main walls AND IVY + 2316, // 0 1001 0000 1100 Bushes, inner flower walkway a ramp and a box + // Number 10 + 2568, // 0 1010 0000 1000 Lots of solids; walls, tents also some tent details WITH alpa + // Number 11 + 2569, // 0 1010 0000 1001 Solids like walls and roofs and appernt non solids like ropes + 2572, // 0 1010 0000 1100 Solid wooden beems, lamp posts + 2573, // 0 1010 0000 1101 Lamp holders, bushes, fences, apparent non solids + 2584, // 0 1010 0001 1000 Fountain Well water + 2824, // 0 1011 0000 1000 Windows, sign arrows, cloth roofs (non solids) BUT straw roofs + 2828, // 0 1011 0000 1100 A few fence post (non solids) + 2840, // 0 1011 0001 1000 Fountain running water + pipe water + 4617, // 1 0010 0000 1001 Found nothing + 6664, // 1 1010 0000 1000 Two groups of solid boxes + ]; + // let alphaMask0 = 0x0001 // + 0x0100 + 0x0200; + // let alphaMask1 = 0x0010 + // let alphaMask2 = 0x0100 + 0x0200 + // let alphaMask2b = 0x0200 + const texMask = 0x8 + 0x0800; + if (knownflags.indexOf(mesh.materialFlags) !== 11) { + // return; + } + // No smoke etc + if (mesh.materialFlags === 520) { + // return; + } + // Must have texture + if (!showUnmaterialed && !(mesh.materialFlags & texMask)) { + return; + } + // NO lods + if (mesh.flags === 4 || mesh.flags === 1 || mesh.flags === 0) { + // return; + } + // Add to final colection + finalMeshes.push(mesh); + }); /// END FOR EACH meshes + callback(finalMeshes, boundingSphere); + }); /// END LOAD MATERIALS CALLBACK + } + catch (e) { + console.warn("Failed rendering model " + filename, e); + const mesh = new THREE.Mesh(new THREE.BoxGeometry(200, 2000, 200), new THREE.MeshNormalMaterial()); + //@ts-ignore + mesh.flags = 4; + //@ts-ignore + mesh.materialFlags = 2056; + //@ts-ignore + mesh.lodOverride = [1000000, 1000000]; + finalMeshes.push(mesh); + /// Send the final meshes to callback function + callback(finalMeshes); + } + }); /// END FILE LOADED CALLBACK FUNCTION + } + /** + * Gets a mesh array from Model file and sends as argument to callback. Uses a cache of meshes in order + * to never read the same model file twice. + * + * @memberof RenderUtils + * @async + * @param {Number} filename The fileId or baseId of the Model file to load + * @param {Array} color RGBA array of 4 integers + * @param {LocalReader} localReader The LocalReader object used to read data from the GW2 .dat file. + * @param {Object} sharedMeshes Value Object for keeping the texture cache. + * @param {Object} sharedTextures Value Object for keeping the texture cache. + * @param {boolean} showUnmaterialed If false does not render any models with missing materials. + * @param {Function} callback Fired once all meshes have been loaded. + * three arguments are passed to the callback function. + * + * The first argument is an Array with each textured THREE.Mesh objects. + * + * The second argument is a boolean, true indicates that these meshes were not + * loaded from the dat file, but retrieved from the run time cache. + * + * The third argument is the bounding spehere of this model file. + */ + function getMeshesForFilename(filename, color, localReader, sharedMeshes, sharedTextures, showUnmaterialed, callback) { + /// If this file has already been loaded, just return a reference to the meshes. + /// isCached will be set to true to inform the caller the meshes will probably + /// have to be cloned in some way. + if (sharedMeshes[filename]) { + callback(sharedMeshes[filename].meshes, true, sharedMeshes[filename].boundingSphere); + } + /// If this file has never been loaded, load it using loadMeshFromModelFile + /// the resulting mesh array will be cached within this model's scope. + else { + loadMeshFromModelFile(filename, color, localReader, sharedTextures, showUnmaterialed, function (meshes, boundingSphere) { + /// Cache result if any. + if (meshes) { + sharedMeshes[filename] = { + meshes: meshes, + boundingSphere: boundingSphere, + }; + } + /// Allways fire callback. + callback(meshes, false, boundingSphere); + }); + } + } + /** + * WIP, Tries to find all fileIds refered by a model file. + * + * @memberof RenderUtils + * @async + * @param {Number} filename Model file Id + * @param {LocalReader} localReader LocalReader instance to read from + * @param {Function} callback First argument is list of used file IDs + */ + function getFilesUsedByModel(filename, localReader, callback) { + const fileIds = [filename]; + /// Load model file + localReader.loadFile(filename, function (inflatedData) { + try { + if (!inflatedData) { + throw "Could not find MFT entry for " + filename; + } + const modelFile = new t3dParser.FileParser(inflatedData); + // MODL for materials -> textures + const modelDataChunk = modelFile.getChunk("modl"); + /// Get materials used by model + const mats = modelDataChunk.data.permutations[0].materials; + /// Add each material file AND referenced TEXTURES + mats.forEach(function (mat) { + /// Add material file id + const matFileName = mat.filename; + fileIds.push(matFileName); + /// Add each texture file id + mat.textures.forEach(function (tex) { + fileIds.push(tex.filename); + }); + }); + } + catch (e) { + console.warn("Could not export any data", e); + } + callback(fileIds); + }); + } + + var RenderUtils = /*#__PURE__*/Object.freeze({ + __proto__: null, + getFilesUsedByModel: getFilesUsedByModel, + getInstancedMesh: getInstancedMesh, + getMeshesForFilename: getMeshesForFilename, + loadMeshFromModelFile: loadMeshFromModelFile, + renderGeomChunk: renderGeomChunk, + renderRect: renderRect + }); + + /** + * A Logger class for T3D + * + * This satic class defines severity levels of messages and provides + * basic logging functionality. Replacing the reference to + * + * @namespace + * @static + */ + class Logger { + TYPE_ERROR = 4; + TYPE_WARNING = 3; + TYPE_MESSAGE = 2; + TYPE_PROGRESS = 1; + TYPE_DEBUG = 0; + logFunctions = new Array(5); + constructor() { + this.logFunctions[this.TYPE_ERROR] = function (...args) { + console.error(...args); + }; + this.logFunctions[this.TYPE_WARNING] = function (...args) { + console.warn(...args); + }; + this.logFunctions[this.TYPE_MESSAGE] = function (...args) { + console.log(...args); + }; + this.logFunctions[this.TYPE_PROGRESS] = function (...args) { + const argArr = args; + argArr.unshift("Progress: "); + console.log(...argArr); + }; + this.logFunctions[this.TYPE_DEBUG] = function (...args) { + const argArr = args; + console.debug(...argArr); + }; + } + /** + * Main logging method. Takes 1 to N arguments. If there are more than 1 arguments + * the first argument is interpreted as severity. If there is only one argument + * severity defaults to + * {{#crossLink "Logger/TYPE_MESSAGE:property"}}{{/crossLink}}. + * + * The following arguments are passed to a logging function matching the + * severity. + * + + * + */ + log(...args) { + /// Require at least 1 argument + if (arguments.length === 0) { + return; + } + /// Parse arguments to an actual array + const argArr = args; + /// Default to message if just one argument was passed + if (argArr.length === 1) { + argArr.unshift(this.TYPE_MESSAGE); + } + /// Otherwise 1st arg is severity, log/warn/error + const severity = Math.max(0, Math.min(this.logFunctions.length, argArr.shift())); + const logFunc = this.logFunctions[severity]; + /// Ouput the rest of the arguments + logFunc.apply(this, argArr); + } + } + const logger = new Logger(); + + // A progress cache is needed to debounce logs at the same percentage + const progressCache = {}; + /** + * This utility function is a helper for showing loading progress of dataRenderers. + * It automatically generates progress logs which can be used outside of the library to show progress bars. + * Must be used on loop implementations where the maximum index is known in advance + * + * @param {Object} logger The default logger or given one + * @param {Number} currentIndex Current index of the item being loaded + * @param {Number} maxIndex Maximum index of items to load + * @param {String} progressName Name of the resource being loaded + */ + function progress(logger$1, currentIndex, maxIndex, progressName) { + const percent = Math.round((1000.0 * currentIndex) / maxIndex) / 10.0; + // Make sure we don't spam logs + if (progressCache[progressName] !== percent) { + const consistentPercent = percent + (percent.toString().indexOf(".") < 0 ? ".0" : ""); + logger$1.log(logger.TYPE_PROGRESS, progressName, consistentPercent); + progressCache[progressName] = percent; + } + // Clean cache on last item + if (currentIndex === maxIndex) { + progressCache[progressName] = undefined; + } + } + + /** + * + * A renderer that generates property models for a map. + * + * @class PropertiesRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "mapFile", a FileParser. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class PropertiesRenderer extends DataRenderer { + static rendererName = "PropertiesRenderer"; + showUnmaterialized; + mapFile; + meshCache; + textureCache; + models; + modelsList = []; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "PropertiesRenderer"); + this.mapFile = this.settings.mapFile; + this.showUnmaterialized = this.settings.showUnmaterialized || false; + this.meshCache = {}; + this.textureCache = {}; + this.models = {}; + } + /** + * Renders all property meshes in a GW2 map described by the map's PROP chunk. + * Output fileds generated: + * + * - *meshes* An array of THREE.Mesh objects visualizing all property models refered by this map. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + this.getOutput().meshes = []; + const propertiesChunkData = this.mapFile.getChunk("prp2").data; + if (!propertiesChunkData) { + return callback(); + } + // Get all different prop types + const props = [] + .concat(propertiesChunkData.propArray) + .concat(propertiesChunkData.propAnimArray) + .concat(propertiesChunkData.propInstanceArray) + .concat(propertiesChunkData.propMetaArray); + /// Build an object containing all the data we need for each prop + this.models = props.reduce((models, prop) => { + const propSize = prop.transforms ? prop.transforms.length + 1 : 1; + if (models[prop.filename]) { + models[prop.filename].props.push(prop); + models[prop.filename].size += propSize; + } + else { + models[prop.filename] = { + props: [prop], + size: propSize, + }; + } + return models; + }, {}); + this.modelsList = Object.keys(this.models); + this.renderModel(0, callback); + } + getFileIdsAsync(callback) { + this.logger.log(T3D.Logger.TYPE_WARNING, "PropertiesRenderer.getFileIdsAsync is not implemented"); + callback([]); + } + /** + * PRIVATE METHODS + */ + /** + * To optimize the rendering on the GPU we render each model only once and use instances for + * any other place using the same model. This allows us to have a much lower amount of draw calls + * and usage of GPU memory compared to a naive approach having a mesh for each model. + */ + renderModel(index, callback) { + if (index >= this.modelsList.length) { + this.meshCache = {}; + this.textureCache = {}; + this.models = {}; + return callback(); + } + progress(this.logger, index, this.modelsList.length, "Loading 3D Models (Props)"); + const modelName = parseInt(this.modelsList[index]); + getMeshesForFilename(modelName, this.models[modelName].props[0].color, this.localReader, this.meshCache, this.textureCache, this.showUnmaterialized, + // We don't care about cached meshes since we know we only ask for each meshes once. + (meshes) => { + if (meshes) { + this.placeModelOnScene(modelName, meshes /*, boundingSphere*/); + } + this.renderModel(index + 1, callback); + }); + } + /** + * Gets the meshes of a specific model, merge them together as an instanced mesh + * and place them in the scene where they are referenced by the props. + * @param {number} modelName The baseId of the model + * @param {*} meshes The 3d models of the model + */ + placeModelOnScene(modelName, meshes) { + const model = this.models[modelName]; + const instancedMesh = getInstancedMesh(meshes, model.size); + let instancedIndex = 0; + for (const prop of model.props) { + instancedMesh.setMatrixAt(instancedIndex, getMatrixForProp(prop)); + instancedIndex += 1; + for (const transform of prop.transforms || []) { + instancedMesh.setMatrixAt(instancedIndex, getMatrixForProp(transform)); + instancedIndex += 1; + } + } + this.getOutput().meshes.push(instancedMesh); + } + } + /** + * Return a Matrix4 for a given prop defining the Scale Rotation and Location of a model + * @param {Object} propData + * @returns {THREE.Matrix4} + */ + function getMatrixForProp(propData) { + const matrix = new THREE.Matrix4(); + matrix.makeRotationFromEuler(new THREE.Euler(propData.rotation[0], -propData.rotation[2], -propData.rotation[1], "ZXY")); + matrix.scale(new THREE.Vector3(propData.scale, propData.scale, propData.scale)); + matrix.setPosition(propData.position[0], -propData.position[2], -propData.position[1]); + return matrix; + } + + /** + * + * A renderer that generates meshes for a single model file. + * + * @class SingleModelRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "id" the base ID or file ID of the model to generate meshes for. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class SingleModelRenderer extends DataRenderer { + static rendererName = "SingleModelRenderer"; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "SingleModelRenderer"); + } + /** + * Output fileds generated: + * + * - *meshes* An array of THREE.Mesh objects visualizing this model file. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + const self = this; + /// Get file id + const fileId = this.settings.id; + const showUnmaterialed = true; + /// Load the model file + let meshCache = {}; + const textureCache = {}; + /// Set up output array + self.getOutput().meshes = []; + getMeshesForFilename(fileId, 0x00ff00, self.localReader, meshCache, textureCache, showUnmaterialed, function (meshes, isCached, boundingSphere) { + if (meshes) { + meshes.forEach(function (mesh) { + mesh.boundingSphere = boundingSphere; + self.getOutput().meshes.push(mesh); + }); + } + /// Fire callback after all meshes have been added. + meshCache = {}; + callback(); + }); + } + } + + /// TODO: port fog from in-engine + function getFragmentShader() { + return [ + "uniform vec2 uvScale;", + "uniform vec2 offset;", + "uniform sampler2D texturePicker;", + "uniform sampler2D texturePicker2;", + "uniform sampler2D texture1;", + "uniform sampler2D texture2;", + "uniform sampler2D texture3;", + "uniform sampler2D texture4;", + "#include ", + "#include ", + "varying vec2 vUv;", + "varying vec3 vecNormal;", + "vec3 blend(", + "vec4 texture1, float a1, vec4 texture2, float a2,", + "vec4 texture3, float a3, vec4 texture4, float a4)", + "{", + "float depth = 2.0;", + "float alphaMult = 1.0;", + "float alphaAdd = 0.0;", + "a1 *= 4.0;", + "a2 *= 4.0;", + "a3 *= 4.0;", + "a4 *= 4.0;", + "a1 = a1+(1.5+texture1.a);", + "a2 = a2+(1.5+texture2.a);", + "a3 = a3+(1.5+texture3.a);", + "a4 = a4+(1.5+texture4.a);", + "float ma = max(a1,a2);", + "ma = max(ma,a3);", + "ma = max(ma,a4);", + "ma -= depth;", + "float b1 = max(a1 - ma, 0.0);", + "float b2 = max(a2 - ma, 0.0);", + "float b3 = max(a3 - ma, 0.0);", + "float b4 = max(a4 - ma, 0.0);", + "return (", + "texture1.rgb * b1 + texture2.rgb * b2 +", + "texture3.rgb * b3 + texture4.rgb * b4 ", + ") / (b1 + b2 + b3 + b4);", + "}", + "void main( void ) {", + "vec2 position = vUv*uvScale;", + "float edge = 1.0/1024.0;", + "vec2 compPos = edge + (vUv*0.25 + offset) * (1.0-edge*2.0);", + "vec4 tp1 = texture2D( texturePicker, compPos);", + "vec4 tp2 = texture2D( texturePicker2, compPos);", + "vec4 composite = tp1;", + "vec4 t1 = texture2D( texture1, position );", + "vec4 t2 = texture2D( texture2, position );", + "vec4 t3 = texture2D( texture3, position );", + "vec4 t4 = texture2D( texture4, position );", + "vec3 color = blend(", + "t1, tp1.a,", + "t2, tp1.b,", + "t3, tp1.g,", + "t4, tp1.r", + ");", + "color *= 0.5+tp2.r;", + "gl_FragColor = vec4(color,1.0);", + "#include ", + "}", + ].join("\n"); + } + function getVertexShader() { + return [ + "varying vec2 vUv;", + "varying vec3 vecNormal;", + "#include ", + "#include ", + "void main()", + "{", + "vUv = uv;", + "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", + "vecNormal = (modelMatrix * vec4(normal, 0.0)).xyz;", + "gl_Position = projectionMatrix * mvPosition;", + "#include ", + "}", + ].join("\n"); + } + + /** + * + * A renderer that generates the meshes for the terrain of a map. + * + * + * Requires a context previously populated by a + * {{#crossLink "EnvironmentRenderer"}}{{/crossLink}}. + * + * @class TerrainRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "mapFile", a FileParser. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class TerrainRenderer extends DataRenderer { + static rendererName = "TerrainRenderer"; + mapFile; + mapRect; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "TerrainRenderer"); + this.mapFile = this.settings.mapFile; + } + drawWater(rect) { + /// Add Water + const material = new THREE.MeshBasicMaterial({ + color: 0x5bb1e8, + wireframe: false, + opacity: 0.35, + }); + material.transparent = true; + return renderRect(rect, 0, material); + } + parseNumChunks(terrainData) { + terrainData.numChunksD_1 = Math.sqrt((terrainData.dims[0] * terrainData.chunkArray.length) / terrainData.dims[1]); + terrainData.numChunksD_2 = terrainData.chunkArray.length / terrainData.numChunksD_1; + } + loadPagedImageCallback(callback, inflatedBuffer) { + const self = this; + // Prep output array + self.getOutput().terrainTiles = []; + const pimgFile = new t3dParser.FileParser(inflatedBuffer); + const pimgTableDataChunk = pimgFile.getChunk("pgtb"); + const pimgData = pimgTableDataChunk && pimgTableDataChunk.data; + this.mapRect = null; + /// Fetch chunks + const terrainData = this.mapFile.getChunk("trn").data; + const parameterData = this.mapFile.getChunk("parm").data; + /// Read settings + const maxAnisotropy = this.settings.anisotropy ? this.settings.anisotropy : 1; + //let chunks = []; + const chunkW = 35; + /// Calculate numChunksD_1 and _2 + this.parseNumChunks(terrainData); + const xChunks = terrainData.numChunksD_1; + const yChunks = terrainData.numChunksD_2; + const allMaterials = terrainData.materials.materials; + const allTextures = terrainData.materials.texFileArray; + // Total map dx and dy + /* + old parameter data definition: + "x1", "float32", + "y1", "float32", + "x2", "float32", + "y2", "float32" + */ + // var dx = parameterData.rect.x2 - parameterData.rect.x1; + // var dy = parameterData.rect.y2 - parameterData.rect.y1; + const dx = parameterData.rect[2] - parameterData.rect[0]; + const dy = parameterData.rect[3] - parameterData.rect[1]; + // Each chunk dx and dy + const cdx = (dx / terrainData.numChunksD_1) * 1; // 35/33; + const cdy = (dy / terrainData.numChunksD_2) * 1; // 35/33; + let n = 0; + const customMaterial = new THREE.MeshLambertMaterial({ + side: THREE.DoubleSide, + color: 0x666666, + flatShading: true, + }); + //let texMats = {}; + /// Load textures from PIMG and inject as material maps (textures) + const chunkTextures = {}; + /// Load textures + if (pimgData) { + const strippedPages = pimgData.strippedPages; + /// Only use layer 0 + strippedPages.forEach(function (page) { + /// Only load layer 0 and 1 + if (page.layer <= 1) { + const filename = page.filename; + //let color = page.solidColor; + const coord = page.coord; + let matName = coord[0] + "," + coord[1]; + if (page.layer === 1) + matName += "-2"; + /// Add texture to list, note that coord name is used, not actual file name + if (!chunkTextures[matName]) { + /// Load local texture, here we use file name! + const chunkTex = loadLocalTexture(self.localReader, filename); + if (chunkTex) { + /// Set repeat, antistropy and repeat Y + chunkTex.anisotropy = maxAnisotropy; + chunkTex.wrapS = THREE.RepeatWrapping; + chunkTex.wrapT = THREE.RepeatWrapping; + } + /// ...But store in coord name + chunkTextures[matName] = chunkTex; + } + } + }); /// end for each stripped page in pimgData + } + /// Render Each chunk + /// We'll make this async in order for the screen to be able to update + const renderChunk = function (cx, cy) { + const chunkIndex = cy * xChunks + cx; + const pageX = Math.floor(cx / 4); + const pageY = Math.floor(cy / 4); + // TODO: Terrain texture LOD ? + const chunkTextureIndices = allMaterials[chunkIndex].loResMaterial.texIndexArray; + // let matFileName = allMaterials[chunkIndex].loResMaterial.materialFile; + // let chunkTextureIndices = allMaterials[chunkIndex].hiResMaterial.texIndexArray; + // let matFileName = allMaterials[chunkIndex].hiResMaterial.materialFile; + // let chunkData = terrainData.chunkArray[chunkIndex]; + // let mainTex = allTextures[chunkTextureIndices[0]]; + let mat = customMaterial; + /// TODO: just tick invert y = false...? + const pageOffetX = (cx % 4) / 4.0; + const pageOffetY = 0.75 - (cy % 4) / 4.0; + // offset 0 -> 0.75 + // Make sure we have shared textures + /// Load and store all tiled textures + const fileNames = []; + for (let gi = 0; gi < chunkTextureIndices.length / 2; gi++) { + const textureFileName = allTextures[chunkTextureIndices[gi]].filename; + fileNames.push(textureFileName); + /// If the texture is not already loaded, read it from the .dat! + if (!chunkTextures[textureFileName]) { + /// Load local texture + const chunkTex = loadLocalTexture(self.localReader, textureFileName); + if (chunkTex) { + /// Set repeat, antistropy and repeat Y + chunkTex.anisotropy = maxAnisotropy; + chunkTex.wrapS = THREE.RepeatWrapping; + chunkTex.wrapT = THREE.RepeatWrapping; + } + chunkTextures[textureFileName] = chunkTex; + } + } /// End for each chunkTextureIndices + /// Create Composite texture material, refering the shared textures + const pageTexName = pageX + "," + pageY; + const pageTexName2 = pageX + "," + pageY + "-2"; + /// Get haze color from environment rednerer + const envOutput = self.getOutput(T3D.EnvironmentRenderer); + if (envOutput.hazeColor) { + envOutput.hazeColor[2] / 255.0; + envOutput.hazeColor[1] / 255.0; + envOutput.hazeColor[0] / 255.0; + } + const uniforms = THREE.UniformsUtils.merge([THREE.UniformsLib["lights"]]); + /// TODO: READ FROM VO, don't default to hard coded scale + uniforms.uvScale = { type: "v2", value: new THREE.Vector2(8.0, 8.0) }; + uniforms.offset = { + type: "v2", + value: new THREE.Vector2(pageOffetX, pageOffetY), + }; + uniforms.texturePicker = { + type: "t", + value: chunkTextures[pageTexName], + }; + uniforms.texturePicker2 = { + type: "t", + value: chunkTextures[pageTexName2], + }; + uniforms.texture1 = { type: "t", value: chunkTextures[fileNames[0]] }; + uniforms.texture2 = { type: "t", value: chunkTextures[fileNames[1]] }; + uniforms.texture3 = { type: "t", value: chunkTextures[fileNames[2]] }; + uniforms.texture4 = { type: "t", value: chunkTextures[fileNames[3]] }; + if (self.settings && self.settings.export) { + mat = new THREE.MeshBasicMaterial({ visible: true }); + } + else { + mat = new THREE.ShaderMaterial({ + uniforms: uniforms, + fragmentShader: getFragmentShader(), + vertexShader: getVertexShader(), + }); + } + /// -1 for faces -> vertices , -2 for ignoring outer faces + const chunkGeo = new THREE.PlaneBufferGeometry(cdx, cdy, chunkW - 3, chunkW - 3); + let cn = 0; + /// Render chunk + /// Each chunk vertex + for (let y = 0; y < chunkW; y++) { + for (let x = 0; x < chunkW; x++) { + if (x !== 0 && x !== chunkW - 1 && y !== 0 && y !== chunkW - 1) { + //@ts-ignore + chunkGeo.getAttribute("position").array[cn * 3 + 2] = terrainData.heightMapArray[n]; + cn++; + } + n++; + } + } // End each chunk vertex + /// Flip the plane to fit wonky THREE js world axes + const mS = new THREE.Matrix4().identity(); + mS.elements[5] = -1; + chunkGeo.applyMatrix4(mS); + /// Compute face normals for lighting, not used when textured + //@ts-ignore + chunkGeo.computeFaceNormals(); + chunkGeo.computeVertexNormals(); + /// Build chunk mesh! + let chunk; + chunk = new THREE.Mesh(chunkGeo, customMaterial); + if (Array.isArray(mat)) { + chunk = THREE.SceneUtils.createMultiMaterialObject(chunkGeo, mat); + } + else { + chunk = new THREE.Mesh(chunkGeo, mat); + } + /// Move and rotate Mesh to fit in place + chunk.rotation.set(Math.PI / 2, 0, 0); + /// Last term is the new one: -cdx*(2/35) + const globalOffsetX = parameterData.rect[0] + cdx / 2; + const chunkOffsetX = cx * cdx; + chunk.position.x = globalOffsetX + chunkOffsetX; + /// Adjust for odd / even number of chunks + if (terrainData.numChunksD_2 % 2 === 0) { + /// Last term is the new one: -cdx*(2/35) + const globalOffsetY = parameterData.rect[1] + cdy / 2 - 0; // -cdy*(1/35); + const chunkOffsetY = cy * cdy * 1; // 33/35; + chunk.position.z = chunkOffsetY + globalOffsetY; + } + else { + const globalOffsetY = parameterData.rect[1] - cdy / 2 + 0; // cdy*(1/35); + const chunkOffsetY = cy * cdy * 1; // 33/35; + chunk.position.z = globalOffsetY + chunkOffsetY; + } + const px = chunk.position.x; + const py = chunk.position.z; + if (!self.mapRect) { + self.mapRect = { + x1: px - cdx / 2, + x2: px + cdx / 2, + y1: py - cdy / 2, + y2: py + cdy / 2, + }; + } + self.mapRect.x1 = Math.min(self.mapRect.x1, px - cdx / 2); + self.mapRect.x2 = Math.max(self.mapRect.x2, px + cdx / 2); + self.mapRect.y1 = Math.min(self.mapRect.y1, py - cdy / 2); + self.mapRect.y2 = Math.max(self.mapRect.y2, py + cdy / 2); + chunk.updateMatrix(); + chunk.updateMatrixWorld(); + /// Add to list of stuff to render + /// TODO: Perhaps use some kind of props for each entry instead? + self.getOutput().terrainTiles.push(chunk); + }; /// End render chunk function + const stepChunk = function (cx, cy) { + if (cx >= xChunks) { + cx = 0; + cy++; + } + if (cy >= yChunks) { + /// Draw water surface using map bounds + self.getOutput().water = self.drawWater(self.mapRect); + /// Set bounds in output VO + self.getOutput().bounds = self.mapRect; + /// Fire call back, we're done rendering. + callback(); + return; + } + const pct = Math.floor((100 * (cy * xChunks + cx)) / (xChunks * yChunks)); + self.logger.log(T3D.Logger.TYPE_PROGRESS, "Loading Terrain", pct); + renderChunk(cx, cy); + setTimeout(stepChunk, 1, cx + 1, cy); + }; + stepChunk(0, 0); + } + /** + * Output fileds generated: + * + * - *terrainTiles* An array of THREE.Mesh objects visualizing terrain of the map. + * + * - *water* A THREE.Mesh object visualizing the bounds of the map. + * + * - *bounds* An object wiht x1, x2, y1, and y2 properties specifying the bounds of the map. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + /// Load all paged Images, requires inflation of other pack files! + const pagedImageId = this.mapFile.getChunk("trn").data.materials.pagedImage; + //@ts-ignore + this.localReader.loadFile(pagedImageId, this.loadPagedImageCallback.bind(this, callback)); + } + /** + * TODO: write description. Used for export feature + * + * @param {Function} callback [description] + * @return {*} [description] + */ + getFileIdsAsync( /* callback */) { + const terrainChunk = this.mapFile.getChunk("trn"); + const pimgTableDataChunk = this.mapFile.getChunk("pimg"); + const fileIds = []; + /// ------------ SPLASH TEXTURES ------------ + const pimgData = pimgTableDataChunk && pimgTableDataChunk.data; + const strippedPages = pimgData.strippedPages; + /// Only use layer 0 + strippedPages.forEach(function (page) { + /// Only load layer 0 and 1 + if (page.layer <= 1 && page.filename > 0) { + fileIds.push(page.filename); + } + }); + /// ------------ END SPLASH TEXTURES ------------ + /// ------------ TILED IMAGES ------------ + const terrainData = terrainChunk.data; + const allTextures = terrainData.materials.texFileArray; + allTextures.forEach(function (texture) { + if (texture.filename > 0) + fileIds.push(texture.filename); + }); + /// ------------ END TILED IMAGES ------------ + return fileIds; + } + } + + /** + * + * A renderer that generates zone models for a map. + * + * @class ZoneRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "mapFile", a FileParser. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class ZoneRenderer extends DataRenderer { + static rendererName = "ZoneRenderer"; + meshCache; + textureCache; + mapFile; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "ZoneRenderer"); + this.mapFile = this.settings.mapFile; + } + /** + * TODO + * + * @param {*} zone [description] + * @param {*} zoneDefs [description] + * @param {*} mapRect [description] + * @param {*} renderZoneCallback [description] + * @return {*} [description] + */ + renderZone(zone, zoneDefs, mapRect, renderZoneCallback) { + const self = this; + /// Get Zone Definition + let zoneDef = null; + zoneDefs.forEach(function (zd) { + if (!zoneDef && zd.token === zone.defToken) + zoneDef = zd; + }); + /// Create array of all models to add: + // let models = [] + const modelGroups = this.getModelGroups(zone, zoneDef, mapRect); + /// Create empty mesh cache + self.meshCache = {}; + self.textureCache = {}; + /* + * ---Keeping this out of the doc for now--- + * Steps trough each model and renders it to the scene, allowing for efficient caching. + * @param {Number} i - Current index within the models array + */ + // var lastPct = -1; + const groupKeys = Object.keys(modelGroups); + function stepModels(i) { + /* var pct = Math.round(100.0*i / groupKeys.length); + if(lastPct!=pct){ + console.log("Rendering ZONE models "+pct); + lastPct = pct; + } */ + if (i >= groupKeys.length) { + /// Empty mesh cache + self.meshCache = {}; + self.textureCache = {}; + /// Tell caller this zone is done loading + renderZoneCallback(); + return; + } + /// Read model at index + /// var model = models[i]; + const key = groupKeys[i]; /// key is model filename + const group = modelGroups[key]; + const meshGroups = []; + /// Get model just once for this group + const showUnmaterialed = false; + getMeshesForFilename(key, null, self.localReader, self.meshCache, self.textureCache, showUnmaterialed, function (meshes /*, isCached*/) { + /// If there were meshes, add them to the scene with correct scaling rotation etc. + if (meshes /* && meshes.length == 3 */) { + /// Add one copy per model instance + /// TODO: add rotation! + /// TODO: fine tune position? + /// TODO: POTIMIZE! + group.forEach(function (model, instanceIdx) { + //let isCached = true; + //let scale = 1.0; + /// For each Mesh in the model + meshes.forEach(function (mesh, meshIdx) { + if (mesh.materialFlags === 525 /* || mesh.materialFlags == 520 || mesh.materialFlags == 521 */) { + // console.log("Skipping lod"); + return; + } + const move = { x: 0, y: 0, z: 0 }; + /// Add to big mesh + if (!meshGroups[meshIdx]) { + const mg = mesh.geometry.clone(); + meshGroups[meshIdx] = { + readVerts: mg.getAttribute("position").array, + verts: new Float32Array(group.length * mg.getAttribute("position").array.length), + readIndices: mg.getIndex().array, + indices: new Uint32Array(group.length * mg.getIndex().array.length), + readUVs: mg.getAttribute("uv").array, + uvs: new Float32Array(group.length * mg.getAttribute("uv").array.length), + readNormals: mg.getAttribute("normal").array, + normals: new Float32Array(group.length * mg.getAttribute("normal").array.length), + material: mesh.material, + // material:new THREE.MeshBasicMaterial( {color: 0xffcccc, wireframe:true} ), + /* material : new THREE.PointCloudMaterial ({ + color: 0xFF0000, + size: 20 + }), */ + position: { x: model.x, y: model.y, z: model.z }, + }; + } + else { + /// Translate + move.x = model.x - meshGroups[meshIdx].position.x; + move.y = model.z - meshGroups[meshIdx].position.z; + move.z = model.y - meshGroups[meshIdx].position.y; + } + /// Add geom verts + const readVerts = meshGroups[meshIdx].readVerts; + const writeVerts = meshGroups[meshIdx].verts; + const stride = readVerts.length; + for (let i = 0, j = instanceIdx * stride; i < stride; i += 3, j += 3) { + writeVerts[j + 0] = readVerts[i + 0] + move.x; + writeVerts[j + 1] = readVerts[i + 1] + move.y; + writeVerts[j + 2] = readVerts[i + 2] + move.z; + } + const readIndices = meshGroups[meshIdx].readIndices; + const writeIndices = meshGroups[meshIdx].indices; + const strideIndices = readIndices.length; + const shift = (stride * instanceIdx) / 3; + for (let i = 0, j = instanceIdx * strideIndices; i < strideIndices; i++, j++) { + writeIndices[j] = readIndices[i] + shift; + } + const readUVs = meshGroups[meshIdx].readUVs; + const writeUvs = meshGroups[meshIdx].uvs; + const uvStride = readUVs.length; + for (let i = 0, j = instanceIdx * uvStride; i < uvStride; i++, j++) { + writeUvs[j] = readUVs[i]; + } + const readNormals = meshGroups[meshIdx].readNormals; + const writeNormals = meshGroups[meshIdx].normals; + const normalStride = readNormals.length; + for (let i = 0, j = instanceIdx * normalStride; i < normalStride; i++, j++) { + writeNormals[j] = readNormals[i]; + } + }); + }); // End for each model in group + } /// End if meshes + /// Add each cluster of merged meshes to scene + meshGroups.forEach(function (meshGroup) { + const mergedGeom = new THREE.BufferGeometry(); + mergedGeom.setAttribute("position", new THREE.BufferAttribute(meshGroup.verts, 3)); + // mergedGeom.setAttribute( 'index', new THREE.BufferAttribute( meshGroup.indices, 1) ); + mergedGeom.setIndex(new THREE.BufferAttribute(meshGroup.indices, 1)); + mergedGeom.setAttribute("normal", new THREE.BufferAttribute(meshGroup.normals, 3)); + mergedGeom.setAttribute("uv", new THREE.BufferAttribute(meshGroup.uvs, 2)); + //@ts-ignore + mergedGeom.buffersNeedUpdate = true; + const mesh = new THREE.Mesh(mergedGeom, meshGroup.material); + mesh.position.set(meshGroup.position.x, meshGroup.position.z, meshGroup.position.y); + self.getOutput().meshes.push(mesh); + }); // End for each meshgroup + /// Rendering is done, render next. + stepModels(i + 1); + }); + } /// End function stepModels + /// Begin stepping trough the models, rendering them. + stepModels(0); + } + /** + * TODO + * + * @param {*} zone [description] + * @param {*} zoneDef [description] + * @param {*} mapRect [description] + * @return {*} [description] + */ + getModelGroups(zone, zoneDef, mapRect) { + /// Calculate rect in global coordinates + // let zPos = zone.zPos; + const mapX = mapRect[0]; + const mapY = mapRect[1]; + const c = 32 + 16; + // ["x1","uint32","y1","uint32","x2","uint32", "y2", "uint32"] + const zoneRect = { + x1: zone.vertRect[0] * c + mapX, + x2: zone.vertRect[2] * c + mapX, + y1: zone.vertRect[1] * -c - mapY, + y2: zone.vertRect[3] * -c - mapY, + }; + /// Zone width and depth in local corrdinates + /* var zdx = zone.vertRect.x1-zone.vertRect.x2; + var zdy = zone.vertRect.y1-zone.vertRect.y2; */ + /// These zones seems to overflow :/ + if (zone.encodeData.length === 0) { + return {}; + } + // console.log("Get mdl groups", zone); + /// Testing: Render Zone Vert Rect + // RenderUtils.renderRect(zoneRect, -zPos); + const zdx = zone.vertRect[0] - zone.vertRect[2]; + // let zdy = zone.vertRect[1] - zone.vertRect[3]; + /// Zone Flags increases a linear position, used to step trough the Zone. + let linearPos = 0; + const modelGroups = {}; + const terrainTiles = this.getOutput(T3D.TerrainRenderer).terrainTiles; + for (let i = 0; i < zone.flags.length; i += 2) { + /// Step forward + linearPos += zone.flags[i]; + /// Check if a model should be placed + const flag = zone.flags[i + 1]; + if (flag !== 0) { + /// Extract flag data + /// Layer is written in the last 4 bytes + const zoneDefLayer = flag >> 4; + /// Get Zone Definition Layer + const layer = zoneDef.layerDefArray[zoneDefLayer - 1]; + /// TESTING Only show layers with height >= 3 + if (layer /* && layer.height >= 0 */) { + /// Get X and Y from linear position + const modelX = (linearPos % zdx) * c + zoneRect.x1; + const modelY = Math.floor(linearPos / zdx) * c + zoneRect.y1; + /// Get Z from intersection with terrain + let modelZ = null; + const startZ = 100000; + const raycaster = new THREE.Raycaster(new THREE.Vector3(modelX, startZ, modelY), new THREE.Vector3(0, -1, 0)); + /// TODO: OPT? + terrainTiles.forEach(function (chunk) { + if (modelZ === null) { + const intersections = raycaster.intersectObject(chunk); + if (intersections.length > 0) { + modelZ = startZ - intersections[0].distance; + } + } + }); + /// Get model id + /// TODO: check with modelIdx = flag & 0xf; + const modelIdx = 0; + const model = layer.modelArray[modelIdx]; + const modelFilename = model.filename; + // let zOffsets = model.zOffsets; + // let layerFlags = layer.layerFlags; // NOrmaly 128, 128 + // TODO: flip z,y? + const rotRangeX = layer.rotRangeX; // max min + const rotRangeY = layer.rotRangeY; // max min + const rotRangeZ = layer.rotRangeZ; // max min + const scaleRange = layer.scaleRange; // max min + const fadeRange = layer.fadeRange; // max min + // Unused + // tiling: 3 + // type: 1 + // width: 2 + // radiusGround: 2 + /// Create modelGroup (this zone only) + if (!modelGroups[modelFilename]) { + modelGroups[modelFilename] = []; + } + /// Add entry to model group + modelGroups[modelFilename].push({ + x: modelX, + y: modelY, + z: modelZ, + rotRangeX: rotRangeX, + rotRangeY: rotRangeY, + rotRangeZ: rotRangeZ, + scaleRange: scaleRange, + fadeRange: fadeRange, + }); + } /// End if layer + } /// End if flag != 0 + } /// End for each flag + return modelGroups; + } + /** + * Renders all zone meshes in a GW2 map described by the map's "zon2" chunk. + * Output fileds generated: + * + * - *meshes* An array of THREE.Mesh objects visualizing all zone models refered by this map. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + const self = this; + /// Set up output array + self.getOutput().meshes = []; + const zoneChunkData = this.mapFile.getChunk("zon2").data; + const parameterChunkData = this.mapFile.getChunk("parm").data; + // let terrainChunkData = this.mapFile.getChunk("trn").data; + const mapRect = parameterChunkData.rect; + /// Zone data + const zones = zoneChunkData.zoneArray; + const zoneDefs = zoneChunkData.zoneDefArray; + /// Render each zone + let lastPct = -1; + /// Main render loop, render each zone + function stepZone(i) { + const pct = Math.round((100.0 * i) / zones.length); + if (lastPct !== pct) { + self.logger.log(T3D.Logger.TYPE_PROGRESS, "Loading 3D Models (Zone)", pct); + lastPct = pct; + } + if (i >= zones.length) { + callback(); + return; + } + /// Main zone render function call + self.renderZone(zones[i], zoneDefs, mapRect, stepZone.bind(self, i + 1)); + } + stepZone(0); + } + } + /* + /// NOT USED?? + // eslint-disable-next-line no-unused-vars + function addZoneMeshesToScene(meshes, isCached, position, scale, rotation) { + /// Called for each mesh in the zone + /// TODO: Opt opt opt... + + meshes.forEach(function (mesh) { + /// Create new mesh if we got back a cached original. + if (isCached) mesh = new THREE.Mesh(mesh.geometry, mesh.material); + + /// Scale, position and rotate. + mesh.scale.set(scale, scale, scale); + if (rotation) { + mesh.rotation.order = "ZXY"; + mesh.rotation.set(rotation.x, rotation.y, rotation.z); + } + mesh.position.set(position.x, position.y, position.z); + + /// Add to export + this.getOutput().meshes.push(mesh); + }); + } + */ + /// / Not used: zone defintion per chunk data "images" 32*32 points + /* + //Total map dx and dy + var d = terrainChunkHeader.data; + var pd = parameterChunkHeader.data; + var dx = (pd.rect.x2-pd.rect.x1); + var dy = (pd.rect.y2-pd.rect.y1); + + //Each chunk dx and dy + + var c =1; + var cdx = c*dx/d.dims.dim1; + + var cdy = c*dy/d.dims.dim2; + + var cdx = dx/(d.numChunksD_1*2); + var cdy =dy/(d.numChunksD_2*2); + + for(var i=0; i0){ + // console.log("Found flag",flags[j],"@ zoneDef",zoneDef.token,"coord",coord,"index",j); + // } + //} + }); + + } + + } */ + + /** + * + * A renderer that generates a list of readable strings from a "strs" file. + * + * @class StringRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "id" the base ID or file ID of the string file to read strings from. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class StringRenderer extends DataRenderer { + static rendererName = "StringRenderer"; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "StringRenderer"); + } + /** + * Output fileds generated: + * + * - *strings* An array of objects. Each object has a "recid"-property specifing on what index within the file + * a given string was found, and a "value"-property specigying the string value. + * + * - *language* An integer specifing the language of the loaded file. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + const self = this; + /// Get file id + // const fileId = this.settings.id; + /// Load the string file + /// Set up output array + this.getOutput().strings = []; + this.localReader.loadFile(this.settings.id, function (inflatedData) { + const dataView = new DataView(inflatedData); + const end = dataView.byteLength - 2; + /// skip past fcc + let cursor = 4; + let entryIndex = 0; + while (end - cursor > 6) { + const size = dataView.getUint16(cursor, true); + cursor += 2; + const decryptionOffset = dataView.getUint16(cursor, true); + cursor += 2; + const bitsPerSymbol = dataView.getUint16(cursor, true); + cursor += 2; + const entry = { size, decryptionOffset, bitsPerSymbol }; + entry.size -= 6; + if (entry.size > 0) { + const isEncrypted = entry.decryptionOffset !== 0 || entry.bitsPerSymbol !== 0x10; + /// UTF-16 + if (!isEncrypted) { + const value = new Uint16Array(inflatedData, cursor, entry.size / 2); + cursor += entry.size; + self.getOutput().strings.push({ value: String.fromCharCode(...value), recid: entryIndex }); + } + } + entryIndex++; + } + self.getOutput().language = dataView.getUint16(end, true); + callback(); + }); + } + } + + var version = "3.0.0"; + + /* INCLUDES */ + /* PRIVATE VARS */ + const _settings = { + t3dtoolsWorker: "modules/t3dtools/t3dworker.js", + concurrentTasks: typeof navigator !== "undefined" ? navigator.hardwareConcurrency : 1, + }; + // eslint-disable-next-line prefer-const + T3D = { + version: version, + DataRenderer: DataRenderer, + EnvironmentRenderer: EnvironmentRenderer, + HavokRenderer: HavokRenderer, + PropertiesRenderer: PropertiesRenderer, + SingleModelRenderer: SingleModelRenderer, + TerrainRenderer: TerrainRenderer, + ZoneRenderer: ZoneRenderer, + StringRenderer: StringRenderer, + Logger: logger, + MapFileList: mapMap, + MaterialUtils: MaterialUtils, + MathUtils: MathUtils, + RenderUtils: RenderUtils, + PersistantStore: PersistantStore, + FileTypes: FileTypes, + /** + * Creates a new instance of LocalReader with an pNaCl inflater connected to it. + */ + getLocalReader: function (file, callback, t3dtoolsWorker, noIndexedDB) { + const path = t3dtoolsWorker || _settings.t3dtoolsWorker; + // Create the instance and init the threads + const lrInstance = new LocalReader({ + workerPath: path, + workersNb: _settings.concurrentTasks, + noIndexedDB, + }); + /// Callback with the lrInstance + lrInstance.openArchive(file).then(() => { + callback(lrInstance); + }); + return lrInstance; + }, + /** + * Utility method for acceccing a list containing information about all files + * in the .dat connected to the provided LocalReader instance. This method first + * tries to read a local indexing list from the client's localstorage and + * fallbacks to generating the list by scanning the MFT indices of the .dat + * and peeking each file in order to find out what filetype it has. + * + * Note that peeking the files is the time consuming task, so if you don't want + * yout application to spend time indexing the .dat and have a priori knowledge + * about the required file Id's you should not use this method. + **/ + getFileListAsync: function (localReader, callback) { + localReader.readFileList().then((result) => { + const returnObj = {}; + for (const fileEntry of result) { + if (returnObj[fileEntry.fileType] === undefined) { + returnObj[fileEntry.fileType] = []; + } + returnObj[fileEntry.fileType].push(fileEntry.mftId); + } + callback(returnObj); + }); + }, + /** + * Utility method for acceccing a list containing information about all map files + * in the .dat connected to the provided LocalReader instance. This method first + * tries to read a local indexing list from the client's localstorage and + * fallbacks to generating the list by scanning the MFT indices of the .dat + * and peeking each file in order to find out what filetype it has. + * + * If the searchAll flag is not set to true, this process will only scan files + * from the "T3D/MapFileList" property. + **/ + getMapListAsync: function (localReader, callback, searchAll) { + function restoreOuput(array) { + const returnArray = []; + for (const elt of array) { + let category = returnArray.findIndex((i) => i.name === elt.category); + if (category === -1) { + category = returnArray.push({ name: elt.category, maps: [] }) - 1; + } + returnArray[category].maps.push({ + fileName: elt.baseId, + name: elt.name, + }); + } + // And resort it in order + returnArray.sort((i, j) => { + if (i.name < j.name) + return -1; + if (i.name > j.name) + return 1; + return 0; + }); + return { maps: returnArray }; + } + /// If seachAll flag is true, force a deep search + if (searchAll) { + localReader.readFileList().then(() => { + localReader.getMapList().then((result) => { + callback(restoreOuput(result)); + }); + }); + return; + } + else { + localReader.getMapList().then((result) => { + callback(restoreOuput(result)); + }); + } + }, + /** + * Utility method used for rendering map files. Loads a map file and applies + * the provided renderers to it. + **/ + renderMapContentsAsync: function (localReader, fileName, renderers, callback, logger) { + /// VO for storing result from renderers + const context = {}; + let runAllRenderers; + /// Make sure we got an actuall ID number + if (parseInt(fileName)) { + /// File name is baseId, load using local reader. + localReader.loadFile(parseInt(fileName), function (arrayBuffer) { + /// Initiate Map file object. Connect callback + const mapFile = new t3dParser.FileParser(arrayBuffer); + /// Populate VO by running the renderers + runAllRenderers = function (i) { + /// Run each renderer + if (i < renderers.length) { + T3D.runRenderer(renderers[i].renderClass, localReader, Object.assign(renderers[i].settings, { mapFile: mapFile }), context, () => runAllRenderers(i + 1)); + } + /// Fire callback with VO when done + else { + callback(context); + } + }; + /// Starting point for running each renderer + runAllRenderers(0); + }); + } + /// Primitive error message... + else { + const outputLogger = logger || T3D.Logger; + outputLogger.log(T3D.Logger.TYPE_ERROR, "Map id must be an integer!, was:", fileName); + } + }, + /** + * Utility method for applying a single renderer to a LocalReader insatnce. + **/ + runRenderer: function (renderClass, localReader, settings, context, cb) { + const r = new renderClass(localReader, settings, context, undefined, renderClass.rendererName); + r.renderAsync(cb); + }, + getContextValue: function (context, clazz, propName, defaultValue) { + const output = context[clazz.rendererName]; + if (output) { + return output[propName] ? output[propName] : defaultValue; + } + return defaultValue; + }, + /** + * Check if the client web browser can render WebGL 3D content. + * + * @private + * @param {boolean} return_context flag making this method return the canvas object instead of true + * @return {boolean} true if the client is WebGL enabled, false otherwise + */ + hasWebGL: function (return_context) { + if (window.WebGLRenderingContext) { + const canvas = document.createElement("canvas"); + const names = ["webgl", "experimental-webgl", "moz-webgl", "webkit-3d"]; + let context = false; + for (let i = 0; i < 4; i++) { + try { + context = canvas.getContext(names[i]); + if (context && typeof context.getParameter === "function") { + // WebGL is enabled + if (return_context) { + // return WebGL object if the function's argument is present + return { name: names[i], gl: context }; + } + // else, return just true + return true; + } + } + catch { + //continue + } + } + // WebGL is supported, but disabled + return false; + } + // WebGL not supported + return false; + }, + }; + var T3D$1 = T3D; + globalThis.T3D = T3D; + /* PRIVATE METHODS */ + /** + * Performs checks for required browser capabilities and required third party libraries. + * Loggs any warnings or error messages. + * + * @private + * @return {Number} The ammount of errors and warnings generated. + */ + function checkRequirements() { + let numErrors = 0; + if (!globalThis.window || !window.indexedDB) { + T3D.Logger.log(T3D.Logger.TYPE_ERROR, "T3D persistant storing and loading requires indexedDB support."); + numErrors++; + } + if (typeof t3dParser.FileParser === "undefined") { + T3D.Logger.log(T3D.Logger.TYPE_ERROR, "T3D core functionality requires t3d-parser library."); + numErrors++; + } + if (typeof THREE === "undefined") { + T3D.Logger.log(T3D.Logger.TYPE_WARNING, "T3D mesh generation requires three.js library."); + numErrors++; + } + if (numErrors < 1) { + T3D.Logger.log(T3D.Logger.TYPE_MESSAGE, "Tyria 3D API v" + T3D.version + " initialized."); + } + return numErrors; + } + /// Library checks requirements on startup + checkRequirements(); + + return T3D$1; + +})(T3DParser); +//# sourceMappingURL=T3D.js.map diff --git a/browser/static/T3D.js.map b/browser/static/T3D.js.map new file mode 100644 index 0000000..335a7eb --- /dev/null +++ b/browser/static/T3D.js.map @@ -0,0 +1 @@ +{"version":3,"file":"T3D.js","sources":["../src/LocalReader/PersistantStore.ts","../src/LocalReader/DataReader.ts","../src/MapFileList.ts","../src/LocalReader/FileTypes.ts","../src/LocalReader/LocalReader.ts","../src/dataRenderer/DataRenderer.ts","../src/util/MaterialUtils.ts","../src/dataRenderer/EnvironmentRenderer.ts","../src/dataRenderer/HavokRenderer.ts","../src/util/MathUtils.ts","../src/util/RenderUtils.ts","../src/Logger.ts","../src/util/Logs.ts","../src/dataRenderer/PropertiesRenderer.ts","../src/dataRenderer/SingleModelRenderer.ts","../src/util/TerrainShader.ts","../src/dataRenderer/TerrainRenderer.ts","../src/dataRenderer/ZoneRenderer.ts","../src/dataRenderer/StringRenderer.ts","../src/T3DLib.ts"],"sourcesContent":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"names":["FileParser","ArchiveParser","ParsingUtils","MapFileList","FileTypes.getFileType","MaterialUtils.loadLocalTexture","MathUtils.popcount","MathUtils.f16","MaterialUtils.getMaterial","logger","Logger","LogsUtils.progress","RenderUtils.getMeshesForFilename","RenderUtils.getInstancedMesh","RenderUtils.renderRect","TerrainShader.getFragmentShader","TerrainShader.getVertexShader","_version"],"mappings":"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"} \ No newline at end of file diff --git a/browser/static/jquery.js b/browser/static/jquery.js new file mode 100644 index 0000000..2170756 --- /dev/null +++ b/browser/static/jquery.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.0 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-04-10T15:07Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && 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 #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 elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +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.5.0", + + // 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; + }, + + // 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 ); + }, + + // 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; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // 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: http://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" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = 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" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://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; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + 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 + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( 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; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// 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: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( 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, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + 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 ) || rcombinators.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. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } 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( rtrim, "$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 Issue #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 Sizzle + * @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; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "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 + /* jshint -W018 */ + 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 Sizzle 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; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, 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; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // 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 ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // 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 ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // 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" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // 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 + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // 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: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + 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 && + 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 && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( 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 Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.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 contains( context, elem ); +}; + +Sizzle.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 (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = 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 += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // 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 ] ) { + Sizzle.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 ] ) { + Sizzle.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 nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "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 = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "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, uniqueCache, 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 ? + node.nodeName.toLowerCase() === 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 + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ 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 ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ 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 ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ 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 + // http://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() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle 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( 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( rtrim, "$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 (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( 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." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.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 === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || 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 + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://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 ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // 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 = argument < 0 ? + argument + length : + argument > length ? + length : + 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(); + +tokenize = Sizzle.tokenize = function( 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 = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + 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 + return parseOnly ? + soFar.length : + soFar ? + Sizzle.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, uniqueCache, 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 ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ 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 + uniqueCache[ 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++ ) { + Sizzle( 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, + 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, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // 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( 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( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #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( rtrim, "$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: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + 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 ) ) { + results.push( 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 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( 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 Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( 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 + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// 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; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +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; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +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 to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#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 Sizzle + 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+ + // 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.stackTrace ); + } + + // 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 stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = 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 master Deferred + master = 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 ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.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$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // 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, stack ); + } +}; + + + + +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 #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 (#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 = Object.create( null ); + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #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 (#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 (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#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 = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#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 or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _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, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#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 (#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 + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +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 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 (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #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 (#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", returnTrue ); + } + + // 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, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + 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 notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // 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 + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // 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.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +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 (#504, #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: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // 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; + }, + + delegateType: delegateType + }; +} ); + +// 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 = /\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 (#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; + + // Reenable 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 { + 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 Sizzle 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 getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #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 (#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! + 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"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // 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, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + 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]).+)/, + rcustomProp = /^--/, + 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; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += 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; +} + +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, + "columnCount": true, + "fillOpacity": 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, + "widows": true, + "zIndex": true, + "zoom": 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 (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#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 )` (#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. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +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 + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#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 classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( 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 (#14686, #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 (#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 + + +support.focusin = "onfocusin" in window; + + +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 (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#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 (#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 ); + } + } +} ); + + +// 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 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + 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 ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +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, + + // #7653, #8125, #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 (#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 #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 (#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 #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 (#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; + + // #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 + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + 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 (#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 + // #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 #8605, #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 ) { + + // #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( " + + + + + + + + diff --git a/examples/MapExplorer/index.js b/examples/MapExplorer/index.js new file mode 100644 index 0000000..4f27990 --- /dev/null +++ b/examples/MapExplorer/index.js @@ -0,0 +1,519 @@ +(function () { + 'use strict'; + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + var MapExplorer = {}; + + let AppRenderer$1 = class AppRenderer { + constructor(logger) { + this.logger = logger; + + /// This example is very inspired by the ModelRenderer example but updated + /// using the latest version of the API. This global object for the app contains + /// all the important data. + + /// All renderers must have access to a LocalReader. + /// The LocalReader is the object that allows us + /// to read from the .dat + this.localReader = null; + + /// The context is an object all the renderer outputs their data to + this.context = null; + + /// THREE js objects + this.scene = null; + this.skyScene = null; + this.camera = null; + this.skyCamera = null; + this.renderer = null; + this.clock = null; + this.mouse = null; + this.controls = null; + this.controlsEnabled = false; + + /// Data: + this._cleanMapData(); + } + + /** + * Public methods + */ + createLocalReader(file, callback) { + this.localReader = T3D.getLocalReader(file, callback, "../static/t3dworker.js", this.logger); + } + + getMapList() { + return this.localReader.getMapList(); + } + + // Setup schene + init() { + const canvasWidth = window.innerWidth; + const canvasHeight = window.innerHeight; + const canvasClearColor = 0x342920; // For happy rendering, always use Van Dyke Brown. + const fov = 60; + const aspect = canvasWidth / canvasHeight; + const fogDistance = Number($("#fogRange").val()); + + this.camera = new THREE.PerspectiveCamera(fov, aspect, 0.1, 100000); + this.skyCamera = new THREE.PerspectiveCamera(fov, aspect, 0.1, 1000000); + this.scene = new THREE.Scene(); + this.skyScene = new THREE.Scene(); + this.mouse = new THREE.Vector2(); + + this.clock = new THREE.Clock(); + /// This scene has one ambient light source and three directional lights + const ambientLight = new THREE.AmbientLight(0x555555); + this.scene.add(ambientLight); + + const directionalLight1 = new THREE.DirectionalLight(0xffffff, 0.5); + directionalLight1.position.set(0, 0, 1); + this.scene.add(directionalLight1); + + const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.5); + directionalLight2.position.set(1, 0, 0); + this.scene.add(directionalLight2); + + const directionalLight3 = new THREE.DirectionalLight(0xffffff, 0.5); + directionalLight3.position.set(0, 1, 0); + this.scene.add(directionalLight3); + + // Fog + this.scene.fog = new THREE.Fog(0xffffff, fogDistance, fogDistance + 1000); + this.camera.far = fogDistance + 1000; + this.camera.updateProjectionMatrix(); + + /// Standard THREE renderer with AA + this.renderer = new THREE.WebGLRenderer({ + antialiasing: true, + logarithmicDepthBuffer: true, + sortObjects: false, + stencil: false, + premultipliedAlpha: false, + }); + this.renderer.autoClear = false; + document.body.appendChild(this.renderer.domElement); + this.renderer.setSize(canvasWidth, canvasHeight); + this.renderer.setClearColor(canvasClearColor); + + window.addEventListener("resize", () => { + const SCREEN_HEIGHT = window.innerHeight; + const SCREEN_WIDTH = window.innerWidth; + + this.camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT; + this.camera.updateProjectionMatrix(); + this.skyCamera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT; + this.skyCamera.updateProjectionMatrix(); + + this.renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT); + }); + + this.setupController(); + + /// Note: constant continous rendering from page load + this._render(); + } + + isCollModelsLoaded() { + this.mapData.collision.loaded; + } + + isPropModelsLoaded() { + return this.mapData.props.loaded; + } + + isZoneModelsLoaded() { + return this.mapData.zone.loaded; + } + + loadMap(mapId) { + // Clean previous render states + this._cleanMapData(); + this.mapData.id = mapId; + + /// Renderer settings (see the documentation of each Renderer for details) + const renderers = [ + { + renderClass: T3D.EnvironmentRenderer, + settings: {}, + }, + { + renderClass: T3D.TerrainRenderer, + settings: {}, + }, + ]; + /// Load for the first time the renderer and spawn the context + T3D.renderMapContentsAsync( + this.localReader, + this.mapData.id, + renderers, + (context) => { + this._onRendererDone(context); + }, + this.logger + ); + + // Cache mapFile for later use + if (parseInt(this.mapData.id)) { + this.localReader.loadFile(this.mapData.id, (arrayBuffer) => { + this.mapData.mapFile = new T3DParser.FileParser(arrayBuffer); + }); + } + } + + loadZoneModels(callback) { + this._loadMeshes(T3D.ZoneRenderer, this.mapData.zone, callback); + } + + loadPropModels(callback) { + this._loadMeshes(T3D.PropertiesRenderer, this.mapData.props, callback); + } + + loadCollModels(callback) { + this._loadMeshes(T3D.HavokRenderer, this.mapData.collision, callback); + } + + setFog(fogDistance) { + if (this.scene && this.scene.fog) { + this.scene.fog.near = fogDistance; + this.scene.fog.far = fogDistance + 1000; + } + if (this.camera) { + this.camera.far = fogDistance + 1000; + this.camera.updateProjectionMatrix(); + } + } + + setMovementSpeed(speed) { + if (this.controls) { + this.controls.movementSpeed = speed; + } + } + + getMovementSpeed() { + if (this.controls) { + return this.controls.movementSpeed; + } + + return 0; + } + + toggleZoneModels() { + return this._toggleModels("zone"); + } + + togglePropModels() { + return this._toggleModels("props"); + } + + toggleCollModels() { + return this._toggleModels("collision"); + } + + /** + * Private methods + */ + + _cleanMapData() { + this.mapData = { + id: null, + mapFile: null, + terrain: { + data: [], + }, + collision: { + enabled: false, + loaded: false, + data: [], + }, + props: { + enabled: false, + loaded: false, + data: [], + }, + zone: { + enabled: false, + loaded: false, + data: [], + }, + }; + } + + /// Wipes out the data + _cleanScene() { + for (const type of ["terrain", "props", "zone", "collision"]) { + for (const elem of this.mapData[type].data) { + this.scene.remove(elem); + } + this.mapData[type].data = []; + } + + for (const type of ["props", "zone", "collision"]) { + this.mapData[type].loaded = false; + this.mapData[type].enabled = false; + } + } + + /// Run a renderer manually and populates the data object + _loadMeshes(rendererClass, outRendererData, callback) { + T3D.runRenderer( + rendererClass, + this.localReader, + { visible: true, mapFile: this.mapData.mapFile, showUnmaterialized: false }, + this.context, + () => { + outRendererData.data = T3D.getContextValue(this.context, rendererClass, "meshes"); + outRendererData.loaded = true; + callback(); + } + ); + } + + setupController() { + if (this.controls) { + this.controls.dispose(); + } + + const controls = new THREE.FlyControls(this.camera, this.renderer.domElement); + + controls.movementSpeed = Number($("#mvntSpeedRange").val()) | 1000; + controls.domElement = this.renderer.domElement; + controls.rollSpeed = Math.PI / 6; + controls.autoForward = false; + controls.dragToLook = true; + this.controls = controls; + } + + _render() { + commonjsGlobal.stats.update(); + window.requestAnimationFrame(() => this._render()); + + const delta = this.clock.getDelta(); + this.controls.update(delta); + + // Render first skyCamera + this.skyCamera.quaternion.copy(this.camera.quaternion); + this.renderer.clear(this.renderer.getClearColor()); + this.renderer.render(this.skyScene, this.skyCamera); + + this.renderer.render(this.scene, this.camera); + } + + _toggleModels(meshType) { + if (this.mapData[meshType].enabled) { + for (const elem of this.mapData[meshType].data) { + this.scene.remove(elem); + } + this.mapData[meshType].enabled = false; + return false; + } else { + for (const elem of this.mapData[meshType].data) { + this.scene.add(elem); + } + this.mapData[meshType].enabled = true; + return true; + } + } + + /// Runs when the ModelRenderer is finished + _onRendererDone(context) { + this._cleanScene(); + + /// Populate our context with the context returned + this.context = context; + + /// Take all the terrain tiles generated by the TerrainRenderer and add them to the scene + for (const elem of T3D.getContextValue(context, T3D.TerrainRenderer, "terrainTiles")) { + this.scene.add(elem); + this.mapData.terrain.data.push(elem); + } + + /// Skybox + const skyBox = T3D.getContextValue(context, T3D.EnvironmentRenderer, "skyBox"); + this.skyScene.add(skyBox); + const hazeColor = T3D.getContextValue(context, T3D.EnvironmentRenderer, "hazeColor"); + if (hazeColor) { + this.renderer.setClearColor(new THREE.Color(hazeColor[2] / 255, hazeColor[1] / 255, hazeColor[0] / 255)); + } + + /// Add the water level to the scene + const water = T3D.getContextValue(context, T3D.TerrainRenderer, "water"); + this.scene.add(water); + this.mapData.terrain.data.push(water); + + /// Move the camera initial place depending on the map bounds + const bounds = T3D.getContextValue(context, T3D.TerrainRenderer, "bounds"); + this.camera.position.x = 0; + this.camera.position.y = bounds ? bounds.y2 : 0; + this.camera.position.z = 0; + this.camera.rotation.x = (-90 * Math.PI) / 180; + } + }; + + var renderer = AppRenderer$1; + + const AppRenderer = renderer; + + const stats = new Stats(); + $("body").append(stats.domElement); + $(stats.domElement).hide(); + stats.toggle = () => $(stats.domElement).toggle(); + commonjsGlobal.stats = stats; + + /// Extend Original Logger + const myLogger = { + lastMessageType: null, + log: function () { + const htmlOutput = $("#log"); + const str = Array.prototype.slice.call(arguments, 1).join(" "); + if (arguments[1] === myLogger.lastMessageType) { + $("#log p:last-of-type")[0].innerHTML = str; + } else { + htmlOutput.append($("

-------------

")); + htmlOutput.append($("

" + str + "

")); + } + htmlOutput[0].scrollTop = htmlOutput[0].scrollHeight; + myLogger.lastMessageType = arguments[1]; + }, + }; + + const mapRenderer = new AppRenderer(myLogger); + + $(document).ready(function () { + /// Build TREE scene + mapRenderer.init(); + + /// Handle file pick + $("#filePicker").change(function (evt) { + const file = evt.target.files[0]; + // Disable button + $("#filePicker").prop("disabled", true); + + mapRenderer.createLocalReader(file, onReaderCreated); + }); + + /// Handle button click + $("#loadMapBtn").click(onLoadMapClick); + }); + + /// Callback for when the LocalReader has finished setting up! + async function onReaderCreated() { + const mapFileList = await mapRenderer.getMapList(); + const categoryList = mapFileList.reduce((list, map) => { + if (!list.includes(map.category)) { + list.push(map.category); + } + return list; + }, []); + for (const category of categoryList) { + const opt = document.createElement("option"); + opt.disabled = true; + opt.innerHTML = category; + $("#fileMapSelect").append(opt); + + for (const map of mapFileList.filter((m) => m.category === category)) { + const opt = document.createElement("option"); + opt.value = map.baseId; + opt.innerHTML = map.name; // whatever property it has + if (map.baseId === 294938) { + opt.setAttribute("selected", true); + } + + // then append it to the select element + $("#fileMapSelect").append(opt); + } + } + + $("#fileMapSelect").removeAttr("disabled"); + $("#loadMapBtn").removeAttr("disabled"); + } + + /// The insterresting part! + function onLoadMapClick() { + $("#loadMapBtn").prop("disabled", true); + $("#loadCollBtn").click(loadCollModels); + $("#loadCollBtn").removeAttr("disabled"); + $("#loadPropsBtn").click(loadPropModels); + $("#loadPropsBtn").removeAttr("disabled"); + $("#loadZoneBtn").click(loadZoneModels); + $("#loadZoneBtn").removeAttr("disabled"); + $("#mvntSpeedRange").removeAttr("disabled"); + $("#mvntSpeedRange").change((event) => mapRenderer.setMovementSpeed(event.target.valueAsNumber)); + $("#fogRange").removeAttr("disabled"); + $("#fogRange").change((event) => { + mapRenderer.setFog(event.target.valueAsNumber); + }); + $("#controllerReset").click(() => mapRenderer.setupController()); + $("#controllerReset").removeAttr("disabled"); + + $("canvas").on("wheel", onMouseWheel); + + mapRenderer.loadMap($("#fileMapSelect").val()); + + $("#fileMapSelect").prop("disabled", true); + + /// Setup the logger (hacky way because very verbose) + T3D.Logger.logFunctions[T3D.Logger.TYPE_PROGRESS] = function () { + myLogger.log(arguments[0], arguments[0], arguments[1]); + console.log(arguments[0], arguments[1]); + }; + } + + /// Action when the load zone props button is clicked + function loadZoneModels() { + const buttonId = "#loadZoneBtn"; + if (!mapRenderer.isZoneModelsLoaded()) { + mapRenderer.loadZoneModels(function () { + mapRenderer.toggleZoneModels(); + $(buttonId)[0].innerHTML = $(buttonId)[0].innerHTML.replace("Load", "Unload"); + }); + } else { + mapRenderer.toggleZoneModels(); + $(buttonId)[0].innerHTML = $(buttonId)[0].innerHTML.replace("Unload", "Load"); + } + } + + /// Action when the load props button is clicked + function loadPropModels() { + const buttonId = "#loadPropsBtn"; + if (!mapRenderer.isPropModelsLoaded()) { + mapRenderer.loadPropModels(function () { + mapRenderer.togglePropModels(); + $(buttonId)[0].innerHTML = $(buttonId)[0].innerHTML.replace("Load", "Unload"); + }); + } else { + mapRenderer.togglePropModels(); + $(buttonId)[0].innerHTML = $(buttonId)[0].innerHTML.replace("Unload", "Load"); + } + } + + /// Action when the load collisions button is clicked + function loadCollModels() { + const buttonId = "#loadCollBtn"; + if (!mapRenderer.isCollModelsLoaded()) { + mapRenderer.loadCollModels(function () { + mapRenderer.toggleCollModels(); + $(buttonId)[0].innerHTML = $(buttonId)[0].innerHTML.replace("Load", "Unload"); + }); + } else { + mapRenderer.toggleCollModels(); + $(buttonId)[0].innerHTML = $(buttonId)[0].innerHTML.replace("Unload", "Load"); + } + } + + function onMouseWheel(event) { + let newSpeed; + if (event.originalEvent.deltaY < 0) { + newSpeed = Math.min(mapRenderer.getMovementSpeed() + 100, 10000); + } else { + newSpeed = Math.max(mapRenderer.getMovementSpeed() - 100, 500); + } + mapRenderer.setMovementSpeed(newSpeed); + $("#mvntSpeedRange").val(newSpeed); + } + + return MapExplorer; + +})(); +//# sourceMappingURL=index.js.map diff --git a/examples/MapExplorer/index.js.map b/examples/MapExplorer/index.js.map new file mode 100644 index 0000000..748185e --- /dev/null +++ b/examples/MapExplorer/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sources":["../../src/MapExplorer/renderer.js","../../src/MapExplorer/index.js"],"sourcesContent":["class AppRenderer {\n constructor(logger) {\n this.logger = logger;\n\n /// This example is very inspired by the ModelRenderer example but updated\n /// using the latest version of the API. This global object for the app contains\n /// all the important data.\n\n /// All renderers must have access to a LocalReader.\n /// The LocalReader is the object that allows us\n /// to read from the .dat\n this.localReader = null;\n\n /// The context is an object all the renderer outputs their data to\n this.context = null;\n\n /// THREE js objects\n this.scene = null;\n this.skyScene = null;\n this.camera = null;\n this.skyCamera = null;\n this.renderer = null;\n this.clock = null;\n this.mouse = null;\n this.controls = null;\n this.controlsEnabled = false;\n\n /// Data:\n this._cleanMapData();\n }\n\n /**\n * Public methods\n */\n createLocalReader(file, callback) {\n this.localReader = T3D.getLocalReader(file, callback, \"../static/t3dworker.js\", this.logger);\n }\n\n getMapList() {\n return this.localReader.getMapList();\n }\n\n // Setup schene\n init() {\n const canvasWidth = window.innerWidth;\n const canvasHeight = window.innerHeight;\n const canvasClearColor = 0x342920; // For happy rendering, always use Van Dyke Brown.\n const fov = 60;\n const aspect = canvasWidth / canvasHeight;\n const fogDistance = Number($(\"#fogRange\").val());\n\n this.camera = new THREE.PerspectiveCamera(fov, aspect, 0.1, 100000);\n this.skyCamera = new THREE.PerspectiveCamera(fov, aspect, 0.1, 1000000);\n this.scene = new THREE.Scene();\n this.skyScene = new THREE.Scene();\n this.mouse = new THREE.Vector2();\n\n this.clock = new THREE.Clock();\n /// This scene has one ambient light source and three directional lights\n const ambientLight = new THREE.AmbientLight(0x555555);\n this.scene.add(ambientLight);\n\n const directionalLight1 = new THREE.DirectionalLight(0xffffff, 0.5);\n directionalLight1.position.set(0, 0, 1);\n this.scene.add(directionalLight1);\n\n const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.5);\n directionalLight2.position.set(1, 0, 0);\n this.scene.add(directionalLight2);\n\n const directionalLight3 = new THREE.DirectionalLight(0xffffff, 0.5);\n directionalLight3.position.set(0, 1, 0);\n this.scene.add(directionalLight3);\n\n // Fog\n this.scene.fog = new THREE.Fog(0xffffff, fogDistance, fogDistance + 1000);\n this.camera.far = fogDistance + 1000;\n this.camera.updateProjectionMatrix();\n\n /// Standard THREE renderer with AA\n this.renderer = new THREE.WebGLRenderer({\n antialiasing: true,\n logarithmicDepthBuffer: true,\n sortObjects: false,\n stencil: false,\n premultipliedAlpha: false,\n });\n this.renderer.autoClear = false;\n document.body.appendChild(this.renderer.domElement);\n this.renderer.setSize(canvasWidth, canvasHeight);\n this.renderer.setClearColor(canvasClearColor);\n\n window.addEventListener(\"resize\", () => {\n const SCREEN_HEIGHT = window.innerHeight;\n const SCREEN_WIDTH = window.innerWidth;\n\n this.camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT;\n this.camera.updateProjectionMatrix();\n this.skyCamera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT;\n this.skyCamera.updateProjectionMatrix();\n\n this.renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);\n });\n\n this.setupController();\n\n /// Note: constant continous rendering from page load\n this._render();\n }\n\n isCollModelsLoaded() {\n this.mapData.collision.loaded;\n }\n\n isPropModelsLoaded() {\n return this.mapData.props.loaded;\n }\n\n isZoneModelsLoaded() {\n return this.mapData.zone.loaded;\n }\n\n loadMap(mapId) {\n // Clean previous render states\n this._cleanMapData();\n this.mapData.id = mapId;\n\n /// Renderer settings (see the documentation of each Renderer for details)\n const renderers = [\n {\n renderClass: T3D.EnvironmentRenderer,\n settings: {},\n },\n {\n renderClass: T3D.TerrainRenderer,\n settings: {},\n },\n ];\n /// Load for the first time the renderer and spawn the context\n T3D.renderMapContentsAsync(\n this.localReader,\n this.mapData.id,\n renderers,\n (context) => {\n this._onRendererDone(context);\n },\n this.logger\n );\n\n // Cache mapFile for later use\n if (parseInt(this.mapData.id)) {\n this.localReader.loadFile(this.mapData.id, (arrayBuffer) => {\n this.mapData.mapFile = new T3DParser.FileParser(arrayBuffer);\n });\n }\n }\n\n loadZoneModels(callback) {\n this._loadMeshes(T3D.ZoneRenderer, this.mapData.zone, callback);\n }\n\n loadPropModels(callback) {\n this._loadMeshes(T3D.PropertiesRenderer, this.mapData.props, callback);\n }\n\n loadCollModels(callback) {\n this._loadMeshes(T3D.HavokRenderer, this.mapData.collision, callback);\n }\n\n setFog(fogDistance) {\n if (this.scene && this.scene.fog) {\n this.scene.fog.near = fogDistance;\n this.scene.fog.far = fogDistance + 1000;\n }\n if (this.camera) {\n this.camera.far = fogDistance + 1000;\n this.camera.updateProjectionMatrix();\n }\n }\n\n setMovementSpeed(speed) {\n if (this.controls) {\n this.controls.movementSpeed = speed;\n }\n }\n\n getMovementSpeed() {\n if (this.controls) {\n return this.controls.movementSpeed;\n }\n\n return 0;\n }\n\n toggleZoneModels() {\n return this._toggleModels(\"zone\");\n }\n\n togglePropModels() {\n return this._toggleModels(\"props\");\n }\n\n toggleCollModels() {\n return this._toggleModels(\"collision\");\n }\n\n /**\n * Private methods\n */\n\n _cleanMapData() {\n this.mapData = {\n id: null,\n mapFile: null,\n terrain: {\n data: [],\n },\n collision: {\n enabled: false,\n loaded: false,\n data: [],\n },\n props: {\n enabled: false,\n loaded: false,\n data: [],\n },\n zone: {\n enabled: false,\n loaded: false,\n data: [],\n },\n };\n }\n\n /// Wipes out the data\n _cleanScene() {\n for (const type of [\"terrain\", \"props\", \"zone\", \"collision\"]) {\n for (const elem of this.mapData[type].data) {\n this.scene.remove(elem);\n }\n this.mapData[type].data = [];\n }\n\n for (const type of [\"props\", \"zone\", \"collision\"]) {\n this.mapData[type].loaded = false;\n this.mapData[type].enabled = false;\n }\n }\n\n /// Run a renderer manually and populates the data object\n _loadMeshes(rendererClass, outRendererData, callback) {\n T3D.runRenderer(\n rendererClass,\n this.localReader,\n { visible: true, mapFile: this.mapData.mapFile, showUnmaterialized: false },\n this.context,\n () => {\n outRendererData.data = T3D.getContextValue(this.context, rendererClass, \"meshes\");\n outRendererData.loaded = true;\n callback();\n }\n );\n }\n\n setupController() {\n if (this.controls) {\n this.controls.dispose();\n }\n\n const controls = new THREE.FlyControls(this.camera, this.renderer.domElement);\n\n controls.movementSpeed = Number($(\"#mvntSpeedRange\").val()) | 1000;\n controls.domElement = this.renderer.domElement;\n controls.rollSpeed = Math.PI / 6;\n controls.autoForward = false;\n controls.dragToLook = true;\n this.controls = controls;\n }\n\n _render() {\n global.stats.update();\n window.requestAnimationFrame(() => this._render());\n\n const delta = this.clock.getDelta();\n this.controls.update(delta);\n\n // Render first skyCamera\n this.skyCamera.quaternion.copy(this.camera.quaternion);\n this.renderer.clear(this.renderer.getClearColor());\n this.renderer.render(this.skyScene, this.skyCamera);\n\n this.renderer.render(this.scene, this.camera);\n }\n\n _toggleModels(meshType) {\n if (this.mapData[meshType].enabled) {\n for (const elem of this.mapData[meshType].data) {\n this.scene.remove(elem);\n }\n this.mapData[meshType].enabled = false;\n return false;\n } else {\n for (const elem of this.mapData[meshType].data) {\n this.scene.add(elem);\n }\n this.mapData[meshType].enabled = true;\n return true;\n }\n }\n\n /// Runs when the ModelRenderer is finished\n _onRendererDone(context) {\n this._cleanScene();\n\n /// Populate our context with the context returned\n this.context = context;\n\n /// Take all the terrain tiles generated by the TerrainRenderer and add them to the scene\n for (const elem of T3D.getContextValue(context, T3D.TerrainRenderer, \"terrainTiles\")) {\n this.scene.add(elem);\n this.mapData.terrain.data.push(elem);\n }\n\n /// Skybox\n const skyBox = T3D.getContextValue(context, T3D.EnvironmentRenderer, \"skyBox\");\n this.skyScene.add(skyBox);\n const hazeColor = T3D.getContextValue(context, T3D.EnvironmentRenderer, \"hazeColor\");\n if (hazeColor) {\n this.renderer.setClearColor(new THREE.Color(hazeColor[2] / 255, hazeColor[1] / 255, hazeColor[0] / 255));\n }\n\n /// Add the water level to the scene\n const water = T3D.getContextValue(context, T3D.TerrainRenderer, \"water\");\n this.scene.add(water);\n this.mapData.terrain.data.push(water);\n\n /// Move the camera initial place depending on the map bounds\n const bounds = T3D.getContextValue(context, T3D.TerrainRenderer, \"bounds\");\n this.camera.position.x = 0;\n this.camera.position.y = bounds ? bounds.y2 : 0;\n this.camera.position.z = 0;\n this.camera.rotation.x = (-90 * Math.PI) / 180;\n }\n}\n\nmodule.exports = AppRenderer;\n","const AppRenderer = require(\"./renderer\");\n\nconst stats = new Stats();\n$(\"body\").append(stats.domElement);\n$(stats.domElement).hide();\nstats.toggle = () => $(stats.domElement).toggle();\nglobal.stats = stats;\n\n/// Extend Original Logger\nconst myLogger = {\n lastMessageType: null,\n log: function () {\n const htmlOutput = $(\"#log\");\n const str = Array.prototype.slice.call(arguments, 1).join(\" \");\n if (arguments[1] === myLogger.lastMessageType) {\n $(\"#log p:last-of-type\")[0].innerHTML = str;\n } else {\n htmlOutput.append($(\"

-------------

\"));\n htmlOutput.append($(\"

\" + str + \"

\"));\n }\n htmlOutput[0].scrollTop = htmlOutput[0].scrollHeight;\n myLogger.lastMessageType = arguments[1];\n },\n};\n\nconst mapRenderer = new AppRenderer(myLogger);\n\n$(document).ready(function () {\n /// Build TREE scene\n mapRenderer.init();\n\n /// Handle file pick\n $(\"#filePicker\").change(function (evt) {\n const file = evt.target.files[0];\n // Disable button\n $(\"#filePicker\").prop(\"disabled\", true);\n\n mapRenderer.createLocalReader(file, onReaderCreated);\n });\n\n /// Handle button click\n $(\"#loadMapBtn\").click(onLoadMapClick);\n});\n\n/// Callback for when the LocalReader has finished setting up!\nasync function onReaderCreated() {\n const mapFileList = await mapRenderer.getMapList();\n const categoryList = mapFileList.reduce((list, map) => {\n if (!list.includes(map.category)) {\n list.push(map.category);\n }\n return list;\n }, []);\n for (const category of categoryList) {\n const opt = document.createElement(\"option\");\n opt.disabled = true;\n opt.innerHTML = category;\n $(\"#fileMapSelect\").append(opt);\n\n for (const map of mapFileList.filter((m) => m.category === category)) {\n const opt = document.createElement(\"option\");\n opt.value = map.baseId;\n opt.innerHTML = map.name; // whatever property it has\n if (map.baseId === 294938) {\n opt.setAttribute(\"selected\", true);\n }\n\n // then append it to the select element\n $(\"#fileMapSelect\").append(opt);\n }\n }\n\n $(\"#fileMapSelect\").removeAttr(\"disabled\");\n $(\"#loadMapBtn\").removeAttr(\"disabled\");\n}\n\n/// The insterresting part!\nfunction onLoadMapClick() {\n $(\"#loadMapBtn\").prop(\"disabled\", true);\n $(\"#loadCollBtn\").click(loadCollModels);\n $(\"#loadCollBtn\").removeAttr(\"disabled\");\n $(\"#loadPropsBtn\").click(loadPropModels);\n $(\"#loadPropsBtn\").removeAttr(\"disabled\");\n $(\"#loadZoneBtn\").click(loadZoneModels);\n $(\"#loadZoneBtn\").removeAttr(\"disabled\");\n $(\"#mvntSpeedRange\").removeAttr(\"disabled\");\n $(\"#mvntSpeedRange\").change((event) => mapRenderer.setMovementSpeed(event.target.valueAsNumber));\n $(\"#fogRange\").removeAttr(\"disabled\");\n $(\"#fogRange\").change((event) => {\n mapRenderer.setFog(event.target.valueAsNumber);\n });\n $(\"#controllerReset\").click(() => mapRenderer.setupController());\n $(\"#controllerReset\").removeAttr(\"disabled\");\n\n $(\"canvas\").on(\"wheel\", onMouseWheel);\n\n mapRenderer.loadMap($(\"#fileMapSelect\").val());\n\n $(\"#fileMapSelect\").prop(\"disabled\", true);\n\n /// Setup the logger (hacky way because very verbose)\n T3D.Logger.logFunctions[T3D.Logger.TYPE_PROGRESS] = function () {\n myLogger.log(arguments[0], arguments[0], arguments[1]);\n console.log(arguments[0], arguments[1]);\n };\n}\n\n/// Action when the load zone props button is clicked\nfunction loadZoneModels() {\n const buttonId = \"#loadZoneBtn\";\n if (!mapRenderer.isZoneModelsLoaded()) {\n mapRenderer.loadZoneModels(function () {\n mapRenderer.toggleZoneModels();\n $(buttonId)[0].innerHTML = $(buttonId)[0].innerHTML.replace(\"Load\", \"Unload\");\n });\n } else {\n mapRenderer.toggleZoneModels();\n $(buttonId)[0].innerHTML = $(buttonId)[0].innerHTML.replace(\"Unload\", \"Load\");\n }\n}\n\n/// Action when the load props button is clicked\nfunction loadPropModels() {\n const buttonId = \"#loadPropsBtn\";\n if (!mapRenderer.isPropModelsLoaded()) {\n mapRenderer.loadPropModels(function () {\n mapRenderer.togglePropModels();\n $(buttonId)[0].innerHTML = $(buttonId)[0].innerHTML.replace(\"Load\", \"Unload\");\n });\n } else {\n mapRenderer.togglePropModels();\n $(buttonId)[0].innerHTML = $(buttonId)[0].innerHTML.replace(\"Unload\", \"Load\");\n }\n}\n\n/// Action when the load collisions button is clicked\nfunction loadCollModels() {\n const buttonId = \"#loadCollBtn\";\n if (!mapRenderer.isCollModelsLoaded()) {\n mapRenderer.loadCollModels(function () {\n mapRenderer.toggleCollModels();\n $(buttonId)[0].innerHTML = $(buttonId)[0].innerHTML.replace(\"Load\", \"Unload\");\n });\n } else {\n mapRenderer.toggleCollModels();\n $(buttonId)[0].innerHTML = $(buttonId)[0].innerHTML.replace(\"Unload\", \"Load\");\n }\n}\n\nfunction onMouseWheel(event) {\n let newSpeed;\n if (event.originalEvent.deltaY < 0) {\n newSpeed = Math.min(mapRenderer.getMovementSpeed() + 100, 10000);\n } else {\n newSpeed = Math.max(mapRenderer.getMovementSpeed() - 100, 500);\n }\n mapRenderer.setMovementSpeed(newSpeed);\n $(\"#mvntSpeedRange\").val(newSpeed);\n}\n"],"names":["global","AppRenderer","require$$0"],"mappings":";;;;;;;qBAAA,MAAM,WAAW,CAAC;CAClB,EAAE,WAAW,CAAC,MAAM,EAAE;CACtB,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;AACzB;CACA;CACA;CACA;AACA;CACA;CACA;CACA;CACA,IAAI,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;AAC5B;CACA;CACA,IAAI,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;AACxB;CACA;CACA,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;CACtB,IAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;CACzB,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;CACvB,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;CAC1B,IAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;CACzB,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;CACtB,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;CACtB,IAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;CACzB,IAAI,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;AACjC;CACA;CACA,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;CACzB,GAAG;AACH;CACA;CACA;CACA;CACA,EAAE,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE;CACpC,IAAI,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,wBAAwB,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;CACjG,GAAG;AACH;CACA,EAAE,UAAU,GAAG;CACf,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;CACzC,GAAG;AACH;CACA;CACA,EAAE,IAAI,GAAG;CACT,IAAI,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC;CAC1C,IAAI,MAAM,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC;CAC5C,IAAI,MAAM,gBAAgB,GAAG,QAAQ,CAAC;CACtC,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC;CACnB,IAAI,MAAM,MAAM,GAAG,WAAW,GAAG,YAAY,CAAC;CAC9C,IAAI,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;AACrD;CACA,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,KAAK,CAAC,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;CACxE,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,KAAK,CAAC,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;CAC5E,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;CACnC,IAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;CACtC,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;AACrC;CACA,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;CACnC;CACA,IAAI,MAAM,YAAY,GAAG,IAAI,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;CAC1D,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AACjC;CACA,IAAI,MAAM,iBAAiB,GAAG,IAAI,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;CACxE,IAAI,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;CAC5C,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AACtC;CACA,IAAI,MAAM,iBAAiB,GAAG,IAAI,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;CACxE,IAAI,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;CAC5C,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AACtC;CACA,IAAI,MAAM,iBAAiB,GAAG,IAAI,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;CACxE,IAAI,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;CAC5C,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AACtC;CACA;CACA,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC,CAAC;CAC9E,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,WAAW,GAAG,IAAI,CAAC;CACzC,IAAI,IAAI,CAAC,MAAM,CAAC,sBAAsB,EAAE,CAAC;AACzC;CACA;CACA,IAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC;CAC5C,MAAM,YAAY,EAAE,IAAI;CACxB,MAAM,sBAAsB,EAAE,IAAI;CAClC,MAAM,WAAW,EAAE,KAAK;CACxB,MAAM,OAAO,EAAE,KAAK;CACpB,MAAM,kBAAkB,EAAE,KAAK;CAC/B,KAAK,CAAC,CAAC;CACP,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,GAAG,KAAK,CAAC;CACpC,IAAI,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;CACxD,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;CACrD,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC;AAClD;CACA,IAAI,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM;CAC5C,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,WAAW,CAAC;CAC/C,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,UAAU,CAAC;AAC7C;CACA,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,YAAY,GAAG,aAAa,CAAC;CACxD,MAAM,IAAI,CAAC,MAAM,CAAC,sBAAsB,EAAE,CAAC;CAC3C,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,YAAY,GAAG,aAAa,CAAC;CAC3D,MAAM,IAAI,CAAC,SAAS,CAAC,sBAAsB,EAAE,CAAC;AAC9C;CACA,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;CACzD,KAAK,CAAC,CAAC;AACP;CACA,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;AAC3B;CACA;CACA,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;CACnB,GAAG;AACH;CACA,EAAE,kBAAkB,GAAG;CACvB,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC;CAClC,GAAG;AACH;CACA,EAAE,kBAAkB,GAAG;CACvB,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC;CACrC,GAAG;AACH;CACA,EAAE,kBAAkB,GAAG;CACvB,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;CACpC,GAAG;AACH;CACA,EAAE,OAAO,CAAC,KAAK,EAAE;CACjB;CACA,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;CACzB,IAAI,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG,KAAK,CAAC;AAC5B;CACA;CACA,IAAI,MAAM,SAAS,GAAG;CACtB,MAAM;CACN,QAAQ,WAAW,EAAE,GAAG,CAAC,mBAAmB;CAC5C,QAAQ,QAAQ,EAAE,EAAE;CACpB,OAAO;CACP,MAAM;CACN,QAAQ,WAAW,EAAE,GAAG,CAAC,eAAe;CACxC,QAAQ,QAAQ,EAAE,EAAE;CACpB,OAAO;CACP,KAAK,CAAC;CACN;CACA,IAAI,GAAG,CAAC,sBAAsB;CAC9B,MAAM,IAAI,CAAC,WAAW;CACtB,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE;CACrB,MAAM,SAAS;CACf,MAAM,CAAC,OAAO,KAAK;CACnB,QAAQ,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;CACtC,OAAO;CACP,MAAM,IAAI,CAAC,MAAM;CACjB,KAAK,CAAC;AACN;CACA;CACA,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;CACnC,MAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,WAAW,KAAK;CAClE,QAAQ,IAAI,CAAC,OAAO,CAAC,OAAO,GAAG,IAAI,SAAS,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;CACrE,OAAO,CAAC,CAAC;CACT,KAAK;CACL,GAAG;AACH;CACA,EAAE,cAAc,CAAC,QAAQ,EAAE;CAC3B,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;CACpE,GAAG;AACH;CACA,EAAE,cAAc,CAAC,QAAQ,EAAE;CAC3B,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;CAC3E,GAAG;AACH;CACA,EAAE,cAAc,CAAC,QAAQ,EAAE;CAC3B,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;CAC1E,GAAG;AACH;CACA,EAAE,MAAM,CAAC,WAAW,EAAE;CACtB,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;CACtC,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,WAAW,CAAC;CACxC,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,WAAW,GAAG,IAAI,CAAC;CAC9C,KAAK;CACL,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE;CACrB,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,WAAW,GAAG,IAAI,CAAC;CAC3C,MAAM,IAAI,CAAC,MAAM,CAAC,sBAAsB,EAAE,CAAC;CAC3C,KAAK;CACL,GAAG;AACH;CACA,EAAE,gBAAgB,CAAC,KAAK,EAAE;CAC1B,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE;CACvB,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,GAAG,KAAK,CAAC;CAC1C,KAAK;CACL,GAAG;AACH;CACA,EAAE,gBAAgB,GAAG;CACrB,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE;CACvB,MAAM,OAAO,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC;CACzC,KAAK;AACL;CACA,IAAI,OAAO,CAAC,CAAC;CACb,GAAG;AACH;CACA,EAAE,gBAAgB,GAAG;CACrB,IAAI,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;CACtC,GAAG;AACH;CACA,EAAE,gBAAgB,GAAG;CACrB,IAAI,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;CACvC,GAAG;AACH;CACA,EAAE,gBAAgB,GAAG;CACrB,IAAI,OAAO,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;CAC3C,GAAG;AACH;CACA;CACA;CACA;AACA;CACA,EAAE,aAAa,GAAG;CAClB,IAAI,IAAI,CAAC,OAAO,GAAG;CACnB,MAAM,EAAE,EAAE,IAAI;CACd,MAAM,OAAO,EAAE,IAAI;CACnB,MAAM,OAAO,EAAE;CACf,QAAQ,IAAI,EAAE,EAAE;CAChB,OAAO;CACP,MAAM,SAAS,EAAE;CACjB,QAAQ,OAAO,EAAE,KAAK;CACtB,QAAQ,MAAM,EAAE,KAAK;CACrB,QAAQ,IAAI,EAAE,EAAE;CAChB,OAAO;CACP,MAAM,KAAK,EAAE;CACb,QAAQ,OAAO,EAAE,KAAK;CACtB,QAAQ,MAAM,EAAE,KAAK;CACrB,QAAQ,IAAI,EAAE,EAAE;CAChB,OAAO;CACP,MAAM,IAAI,EAAE;CACZ,QAAQ,OAAO,EAAE,KAAK;CACtB,QAAQ,MAAM,EAAE,KAAK;CACrB,QAAQ,IAAI,EAAE,EAAE;CAChB,OAAO;CACP,KAAK,CAAC;CACN,GAAG;AACH;CACA;CACA,EAAE,WAAW,GAAG;CAChB,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE;CAClE,MAAM,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE;CAClD,QAAQ,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;CAChC,OAAO;CACP,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC;CACnC,KAAK;AACL;CACA,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE;CACvD,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,KAAK,CAAC;CACxC,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC;CACzC,KAAK;CACL,GAAG;AACH;CACA;CACA,EAAE,WAAW,CAAC,aAAa,EAAE,eAAe,EAAE,QAAQ,EAAE;CACxD,IAAI,GAAG,CAAC,WAAW;CACnB,MAAM,aAAa;CACnB,MAAM,IAAI,CAAC,WAAW;CACtB,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE;CACjF,MAAM,IAAI,CAAC,OAAO;CAClB,MAAM,MAAM;CACZ,QAAQ,eAAe,CAAC,IAAI,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;CAC1F,QAAQ,eAAe,CAAC,MAAM,GAAG,IAAI,CAAC;CACtC,QAAQ,QAAQ,EAAE,CAAC;CACnB,OAAO;CACP,KAAK,CAAC;CACN,GAAG;AACH;CACA,EAAE,eAAe,GAAG;CACpB,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE;CACvB,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;CAC9B,KAAK;AACL;CACA,IAAI,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;AAClF;CACA,IAAI,QAAQ,CAAC,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC;CACvE,IAAI,QAAQ,CAAC,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;CACnD,IAAI,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;CACrC,IAAI,QAAQ,CAAC,WAAW,GAAG,KAAK,CAAC;CACjC,IAAI,QAAQ,CAAC,UAAU,GAAG,IAAI,CAAC;CAC/B,IAAI,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;CAC7B,GAAG;AACH;CACA,EAAE,OAAO,GAAG;CACZ,IAAIA,cAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;CAC1B,IAAI,MAAM,CAAC,qBAAqB,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;AACvD;CACA,IAAI,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;CACxC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChC;CACA;CACA,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;CAC3D,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;CACvD,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;AACxD;CACA,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;CAClD,GAAG;AACH;CACA,EAAE,aAAa,CAAC,QAAQ,EAAE;CAC1B,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE;CACxC,MAAM,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE;CACtD,QAAQ,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;CAChC,OAAO;CACP,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC;CAC7C,MAAM,OAAO,KAAK,CAAC;CACnB,KAAK,MAAM;CACX,MAAM,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE;CACtD,QAAQ,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;CAC7B,OAAO;CACP,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC;CAC5C,MAAM,OAAO,IAAI,CAAC;CAClB,KAAK;CACL,GAAG;AACH;CACA;CACA,EAAE,eAAe,CAAC,OAAO,EAAE;CAC3B,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;AACvB;CACA;CACA,IAAI,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;AAC3B;CACA;CACA,IAAI,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,eAAe,EAAE,cAAc,CAAC,EAAE;CAC1F,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;CAC3B,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;CAC3C,KAAK;AACL;CACA;CACA,IAAI,MAAM,MAAM,GAAG,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC;CACnF,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;CAC9B,IAAI,MAAM,SAAS,GAAG,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAC;CACzF,IAAI,IAAI,SAAS,EAAE;CACnB,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;CAC/G,KAAK;AACL;CACA;CACA,IAAI,MAAM,KAAK,GAAG,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;CAC7E,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;CAC1B,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC1C;CACA;CACA,IAAI,MAAM,MAAM,GAAG,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;CAC/E,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC;CAC/B,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;CACpD,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC;CAC/B,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,IAAI,GAAG,CAAC;CACnD,GAAG;CACH,EAAC;AACD;CACA,IAAA,QAAc,GAAGC,aAAW;;CC1V5B,MAAM,WAAW,GAAGC,QAAqB,CAAC;AAC1C;CACA,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;CAC1B,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;CACnC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;CAC3B,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE,CAAC;AAClDF,eAAM,CAAC,KAAK,GAAG,KAAK,CAAC;AACrB;CACA;CACA,MAAM,QAAQ,GAAG;CACjB,EAAE,eAAe,EAAE,IAAI;CACvB,EAAE,GAAG,EAAE,YAAY;CACnB,IAAI,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;CACjC,IAAI,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;CACnE,IAAI,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,eAAe,EAAE;CACnD,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC;CAClD,KAAK,MAAM;CACX,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC;CACnD,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC;CACjD,KAAK;CACL,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;CACzD,IAAI,QAAQ,CAAC,eAAe,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;CAC5C,GAAG;CACH,CAAC,CAAC;AACF;CACA,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC;AAC9C;CACA,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,YAAY;CAC9B;CACA,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC;AACrB;CACA;CACA,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,UAAU,GAAG,EAAE;CACzC,IAAI,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;CACrC;CACA,IAAI,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AAC5C;CACA,IAAI,WAAW,CAAC,iBAAiB,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;CACzD,GAAG,CAAC,CAAC;AACL;CACA;CACA,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;CACzC,CAAC,CAAC,CAAC;AACH;CACA;CACA,eAAe,eAAe,GAAG;CACjC,EAAE,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,UAAU,EAAE,CAAC;CACrD,EAAE,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,GAAG,KAAK;CACzD,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;CACtC,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;CAC9B,KAAK;CACL,IAAI,OAAO,IAAI,CAAC;CAChB,GAAG,EAAE,EAAE,CAAC,CAAC;CACT,EAAE,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE;CACvC,IAAI,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;CACjD,IAAI,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC;CACxB,IAAI,GAAG,CAAC,SAAS,GAAG,QAAQ,CAAC;CAC7B,IAAI,CAAC,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AACpC;CACA,IAAI,KAAK,MAAM,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,EAAE;CAC1E,MAAM,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;CACnD,MAAM,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC;CAC7B,MAAM,GAAG,CAAC,SAAS,GAAG,GAAG,CAAC,IAAI,CAAC;CAC/B,MAAM,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE;CACjC,QAAQ,GAAG,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;CAC3C,OAAO;AACP;CACA;CACA,MAAM,CAAC,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;CACtC,KAAK;CACL,GAAG;AACH;CACA,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;CAC7C,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;CAC1C,CAAC;AACD;CACA;CACA,SAAS,cAAc,GAAG;CAC1B,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;CAC1C,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;CAC1C,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;CAC3C,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;CAC3C,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;CAC5C,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;CAC1C,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;CAC3C,EAAE,CAAC,CAAC,iBAAiB,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;CAC9C,EAAE,CAAC,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,WAAW,CAAC,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;CACnG,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;CACxC,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK;CACnC,IAAI,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;CACnD,GAAG,CAAC,CAAC;CACL,EAAE,CAAC,CAAC,kBAAkB,CAAC,CAAC,KAAK,CAAC,MAAM,WAAW,CAAC,eAAe,EAAE,CAAC,CAAC;CACnE,EAAE,CAAC,CAAC,kBAAkB,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/C;CACA,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;AACxC;CACA,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;AACjD;CACA,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AAC7C;CACA;CACA,EAAE,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,YAAY;CAClE,IAAI,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;CAC3D,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;CAC5C,GAAG,CAAC;CACJ,CAAC;AACD;CACA;CACA,SAAS,cAAc,GAAG;CAC1B,EAAE,MAAM,QAAQ,GAAG,cAAc,CAAC;CAClC,EAAE,IAAI,CAAC,WAAW,CAAC,kBAAkB,EAAE,EAAE;CACzC,IAAI,WAAW,CAAC,cAAc,CAAC,YAAY;CAC3C,MAAM,WAAW,CAAC,gBAAgB,EAAE,CAAC;CACrC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACpF,KAAK,CAAC,CAAC;CACP,GAAG,MAAM;CACT,IAAI,WAAW,CAAC,gBAAgB,EAAE,CAAC;CACnC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;CAClF,GAAG;CACH,CAAC;AACD;CACA;CACA,SAAS,cAAc,GAAG;CAC1B,EAAE,MAAM,QAAQ,GAAG,eAAe,CAAC;CACnC,EAAE,IAAI,CAAC,WAAW,CAAC,kBAAkB,EAAE,EAAE;CACzC,IAAI,WAAW,CAAC,cAAc,CAAC,YAAY;CAC3C,MAAM,WAAW,CAAC,gBAAgB,EAAE,CAAC;CACrC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACpF,KAAK,CAAC,CAAC;CACP,GAAG,MAAM;CACT,IAAI,WAAW,CAAC,gBAAgB,EAAE,CAAC;CACnC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;CAClF,GAAG;CACH,CAAC;AACD;CACA;CACA,SAAS,cAAc,GAAG;CAC1B,EAAE,MAAM,QAAQ,GAAG,cAAc,CAAC;CAClC,EAAE,IAAI,CAAC,WAAW,CAAC,kBAAkB,EAAE,EAAE;CACzC,IAAI,WAAW,CAAC,cAAc,CAAC,YAAY;CAC3C,MAAM,WAAW,CAAC,gBAAgB,EAAE,CAAC;CACrC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACpF,KAAK,CAAC,CAAC;CACP,GAAG,MAAM;CACT,IAAI,WAAW,CAAC,gBAAgB,EAAE,CAAC;CACnC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;CAClF,GAAG;CACH,CAAC;AACD;CACA,SAAS,YAAY,CAAC,KAAK,EAAE;CAC7B,EAAE,IAAI,QAAQ,CAAC;CACf,EAAE,IAAI,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE;CACtC,IAAI,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,gBAAgB,EAAE,GAAG,GAAG,EAAE,KAAK,CAAC,CAAC;CACrE,GAAG,MAAM;CACT,IAAI,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,gBAAgB,EAAE,GAAG,GAAG,EAAE,GAAG,CAAC,CAAC;CACnE,GAAG;CACH,EAAE,WAAW,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;CACzC,EAAE,CAAC,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;CACrC;;;;;;;;"} \ No newline at end of file diff --git a/examples/MapScan/index.html b/examples/MapScan/index.html new file mode 100644 index 0000000..712225b --- /dev/null +++ b/examples/MapScan/index.html @@ -0,0 +1,19 @@ + + + New LocalReader V2 API demo + + + + + + +

+

+ + + + + + diff --git a/examples/MapScan/index.js b/examples/MapScan/index.js new file mode 100644 index 0000000..a903743 --- /dev/null +++ b/examples/MapScan/index.js @@ -0,0 +1,24 @@ +(function () { + 'use strict'; + + $("#filePicker").change(onLoad); + + function onLoad(event) { + const file = event.target.files[0]; + T3D.getLocalReader(file, onLoaded, "../static/t3dworker.js"); + } + + async function onLoaded(localReader) { + $(".logs").append("Scanning archive...
"); + await localReader.readFileList(); + + $(".logs").append("Sorting maps...
"); + const maps = await localReader.getMapList(); + console.log(maps); + + $(".logs").append("Done
"); + $(".fileList").append(JSON.stringify(maps, null, 2)); + } + +})(); +//# sourceMappingURL=index.js.map diff --git a/examples/MapScan/index.js.map b/examples/MapScan/index.js.map new file mode 100644 index 0000000..1fcb9ad --- /dev/null +++ b/examples/MapScan/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sources":["../../src/MapScan/index.js"],"sourcesContent":["$(\"#filePicker\").change(onLoad);\n\nfunction onLoad(event) {\n const file = event.target.files[0];\n T3D.getLocalReader(file, onLoaded, \"../static/t3dworker.js\");\n}\n\nasync function onLoaded(localReader) {\n $(\".logs\").append(\"Scanning archive...
\");\n await localReader.readFileList();\n\n $(\".logs\").append(\"Sorting maps...
\");\n const maps = await localReader.getMapList();\n console.log(maps);\n\n $(\".logs\").append(\"Done
\");\n $(\".fileList\").append(JSON.stringify(maps, null, 2));\n}\n"],"names":[],"mappings":";;;EAAA,CAAC,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAChC;EACA,SAAS,MAAM,CAAC,KAAK,EAAE;EACvB,EAAE,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;EACrC,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,wBAAwB,CAAC,CAAC;EAC/D,CAAC;AACD;EACA,eAAe,QAAQ,CAAC,WAAW,EAAE;EACrC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC;EAChD,EAAE,MAAM,WAAW,CAAC,YAAY,EAAE,CAAC;AACnC;EACA,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;EAC5C,EAAE,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,UAAU,EAAE,CAAC;EAC9C,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACpB;EACA,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;EACjC,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;EACvD;;;;;;"} \ No newline at end of file diff --git a/examples/ModelRenderer/index.html b/examples/ModelRenderer/index.html new file mode 100644 index 0000000..6729849 --- /dev/null +++ b/examples/ModelRenderer/index.html @@ -0,0 +1,81 @@ + + + + + + T3D API - Examples : Single Model Rendering + + + +

Single Model Render

+ + + + + + +

+ Hold left mouse button and drag to orbit.
+ Hold right mouse button and drag to pan.
+ Scroll to zoom. +

+
+ + + + + + + + diff --git a/examples/ModelRenderer/index.js b/examples/ModelRenderer/index.js new file mode 100644 index 0000000..494acef --- /dev/null +++ b/examples/ModelRenderer/index.js @@ -0,0 +1,183 @@ +(function () { + 'use strict'; + + /// This is an example application for the T3D library + /// Skip down to onButtonClick to get to the juicy part + /// This will be updated sooner or later, perhaps with a + /// written guide, who knows. + + let _lr; + let _context; + let _scene; + let _camera; + let _renderer; + let _models = []; + + /// Extend Original Logger + const myLogger = { + log: function () { + const htmlOutput = $("#log"); + let i = 1; + let str = ""; + while (i < arguments.length) { + str += arguments[i]; + i++; + } + htmlOutput.append($("

" + str + "

")); + htmlOutput.append($("

-------------

")); + }, + }; + + $(document).ready(function () { + /// Build TREE scene + setupScene(); + + /// Handle file pick + $("#filePicker").change(function (evt) { + const file = evt.target.files[0]; + + _lr = T3D.getLocalReader(file, onReaderCreated, "../static/t3dworker.js", myLogger); + }); + + /// Handle button click + $("#loadModelBtn").click(onButtonClick); + }); + + /// Callback for when the LocalReader has finished setting up! + function onReaderCreated() { + $("#fileIdInput").removeAttr("disabled"); + $("#loadModelBtn").removeAttr("disabled"); + } + + /// The insterresting part! + function onButtonClick() { + /// Get selected file id + const fileId = $("#fileIdInput").val(); + + /// Let's use the SingleModelRenderer. It renders 3D stuff! + const renderClass = T3D.SingleModelRenderer; + + /// All renderers must have access to a LocalReader. + /// The LocalReader is the object that allows us + /// to read from the .dat + const localReader = _lr; + + /// The settings object is different for all renderers. + /// Accourding to documentation the SingleModelRenderer requires + /// the id of a file. + const settings = { id: fileId }; + + /// This is the value object that renderers use to write output! + /// If we ran multiple renderers that wanted to read output from + /// each other we'd have to pass this object to each Renderer! + /// Note that we'll want to access this object later, so make + /// sure it's stored in a scope we can reach from the callback + /// method. + _context = {}; + + /// The method to run when the renderer is done. Almost all + /// renderers are asynchronous since there is a lot of file + /// reading et cetera. + const callback = onRendererDone; + + /// Running a renderer takes 5 mandatory parameters! Phew! + T3D.runRenderer(renderClass, localReader, settings, _context, callback); + } + + /// Runs when the SingleModelRenderer is finshed + function onRendererDone() { + /// Remove old models from the 3D scene + _models.forEach(function (mdl) { + _scene.remove(mdl); + }); + + /// Now we want to take a look in the output object! + /// The object we told the renderer to write to was _context + const readFromContext = _context; + + /// The generator class we want output for is SingleModelRenderer + const readForClass = T3D.SingleModelRenderer; + + /// The documentation says the generated outputs are: + /// + /// meshes : An array of THREE.Mesh objects visualizing this model file. + /// + /// Lets get that one! + const nameOfValue = "meshes"; + + /// Let's go! + _models = T3D.getContextValue(readFromContext, readForClass, nameOfValue); + + /// From here on it's just THREE stuff: + + /// Keeping track of the biggest model for later + let biggestMdl = null; + + /// Add all models to the scene + _models.forEach(function (model) { + /// Find the biggest model for camera focus/fitting + if (!biggestMdl || biggestMdl.boundingSphere.radius < model.boundingSphere.radius) { + biggestMdl = model; + } + + _scene.add(model); + }); + + _camera.position.x = 200; + _camera.position.y = 50; + + /// Focus camera to the bigest model + if (biggestMdl) _camera.lookAt(biggestMdl.position); + } + + /// Basic THREE stuff, don't mind it + function setupScene() { + const canvasWidth = 500; + const canvasHeight = 500; + const canvasClearColor = 0x342920; // For happy rendering, always use Van Dyke Brown. + const fov = 60; + const aspect = 1; + const near = 0.1; + const far = 50000; + + _camera = new THREE.PerspectiveCamera(fov, aspect, near, far); + + _scene = new THREE.Scene(); + + /// This scene has one ambient light source and three directional lights + const ambientLight = new THREE.AmbientLight(0x555555); + _scene.add(ambientLight); + + const directionalLight1 = new THREE.DirectionalLight(0xffffff, 0.8); + directionalLight1.position.set(0, 0, 1); + _scene.add(directionalLight1); + + const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.8); + directionalLight2.position.set(1, 0, 0); + _scene.add(directionalLight2); + + const directionalLight3 = new THREE.DirectionalLight(0xffffff, 0.8); + directionalLight3.position.set(0, 1, 0); + _scene.add(directionalLight3); + + /// Standard THREE renderer with AA + _renderer = new THREE.WebGLRenderer({ antialiasing: true }); + document.body.appendChild(_renderer.domElement); + _renderer.setSize(canvasWidth, canvasHeight); + _renderer.setClearColor(canvasClearColor); + + /// Add THREE orbit controls, for simple orbiting, panning and zooming + const orbit = new THREE.OrbitControls(_camera, _renderer.domElement); + orbit.enableZoom = true; + + /// Note: constant continous rendering from page load + render(); + } + + function render() { + window.requestAnimationFrame(render); + _renderer.render(_scene, _camera); + } + +})(); +//# sourceMappingURL=index.js.map diff --git a/examples/ModelRenderer/index.js.map b/examples/ModelRenderer/index.js.map new file mode 100644 index 0000000..8291133 --- /dev/null +++ b/examples/ModelRenderer/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sources":["../../src/ModelRenderer/index.js"],"sourcesContent":["/// This is an example application for the T3D library\n/// Skip down to onButtonClick to get to the juicy part\n/// This will be updated sooner or later, perhaps with a\n/// written guide, who knows.\n\nlet _lr;\nlet _context;\nlet _scene;\nlet _camera;\nlet _renderer;\nlet _models = [];\n\n/// Extend Original Logger\nconst myLogger = {\n log: function () {\n const htmlOutput = $(\"#log\");\n let i = 1;\n let str = \"\";\n while (i < arguments.length) {\n str += arguments[i];\n i++;\n }\n htmlOutput.append($(\"

\" + str + \"

\"));\n htmlOutput.append($(\"

-------------

\"));\n },\n};\n\n$(document).ready(function () {\n /// Build TREE scene\n setupScene();\n\n /// Handle file pick\n $(\"#filePicker\").change(function (evt) {\n const file = evt.target.files[0];\n\n _lr = T3D.getLocalReader(file, onReaderCreated, \"../static/t3dworker.js\", myLogger);\n });\n\n /// Handle button click\n $(\"#loadModelBtn\").click(onButtonClick);\n});\n\n/// Callback for when the LocalReader has finished setting up!\nfunction onReaderCreated() {\n $(\"#fileIdInput\").removeAttr(\"disabled\");\n $(\"#loadModelBtn\").removeAttr(\"disabled\");\n}\n\n/// The insterresting part!\nfunction onButtonClick() {\n /// Get selected file id\n const fileId = $(\"#fileIdInput\").val();\n\n /// Let's use the SingleModelRenderer. It renders 3D stuff!\n const renderClass = T3D.SingleModelRenderer;\n\n /// All renderers must have access to a LocalReader.\n /// The LocalReader is the object that allows us\n /// to read from the .dat\n const localReader = _lr;\n\n /// The settings object is different for all renderers.\n /// Accourding to documentation the SingleModelRenderer requires\n /// the id of a file.\n const settings = { id: fileId };\n\n /// This is the value object that renderers use to write output!\n /// If we ran multiple renderers that wanted to read output from\n /// each other we'd have to pass this object to each Renderer!\n /// Note that we'll want to access this object later, so make\n /// sure it's stored in a scope we can reach from the callback\n /// method.\n _context = {};\n\n /// The method to run when the renderer is done. Almost all\n /// renderers are asynchronous since there is a lot of file\n /// reading et cetera.\n const callback = onRendererDone;\n\n /// Running a renderer takes 5 mandatory parameters! Phew!\n T3D.runRenderer(renderClass, localReader, settings, _context, callback);\n}\n\n/// Runs when the SingleModelRenderer is finshed\nfunction onRendererDone() {\n /// Remove old models from the 3D scene\n _models.forEach(function (mdl) {\n _scene.remove(mdl);\n });\n\n /// Now we want to take a look in the output object!\n /// The object we told the renderer to write to was _context\n const readFromContext = _context;\n\n /// The generator class we want output for is SingleModelRenderer\n const readForClass = T3D.SingleModelRenderer;\n\n /// The documentation says the generated outputs are:\n ///\n /// meshes : An array of THREE.Mesh objects visualizing this model file.\n ///\n /// Lets get that one!\n const nameOfValue = \"meshes\";\n\n /// Let's go!\n _models = T3D.getContextValue(readFromContext, readForClass, nameOfValue);\n\n /// From here on it's just THREE stuff:\n\n /// Keeping track of the biggest model for later\n let biggestMdl = null;\n\n /// Add all models to the scene\n _models.forEach(function (model) {\n /// Find the biggest model for camera focus/fitting\n if (!biggestMdl || biggestMdl.boundingSphere.radius < model.boundingSphere.radius) {\n biggestMdl = model;\n }\n\n _scene.add(model);\n });\n\n _camera.position.x = 200;\n _camera.position.y = 50;\n\n /// Focus camera to the bigest model\n if (biggestMdl) _camera.lookAt(biggestMdl.position);\n}\n\n/// Basic THREE stuff, don't mind it\nfunction setupScene() {\n const canvasWidth = 500;\n const canvasHeight = 500;\n const canvasClearColor = 0x342920; // For happy rendering, always use Van Dyke Brown.\n const fov = 60;\n const aspect = 1;\n const near = 0.1;\n const far = 50000;\n\n _camera = new THREE.PerspectiveCamera(fov, aspect, near, far);\n\n _scene = new THREE.Scene();\n\n /// This scene has one ambient light source and three directional lights\n const ambientLight = new THREE.AmbientLight(0x555555);\n _scene.add(ambientLight);\n\n const directionalLight1 = new THREE.DirectionalLight(0xffffff, 0.8);\n directionalLight1.position.set(0, 0, 1);\n _scene.add(directionalLight1);\n\n const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.8);\n directionalLight2.position.set(1, 0, 0);\n _scene.add(directionalLight2);\n\n const directionalLight3 = new THREE.DirectionalLight(0xffffff, 0.8);\n directionalLight3.position.set(0, 1, 0);\n _scene.add(directionalLight3);\n\n /// Standard THREE renderer with AA\n _renderer = new THREE.WebGLRenderer({ antialiasing: true });\n document.body.appendChild(_renderer.domElement);\n _renderer.setSize(canvasWidth, canvasHeight);\n _renderer.setClearColor(canvasClearColor);\n\n /// Add THREE orbit controls, for simple orbiting, panning and zooming\n const orbit = new THREE.OrbitControls(_camera, _renderer.domElement);\n orbit.enableZoom = true;\n\n /// Note: constant continous rendering from page load\n render();\n}\n\nfunction render() {\n window.requestAnimationFrame(render);\n _renderer.render(_scene, _camera);\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/examples/SimpleMapRenderer/index.html b/examples/SimpleMapRenderer/index.html new file mode 100644 index 0000000..8f83046 --- /dev/null +++ b/examples/SimpleMapRenderer/index.html @@ -0,0 +1,88 @@ + + + + + + T3D API - Examples : Map Rendering + + + +

Simple Map Render

+ + + + +
+ +
+ +

+ Hold left mouse button and drag to orbit.
+ Hold right mouse button and drag to pan.
+ Scroll to zoom. +

+ +
+ + + + + + + + diff --git a/examples/SimpleMapRenderer/index.js b/examples/SimpleMapRenderer/index.js new file mode 100644 index 0000000..9b5ae13 --- /dev/null +++ b/examples/SimpleMapRenderer/index.js @@ -0,0 +1,277 @@ +(function () { + 'use strict'; + + /// This example is very inspired by the ModelRenderer example but updated + /// using the latest version of the API. This global object for the app contains + /// all the important data. + const cleanMapData = { + id: null, + mapFile: null, + terrain: { + data: [], + }, + props: { + enabled: false, + loaded: false, + data: [], + }, + }; + + const mapRenderer = { + /// All renderers must have access to a LocalReader. + /// The LocalReader is the object that allows us + /// to read from the .dat + localReader: null, + + /// The context is an object all the renderer outputs their data to + context: null, + + /// THREE js objects + scene: null, + camera: null, + renderer: null, + mouse: null, + controls: null, + + /// Data: + mapData: Object.assign({}, cleanMapData), + }; + + /// Extend Original Logger + const myLogger = { + lastMessageType: null, + log: function () { + const htmlOutput = $("#log"); + const str = Array.prototype.slice.call(arguments, 1).join(" "); + if (arguments[1] === myLogger.lastMessageType) { + $("#log p:last-of-type")[0].innerHTML = str; + } else { + htmlOutput.append($("

-------------

")); + htmlOutput.append($("

" + str + "

")); + } + htmlOutput[0].scrollTop = htmlOutput[0].scrollHeight; + myLogger.lastMessageType = arguments[1]; + }, + }; + + $(document).ready(function () { + /// Build TREE scene + setupScene(); + + /// Handle file pick + $("#filePicker").change(function (evt) { + const file = evt.target.files[0]; + + mapRenderer.localReader = T3D.getLocalReader(file, onReaderCreated, "../static/t3dworker.js", myLogger); + }); + + /// Handle button click + $("#loadMapBtn").click(onLoadMapClick); + }); + + /// Callback for when the LocalReader has finished setting up! + async function onReaderCreated() { + $("#fileIdInput").removeAttr("disabled"); + $("#fileMapSelect").removeAttr("disabled"); + $("#loadMapBtn").removeAttr("disabled"); + + const opt = document.createElement("option"); + opt.value = undefined; + opt.innerHTML = ""; // whatever property it has + $("#fileMapSelect").append(opt); + + const mapFileList = await mapRenderer.localReader.getMapList(); + const categoryList = mapFileList.reduce((list, map) => { + if (!list.includes(map.category)) { + list.push(map.category); + } + return list; + }, []); + for (const category of categoryList) { + const opt = document.createElement("option"); + opt.disabled = true; + opt.innerHTML = category; + $("#fileMapSelect").append(opt); + + for (const map of mapFileList.filter((m) => m.category === category)) { + const opt = document.createElement("option"); + opt.value = map.baseId; + opt.innerHTML = map.name; // whatever property it has + + // then append it to the select element + $("#fileMapSelect").append(opt); + } + } + } + + /// The insterresting part! + function onLoadMapClick() { + // Clean previous render states + mapRenderer.mapData = Object.assign({}, cleanMapData); + + /// Get selected file id + mapRenderer.mapData.id = $("#fileIdInput").val(); + + /// Renderer settings (see the documentation of each Renderer for details) + const renderers = [ + { + renderClass: T3D.EnvironmentRenderer, + settings: {}, + }, + { + renderClass: T3D.TerrainRenderer, + settings: {}, + }, + { + renderClass: T3D.PropertiesRenderer, + settings: { + visible: true, + showUnmaterialized: true, + }, + }, + ]; + + /// Setup the logger (hacky way because very verbose) + T3D.Logger.logFunctions[T3D.Logger.TYPE_PROGRESS] = function () { + myLogger.log(arguments[0], arguments[0], arguments[1]); + console.log(arguments[0], arguments[1]); + }; + + /// Load for the first time the renderer and spawn the context + T3D.renderMapContentsAsync(mapRenderer.localReader, mapRenderer.mapData.id, renderers, onRendererDone, myLogger); + + /// And store the mapfile for future use + loadMapFile(mapRenderer.mapData.id, function (data) { + mapRenderer.mapData.mapFile = data; + }); + } + + /// Runs when the ModelRenderer is finshed + function onRendererDone(context) { + document.addEventListener("mousemove", onMouseMove, false); + cleanScene(); + + /// Populate our context with the context returned + mapRenderer.context = context; + + /// Take all the terrain tiles generated by the TerrainRenderer and add them to the scene + for (const elem of T3D.getContextValue(context, T3D.TerrainRenderer, "terrainTiles")) { + mapRenderer.scene.add(elem); + mapRenderer.mapData.terrain.data.push(elem); + } + + /// Skybox + const hazeColor = T3D.getContextValue(context, T3D.EnvironmentRenderer, "hazeColor"); + if (hazeColor) { + mapRenderer.renderer.setClearColor(new THREE.Color(hazeColor[2] / 255, hazeColor[1] / 255, hazeColor[0] / 255)); + } + + /// Add the water level to the scene + const water = T3D.getContextValue(context, T3D.TerrainRenderer, "water"); + mapRenderer.scene.add(water); + mapRenderer.mapData.terrain.data.push(water); + + /// Move the camera initial place depending on the map bounds + const bounds = T3D.getContextValue(context, T3D.TerrainRenderer, "bounds"); + mapRenderer.camera.position.x = 0; + mapRenderer.camera.position.y = bounds ? bounds.y2 : 0; + mapRenderer.camera.position.z = 0; + + /// Add all the meshes from the prop renderer + const propsMeshes = T3D.getContextValue(context, T3D.PropertiesRenderer, "meshes"); + for (const elem of propsMeshes) { + mapRenderer.scene.add(elem); + mapRenderer.mapData.props.data.push(elem); + } + } + + /// It's usually not needed to keep the mapFile independently but + /// because we're loading the colision/props/zone models manually, it is. + function loadMapFile(fileId, callback) { + if (parseInt(fileId)) { + mapRenderer.localReader.loadFile(fileId, function (arrayBuffer) { + const mapFile = new T3DParser.FileParser(arrayBuffer); + callback(mapFile); + }); + } + } + + /// Wipes out the data + function cleanScene() { + for (const type of ["terrain", "props"]) { + for (const elem of mapRenderer.mapData[type].data) { + mapRenderer.scene.remove(elem); + } + mapRenderer.mapData[type].data = []; + } + + for (const type of ["props"]) { + mapRenderer.mapData[type].loaded = false; + mapRenderer.mapData[type].enabled = false; + } + } + + function onMouseMove(event) { + const canvasBounds = mapRenderer.renderer.domElement.getBoundingClientRect(); + mapRenderer.mouse.x = ((event.clientX - canvasBounds.left) / (canvasBounds.right - canvasBounds.left)) * 2 - 1; + mapRenderer.mouse.y = -((event.clientY - canvasBounds.top) / (canvasBounds.bottom - canvasBounds.top)) * 2 + 1; + } + + /// Basic THREE stuff, don't mind it + function setupScene() { + const canvasWidth = 800; + const canvasHeight = 800; + const canvasClearColor = 0x342920; // For happy rendering, always use Van Dyke Brown. + const fov = 60; + const aspect = 1; + + mapRenderer.camera = new THREE.PerspectiveCamera(fov, aspect, 0.1, 100000); + mapRenderer.scene = new THREE.Scene(); + mapRenderer.mouse = new THREE.Vector2(); + + /// This scene has one ambient light source and three directional lights + const ambientLight = new THREE.AmbientLight(0x555555); + mapRenderer.scene.add(ambientLight); + + const directionalLight1 = new THREE.DirectionalLight(0xffffff, 0.8); + directionalLight1.position.set(0, 0, 1); + mapRenderer.scene.add(directionalLight1); + + const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.8); + directionalLight2.position.set(1, 0, 0); + mapRenderer.scene.add(directionalLight2); + + const directionalLight3 = new THREE.DirectionalLight(0xffffff, 0.8); + directionalLight3.position.set(0, 1, 0); + mapRenderer.scene.add(directionalLight3); + + /// Standard THREE renderer with AA + mapRenderer.renderer = new THREE.WebGLRenderer({ + antialiasing: true, + logarithmicDepthBuffer: true, + }); + document.body.appendChild(mapRenderer.renderer.domElement); + mapRenderer.renderer.setSize(canvasWidth, canvasHeight); + mapRenderer.renderer.setClearColor(canvasClearColor); + + setupController(); + + /// Note: constant continous rendering from page load + render(); + } + + function setupController() { + if (!mapRenderer.controls) { + const controls = new THREE.OrbitControls(mapRenderer.camera, mapRenderer.renderer.domElement); + controls.enableZoom = true; + mapRenderer.controls = controls; + } + } + + function render() { + window.requestAnimationFrame(render); + mapRenderer.renderer.render(mapRenderer.scene, mapRenderer.camera); + } + +})(); +//# sourceMappingURL=index.js.map diff --git a/examples/SimpleMapRenderer/index.js.map b/examples/SimpleMapRenderer/index.js.map new file mode 100644 index 0000000..4bfe6e0 --- /dev/null +++ b/examples/SimpleMapRenderer/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sources":["../../src/SimpleMapRenderer/index.js"],"sourcesContent":["/// This example is very inspired by the ModelRenderer example but updated\n/// using the latest version of the API. This global object for the app contains\n/// all the important data.\nconst cleanMapData = {\n id: null,\n mapFile: null,\n terrain: {\n data: [],\n },\n props: {\n enabled: false,\n loaded: false,\n data: [],\n },\n};\n\nconst mapRenderer = {\n /// All renderers must have access to a LocalReader.\n /// The LocalReader is the object that allows us\n /// to read from the .dat\n localReader: null,\n\n /// The context is an object all the renderer outputs their data to\n context: null,\n\n /// THREE js objects\n scene: null,\n camera: null,\n renderer: null,\n mouse: null,\n controls: null,\n\n /// Data:\n mapData: Object.assign({}, cleanMapData),\n};\n\n/// Extend Original Logger\nconst myLogger = {\n lastMessageType: null,\n log: function () {\n const htmlOutput = $(\"#log\");\n const str = Array.prototype.slice.call(arguments, 1).join(\" \");\n if (arguments[1] === myLogger.lastMessageType) {\n $(\"#log p:last-of-type\")[0].innerHTML = str;\n } else {\n htmlOutput.append($(\"

-------------

\"));\n htmlOutput.append($(\"

\" + str + \"

\"));\n }\n htmlOutput[0].scrollTop = htmlOutput[0].scrollHeight;\n myLogger.lastMessageType = arguments[1];\n },\n};\n\n$(document).ready(function () {\n /// Build TREE scene\n setupScene();\n\n /// Handle file pick\n $(\"#filePicker\").change(function (evt) {\n const file = evt.target.files[0];\n\n mapRenderer.localReader = T3D.getLocalReader(file, onReaderCreated, \"../static/t3dworker.js\", myLogger);\n });\n\n /// Handle button click\n $(\"#loadMapBtn\").click(onLoadMapClick);\n});\n\n/// Callback for when the LocalReader has finished setting up!\nasync function onReaderCreated() {\n $(\"#fileIdInput\").removeAttr(\"disabled\");\n $(\"#fileMapSelect\").removeAttr(\"disabled\");\n $(\"#loadMapBtn\").removeAttr(\"disabled\");\n\n const opt = document.createElement(\"option\");\n opt.value = undefined;\n opt.innerHTML = \"\"; // whatever property it has\n $(\"#fileMapSelect\").append(opt);\n\n const mapFileList = await mapRenderer.localReader.getMapList();\n const categoryList = mapFileList.reduce((list, map) => {\n if (!list.includes(map.category)) {\n list.push(map.category);\n }\n return list;\n }, []);\n for (const category of categoryList) {\n const opt = document.createElement(\"option\");\n opt.disabled = true;\n opt.innerHTML = category;\n $(\"#fileMapSelect\").append(opt);\n\n for (const map of mapFileList.filter((m) => m.category === category)) {\n const opt = document.createElement(\"option\");\n opt.value = map.baseId;\n opt.innerHTML = map.name; // whatever property it has\n\n // then append it to the select element\n $(\"#fileMapSelect\").append(opt);\n }\n }\n}\n\n/// The insterresting part!\nfunction onLoadMapClick() {\n // Clean previous render states\n mapRenderer.mapData = Object.assign({}, cleanMapData);\n\n /// Get selected file id\n mapRenderer.mapData.id = $(\"#fileIdInput\").val();\n\n /// Renderer settings (see the documentation of each Renderer for details)\n const renderers = [\n {\n renderClass: T3D.EnvironmentRenderer,\n settings: {},\n },\n {\n renderClass: T3D.TerrainRenderer,\n settings: {},\n },\n {\n renderClass: T3D.PropertiesRenderer,\n settings: {\n visible: true,\n showUnmaterialized: true,\n },\n },\n ];\n\n /// Setup the logger (hacky way because very verbose)\n T3D.Logger.logFunctions[T3D.Logger.TYPE_PROGRESS] = function () {\n myLogger.log(arguments[0], arguments[0], arguments[1]);\n console.log(arguments[0], arguments[1]);\n };\n\n /// Load for the first time the renderer and spawn the context\n T3D.renderMapContentsAsync(mapRenderer.localReader, mapRenderer.mapData.id, renderers, onRendererDone, myLogger);\n\n /// And store the mapfile for future use\n loadMapFile(mapRenderer.mapData.id, function (data) {\n mapRenderer.mapData.mapFile = data;\n });\n}\n\n/// Runs when the ModelRenderer is finshed\nfunction onRendererDone(context) {\n document.addEventListener(\"mousemove\", onMouseMove, false);\n cleanScene();\n\n /// Populate our context with the context returned\n mapRenderer.context = context;\n\n /// Take all the terrain tiles generated by the TerrainRenderer and add them to the scene\n for (const elem of T3D.getContextValue(context, T3D.TerrainRenderer, \"terrainTiles\")) {\n mapRenderer.scene.add(elem);\n mapRenderer.mapData.terrain.data.push(elem);\n }\n\n /// Skybox\n const hazeColor = T3D.getContextValue(context, T3D.EnvironmentRenderer, \"hazeColor\");\n if (hazeColor) {\n mapRenderer.renderer.setClearColor(new THREE.Color(hazeColor[2] / 255, hazeColor[1] / 255, hazeColor[0] / 255));\n }\n\n /// Add the water level to the scene\n const water = T3D.getContextValue(context, T3D.TerrainRenderer, \"water\");\n mapRenderer.scene.add(water);\n mapRenderer.mapData.terrain.data.push(water);\n\n /// Move the camera initial place depending on the map bounds\n const bounds = T3D.getContextValue(context, T3D.TerrainRenderer, \"bounds\");\n mapRenderer.camera.position.x = 0;\n mapRenderer.camera.position.y = bounds ? bounds.y2 : 0;\n mapRenderer.camera.position.z = 0;\n\n /// Add all the meshes from the prop renderer\n const propsMeshes = T3D.getContextValue(context, T3D.PropertiesRenderer, \"meshes\");\n for (const elem of propsMeshes) {\n mapRenderer.scene.add(elem);\n mapRenderer.mapData.props.data.push(elem);\n }\n}\n\n/// It's usually not needed to keep the mapFile independently but\n/// because we're loading the colision/props/zone models manually, it is.\nfunction loadMapFile(fileId, callback) {\n if (parseInt(fileId)) {\n mapRenderer.localReader.loadFile(fileId, function (arrayBuffer) {\n const mapFile = new T3DParser.FileParser(arrayBuffer);\n callback(mapFile);\n });\n }\n}\n\n/// Wipes out the data\nfunction cleanScene() {\n for (const type of [\"terrain\", \"props\"]) {\n for (const elem of mapRenderer.mapData[type].data) {\n mapRenderer.scene.remove(elem);\n }\n mapRenderer.mapData[type].data = [];\n }\n\n for (const type of [\"props\"]) {\n mapRenderer.mapData[type].loaded = false;\n mapRenderer.mapData[type].enabled = false;\n }\n}\n\nfunction onMouseMove(event) {\n const canvasBounds = mapRenderer.renderer.domElement.getBoundingClientRect();\n mapRenderer.mouse.x = ((event.clientX - canvasBounds.left) / (canvasBounds.right - canvasBounds.left)) * 2 - 1;\n mapRenderer.mouse.y = -((event.clientY - canvasBounds.top) / (canvasBounds.bottom - canvasBounds.top)) * 2 + 1;\n}\n\n/// Basic THREE stuff, don't mind it\nfunction setupScene() {\n const canvasWidth = 800;\n const canvasHeight = 800;\n const canvasClearColor = 0x342920; // For happy rendering, always use Van Dyke Brown.\n const fov = 60;\n const aspect = 1;\n\n mapRenderer.camera = new THREE.PerspectiveCamera(fov, aspect, 0.1, 100000);\n mapRenderer.scene = new THREE.Scene();\n mapRenderer.mouse = new THREE.Vector2();\n\n /// This scene has one ambient light source and three directional lights\n const ambientLight = new THREE.AmbientLight(0x555555);\n mapRenderer.scene.add(ambientLight);\n\n const directionalLight1 = new THREE.DirectionalLight(0xffffff, 0.8);\n directionalLight1.position.set(0, 0, 1);\n mapRenderer.scene.add(directionalLight1);\n\n const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.8);\n directionalLight2.position.set(1, 0, 0);\n mapRenderer.scene.add(directionalLight2);\n\n const directionalLight3 = new THREE.DirectionalLight(0xffffff, 0.8);\n directionalLight3.position.set(0, 1, 0);\n mapRenderer.scene.add(directionalLight3);\n\n /// Standard THREE renderer with AA\n mapRenderer.renderer = new THREE.WebGLRenderer({\n antialiasing: true,\n logarithmicDepthBuffer: true,\n });\n document.body.appendChild(mapRenderer.renderer.domElement);\n mapRenderer.renderer.setSize(canvasWidth, canvasHeight);\n mapRenderer.renderer.setClearColor(canvasClearColor);\n\n setupController();\n\n /// Note: constant continous rendering from page load\n render();\n}\n\nfunction setupController() {\n if (!mapRenderer.controls) {\n const controls = new THREE.OrbitControls(mapRenderer.camera, mapRenderer.renderer.domElement);\n controls.enableZoom = true;\n mapRenderer.controls = controls;\n }\n}\n\nfunction render() {\n window.requestAnimationFrame(render);\n mapRenderer.renderer.render(mapRenderer.scene, mapRenderer.camera);\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/examples/static/FlyControls.js b/examples/static/FlyControls.js new file mode 100644 index 0000000..253d987 --- /dev/null +++ b/examples/static/FlyControls.js @@ -0,0 +1,307 @@ +THREE.FlyControls = function ( object, domElement ) { + + if ( domElement === undefined ) { + + console.warn( 'THREE.FlyControls: The second parameter "domElement" is now mandatory.' ); + domElement = document; + + } + + this.object = object; + this.domElement = domElement; + + if ( domElement ) this.domElement.setAttribute( 'tabindex', - 1 ); + + // API + + this.movementSpeed = 1.0; + this.rollSpeed = 0.005; + + this.dragToLook = false; + this.autoForward = false; + + // disable default target object behavior + + // internals + + var scope = this; + var changeEvent = { type: "change" }; + var EPS = 0.000001; + + this.tmpQuaternion = new THREE.Quaternion(); + + this.mouseStatus = 0; + + this.moveState = { up: 0, down: 0, left: 0, right: 0, forward: 0, back: 0, pitchUp: 0, pitchDown: 0, yawLeft: 0, yawRight: 0, rollLeft: 0, rollRight: 0 }; + this.moveVector = new THREE.Vector3( 0, 0, 0 ); + this.rotationVector = new THREE.Vector3( 0, 0, 0 ); + + this.keydown = function ( event ) { + + if ( event.altKey ) { + + return; + + } + + //event.preventDefault(); + + switch ( event.keyCode ) { + + case 16: /* shift */ this.movementSpeedMultiplier = .1; break; + + case 87: /*W*/ this.moveState.forward = 1; break; + case 83: /*S*/ this.moveState.back = 1; break; + + case 65: /*A*/ this.moveState.left = 1; break; + case 68: /*D*/ this.moveState.right = 1; break; + + case 82: /*R*/ this.moveState.up = 1; break; + case 70: /*F*/ this.moveState.down = 1; break; + + case 38: /*up*/ this.moveState.pitchUp = 1; break; + case 40: /*down*/ this.moveState.pitchDown = 1; break; + + case 37: /*left*/ this.moveState.yawLeft = 1; break; + case 39: /*right*/ this.moveState.yawRight = 1; break; + + case 81: /*Q*/ this.moveState.rollLeft = 1; break; + case 69: /*E*/ this.moveState.rollRight = 1; break; + + } + + this.updateMovementVector(); + this.updateRotationVector(); + + }; + + this.keyup = function ( event ) { + + switch ( event.keyCode ) { + + case 16: /* shift */ this.movementSpeedMultiplier = 1; break; + + case 87: /*W*/ this.moveState.forward = 0; break; + case 83: /*S*/ this.moveState.back = 0; break; + + case 65: /*A*/ this.moveState.left = 0; break; + case 68: /*D*/ this.moveState.right = 0; break; + + case 82: /*R*/ this.moveState.up = 0; break; + case 70: /*F*/ this.moveState.down = 0; break; + + case 38: /*up*/ this.moveState.pitchUp = 0; break; + case 40: /*down*/ this.moveState.pitchDown = 0; break; + + case 37: /*left*/ this.moveState.yawLeft = 0; break; + case 39: /*right*/ this.moveState.yawRight = 0; break; + + case 81: /*Q*/ this.moveState.rollLeft = 0; break; + case 69: /*E*/ this.moveState.rollRight = 0; break; + + } + + this.updateMovementVector(); + this.updateRotationVector(); + + }; + + this.mousedown = function ( event ) { + + if ( this.domElement !== document ) { + + this.domElement.focus(); + + } + + event.preventDefault(); + event.stopPropagation(); + + if ( this.dragToLook ) { + + this.mouseStatus ++; + + } else { + + switch ( event.button ) { + + case 0: this.moveState.forward = 1; break; + case 2: this.moveState.back = 1; break; + + } + + this.updateMovementVector(); + + } + + }; + + this.mousemove = function ( event ) { + + if ( ! this.dragToLook || this.mouseStatus > 0 ) { + + var container = this.getContainerDimensions(); + var halfWidth = container.size[ 0 ] / 2; + var halfHeight = container.size[ 1 ] / 2; + + this.moveState.yawLeft = - ( ( event.pageX - container.offset[ 0 ] ) - halfWidth ) / halfWidth; + this.moveState.pitchDown = ( ( event.pageY - container.offset[ 1 ] ) - halfHeight ) / halfHeight; + + this.updateRotationVector(); + + } + + }; + + this.mouseup = function ( event ) { + + event.preventDefault(); + event.stopPropagation(); + + if ( this.dragToLook ) { + + this.mouseStatus --; + + this.moveState.yawLeft = this.moveState.pitchDown = 0; + + } else { + + switch ( event.button ) { + + case 0: this.moveState.forward = 0; break; + case 2: this.moveState.back = 0; break; + + } + + this.updateMovementVector(); + + } + + this.updateRotationVector(); + + }; + + this.update = function () { + + var lastQuaternion = new THREE.Quaternion(); + var lastPosition = new THREE.Vector3(); + + return function ( delta ) { + + var moveMult = delta * scope.movementSpeed; + var rotMult = delta * scope.rollSpeed; + + scope.object.translateX( scope.moveVector.x * moveMult ); + scope.object.translateY( scope.moveVector.y * moveMult ); + scope.object.translateZ( scope.moveVector.z * moveMult ); + + scope.tmpQuaternion.set( scope.rotationVector.x * rotMult, scope.rotationVector.y * rotMult, scope.rotationVector.z * rotMult, 1 ).normalize(); + scope.object.quaternion.multiply( scope.tmpQuaternion ); + + if ( + lastPosition.distanceToSquared( scope.object.position ) > EPS || + 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS + ) { + + scope.dispatchEvent( changeEvent ); + lastQuaternion.copy( scope.object.quaternion ); + lastPosition.copy( scope.object.position ); + + } + + }; + + }(); + + this.updateMovementVector = function () { + + var forward = ( this.moveState.forward || ( this.autoForward && ! this.moveState.back ) ) ? 1 : 0; + + this.moveVector.x = ( - this.moveState.left + this.moveState.right ); + this.moveVector.y = ( - this.moveState.down + this.moveState.up ); + this.moveVector.z = ( - forward + this.moveState.back ); + + //console.log( 'move:', [ this.moveVector.x, this.moveVector.y, this.moveVector.z ] ); + + }; + + this.updateRotationVector = function () { + + this.rotationVector.x = ( - this.moveState.pitchDown + this.moveState.pitchUp ); + this.rotationVector.y = ( - this.moveState.yawRight + this.moveState.yawLeft ); + this.rotationVector.z = ( - this.moveState.rollRight + this.moveState.rollLeft ); + + //console.log( 'rotate:', [ this.rotationVector.x, this.rotationVector.y, this.rotationVector.z ] ); + + }; + + this.getContainerDimensions = function () { + + if ( this.domElement != document ) { + + return { + size: [ this.domElement.offsetWidth, this.domElement.offsetHeight ], + offset: [ this.domElement.offsetLeft, this.domElement.offsetTop ] + }; + + } else { + + return { + size: [ window.innerWidth, window.innerHeight ], + offset: [ 0, 0 ] + }; + + } + + }; + + function bind( scope, fn ) { + + return function () { + + fn.apply( scope, arguments ); + + }; + + } + + function contextmenu( event ) { + + event.preventDefault(); + + } + + this.dispose = function () { + + this.domElement.removeEventListener( 'contextmenu', contextmenu, false ); + this.domElement.removeEventListener( 'mousedown', _mousedown, false ); + this.domElement.removeEventListener( 'mousemove', _mousemove, false ); + this.domElement.removeEventListener( 'mouseup', _mouseup, false ); + + window.removeEventListener( 'keydown', _keydown, false ); + window.removeEventListener( 'keyup', _keyup, false ); + + }; + + var _mousemove = bind( this, this.mousemove ); + var _mousedown = bind( this, this.mousedown ); + var _mouseup = bind( this, this.mouseup ); + var _keydown = bind( this, this.keydown ); + var _keyup = bind( this, this.keyup ); + + this.domElement.addEventListener( 'contextmenu', contextmenu, false ); + + this.domElement.addEventListener( 'mousemove', _mousemove, false ); + this.domElement.addEventListener( 'mousedown', _mousedown, false ); + this.domElement.addEventListener( 'mouseup', _mouseup, false ); + + window.addEventListener( 'keydown', _keydown, false ); + window.addEventListener( 'keyup', _keyup, false ); + + this.updateMovementVector(); + this.updateRotationVector(); + +}; + +THREE.FlyControls.prototype = Object.create( THREE.EventDispatcher.prototype ); +THREE.FlyControls.prototype.constructor = THREE.FlyControls; diff --git a/examples/static/OBJExporter.js b/examples/static/OBJExporter.js new file mode 100644 index 0000000..ba1cb26 --- /dev/null +++ b/examples/static/OBJExporter.js @@ -0,0 +1,328 @@ +THREE.OBJExporter = function () {}; + +THREE.OBJExporter.prototype = { + + constructor: THREE.OBJExporter, + + parse: function ( object ) { + + var output = ''; + + var indexVertex = 0; + var indexVertexUvs = 0; + var indexNormals = 0; + + var vertex = new THREE.Vector3(); + var color = new THREE.Color(); + var normal = new THREE.Vector3(); + var uv = new THREE.Vector2(); + + var i, j, k, l, m, face = []; + + var parseMesh = function ( mesh ) { + + var nbVertex = 0; + var nbNormals = 0; + var nbVertexUvs = 0; + + var geometry = mesh.geometry; + + var normalMatrixWorld = new THREE.Matrix3(); + + if ( geometry instanceof THREE.Geometry ) { + + geometry = new THREE.BufferGeometry().setFromObject( mesh ); + + } + + if ( geometry instanceof THREE.BufferGeometry ) { + + // shortcuts + var vertices = geometry.getAttribute( 'position' ); + var normals = geometry.getAttribute( 'normal' ); + var uvs = geometry.getAttribute( 'uv' ); + var indices = geometry.getIndex(); + + // name of the mesh object + output += 'o ' + mesh.name + '\n'; + + // name of the mesh material + if ( mesh.material && mesh.material.name ) { + + output += 'usemtl ' + mesh.material.name + '\n'; + + } + + // vertices + + if ( vertices !== undefined ) { + + for ( i = 0, l = vertices.count; i < l; i ++, nbVertex ++ ) { + + vertex.x = vertices.getX( i ); + vertex.y = vertices.getY( i ); + vertex.z = vertices.getZ( i ); + + // transform the vertex to world space + vertex.applyMatrix4( mesh.matrixWorld ); + + // transform the vertex to export format + output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'; + + } + + } + + // uvs + + if ( uvs !== undefined ) { + + for ( i = 0, l = uvs.count; i < l; i ++, nbVertexUvs ++ ) { + + uv.x = uvs.getX( i ); + uv.y = uvs.getY( i ); + + // transform the uv to export format + output += 'vt ' + uv.x + ' ' + uv.y + '\n'; + + } + + } + + // normals + + if ( normals !== undefined ) { + + normalMatrixWorld.getNormalMatrix( mesh.matrixWorld ); + + for ( i = 0, l = normals.count; i < l; i ++, nbNormals ++ ) { + + normal.x = normals.getX( i ); + normal.y = normals.getY( i ); + normal.z = normals.getZ( i ); + + // transform the normal to world space + normal.applyMatrix3( normalMatrixWorld ).normalize(); + + // transform the normal to export format + output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n'; + + } + + } + + // faces + + if ( indices !== null ) { + + for ( i = 0, l = indices.count; i < l; i += 3 ) { + + for ( m = 0; m < 3; m ++ ) { + + j = indices.getX( i + m ) + 1; + + face[ m ] = ( indexVertex + j ) + ( normals || uvs ? '/' + ( uvs ? ( indexVertexUvs + j ) : '' ) + ( normals ? '/' + ( indexNormals + j ) : '' ) : '' ); + + } + + // transform the face to export format + output += 'f ' + face.join( ' ' ) + "\n"; + + } + + } else { + + for ( i = 0, l = vertices.count; i < l; i += 3 ) { + + for ( m = 0; m < 3; m ++ ) { + + j = i + m + 1; + + face[ m ] = ( indexVertex + j ) + ( normals || uvs ? '/' + ( uvs ? ( indexVertexUvs + j ) : '' ) + ( normals ? '/' + ( indexNormals + j ) : '' ) : '' ); + + } + + // transform the face to export format + output += 'f ' + face.join( ' ' ) + "\n"; + + } + + } + + } else { + + console.warn( 'THREE.OBJExporter.parseMesh(): geometry type unsupported', geometry ); + + } + + // update index + indexVertex += nbVertex; + indexVertexUvs += nbVertexUvs; + indexNormals += nbNormals; + + }; + + var parseLine = function ( line ) { + + var nbVertex = 0; + + var geometry = line.geometry; + var type = line.type; + + if ( geometry instanceof THREE.Geometry ) { + + geometry = new THREE.BufferGeometry().setFromObject( line ); + + } + + if ( geometry instanceof THREE.BufferGeometry ) { + + // shortcuts + var vertices = geometry.getAttribute( 'position' ); + + // name of the line object + output += 'o ' + line.name + '\n'; + + if ( vertices !== undefined ) { + + for ( i = 0, l = vertices.count; i < l; i ++, nbVertex ++ ) { + + vertex.x = vertices.getX( i ); + vertex.y = vertices.getY( i ); + vertex.z = vertices.getZ( i ); + + // transform the vertex to world space + vertex.applyMatrix4( line.matrixWorld ); + + // transform the vertex to export format + output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'; + + } + + } + + if ( type === 'Line' ) { + + output += 'l '; + + for ( j = 1, l = vertices.count; j <= l; j ++ ) { + + output += ( indexVertex + j ) + ' '; + + } + + output += '\n'; + + } + + if ( type === 'LineSegments' ) { + + for ( j = 1, k = j + 1, l = vertices.count; j < l; j += 2, k = j + 1 ) { + + output += 'l ' + ( indexVertex + j ) + ' ' + ( indexVertex + k ) + '\n'; + + } + + } + + } else { + + console.warn( 'THREE.OBJExporter.parseLine(): geometry type unsupported', geometry ); + + } + + // update index + indexVertex += nbVertex; + + }; + + var parsePoints = function ( points ) { + + var nbVertex = 0; + + var geometry = points.geometry; + + if ( geometry instanceof THREE.Geometry ) { + + geometry = new THREE.BufferGeometry().setFromObject( points ); + + } + + if ( geometry instanceof THREE.BufferGeometry ) { + + var vertices = geometry.getAttribute( 'position' ); + var colors = geometry.getAttribute( 'color' ); + + output += 'o ' + points.name + '\n'; + + if ( vertices !== undefined ) { + + for ( i = 0, l = vertices.count; i < l; i ++, nbVertex ++ ) { + + vertex.fromBufferAttribute( vertices, i ); + vertex.applyMatrix4( points.matrixWorld ); + + output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z; + + if ( colors !== undefined ) { + + color.fromBufferAttribute( colors, i ); + + output += ' ' + color.r + ' ' + color.g + ' ' + color.b; + + } + + output += '\n'; + + } + + } + + output += 'p '; + + for ( j = 1, l = vertices.count; j <= l; j ++ ) { + + output += ( indexVertex + j ) + ' '; + + } + + output += '\n'; + + } else { + + console.warn( 'THREE.OBJExporter.parsePoints(): geometry type unsupported', geometry ); + + } + + // update index + indexVertex += nbVertex; + + }; + + object.traverse( function ( child ) { + + if ( child instanceof THREE.Mesh ) { + + parseMesh( child ); + + } + + if ( child instanceof THREE.Line ) { + + parseLine( child ); + + } + + if ( child instanceof THREE.Points ) { + + parsePoints( child ); + + } + + } ); + + return output; + + } + +}; diff --git a/examples/static/OrbitControls.js b/examples/static/OrbitControls.js new file mode 100644 index 0000000..97b9396 --- /dev/null +++ b/examples/static/OrbitControls.js @@ -0,0 +1,1207 @@ +// This set of controls performs orbiting, dollying (zooming), and panning. +// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). +// +// Orbit - left mouse / touch: one-finger move +// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish +// Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move + +THREE.OrbitControls = function ( object, domElement ) { + + if ( domElement === undefined ) console.warn( 'THREE.OrbitControls: The second parameter "domElement" is now mandatory.' ); + if ( domElement === document ) console.error( 'THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.' ); + + this.object = object; + this.domElement = domElement; + + // Set to false to disable this control + this.enabled = true; + + // "target" sets the location of focus, where the object orbits around + this.target = new THREE.Vector3(); + + // How far you can dolly in and out ( PerspectiveCamera only ) + this.minDistance = 0; + this.maxDistance = Infinity; + + // How far you can zoom in and out ( OrthographicCamera only ) + this.minZoom = 0; + this.maxZoom = Infinity; + + // How far you can orbit vertically, upper and lower limits. + // Range is 0 to Math.PI radians. + this.minPolarAngle = 0; // radians + this.maxPolarAngle = Math.PI; // radians + + // How far you can orbit horizontally, upper and lower limits. + // If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI ) + this.minAzimuthAngle = - Infinity; // radians + this.maxAzimuthAngle = Infinity; // radians + + // Set to true to enable damping (inertia) + // If damping is enabled, you must call controls.update() in your animation loop + this.enableDamping = false; + this.dampingFactor = 0.05; + + // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. + // Set to false to disable zooming + this.enableZoom = true; + this.zoomSpeed = 1.0; + + // Set to false to disable rotating + this.enableRotate = true; + this.rotateSpeed = 1.0; + + // Set to false to disable panning + this.enablePan = true; + this.panSpeed = 1.0; + this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up + this.keyPanSpeed = 7.0; // pixels moved per arrow key push + + // Set to true to automatically rotate around the target + // If auto-rotate is enabled, you must call controls.update() in your animation loop + this.autoRotate = false; + this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 + + // Set to false to disable use of the keys + this.enableKeys = true; + + // The four arrow keys + this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; + + // Mouse buttons + this.mouseButtons = { LEFT: THREE.MOUSE.ROTATE, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.PAN }; + + // Touch fingers + this.touches = { ONE: THREE.TOUCH.ROTATE, TWO: THREE.TOUCH.DOLLY_PAN }; + + // for reset + this.target0 = this.target.clone(); + this.position0 = this.object.position.clone(); + this.zoom0 = this.object.zoom; + + // + // public methods + // + + this.getPolarAngle = function () { + + return spherical.phi; + + }; + + this.getAzimuthalAngle = function () { + + return spherical.theta; + + }; + + this.saveState = function () { + + scope.target0.copy( scope.target ); + scope.position0.copy( scope.object.position ); + scope.zoom0 = scope.object.zoom; + + }; + + this.reset = function () { + + scope.target.copy( scope.target0 ); + scope.object.position.copy( scope.position0 ); + scope.object.zoom = scope.zoom0; + + scope.object.updateProjectionMatrix(); + scope.dispatchEvent( changeEvent ); + + scope.update(); + + state = STATE.NONE; + + }; + + // this method is exposed, but perhaps it would be better if we can make it private... + this.update = function () { + + var offset = new THREE.Vector3(); + + // so camera.up is the orbit axis + var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) ); + var quatInverse = quat.clone().invert(); + + var lastPosition = new THREE.Vector3(); + var lastQuaternion = new THREE.Quaternion(); + + var twoPI = 2 * Math.PI; + + return function update() { + + var position = scope.object.position; + + offset.copy( position ).sub( scope.target ); + + // rotate offset to "y-axis-is-up" space + offset.applyQuaternion( quat ); + + // angle from z-axis around y-axis + spherical.setFromVector3( offset ); + + if ( scope.autoRotate && state === STATE.NONE ) { + + rotateLeft( getAutoRotationAngle() ); + + } + + if ( scope.enableDamping ) { + + spherical.theta += sphericalDelta.theta * scope.dampingFactor; + spherical.phi += sphericalDelta.phi * scope.dampingFactor; + + } else { + + spherical.theta += sphericalDelta.theta; + spherical.phi += sphericalDelta.phi; + + } + + // restrict theta to be between desired limits + + var min = scope.minAzimuthAngle; + var max = scope.maxAzimuthAngle; + + if ( isFinite( min ) && isFinite( max ) ) { + + if ( min < - Math.PI ) min += twoPI; else if ( min > Math.PI ) min -= twoPI; + + if ( max < - Math.PI ) max += twoPI; else if ( max > Math.PI ) max -= twoPI; + + if ( min <= max ) { + + spherical.theta = Math.max( min, Math.min( max, spherical.theta ) ); + + } else { + + spherical.theta = ( spherical.theta > ( min + max ) / 2 ) ? + Math.max( min, spherical.theta ) : + Math.min( max, spherical.theta ); + + } + + } + + // restrict phi to be between desired limits + spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) ); + + spherical.makeSafe(); + + + spherical.radius *= scale; + + // restrict radius to be between desired limits + spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) ); + + // move target to panned location + + if ( scope.enableDamping === true ) { + + scope.target.addScaledVector( panOffset, scope.dampingFactor ); + + } else { + + scope.target.add( panOffset ); + + } + + offset.setFromSpherical( spherical ); + + // rotate offset back to "camera-up-vector-is-up" space + offset.applyQuaternion( quatInverse ); + + position.copy( scope.target ).add( offset ); + + scope.object.lookAt( scope.target ); + + if ( scope.enableDamping === true ) { + + sphericalDelta.theta *= ( 1 - scope.dampingFactor ); + sphericalDelta.phi *= ( 1 - scope.dampingFactor ); + + panOffset.multiplyScalar( 1 - scope.dampingFactor ); + + } else { + + sphericalDelta.set( 0, 0, 0 ); + + panOffset.set( 0, 0, 0 ); + + } + + scale = 1; + + // update condition is: + // min(camera displacement, camera rotation in radians)^2 > EPS + // using small-angle approximation cos(x/2) = 1 - x^2 / 8 + + if ( zoomChanged || + lastPosition.distanceToSquared( scope.object.position ) > EPS || + 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) { + + scope.dispatchEvent( changeEvent ); + + lastPosition.copy( scope.object.position ); + lastQuaternion.copy( scope.object.quaternion ); + zoomChanged = false; + + return true; + + } + + return false; + + }; + + }(); + + this.dispose = function () { + + scope.domElement.removeEventListener( 'contextmenu', onContextMenu, false ); + + scope.domElement.removeEventListener( 'pointerdown', onPointerDown, false ); + scope.domElement.removeEventListener( 'wheel', onMouseWheel, false ); + + scope.domElement.removeEventListener( 'touchstart', onTouchStart, false ); + scope.domElement.removeEventListener( 'touchend', onTouchEnd, false ); + scope.domElement.removeEventListener( 'touchmove', onTouchMove, false ); + + scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove, false ); + scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp, false ); + + scope.domElement.removeEventListener( 'keydown', onKeyDown, false ); + + //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here? + + }; + + // + // internals + // + + var scope = this; + + var changeEvent = { type: 'change' }; + var startEvent = { type: 'start' }; + var endEvent = { type: 'end' }; + + var STATE = { + NONE: - 1, + ROTATE: 0, + DOLLY: 1, + PAN: 2, + TOUCH_ROTATE: 3, + TOUCH_PAN: 4, + TOUCH_DOLLY_PAN: 5, + TOUCH_DOLLY_ROTATE: 6 + }; + + var state = STATE.NONE; + + var EPS = 0.000001; + + // current position in spherical coordinates + var spherical = new THREE.Spherical(); + var sphericalDelta = new THREE.Spherical(); + + var scale = 1; + var panOffset = new THREE.Vector3(); + var zoomChanged = false; + + var rotateStart = new THREE.Vector2(); + var rotateEnd = new THREE.Vector2(); + var rotateDelta = new THREE.Vector2(); + + var panStart = new THREE.Vector2(); + var panEnd = new THREE.Vector2(); + var panDelta = new THREE.Vector2(); + + var dollyStart = new THREE.Vector2(); + var dollyEnd = new THREE.Vector2(); + var dollyDelta = new THREE.Vector2(); + + function getAutoRotationAngle() { + + return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; + + } + + function getZoomScale() { + + return Math.pow( 0.95, scope.zoomSpeed ); + + } + + function rotateLeft( angle ) { + + sphericalDelta.theta -= angle; + + } + + function rotateUp( angle ) { + + sphericalDelta.phi -= angle; + + } + + var panLeft = function () { + + var v = new THREE.Vector3(); + + return function panLeft( distance, objectMatrix ) { + + v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix + v.multiplyScalar( - distance ); + + panOffset.add( v ); + + }; + + }(); + + var panUp = function () { + + var v = new THREE.Vector3(); + + return function panUp( distance, objectMatrix ) { + + if ( scope.screenSpacePanning === true ) { + + v.setFromMatrixColumn( objectMatrix, 1 ); + + } else { + + v.setFromMatrixColumn( objectMatrix, 0 ); + v.crossVectors( scope.object.up, v ); + + } + + v.multiplyScalar( distance ); + + panOffset.add( v ); + + }; + + }(); + + // deltaX and deltaY are in pixels; right and down are positive + var pan = function () { + + var offset = new THREE.Vector3(); + + return function pan( deltaX, deltaY ) { + + var element = scope.domElement; + + if ( scope.object.isPerspectiveCamera ) { + + // perspective + var position = scope.object.position; + offset.copy( position ).sub( scope.target ); + var targetDistance = offset.length(); + + // half of the fov is center to top of screen + targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 ); + + // we use only clientHeight here so aspect ratio does not distort speed + panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix ); + panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix ); + + } else if ( scope.object.isOrthographicCamera ) { + + // orthographic + panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix ); + panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix ); + + } else { + + // camera neither orthographic nor perspective + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' ); + scope.enablePan = false; + + } + + }; + + }(); + + function dollyOut( dollyScale ) { + + if ( scope.object.isPerspectiveCamera ) { + + scale /= dollyScale; + + } else if ( scope.object.isOrthographicCamera ) { + + scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) ); + scope.object.updateProjectionMatrix(); + zoomChanged = true; + + } else { + + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); + scope.enableZoom = false; + + } + + } + + function dollyIn( dollyScale ) { + + if ( scope.object.isPerspectiveCamera ) { + + scale *= dollyScale; + + } else if ( scope.object.isOrthographicCamera ) { + + scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) ); + scope.object.updateProjectionMatrix(); + zoomChanged = true; + + } else { + + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); + scope.enableZoom = false; + + } + + } + + // + // event callbacks - update the object state + // + + function handleMouseDownRotate( event ) { + + rotateStart.set( event.clientX, event.clientY ); + + } + + function handleMouseDownDolly( event ) { + + dollyStart.set( event.clientX, event.clientY ); + + } + + function handleMouseDownPan( event ) { + + panStart.set( event.clientX, event.clientY ); + + } + + function handleMouseMoveRotate( event ) { + + rotateEnd.set( event.clientX, event.clientY ); + + rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); + + var element = scope.domElement; + + rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height + + rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); + + rotateStart.copy( rotateEnd ); + + scope.update(); + + } + + function handleMouseMoveDolly( event ) { + + dollyEnd.set( event.clientX, event.clientY ); + + dollyDelta.subVectors( dollyEnd, dollyStart ); + + if ( dollyDelta.y > 0 ) { + + dollyOut( getZoomScale() ); + + } else if ( dollyDelta.y < 0 ) { + + dollyIn( getZoomScale() ); + + } + + dollyStart.copy( dollyEnd ); + + scope.update(); + + } + + function handleMouseMovePan( event ) { + + panEnd.set( event.clientX, event.clientY ); + + panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); + + pan( panDelta.x, panDelta.y ); + + panStart.copy( panEnd ); + + scope.update(); + + } + + function handleMouseUp( /*event*/ ) { + + // no-op + + } + + function handleMouseWheel( event ) { + + if ( event.deltaY < 0 ) { + + dollyIn( getZoomScale() ); + + } else if ( event.deltaY > 0 ) { + + dollyOut( getZoomScale() ); + + } + + scope.update(); + + } + + function handleKeyDown( event ) { + + var needsUpdate = false; + + switch ( event.keyCode ) { + + case scope.keys.UP: + pan( 0, scope.keyPanSpeed ); + needsUpdate = true; + break; + + case scope.keys.BOTTOM: + pan( 0, - scope.keyPanSpeed ); + needsUpdate = true; + break; + + case scope.keys.LEFT: + pan( scope.keyPanSpeed, 0 ); + needsUpdate = true; + break; + + case scope.keys.RIGHT: + pan( - scope.keyPanSpeed, 0 ); + needsUpdate = true; + break; + + } + + if ( needsUpdate ) { + + // prevent the browser from scrolling on cursor keys + event.preventDefault(); + + scope.update(); + + } + + + } + + function handleTouchStartRotate( event ) { + + if ( event.touches.length == 1 ) { + + rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + + rotateStart.set( x, y ); + + } + + } + + function handleTouchStartPan( event ) { + + if ( event.touches.length == 1 ) { + + panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + + panStart.set( x, y ); + + } + + } + + function handleTouchStartDolly( event ) { + + var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; + var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + + var distance = Math.sqrt( dx * dx + dy * dy ); + + dollyStart.set( 0, distance ); + + } + + function handleTouchStartDollyPan( event ) { + + if ( scope.enableZoom ) handleTouchStartDolly( event ); + + if ( scope.enablePan ) handleTouchStartPan( event ); + + } + + function handleTouchStartDollyRotate( event ) { + + if ( scope.enableZoom ) handleTouchStartDolly( event ); + + if ( scope.enableRotate ) handleTouchStartRotate( event ); + + } + + function handleTouchMoveRotate( event ) { + + if ( event.touches.length == 1 ) { + + rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + + rotateEnd.set( x, y ); + + } + + rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); + + var element = scope.domElement; + + rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height + + rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); + + rotateStart.copy( rotateEnd ); + + } + + function handleTouchMovePan( event ) { + + if ( event.touches.length == 1 ) { + + panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + + panEnd.set( x, y ); + + } + + panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); + + pan( panDelta.x, panDelta.y ); + + panStart.copy( panEnd ); + + } + + function handleTouchMoveDolly( event ) { + + var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; + var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + + var distance = Math.sqrt( dx * dx + dy * dy ); + + dollyEnd.set( 0, distance ); + + dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) ); + + dollyOut( dollyDelta.y ); + + dollyStart.copy( dollyEnd ); + + } + + function handleTouchMoveDollyPan( event ) { + + if ( scope.enableZoom ) handleTouchMoveDolly( event ); + + if ( scope.enablePan ) handleTouchMovePan( event ); + + } + + function handleTouchMoveDollyRotate( event ) { + + if ( scope.enableZoom ) handleTouchMoveDolly( event ); + + if ( scope.enableRotate ) handleTouchMoveRotate( event ); + + } + + function handleTouchEnd( /*event*/ ) { + + // no-op + + } + + // + // event handlers - FSM: listen for events and reset state + // + + function onPointerDown( event ) { + + if ( scope.enabled === false ) return; + + switch ( event.pointerType ) { + + case 'mouse': + case 'pen': + onMouseDown( event ); + break; + + // TODO touch + + } + + } + + function onPointerMove( event ) { + + if ( scope.enabled === false ) return; + + switch ( event.pointerType ) { + + case 'mouse': + case 'pen': + onMouseMove( event ); + break; + + // TODO touch + + } + + } + + function onPointerUp( event ) { + + switch ( event.pointerType ) { + + case 'mouse': + case 'pen': + onMouseUp( event ); + break; + + // TODO touch + + } + + } + + function onMouseDown( event ) { + + // Prevent the browser from scrolling. + event.preventDefault(); + + // Manually set the focus since calling preventDefault above + // prevents the browser from setting it automatically. + + scope.domElement.focus ? scope.domElement.focus() : window.focus(); + + var mouseAction; + + switch ( event.button ) { + + case 0: + + mouseAction = scope.mouseButtons.LEFT; + break; + + case 1: + + mouseAction = scope.mouseButtons.MIDDLE; + break; + + case 2: + + mouseAction = scope.mouseButtons.RIGHT; + break; + + default: + + mouseAction = - 1; + + } + + switch ( mouseAction ) { + + case THREE.MOUSE.DOLLY: + + if ( scope.enableZoom === false ) return; + + handleMouseDownDolly( event ); + + state = STATE.DOLLY; + + break; + + case THREE.MOUSE.ROTATE: + + if ( event.ctrlKey || event.metaKey || event.shiftKey ) { + + if ( scope.enablePan === false ) return; + + handleMouseDownPan( event ); + + state = STATE.PAN; + + } else { + + if ( scope.enableRotate === false ) return; + + handleMouseDownRotate( event ); + + state = STATE.ROTATE; + + } + + break; + + case THREE.MOUSE.PAN: + + if ( event.ctrlKey || event.metaKey || event.shiftKey ) { + + if ( scope.enableRotate === false ) return; + + handleMouseDownRotate( event ); + + state = STATE.ROTATE; + + } else { + + if ( scope.enablePan === false ) return; + + handleMouseDownPan( event ); + + state = STATE.PAN; + + } + + break; + + default: + + state = STATE.NONE; + + } + + if ( state !== STATE.NONE ) { + + scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove, false ); + scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp, false ); + + scope.dispatchEvent( startEvent ); + + } + + } + + function onMouseMove( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); + + switch ( state ) { + + case STATE.ROTATE: + + if ( scope.enableRotate === false ) return; + + handleMouseMoveRotate( event ); + + break; + + case STATE.DOLLY: + + if ( scope.enableZoom === false ) return; + + handleMouseMoveDolly( event ); + + break; + + case STATE.PAN: + + if ( scope.enablePan === false ) return; + + handleMouseMovePan( event ); + + break; + + } + + } + + function onMouseUp( event ) { + + scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove, false ); + scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp, false ); + + if ( scope.enabled === false ) return; + + handleMouseUp( event ); + + scope.dispatchEvent( endEvent ); + + state = STATE.NONE; + + } + + function onMouseWheel( event ) { + + if ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return; + + event.preventDefault(); + event.stopPropagation(); + + scope.dispatchEvent( startEvent ); + + handleMouseWheel( event ); + + scope.dispatchEvent( endEvent ); + + } + + function onKeyDown( event ) { + + if ( scope.enabled === false || scope.enableKeys === false || scope.enablePan === false ) return; + + handleKeyDown( event ); + + } + + function onTouchStart( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); // prevent scrolling + + switch ( event.touches.length ) { + + case 1: + + switch ( scope.touches.ONE ) { + + case THREE.TOUCH.ROTATE: + + if ( scope.enableRotate === false ) return; + + handleTouchStartRotate( event ); + + state = STATE.TOUCH_ROTATE; + + break; + + case THREE.TOUCH.PAN: + + if ( scope.enablePan === false ) return; + + handleTouchStartPan( event ); + + state = STATE.TOUCH_PAN; + + break; + + default: + + state = STATE.NONE; + + } + + break; + + case 2: + + switch ( scope.touches.TWO ) { + + case THREE.TOUCH.DOLLY_PAN: + + if ( scope.enableZoom === false && scope.enablePan === false ) return; + + handleTouchStartDollyPan( event ); + + state = STATE.TOUCH_DOLLY_PAN; + + break; + + case THREE.TOUCH.DOLLY_ROTATE: + + if ( scope.enableZoom === false && scope.enableRotate === false ) return; + + handleTouchStartDollyRotate( event ); + + state = STATE.TOUCH_DOLLY_ROTATE; + + break; + + default: + + state = STATE.NONE; + + } + + break; + + default: + + state = STATE.NONE; + + } + + if ( state !== STATE.NONE ) { + + scope.dispatchEvent( startEvent ); + + } + + } + + function onTouchMove( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); // prevent scrolling + event.stopPropagation(); + + switch ( state ) { + + case STATE.TOUCH_ROTATE: + + if ( scope.enableRotate === false ) return; + + handleTouchMoveRotate( event ); + + scope.update(); + + break; + + case STATE.TOUCH_PAN: + + if ( scope.enablePan === false ) return; + + handleTouchMovePan( event ); + + scope.update(); + + break; + + case STATE.TOUCH_DOLLY_PAN: + + if ( scope.enableZoom === false && scope.enablePan === false ) return; + + handleTouchMoveDollyPan( event ); + + scope.update(); + + break; + + case STATE.TOUCH_DOLLY_ROTATE: + + if ( scope.enableZoom === false && scope.enableRotate === false ) return; + + handleTouchMoveDollyRotate( event ); + + scope.update(); + + break; + + default: + + state = STATE.NONE; + + } + + } + + function onTouchEnd( event ) { + + if ( scope.enabled === false ) return; + + handleTouchEnd( event ); + + scope.dispatchEvent( endEvent ); + + state = STATE.NONE; + + } + + function onContextMenu( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); + + } + + // + + scope.domElement.addEventListener( 'contextmenu', onContextMenu, false ); + + scope.domElement.addEventListener( 'pointerdown', onPointerDown, false ); + scope.domElement.addEventListener( 'wheel', onMouseWheel, false ); + + scope.domElement.addEventListener( 'touchstart', onTouchStart, false ); + scope.domElement.addEventListener( 'touchend', onTouchEnd, false ); + scope.domElement.addEventListener( 'touchmove', onTouchMove, false ); + + scope.domElement.addEventListener( 'keydown', onKeyDown, false ); + + // force an update at start + + this.update(); + +}; + +THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype ); +THREE.OrbitControls.prototype.constructor = THREE.OrbitControls; + + +// This set of controls performs orbiting, dollying (zooming), and panning. +// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). +// This is very similar to OrbitControls, another set of touch behavior +// +// Orbit - right mouse, or left mouse + ctrl/meta/shiftKey / touch: two-finger rotate +// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish +// Pan - left mouse, or arrow keys / touch: one-finger move + +THREE.MapControls = function ( object, domElement ) { + + THREE.OrbitControls.call( this, object, domElement ); + + this.screenSpacePanning = false; // pan orthogonal to world-space direction camera.up + + this.mouseButtons.LEFT = THREE.MOUSE.PAN; + this.mouseButtons.RIGHT = THREE.MOUSE.ROTATE; + + this.touches.ONE = THREE.TOUCH.PAN; + this.touches.TWO = THREE.TOUCH.DOLLY_ROTATE; + +}; + +THREE.MapControls.prototype = Object.create( THREE.EventDispatcher.prototype ); +THREE.MapControls.prototype.constructor = THREE.MapControls; diff --git a/examples/static/PointerLockControls.js b/examples/static/PointerLockControls.js new file mode 100644 index 0000000..282d60d --- /dev/null +++ b/examples/static/PointerLockControls.js @@ -0,0 +1,156 @@ +THREE.PointerLockControls = function ( camera, domElement ) { + + if ( domElement === undefined ) { + + console.warn( 'THREE.PointerLockControls: The second parameter "domElement" is now mandatory.' ); + domElement = document.body; + + } + + this.domElement = domElement; + this.isLocked = false; + + // Set to constrain the pitch of the camera + // Range is 0 to Math.PI radians + this.minPolarAngle = 0; // radians + this.maxPolarAngle = Math.PI; // radians + + // + // internals + // + + var scope = this; + + var changeEvent = { type: 'change' }; + var lockEvent = { type: 'lock' }; + var unlockEvent = { type: 'unlock' }; + + var euler = new THREE.Euler( 0, 0, 0, 'YXZ' ); + + var PI_2 = Math.PI / 2; + + var vec = new THREE.Vector3(); + + function onMouseMove( event ) { + + if ( scope.isLocked === false ) return; + + var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; + var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; + + euler.setFromQuaternion( camera.quaternion ); + + euler.y -= movementX * 0.002; + euler.x -= movementY * 0.002; + + euler.x = Math.max( PI_2 - scope.maxPolarAngle, Math.min( PI_2 - scope.minPolarAngle, euler.x ) ); + + camera.quaternion.setFromEuler( euler ); + + scope.dispatchEvent( changeEvent ); + + } + + function onPointerlockChange() { + + if ( scope.domElement.ownerDocument.pointerLockElement === scope.domElement ) { + + scope.dispatchEvent( lockEvent ); + + scope.isLocked = true; + + } else { + + scope.dispatchEvent( unlockEvent ); + + scope.isLocked = false; + + } + + } + + function onPointerlockError() { + + console.error( 'THREE.PointerLockControls: Unable to use Pointer Lock API' ); + + } + + this.connect = function () { + + scope.domElement.ownerDocument.addEventListener( 'mousemove', onMouseMove, false ); + scope.domElement.ownerDocument.addEventListener( 'pointerlockchange', onPointerlockChange, false ); + scope.domElement.ownerDocument.addEventListener( 'pointerlockerror', onPointerlockError, false ); + + }; + + this.disconnect = function () { + + scope.domElement.ownerDocument.removeEventListener( 'mousemove', onMouseMove, false ); + scope.domElement.ownerDocument.removeEventListener( 'pointerlockchange', onPointerlockChange, false ); + scope.domElement.ownerDocument.removeEventListener( 'pointerlockerror', onPointerlockError, false ); + + }; + + this.dispose = function () { + + this.disconnect(); + + }; + + this.getObject = function () { // retaining this method for backward compatibility + + return camera; + + }; + + this.getDirection = function () { + + var direction = new THREE.Vector3( 0, 0, - 1 ); + + return function ( v ) { + + return v.copy( direction ).applyQuaternion( camera.quaternion ); + + }; + + }(); + + this.moveForward = function ( distance ) { + + // move forward parallel to the xz-plane + // assumes camera.up is y-up + + vec.setFromMatrixColumn( camera.matrix, 0 ); + + vec.crossVectors( camera.up, vec ); + + camera.position.addScaledVector( vec, distance ); + + }; + + this.moveRight = function ( distance ) { + + vec.setFromMatrixColumn( camera.matrix, 0 ); + + camera.position.addScaledVector( vec, distance ); + + }; + + this.lock = function () { + + this.domElement.requestPointerLock(); + + }; + + this.unlock = function () { + + scope.domElement.ownerDocument.exitPointerLock(); + + }; + + this.connect(); + +}; + +THREE.PointerLockControls.prototype = Object.create( THREE.EventDispatcher.prototype ); +THREE.PointerLockControls.prototype.constructor = THREE.PointerLockControls; diff --git a/examples/static/T3D.js b/examples/static/T3D.js new file mode 100644 index 0000000..2a85d29 --- /dev/null +++ b/examples/static/T3D.js @@ -0,0 +1,4271 @@ +/* +Copyright © 2024 T3D project contributors. + +This file is part of the T3D Library. + +T3D Library is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +T3D Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the T3D Library. If not, see . +*/ + +var T3D = (function (t3dParser) { + 'use strict'; + + /// Indexed DB versioning + const DB_VERSION = 4; + /** + * This class handles offline storage of the .dat indexes and files metadata + * @class PersistantStore + */ + class PersistantStore { + _dbConnection; + constructor() { + // They may be multiple connection request issued at the same time, but it's actually okay since + // as soon as they are registered, the not-used ones will get garbage collected + this._dbConnection = undefined; + this._getConnection(); + } + /** + * Initialize the IndexedDB connection and manages version changes. + * + * @async + * @private + * @returns {Promise} Promise to the Database connection + */ + _getConnection() { + const self = this; + return new Promise((resolve, reject) => { + if (self._dbConnection) + resolve(self._dbConnection); + // Let us open our database + const request = window.indexedDB.open("Tyria3DLibrary", DB_VERSION); + /// onblocked is fired when the db needs an upgrade but an older version is opened in another tab + request.onblocked = () => { + T3D.Logger.log(T3D.Logger.TYPE_ERROR, "The T3D persistant database cannot be upgraded while the app is opened somewhere else."); + }; + /// fired when the database needs to be upgraded (or the first time) + request.onupgradeneeded = (event) => { + // Probably bugged + //@ts-ignore + const db = event.target.result; + const currentVersion = event.oldVersion; + if (currentVersion < 2) { + db.createObjectStore("listings", { + autoIncrement: true, + }); + } + if (currentVersion < 3) { + const storeListing = event.currentTarget.transaction.objectStore("listings"); + storeListing.createIndex("filename", "filename", { unique: false }); + } + }; + request.onsuccess = (event) => { + self._dbConnection = event.target.result; + //@ts-ignore + self.isReady = true; + resolve(self._dbConnection); + }; + request.onerror = () => { + T3D.Logger.log(T3D.Logger.TYPE_ERROR, "The T3D persistant database could not be opened."); + reject(); + }; + }); + } + /** + * Add or update a listing into the database + * + * @async + * @param {number|undefined} id This ID doesn't really matter, it's just the index of the object in the database, can be undefined + * @param {Array} listing + * @param {string} fileName .dat file name, allows to have multiple listings for different .dat files. + * @param {boolean} isComplete Keep back the information if that was the last update on the current scan or not. + * @returns {Promise} On success, the number is the object key in the database + */ + putListing(id, listing, fileName, isComplete) { + const self = this; + return new Promise((resolve, reject) => { + self._getConnection().then((db) => { + const store = db.transaction(["listings"], "readwrite").objectStore("listings"); + const request = id + ? store.put({ array: listing, filename: fileName, complete: isComplete }, id) + : store.put({ array: listing, name: fileName }); + request.onsuccess = () => { + resolve(request.result); + }; + request.onerror = () => { + reject(); + }; + }); + }); + } + /** + * Returns the last valid listing in the database + * + * @async + * @param {string} fileName .dat file name, allows to have multiple listings for different .dat files. + * @returns {Promise<{array: Array, key: number, complete: boolean}>} + * array: the last listing + * key: the index of the last listing in the database + */ + getLastListing(fileName) { + const self = this; + return new Promise((resolve) => { + self._getConnection().then((db) => { + const listingsStore = db.transaction(["listings"], "readonly").objectStore("listings").index("filename"); + listingsStore.openCursor(IDBKeyRange.only(fileName), "prev").onsuccess = (event) => { + const cursor = event.target.result; + if (!cursor) + resolve({ array: [], key: undefined, complete: true }); + else { + resolve({ + array: cursor.value.array, + key: cursor.primaryKey, + complete: cursor.value.complete, + }); + } + }; + }); + }); + } + } + + /** + * Organized thread pool of extractors + */ + class DataReader { + settings; + _workerPool; + _workerLoad; + _inflateCallbacks; + constructor(settings) { + this.settings = settings; + this._workerPool = []; + this._workerLoad = []; + this._inflateCallbacks = []; + for (let i = 0; i < settings.workersNb; i++) { + this._startWorker(settings.workerPath); + } + } + inflate(buffer, size, mftId, isImage, capLength) { + return new Promise((resolve, reject) => { + const arrayBuffer = buffer; + // If no capLength then inflate the whole file + if (!capLength || capLength < 0) { + capLength = 0; + } + // Buffer length size check + if (arrayBuffer.byteLength < 12) { + T3D.Logger.log(T3D.Logger.TYPE_WARNING, `not inflating, length is too short (${arrayBuffer.byteLength})`, mftId); + reject(new Error("Couldn't inflate " + mftId + " (mftId)")); + return; + } + // Register the callback + if (this._inflateCallbacks[mftId]) { + this._inflateCallbacks[mftId].push({ + resolve: resolve, + reject: reject, + }); + /// No need to make another call, just wait for callback event to fire. + return; + } + else { + this._inflateCallbacks[mftId] = [{ resolve: resolve, reject: reject }]; + } + // Add the load to the worker + const workerId = this._getBestWorkerIndex(); + this._workerLoad[workerId] += 1; + this._workerPool[workerId].postMessage([mftId, arrayBuffer, isImage === true, capLength]); + }); + } + // Initialization function for creating a new worker (thread) + _startWorker(path) { + const self = this; + const worker = new Worker(path); + const selfWorkerId = this._workerPool.push(worker) - 1; + if (this._workerLoad.push(0) !== selfWorkerId + 1) { + throw new Error("WorkerLoad and WorkerPool don't have the same length"); + } + worker.onmessage = function (message_event) { + let mftId; + // Remove load + self._workerLoad[selfWorkerId] -= 1; + // If error + if (typeof message_event.data === "string") { + T3D.Logger.log(T3D.Logger.TYPE_WARNING, "Inflater threw an error", message_event.data); + mftId = parseInt(message_event.data.split(":")[0]); + for (const callback of self._inflateCallbacks[mftId]) { + callback.reject(); + } + } + else { + mftId = message_event.data[0]; + // On success + if (self._inflateCallbacks[mftId]) { + for (const callback of self._inflateCallbacks[mftId]) { + const data = message_event.data; + // Array buffer, dxtType, imageWidth, imageHeight + callback.resolve({ + buffer: data[1], + dxtType: data[2], + imageWidth: data[3], + imageHeight: data[4], + }); + } + // Remove triggered listeners + self._inflateCallbacks[mftId] = null; + } + // Unknown error + else { + T3D.Logger.log(T3D.Logger.TYPE_ERROR, "Inflater threw an error", message_event.data); + } + } + }; + } + // Get the worker with the less load + _getBestWorkerIndex() { + return this._workerLoad.indexOf(Math.min(...this._workerLoad)); + } + } + + const mapMap = { + /** + * @property maps + * @type {Array.<{name: String, maps: Array.<{fileName: String, name: String}>}>} + */ + maps: [ + { + name: "Core - Ascalon [Regrown]", + maps: [ + { fileName: "131944.data", name: "(City) Black Citadel" }, + { fileName: "196585.data", name: "(City) Black Citadel [MapRegrownCitadel]" }, + { fileName: "1968107.data", name: "(City) Black Citadel" }, + { fileName: "126118.data", name: "(1-15) Plains of Ashford" }, + { fileName: "188591.data", name: "(1-15) Plains of Ashford [MapRegrownAshford]" }, + { fileName: "127888.data", name: "(15-25) Diessa Plateau" }, + { fileName: "190490.data", name: "(15-25) Diessa Plateau [MapRegrownRange]" }, + { fileName: "283574.data", name: "(30-40) Fields of Ruin [MapRegrownHawke]" }, + { fileName: "282668.data", name: "(40-50) Iron Marches [MapRegrownGullet]" }, + { fileName: "280025.data", name: "(50-60) Blazeridge Steppes [MapRegrownBrand]" }, + { fileName: "281313.data", name: "(60-70) Fireheart Rise [MapRegrownFlame]" }, + ], + }, + { + name: "Core - Kryta [Valley]", + maps: [ + { fileName: "128151.data", name: "(City) Divinity's Reach" }, + { fileName: "191265.data", name: "(City) Divinity's Reach [MapValleyDivinity]" }, + { fileName: "1968748.data", name: "(City) Divinity's Reach" }, + { fileName: "129524.data", name: "(1-15) Queensdale" }, + { fileName: "192711.data", name: "(1-15) Queensdale [MapValleyHill]" }, + { fileName: "130970.data", name: "(15-25) Kessex Hills" }, + { fileName: "194288.data", name: "(15-25) Kessex Hills [MapValleyWilderness]" }, + { fileName: "861815.data", name: "(15-25) Kessex Hills [MapValleyWildernessFortSalma]" }, + { fileName: "2737234.data", name: "(15-25) Kessex Hills [MapValleyWildernessTower]" }, + { fileName: "289176.data", name: "(25-35) Gendarran Fields, Vigil Headquarters [MapValleySettlement]" }, + { fileName: "191000.data", name: "(City) Lion's Arch [MapValleyArch]" }, + { fileName: "1796999.data", name: "(City) Lion's Arch [MapValleyArchKiel]" }, + { fileName: "1968576.data", name: "(City) Lion's Arch" }, + { fileName: "287870.data", name: "(35-45) Harathi Hinterlands [MapValleyHeadland]" }, + { fileName: "286945.data", name: "(45-55) Bloodtide Coast [MapValleyCoast]" }, + { fileName: "295005.data", name: "(45-55) Chantry of Secrets [MapValleyWhisper]" }, + { fileName: "520479.data", name: "(80) Southsun Cove, Crab Toss, Southsun Survival [MapEventValleyLost]" }, + ], + }, + { + name: "Core - Shiverpeak Mountains [Alpine]", + maps: [ + { fileName: "132434.data", name: "(City) Hoelbrak, Keg Brawl" }, + { fileName: "197122.data", name: "(City) Hoelbrak, Keg Brawl [MapAlpineHall]" }, + { fileName: "1966018.data", name: "(City) Hoelbrak, Keg Brawl" }, + { fileName: "125199.data", name: "(1-15) Wayfarer Foothills" }, + { fileName: "187611.data", name: "(1-15) Wayfarer Foothills [MapAlpineSnowline]" }, + { fileName: "124093.data", name: "(15-25) Snowden Drifts" }, + { fileName: "186397.data", name: "(15-25) Snowden Drifts [MapAlpinePowder]" }, + { fileName: "277587.data", name: "(25-40) Lornar's Pass, The Durmand Priory [MapAlpineSlope]" }, + { fileName: "275155.data", name: "(40-50) Dredgehaunt Cliffs [MapAlpineCrest]" }, + { fileName: "278717.data", name: "(50-60) Timberline Falls [MapAlpineTimberland]" }, + { fileName: "846866.data", name: "(50-60) Timberline Falls" }, + { fileName: "276252.data", name: "(70-80) Frostgorge Sound [MapAlpineGlacier]" }, + { fileName: "295282.data", name: "(HoM) Eye of the North [MapAlpineMonument]" }, + ], + }, + { + name: "Core - Tarnished Coast [Wetland]", + maps: [ + { fileName: "198272.data", name: "(City) Rata Sum [MapWetlandComplex]" }, + { fileName: "1968896.data", name: "(City) Rata Sum" }, + { fileName: "198076.data", name: "(City) The Grove [MapWetlandGrove]" }, + { fileName: "1969341.data", name: "(City) The Grove" }, + { fileName: "195149.data", name: "(1-15) Caledon Forest [MapWetlandBayou]" }, + { fileName: "195493.data", name: "(1-15) Metrica Province [MapWetlandRiverside]" }, + { fileName: "293307.data", name: "(15-25) Brisban Wildlands [MapWetlandGrotto]" }, + { fileName: "292254.data", name: "(55-65) Sparkfly Fen [MapWetlandGlade]" }, + { fileName: "291064.data", name: "(60-70) Mount Maelstrom [MapWetlandCape]" }, + ], + }, + { + name: "Core - Ruins of Orr [Risen]", + maps: [ + { fileName: "284829.data", name: "(70-75) Straits of Devastation [MapRisenBeachhead]" }, + { fileName: "285089.data", name: "(75-80) Malchor's Leap [MapRisenCliff]" }, + { fileName: "285634.data", name: "(80) Cursed Shore [MapRisenShore]" }, + ], + }, + { + name: "Core - Personal Story", + maps: [ + { + fileName: "295962.data", + name: "(20-60) A Vision of Darkness, A Light in the Darkness [MapWetlandDestiny]", + }, + { fileName: "1019669.data", name: "(40-60) Old Lion's Arch [MapValleyArchOrig]" }, + { fileName: "294938.data", name: "(60) Claw Island [MapValleyClaw]" }, + { + fileName: "1018612.data", + name: "(70) Forging the Pact [MapAlpineTimberlandBeforeConcordiaVines]", + }, + { + fileName: "295179.data", + name: "(80) Temple of the Forgotten God [MapRisenBeachheadAbaddon]", + }, + { fileName: "473765.data", name: "(80) Victory or Death [MapRisenDragonStory]" }, + ], + }, + { + name: "Core - Dungeon", + maps: [ + { fileName: "126840.data", name: "(30-35) Ascalonian Catacombs" }, + { fileName: "189364.data", name: "(30-35) Ascalonian Catacombs [MapRegrownCatacomb]" }, + { fileName: "287214.data", name: "(40-45) Caudecus's Manor [MapValleyEstate]" }, + { fileName: "291284.data", name: "(50) Twilight Arbor [MapWetlandGarden]" }, + { fileName: "645968.data", name: "(55-80) Twilight Arbor [MapWetlandGardenRepeat]" }, + { fileName: "275474.data", name: "(60-65) Sorrow's Embrace [MapAlpineFurnace]" }, + { fileName: "284039.data", name: "(70-75) Citadel of Flame [MapRegrownShaman]" }, + { fileName: "276520.data", name: "(76-80) Honor of the Waves [MapAlpineIceberg]" }, + { fileName: "293606.data", name: "(78-80) Crucible of Eternity [MapWetlandWeapon]" }, + { fileName: "473930.data", name: "(80) The Ruined City of Arah [MapRisenDragonRepeat]" }, + ], + }, + { + name: "(LW1) Living World Season 1: Scarlet's War - (SM) Strike Mission", + maps: [ + { + fileName: "2771534.data", + name: "(Lounge) Memory of Old Lion's Arch [MapValleyArchProbed]", + }, + { fileName: "568778.data", name: "(LW1.E1) Cragstead [MapAlpineEnclave]" }, + { fileName: "580061.data", name: "(LW1.E1) Molten Furnace [MapFlameFrost]" }, + { + fileName: "2690992.data", + name: "(LW1.E2) Memorials on the Pyre, The Scene of the Crime [MapValleyArchDragon]", + }, + { fileName: "595722.data", name: "(LW1.E2) Aetherblade Retreat [MapValleyArchDungeon]" }, + { fileName: "2711089.data", name: "(LW1.E3) Scarlet's Playhouse [MapJubileeArena-2]" }, + { + fileName: "672138.data", + name: "(LW1.E4) The Nightmare Unveiled [MapValleyWildernessKraitTowerInstance]", + }, + { fileName: "679089.data", name: "(LW1.E4) The Tower of Nightmares [MapValleyWildernessKraitTowerInterior]" }, + { + fileName: "2469960.data", + name: "(LW1.E5) The Twisted Marionette [MapAlpineSlopeMarionette]", + }, + { fileName: "2770873.data", name: "(LW1.E5) The Battle For Lion's Arch [MapValleyArch2]" }, + { + fileName: "2773298.data", + name: "(LW1.E5) North Evacuation Camp [MapValleySettlementFeb2014]", + }, + { fileName: "814803.data", name: "(LW1.E5) Lion's Arch: Honored Guests [MapValleyArch3]" }, + { fileName: "2771205.data", name: "(SM) Old Lion's Court [MapValleyArch2Strike]" }, + ], + }, + { + name: "(LW2) Living World Season 2: Glint's Prophecy", + maps: [ + { fileName: "836211.data", name: "(LW2.E1, LW2.E2, LW2.E4) Dry Top [MapDryTop]" }, + { fileName: "861770.data", name: "(LW2.E1, LW2.E2, LW2.E4) Dry Top [MapDryTopE2]" }, + { fileName: "909361.data", name: "(LW2.E5, LW2.E6, LW2.E7, LW2.E8) The Silverwastes [MapSandCastle]" }, + { fileName: "996202.data", name: "(LW2.E5, LW2.E6, LW2.E7, LW2.E8) The Silverwastes [MapSandcastleToFleet]" }, + { fileName: "908730.data", name: "(LW2.E5.4) Hidden Arcana [MapSandGrain]" }, + { + fileName: "922320.data", + name: "(LW2.E7.2) Meeting the Asura [MapWetlandRiversideAsuraFirstContact]", + }, + ], + }, + { + name: "(X1) Guild Wars 2: Heart of Thorns (HoT) - (Z) Zone - Maguuma Jungle [Jungle]", + maps: [ + { fileName: "969663.data", name: "(Z.1) Verdant Brink [MapJungleFleet]" }, + { fileName: "1263739.data", name: "(Z.2) Auric Basin [MapJungleGold]" }, + { fileName: "1264291.data", name: "(Z.3) Tangled Depths [MapJungleRoots]" }, + { fileName: "1262310.data", name: "(Z.4) Dragon's Stand [MapJungleArmy]" }, + { fileName: "1262460.data", name: "(X1.16) Hearts and Minds [MapJungleArmyNightmare]" }, + ], + }, + { + name: "(LW3) Living World Season 3: Glint's Legacy", + maps: [ + { fileName: "1472635.data", name: "(LW3.E1) Bloodstone Fen [MapJungleBloodstone]" }, + { fileName: "1498071.data", name: "(LW3.E2.1) Taimi's Game [MapHoloRoom]" }, + { fileName: "1498578.data", name: "(LW3.E2) Ember Bay [MapFireIsland]" }, + { fileName: "1605211.data", name: "(LW3.E3) Bitterfrost Frontier [MapAlpineTundra]" }, + { fileName: "1646520.data", name: "(LW3.E4) Lake Doric [MapValleyPort]" }, + { fileName: "1645474.data", name: "(LW3.E4.6) Confessor's End [MapValleyEstatePort]" }, + { fileName: "1682493.data", name: "(LW3.E5) Draconis Mons [MapLavaLamp]" }, + { fileName: "1682763.data", name: "(LW3.E5.5) Heart of the Volcano [MapLavaLampInstance2]" }, + { fileName: "1734839.data", name: "(LW3.E6.1) White Mantle Hideout [MapS0E6AspectHunt]" }, + { fileName: "1735440.data", name: "(LW3.E6.2) Shining Blade Headquarters [MapValleyBlade]" }, + { fileName: "1735346.data", name: "(LW3.E6) Siren's Landing [MapReclaimed]" }, + ], + }, + { + name: "(X2) Guild Wars 2: Path of Fire (PoF) - (Z) Zone - Crystal Desert [Desert]", + maps: [ + { fileName: "1794574.data", name: "(Z.1) Crystal Oasis [MapDesertOasis]" }, + { fileName: "1833034.data", name: "(Z.2) Desert Highlands [MapDesertHighlands]" }, + { + fileName: "1840368.data", + name: "(X2.7, X2.OS) Facing the Truth: The Sanctum, The Dark Library [MapDesertSanctum]", + }, + { fileName: "1840103.data", name: "(Z.3) Elon Riverlands [MapDesertRiver]" }, + { + fileName: "1833726.data", + name: "(X2.8, X2.9) The Way Forward, The Departing [MapDesertMists]", + }, + { fileName: "1842533.data", name: "(Z.4) The Desolation [MapDesertTorment]" }, + { fileName: "1839188.data", name: "(Z.5) Domain of Vabbi [MapDesertPalace]" }, + ], + }, + { + name: "(LW4) Living World Season 4: Rise of Kralkatorrik", + maps: [ + { + fileName: "1903523.data", + name: "(LW4.E1.1) Eye of the Brandstorm [MapDesertOasisInstanceS4E1]", + }, + { fileName: "1902235.data", name: "(LW4.E1) Domain of Istan [MapDesertJewel]" }, + { fileName: "1901428.data", name: "(LW4.E1.6) Fahranur, the First City [MapDesertCity]" }, + { + fileName: "1954984.data", + name: "(LW4.E2.1) Tracking the Scientist [MapDesertArchipelago_Chapter1]", + }, + { + fileName: "1955224.data", + name: "(LW4.E2.2) The Test Subject [MapDesertArchipelago_Chapter2]", + }, + { fileName: "1957526.data", name: "(LW4.E2) Sandswept Isles [MapDesertArchipelagoLargeMap]" }, + { fileName: "1955471.data", name: "(LW4.E2.5) The Charge [MapDesertArchipelago_Chapter5]" }, + { fileName: "1955642.data", name: "(LW4.E2.5) ??? [MapDesertArchipelago_Chapter5Boss_1]" }, + { fileName: "1955915.data", name: "(LW4.E2.5) ??? [MapDesertArchipelago_Chapter5Boss_2]" }, + { fileName: "1956140.data", name: "(LW4.E2.5) ??? [MapDesertArchipelago_Chapter5Boss_3]" }, + { fileName: "1956245.data", name: "(LW4.E2.5) ERROR: SIGNAL LOST [MapDesertArchipelago_Chapter5Boss_4]" }, + { fileName: "2005467.data", name: "(LW4.E3.1) Seized [MapDesertOasisS4E3]" }, + { fileName: "2004704.data", name: "(LW4.E3) Domain of Kourna [MapDesertMoon]" }, + { fileName: "2044320.data", name: "(LW4.E4) Jahai Bluffs, Sun's Refuge [MapDesertBluffs]" }, + { fileName: "2044502.data", name: "(LW4.E4.5) Storm Tracking [MapDesertBluffsCh5]" }, + { fileName: "2093791.data", name: "(LW4.E5.1) Scion & Champion [MapThe_Begining]" }, + { fileName: "2092435.data", name: "(LW4.E5) Thunderhead Peaks [MapAlpineKeep]" }, + { fileName: "2092812.data", name: "(LW4.E5.3) The Crystal Blooms [MapAlpineKeepInstance]" }, + { + fileName: "2093450.data", + name: "(LW4.E5.5) The Crystal Dragon [MapAlpineKeepInstanceKralk]", + }, + { fileName: "2124612.data", name: "(LW4.PP) Mists Rift [MapBrandedMistfight]" }, + { fileName: "2146312.data", name: "(LW4.E6.1) The End [MapDesertDragonfallCh01]" }, + { fileName: "2146346.data", name: "(LW4.E6.1) Dragonflight [MapDesertDragonfallCh02]" }, + { fileName: "2146125.data", name: "(LW4.E6) Dragonfall [MapDesertDragonfall]" }, + { fileName: "2146510.data", name: "(LW4.E6.5) Descent [MapDesertDragonfallFinalInstance]" }, + { fileName: "2146376.data", name: "(LW4.E6.5) Epilogue [MapDesertDragonfallEpilogue]" }, + ], + }, + { + name: "(LW5) Living World Season 5: The Icebrood Saga (IBS) - (SM) Strike Mission, (DRM) Dragon Response Missions", + maps: [ + { fileName: "2203371.data", name: "(LW5.E0, SM.1) Grothmar Valley, Shiverpeaks Pass [MapRegrownBlood]" }, + { fileName: "2251232.data", name: "(LW5.E1, LW5.E2) Bjora Marches [MapBjoraMarchesCombined]" }, + { fileName: "2224355.data", name: "(SM.2) Voice of the Fallen and Claw of the Fallen [MapKodanBNB]" }, + { fileName: "2224381.data", name: "(SM.3) Fraenir of Jormag [Mapshamanbnb]" }, + { fileName: "2224406.data", name: "(SM.4) Boneskinner [MapWendigoBNB]" }, + { fileName: "2249817.data", name: "(LW5.E2.5) Voice in the Deep [MapAlpineMarchesEp2FinalInstance]" }, + { fileName: "2251486.data", name: "(SM.5) Whisper of Jormag [MapWhisperofJormag]" }, + { fileName: "2251447.data", name: "(Lobby) Eye of the North [MapAlpineMonumentDragon]" }, + { fileName: "2272807.data", name: "(LW5.VotP.1, SM.6) Forging Steel [MapAlpineClimb]" }, + { fileName: "2273128.data", name: "(LW5.VotP.2) Darkrime Delves [MapAlpineDelves]" }, + { fileName: "2298865.data", name: "(LW5.E3) Drizzlewood Coast [MapAlpineCascades]" }, + { fileName: "2318029.data", name: "(LW5.E3, LW5.E4) Drizzlewood Coast [MapAlpineCascades02]" }, + { fileName: "2299088.data", name: "(SM.7) Cold War [MapAlpineCascadesStrike]" }, + { fileName: "2369582.data", name: "(LW5.E5.1) Primordus Rising [MapWetlandComplexE5Story]" }, + { + fileName: "2370614.data", + name: "(LW5.E5.3, DRM.1) Metrica Province [MapWetlandRiversideS5E5]", + }, + { + fileName: "2370017.data", + name: "(LW5.E5.3, DRM.2) Brisban Wildlands [MapWetlandGrottoS5E5]", + }, + { + fileName: "2369116.data", + name: "(LW5.E5.3, DRM.3) Gendarran Fields [MapValleySettlementS5E5]", + }, + { fileName: "2366776.data", name: "(LW5.E5.4, DRM.4) Fields of Ruin [MapRegrownHawkeS5E5]" }, + { + fileName: "2364032.data", + name: "(LW5.E5.4, DRM.5) Thunderhead Peaks [MapAlpineKeepS5E5]", + }, + { fileName: "2368400.data", name: "(LW5.E5.5, DRM.6) Lake Doric [MapValleyPortS5E5]" }, + { fileName: "2365787.data", name: "(LW5.E5.5, DRM.7) Snowden Drifts [MapAlpinePowderS5E5]" }, + { fileName: "2369398.data", name: "(LW5.E5.6, DRM.8) Caledon Forest [MapWetlandBayouS5E5]" }, + { fileName: "2414140.data", name: "(LW5.E5.7) Wildfire [MapLavaLampInstance_S5E5]" }, + { fileName: "2367211.data", name: "(LW5.E5.8, DRM.9) Bloodtide Coast [MapValleyCoastS5E5]" }, + { fileName: "2366368.data", name: "(LW5.E5.9, DRM.10) Fireheart Rise [MapRegrownFlameS5E5]" }, + { fileName: "2434582.data", name: "(LW5.E5) Dragonstorm [MapDragonFight]" }, + { fileName: "2434675.data", name: "(LW5.E5.11) Champion's End [MapDragonFightStoryInstance]" }, + ], + }, + { + name: "(X3) Guild Wars 2: End of Dragons (EoD) - (Z) Zone, (SM) Strike Mission - Cantha [Cantha]", + maps: [ + { fileName: "2669133.data", name: "(Lounge) Thousand Seas Pavilion [MapMTXLounge]" }, + { fileName: "2639738.data", name: "(X3.1) Old Friends [MapAlpineSlopeX03]" }, + { fileName: "2639795.data", name: "(X3.1) Aetherblade Armada [MapCanthaArmada]" }, + { fileName: "2647516.data", name: "(Z.1) Seitung Province [MapCanthaShingJea]" }, + { fileName: "2649141.data", name: "(SM.1) Aetherblade Hideout [MapMaiTrin]" }, + { fileName: "2645519.data", name: "(Z.2) New Kaineng City [MapCanthaKaineng]" }, + { fileName: "2645805.data", name: "(X3.7) Deepest Secrets: Yong Reactor [MapCanthaKainengCH5Reactor]" }, + { fileName: "2640407.data", name: "(Lobby) Arborstone [MapCanthaArborstone]" }, + { fileName: "2641850.data", name: "(Z.3) The Echovald Wilds [MapCanthaEchovald]" }, + { + fileName: "2642769.data", + name: "(SM.2) Xunlai Jade Junkyard [MapCanthaEchovaldStrikeMissions]", + }, + { fileName: "2646104.data", name: "(SM.3) Kaineng Overlook [MapCanthaKainengMinSecStrike]" }, + { fileName: "2644196.data", name: "(Z.4) Dragon's End [MapCanthaJadeSea]" }, + { fileName: "2702043.data", name: "(SM.4) Harvest Temple [MapCanthaJadeSeaStrikeMission]" }, + { fileName: "3012212.data", name: "(Z.5) Gyala Delve [MapCanthaDeep]" }, + { fileName: "3043972.data", name: "(Z.5) Gyala Delve [MapCanthaDeepQR2]" }, + { + fileName: "3100947.data", + name: "(X3.18) Forward [MapCanthaShingJeaExpac4AureneInstance]", + }, + ], + }, + { + name: "(X4) Guild Wars 2: Secrets of the Obscure (SotO) - (Z) Zone, (SM) Strike Mission - Skies of Tyria [Sky]", + maps: [ + { + fileName: "3134712.data", + name: "(X4.1) Commander without a Cause: Gendarran Fields [MapValleySettlementExpac4StealthMission]", + }, + { fileName: "3134778.data", name: "(Z.1) Skywatch Archipelago [MapSkyRise]" }, + { + fileName: "3135285.data", + name: "(SM.1) Cosmic Observatory [MapSkyRiseStrikeObservatory]", + }, + { fileName: "3135660.data", name: "(Lobby) The Wizard's Tower [MapSkyTower]" }, + { fileName: "3135805.data", name: "(Z.2) Amnytas [MapSkySpire]" }, + { fileName: "3136072.data", name: "(SM.2) Temple of Febe [MapCerusArena]" }, + { fileName: "3193573.data", name: "(?) Convergences [MapBountyIslands]" }, + { fileName: "3194054.data", name: "(Z.3) Inner Nayos [MapDream]" }, + { fileName: "3264516.data", name: "(Z.3) Inner Nayos [MapDream2]" }, + { fileName: "3316196.data", name: "(Z.3) Inner Nayos [MapDream3]" }, + ], + }, + { + name: "(GH) Guild Halls", + maps: [ + { fileName: "1255378.data", name: "(GH.1-2) Gilded Hollow [MapGuildCavern]" }, + { fileName: "1256064.data", name: "(GH.1-2) Lost Precipice [MapGuildHeights]" }, + { fileName: "1843274.data", name: "(GH.3) Windswept Haven [MapGuildPyramid]" }, + { fileName: "2648082.data", name: "(GH.4) Isle of Reflection [MapGuildIsle]" }, + ], + }, + { + name: "Cooperative - (FotM) Fractals of the Mists", + maps: [ + { fileName: "1733961.data", name: "(Lounge) Mistlock Sanctuary [MapInfiniteCosmicVIPLounge]" }, + { fileName: "1498016.data", name: "(FotM.0) Mistlock Observatory [MapInfiniteHub]" }, + { fileName: "519839.data", name: "(FotM.0-9) Fractals of the Mists [MapInfiniteIslands]" }, + { fileName: "2187042.data", name: "(FotM.0-9) Aquatic Ruins [MapInfiniteUnderwater]" }, + { fileName: "1426653.data", name: "(FotM.0-9) Cliffside [MapInfiniteCliffside]" }, + { fileName: "1472382.data", name: "(FotM.0-9) Snowblind [MapInfiniteSnowblind]" }, + { fileName: "1472406.data", name: "(FotM.0-9) Swampland [MapInfiniteSwamp]" }, + { + fileName: "1498798.data", + name: "(FotM.10-14) Aetherblade, Captain Mai Trin Boss [MapValleyArchDungeonUpdated02]", + }, + { + fileName: "1905739.data", + name: "(FotM.10-14) Molten Furnace, Molten Boss [MapFlameFrostFractalExtended]", + }, + { fileName: "697450.data", name: "(FotM.10-14) Thaumanova Reactor [MapInfiniteReactor]" }, + { fileName: "1472361.data", name: "(FotM.15) Chaos Isles [MapInfiniteChaos]" }, + { fileName: "1605344.data", name: "(FotM.16) Nightmare [MapInfiniteToxic]" }, + { fileName: "1733857.data", name: "(FotM.17) Shattered Observatory [MapInfiniteCosmic]" }, + { fileName: "1905889.data", name: "(FotM.18) Twilight Oasis [MapInfiniteMordant]" }, + { fileName: "2005713.data", name: "(FotM.19) Deepstone [MapInfiniteLabyrinth]" }, + { fileName: "2094098.data", name: "(FotM.20) Siren's Reef [MapInfiniteCove]" }, + { fileName: "2333932.data", name: "(FotM.21) Sunqua Peak [MapFractalElementalIslands]" }, + { fileName: "3100195.data", name: "(FotM.22) Silent Surf [MapLuxonFractal]" }, + { fileName: "3317434.data", name: "(FotM.23) Lonely Tower [MapSkyRiseFractalEparch]" }, + ], + }, + { + name: "Cooperative - (R) Raids", + maps: [ + { + fileName: "1427048.data", + name: "(Lobby, R.0) Lion's Arch Aerodrome, Special Forces Training Area [MapValleyArchRaidLobby]", + }, + { fileName: "1151420.data", name: "(R.1) Spirit Vale [MapRaidJungle01]" }, + { fileName: "1383309.data", name: "(R.2) Salvation Pass [MapE1R2]" }, + { fileName: "1454070.data", name: "(R.3) Stronghold of the Faithful [MapE1R3]" }, + { fileName: "1645215.data", name: "(R.4) Bastion of the Penitent [MapE1R4]" }, + { fileName: "1906329.data", name: "(R.5) Hall of Chains [MapE1R5]" }, + { fileName: "2045250.data", name: "(R.6) Mythwright Gambit [MapE2R2]" }, + { fileName: "2157962.data", name: "(R.7) The Key of Ahdashim [MapE2R3]" }, + ], + }, + { + name: "Competitive - Player vs. Player (PvP) - (CQ) Conquest, (MB) Murderball, (SH) Stronghold, (TDM) Team Deathmatch", + maps: [ + { fileName: "132570.data", name: "(Lobby) Heart of the Mists" }, + { fileName: "197249.data", name: "(Lobby) Heart of the Mists [MapPvPLobby]" }, + { fileName: "1713939.data", name: "(Lobby) Heart of the Mists [Mappvplobbyrework_cats]" }, + { fileName: "1734729.data", name: "(Lobby) Heart of the Mists [Mappvplobbyrework_catsMoreRoom]" }, + { fileName: "2129692.data", name: "(Lobby) Heart of the Mists [MapPvPLobby1016rework]" }, + { fileName: "132710.data", name: "(CQ.1-4) Battle of Khylo" }, + { fileName: "197402.data", name: "(CQ.1-4) Battle of Kyhlo [MapPvPConquestSiege]" }, + { fileName: "1644708.data", name: "(CQ.1-4) Battle of Khylo [MapPvPConquestSiege2]" }, + { fileName: "1666233.data", name: "(CQ.1-4) Battle of Khylo [MapPvPConquestSiege3]" }, + { fileName: "132837.data", name: "(CQ.1-4) Forest of Niflhel" }, + { fileName: "197545.data", name: "(CQ.1-4) Forest of Niflhel [MapPvPConquestForest]" }, + { fileName: "376916.data", name: "(CQ.1-4) Legacy of the Foefire [MapPvPConquestGuild]" }, + { fileName: "467374.data", name: "(CQ.1-4) Raid on the Capricorn" }, + { fileName: "520609.data", name: "(CQ.5) Temple of the Silent Storm [MapPvPConquestDojo]" }, + { fileName: "556199.data", name: "(CQ.6) Spirit Watch" }, + { fileName: "1473061.data", name: "(CQ.6) Spirit Watch [MapPVPConquestSpirit2]" }, + { fileName: "579383.data", name: "(CQ.7) Skyhammer" }, + { fileName: "677968.data", name: "(CQ.7) Skyhammer" }, + { fileName: "1426736.data", name: "(CQ.7) Skyhammer [MapPvPConquestCannonCapture]" }, + { fileName: "1934470.data", name: "(CQ.7) Skyhammer [MapPvPConquestCannonCapture2]" }, + { fileName: "1472979.data", name: "(CQ.8) Revenge of the Capricorn [MapPvPConquestCoastReturn]" }, + { fileName: "1644624.data", name: "(CQ.8) Revenge of the Capricorn [MapPvPConquestCoastReturnshrunk]" }, + { fileName: "1498174.data", name: "(CQ.9) Eternal Coliseum [MapPVPConquestArenaGods2]" }, + { fileName: "1704155.data", name: "(CQ.9) Eternal Coliseum [MapPVPConquestArenaGods4]" }, + { fileName: "2128880.data", name: "(CQ.9) Eternal Coliseum [MapPVPConquestArenaGodsTheme]" }, + { fileName: "2065760.data", name: "(CQ.10) Djinn's Dominion [Mapdesertconq]" }, + { fileName: "2128938.data", name: "(CQ.10) Djinn's Dominion [MapDesertConqWallMid]" }, + { fileName: "2175965.data", name: "(CQ.10) Djinn's Dominion [MapDesertConqWallMid2]" }, + { fileName: "791564.data", name: "(MB, TDM.2) Courtyard [MapDMCourtyard]" }, + { fileName: "1713054.data", name: "(MB, TDM.2) Courtyard [MapDMCourtyard2]" }, + { fileName: "870987.data", name: "(SH) Battle of Champion's Dusk [MapPvPStrongholdCity]" }, + { fileName: "871093.data", name: "(SH) Battle of Champion's Dusk [MapPvPStrongholdCityMercs]" }, + { fileName: "1712986.data", name: "(TDM.1) Hall of the Mists [MapHallway2v2]" }, + { fileName: "1712945.data", name: "(TDM.3) Asura Arena [Mapasura2v2]" }, + { fileName: "2187125.data", name: "(TDM.4) Auric Span [MapJungle2v2]" }, + ], + }, + { + name: "Competitive - World vs. World (WvW) - (MW) Mist War, (EotM) Edge of the Mists", + maps: [ + { fileName: "2113077.data", name: "(Lounge) Armistice Bastion [MapWvwLounge]" }, + { fileName: "131235.data", name: "(MW) Eternal Battlegrounds, Obsidian Sanctum" }, + { fileName: "195806.data", name: "(MW) Eternal Battlegrounds, Obsidian Sanctum [MapWvWCenter]" }, + { fileName: "1798709.data", name: "(MW) Eternal Battlegrounds, Obsidian Sanctum [MapWvWCenterGliding]" }, + { fileName: "1885693.data", name: "(MW) Eternal Battlegrounds, Obsidian Sanctum [MapWvWCenter4]" }, + { + fileName: "2263889.data", + name: "(MW) Eternal Battlegrounds, Obsidian Sanctum [MapWvWCenterWallChange10_19]", + }, + { fileName: "131574.data", name: "(MW) Alpine Borderlands" }, + { fileName: "641501.data", name: "(MW) Alpine Borderlands [MapWvWRedHomeLake01]" }, + { fileName: "1799855.data", name: "(MW) Alpine Borderlands [MapWvWRedHomeLake01gliding]" }, + { fileName: "1918037.data", name: "(MW) Alpine Borderlands [MapWvWRedHomeLake02]" }, + { fileName: "1427803.data", name: "(MW) Desert Borderlands [MapWvWDesertHomeUpdate]" }, + { fileName: "1647236.data", name: "(MW) Desert Borderlands [MapWvWDesertHomeUpdateMIDrework]" }, + { fileName: "1799442.data", name: "(MW) Desert Borderlands [MapWvWDesertHome4]" }, + { fileName: "2112733.data", name: "(MW) Desert Borderlands [MapWvWDesertHome]" }, + { fileName: "736241.data", name: "(EotM) Edge of the Mists [MapWvWIslands]" }, + ], + }, + { + name: "Festival - (LNY) Lunar New Year", + maps: [ + { fileName: "1625212.data", name: "(City) Divinity's Reach [MapValleyDivinityLNY]" }, + { fileName: "595582.data", name: "(LNY) Dragon Ball Arena [MapDragonBall]" }, + ], + }, + { + name: "Festival - (SAB) Super Adventure Festival - Super Adventure Box [SAB]", + maps: [ + { fileName: "1666365.data", name: "(City) Rata Sum [MapWetlandComplexSAB]" }, + { fileName: "569756.data", name: "(SAB) Super Adventure Box" }, + { fileName: "636133.data", name: "(Lobby) Hub [MapSABHub]" }, + { fileName: "635555.data", name: "(SAB.1) World 1 [MapSABWorld1]" }, + { fileName: "635960.data", name: "(SAB.2) World 2 [MapSABWorld2]" }, + { fileName: "3024941.data", name: "(SAB.3) World 3 [MapSABWorld3-0]" }, + { fileName: "3281398.data", name: "(SAB.3) World 3 [MapSABWorld3-1]" }, + ], + }, + { + name: "Festival - (DB) Dragon Bash", + maps: [{ fileName: "2164993.data", name: "(City) Hoelbrak [MapAlpineHallDragonBash]" }], + }, + { + name: "Festival - (FotFW) Festival of the Four Winds", + maps: [ + { fileName: "606255.data", name: "(FotFW) Labyrinthine Cliffs [MapEvenKiteCity]" }, + { fileName: "605983.data", name: "(FotFW) Sanctum Sprint [MapEvenTriathlonKiteCity]" }, + { fileName: "617120.data", name: "(FotFW) Aspect Arena [MapEvenPVPKiteCity]" }, + { fileName: "622681.data", name: "(FotFW) The Crown Pavilion [MapJubileeArena]" }, + ], + }, + { + name: "Festival - (HW) Halloween - Mad King's Realm [MadKing]", + maps: [ + { fileName: "1869665.data", name: "(City) Lion's Arch [MapValleyArchKielHalloween]" }, + { fileName: "506670.data", name: "(HW) Mad King's Labyrinth, Lunatic Inquisition [MapMadKingMaze]" }, + { fileName: "662436.data", name: "(HW) Mad King's Labyrinth, Lunatic Inquisition [MapMadKingMaze2013]" }, + { fileName: "2499169.data", name: "(HW) Mad King's Labyrinth, Lunatic Inquisition [MapMadKingMaze2021]" }, + { fileName: "506739.data", name: "(HW) Mad King's Clock Tower [MapMadKingTower]" }, + { fileName: "506539.data", name: "(HW) Mad King's Raceway, Reaper's Rumble [MapMadKingField]" }, + { fileName: "506592.data", name: "(HW) Ascent to Madness [MapMadKingBoss]" }, + ], + }, + { + name: "Festival - (WD) Wintersday - (SM) Strike Mission - Wintersday Celebration [Wintersday]", + maps: [ + { + fileName: "705746.data", + name: "(City) Divinity's Reach [MapWintersDayValleyDivinity2013]", + }, + { fileName: "1917775.data", name: "(City) Divinity's Reach [MapValleyDivinityholiday]" }, + { fileName: "529718.data", name: "(WD) Bell Choir Ensemble, Snowball Mayhem [MapWintersdaySnowGlobe]" }, + { fileName: "529896.data", name: "(WD) Tixx's Infinirarium, Toypocalypse [MapWintersdayAirship]" }, + { fileName: "529945.data", name: "(WD) Winter Wonderland [MapWintersdayFrostyland]" }, + { fileName: "2076921.data", name: "(SM) Secret Lair of the Snowmen [MapFrozenTyrant]" }, + ], + }, + { + name: "Miscellaneous", + maps: [ + { fileName: "122695.data", name: "(((Empty Plane)))" }, + { fileName: "129834.data", name: "Lake Doric" }, + { fileName: "132853.data", name: "(((Empty Box)))" }, + { fileName: "184799.data", name: "[MapDummy]" }, + { fileName: "193081.data", name: "Lake Doric [MapValleyReach]" }, + { fileName: "197562.data", name: "[MapPvPBlackBox]" }, + { fileName: "606030.data", name: "Basket Brawl [MapBasketBrawl]" }, + { fileName: "875614.data", name: "[MapTutorialChina]" }, + { fileName: "969964.data", name: "Verdant Brink [MapRootsAfterShip]" }, + { fileName: "1255516.data", name: "[MapGuildColiseum]" }, + { fileName: "1255634.data", name: "(((Unknown Town)))" }, + { fileName: "1282201.data", name: "(((WvW)))" }, + { fileName: "1498193.data", name: "[MapPvPConquestTemp]" }, + { fileName: "1513556.data", name: "[MapPvPInfection2]" }, + { fileName: "1513607.data", name: "[MapPvPConquestTest_01]" }, + { fileName: "1513620.data", name: "[MapPvPConquestTest_02]" }, + { fileName: "1513675.data", name: "[MapPvPConquestTest_04]" }, + { fileName: "1956299.data", name: "[MapDesertArchipelago_Instance]" }, + { fileName: "2204239.data", name: " [MapRegrownBloodCinematic]" }, + { fileName: "2224545.data", name: "Jaga Moraine [MapAlpinemoraine]" }, + { fileName: "2224624.data", name: "[MapAlpineMoraineFinalInstance]" }, + { fileName: "2257438.data", name: "[MapTest]" }, + { fileName: "2649061.data", name: " [MapRegrownBlood_CinematicEOD]" }, + { fileName: "2644298.data", name: "[MapJadeSeaWhirlpool]" }, + { fileName: "2689589.data", name: " [MapDesertHighlandsE3]" }, + ], + }, + ], + }; + + /** + * Parse the beginning of a file to find its type + * + * @memberof FileTypes + */ + function getFileType(buffer) { + const dataView = new DataView(buffer); + const first4 = String.fromCharCode(dataView.getUint8(0), dataView.getUint8(1), dataView.getUint8(2), dataView.getUint8(3)); + // Parse textures + switch (first4) { + case "ATEC": + return "TEXTURE_ATEC"; + case "ATEP": + return "TEXTURE_ATEP"; + case "ATET": + return "TEXTURE_ATET"; + case "ATEU": + return "TEXTURE_ATEU"; + case "ATEX": + return "TEXTURE_ATEX"; + case "ATTX": + return "TEXTURE_ATTX"; + } + if (first4.indexOf("DDS") === 0) + return "TEXTURE_DDS"; + if (first4.indexOf("PNG") === 1) + return "TEXTURE_PNG"; + if (first4.indexOf("RIFF") === 0) + return "TEXTURE_RIFF"; + if (first4.indexOf("YUI") === 0) + return "TEXT_YUI"; + // PackFiles + if (first4.indexOf("PF") === 0) { + const file = new t3dParser.FileParser(buffer, true); /// true for "plz no load chunkz" + return "PF_" + file.header.type; + } + // Binaries + if (first4.indexOf("MZ") === 0) + return "BINARIES"; + // Strings + if (first4.indexOf("strs") === 0) + return "STRINGS"; + // Raw asnd chunk (without pack file) + if (first4.indexOf("asnd") === 0) + return "CHUNK_ASND"; + // TODO: parse all buffers and if all bytes are valid unicode symbols then + // return TEXT_UNKNOWN; + // Unknown + return "UNKNOWN"; + } + + var FileTypes = /*#__PURE__*/Object.freeze({ + __proto__: null, + getFileType: getFileType + }); + + /** + * A statefull class that handles reading and inflating data from a local GW2 dat file. + */ + class LocalReader { + settings; + dataReader; + persistantStore; + file; + indexTable; + fileMetaTable; + persistantData = []; + _fileTypeCache; + constructor(settings) { + this.settings = settings; + this.dataReader = new DataReader(settings); + this.file = undefined; + this.indexTable = []; + this.fileMetaTable = []; + if (settings.noIndexedDB !== false) { + this.persistantStore = new PersistantStore(); + } + } + /** + * Asynchronously loads the archive by parsing its file index and header. + */ + async openArchive(file) { + const { metaTable, indexTable } = await t3dParser.ArchiveParser.readArchive(file); + this.fileMetaTable = metaTable; + this.indexTable = indexTable; + this.file = file; + } + /** + * Gets MFT index by baseId + */ + getFileIndex(baseId) { + return this.indexTable[baseId]; + } + /** + * Returns the metadata of a file stored in the archive + */ + getFileMeta(mftId) { + return this.fileMetaTable[mftId]; + } + /** + * Fetch a file and uncompress it if needed / required. + */ + async readFile(mftId, isImage, raw, fileLength, extractLength) { + if (!this.file) + throw new Error("No file loaded"); + //let buffer, dxtType, imageWidth, imageHeight; + const meta = this.getFileMeta(mftId); + if (!meta) + throw new Error("Unexistant file"); + // Slice up the data + const buffer = await t3dParser.ParsingUtils.sliceFile(this.file, Number(meta.offset), fileLength || meta.size); + // If needed we decompress, if not we keep raw + if (raw || meta.compressed) { + let data = { + buffer: undefined, + dxtType: undefined, + imageWidth: undefined, + imageHeight: undefined, + }; + await this.dataReader + .inflate(buffer, buffer.byteLength, mftId, isImage, extractLength || 0) + .then((result) => { + data = result; + }) + .catch(() => { + data = { + buffer: undefined, + dxtType: undefined, + imageWidth: undefined, + imageHeight: undefined, + }; + }); + return data; + } + else + return { buffer }; + } + /** + * Scans asynchronously the types of all the files listed in the archive. + * Uses persistant store to cache and speed up a rescan. + */ + async readFileList( + // This is a way for platforms not supporting indexDB to provide their own persistant storage. + oldFileList) { + if (!this.file) + throw new Error("No file loaded"); + const self = this; + let persistantList = oldFileList || []; + let persistantId; + // Load previously saved data + if (this.persistantStore) { + const lastListing = await this.persistantStore.getLastListing(this.file.name); + persistantList = lastListing.array; + // If the last scan was not completed then we will just update it.. + if (!lastListing.complete) { + persistantId = lastListing.key; + } + } + // Create a list of all the baseIds we need to inspect + const iterateList = Object.keys(self.indexTable).map((i) => Number(i)); + for (const index in persistantList) { + if (!(index in self.indexTable)) + iterateList.push(index); + } + // Spawn the decompression tasks + const taskArray = []; + for (let i = 0; i < 1; i++) { + taskArray[i] = Promise.resolve({ task: i }); + } + // Helps us to know when we need to update the persistant store + let persistantNeedsUpdate = false; + // Iterate through the array + for (const index in iterateList) { + const baseId = iterateList[index]; + // First use a synchronous function to know if we need to scan the file + const result = this._needsScan(baseId, persistantList); + if (result.scan === true) { + const taskId = (await Promise.race(taskArray)).task; + taskArray[taskId] = this._readFileType(baseId).then((scanResult) => { + // Put the result into our persistant storage + persistantList[baseId] = { + baseId: baseId, + size: scanResult.size, + crc: scanResult.crc, + fileType: scanResult.fileType, + }; + return { task: taskId }; + }); + } + if (result.change === "removed") { + // Update the persistant storage + delete persistantList[baseId]; + } + // Handle persistant storage update + if (result.change !== "none") + persistantNeedsUpdate = true; + // Tasks to do only every % + if (index % Math.floor(iterateList.length / 100) === 0) { + // Print progress + T3D.Logger.log(T3D.Logger.TYPE_PROGRESS, "Finding types", index / Math.floor(iterateList.length / 100)); + // Update the persistant storage if needed + if (self.persistantStore && persistantNeedsUpdate) { + persistantNeedsUpdate = false; + self.persistantStore + .putListing(persistantId, persistantList, self.file.name, false) + .then((res) => (persistantId = res)); + } + } + } + await Promise.all(taskArray).then(() => { + // Finally update the listing as complete + if (self.persistantStore) { + self.persistantStore.putListing(persistantId, persistantList, self.file.name, true); + } + }); + this.persistantData = persistantList; + return this.getFileList(); + } + /** + * Cheap version of the readFileList which will only scan files registered in the mapFileList + * This helps us being sure that we only return files that contain a mapc chunk when using + * the getMapList function + */ + async readMapList() { + const fileList = mapMap.maps.reduce((maps, category) => { + return maps.concat(category.maps.map((entry) => entry.fileName)); + }, []); + const temporaryStore = []; + for (const fileName of fileList) { + const baseId = fileName.split(".data")[0]; + if (this.indexTable[baseId]) { + const scanResult = await this._readFileType(baseId); + temporaryStore[baseId] = { + baseId: Number(baseId), + size: scanResult.size, + crc: scanResult.crc, + fileType: scanResult.fileType, + }; + } + } + // Fill the store without saving it to disk + this.persistantData = temporaryStore; + } + /** + * Returns a list of all the maps with their name and category. + * Uncategorized maps are available only if readFileList have been used before. + */ + async getMapList() { + const self = this; + const mapArray = []; + // If the archive hasn't been completely scanned we do a partial scan for the map files. + // It should be fast + if (this.persistantData.length === 0) { + await this.readMapList(); + } + // Filter the maps out of all our files + const reversedIndex = this.getReverseIndex(); + const maps = this.persistantData + .filter((file) => file.fileType === "PF_mapc") + .filter((id) => id.baseId === reversedIndex[self.getFileIndex(id.baseId)][0]); + for (const map of maps) { + let found = false; + // Try to see if we already have some informations on this map + for (const category of mapMap.maps) { + const fileMap = category.maps.find((item) => Number(item.fileName.split(".data")[0]) === map.baseId); + if (fileMap) { + mapArray.push({ + name: fileMap.name, + category: category.name, + baseId: map.baseId, + categoryIndex: mapMap.maps.indexOf(category), + }); + found = true; + break; + } + } + // If not we register it as Uncategorized + if (!found) { + mapArray.push({ + name: map.baseId.toString(), + category: "Uncategorized", + baseId: map.baseId, + categoryIndex: 99999, + }); + } + } + mapArray.sort((a, b) => a.category.localeCompare(b.category)); + return mapArray; + } + /** + * Return the meta table with extra information such as an array of baseIds and the file types. + * The filetype is available only if readFileList have been used before of course. + */ + getFileList() { + const typeList = this.persistantData ? this.persistantData.map((i) => i.fileType) : []; + const reverseBaseIdList = this.getReverseIndex(); + const fileList = this.fileMetaTable.map((meta, mftId) => { + const baseIds = reverseBaseIdList[mftId] ? reverseBaseIdList[mftId] : []; + const type = reverseBaseIdList[mftId] ? typeList[baseIds[0]] : "Non-Registered"; + return { + mftId: mftId, + baseIdList: baseIds, + size: meta.size, + crc: meta.crc, + fileType: type, + }; + }); + fileList[0] = { + mftId: 0, + baseIdList: [], + size: 0, + crc: 0, + fileType: "Non-Registered", + }; + return fileList; + } + /** + * @returns {Array>} + */ + getReverseIndex() { + return this.indexTable.reduce((reversed, mftId, baseId) => { + if (mftId in reversed) + reversed[mftId].push(baseId); + else + reversed[mftId] = [baseId]; + return reversed; + }, []); + } + // Callback wrapper + /** + * Reads data from a file in the dat. + * If `raw` is true, any infation is skipped and raw data is returned. + */ + loadFile(baseId, callback, isImage, raw) { + const mftId = this.getFileIndex(baseId); + if (mftId <= 0) + return callback(null); + this.readFile(mftId, isImage, raw).then((result) => { + if (result.buffer === undefined) + return callback(null); + callback(result.buffer, result.dxtType, result.imageWidth, result.imageHeight); + }); + } + // Private + _needsScan(baseId, persistantData) { + if (baseId <= 0) + return { change: "none", scan: false }; + const mftId = this.getFileIndex(baseId); + const metaData = this.getFileMeta(mftId); + // Nothing interesting + if (metaData === undefined && !(baseId in persistantData)) { + return { change: "none", scan: false }; + } + // If the file have been deleted + else if (metaData === undefined) { + return { change: "removed", scan: false }; + } + // If the file is new + else if (!(baseId in persistantData)) { + return { change: "added", scan: true }; + } + // If the size or crc don't match + else if (metaData.size !== persistantData[baseId].size || metaData.crc !== persistantData[baseId].crc) { + return { change: "modified", scan: true }; + } + // If everything is the same + else { + return { change: "none", scan: false }; + } + } + async _readFileType(baseId) { + if (!this._fileTypeCache) + this._fileTypeCache = []; + const mftId = this.getFileIndex(baseId); + const metaData = this.getFileMeta(mftId); + let fileType; + if (this._fileTypeCache[baseId] !== undefined) { + fileType = this._fileTypeCache[baseId]; + } + else { + const fileBuffer = (await this.readFile(mftId, false, false, Math.min(metaData.size, 1000), 32)).buffer; + if (fileBuffer === undefined) + return undefined; + fileType = getFileType(fileBuffer); + } + return { fileType: fileType, crc: metaData.crc, size: metaData.size }; + } + } + + /** + * Base class for data interpretors a.k.a. 'Renderers' + * + * Renderers are classes that collect and interpret data from the dat file. + * + * A {{#crossLink "LocalReader"}}{{/crossLink}} instance is used for accessing data from the dat. + * + * A {{#crossLink "Logger"}}{{/crossLink}} is used for posting progress output or error messages. + * + * The generated data, be it strings, numbers or meshes are put into a value object structure called + * the 'context'. The context can store data generated by multiple renderers and makes sure each + * renderer type, or class has it's own value object within the context. This enables one renderer + * to read data written by another renderer wihtout having to worry about overwriting existing data + * within the context. Keep in mind that you will have to manually pass and clean the conext object! + * + * A clean context object should just be the empty javasript object : {}. + * + * When a Renderer is done it will fire the callback and any view interrested in retrieving the generated + * data from the context can read it using + * {{#crossLink "T3D/getContextValue:method"}}{{/crossLink}}. + * + * + * + * + * @class DataRenderer + * @constructor + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class DataRenderer { + localReader; + settings; + context; + rendererName; + static rendererName = "DataRenderer"; + logger; + constructor(localReader, settings, context, logger_, rendererName = "DataRenderer") { + this.localReader = localReader; + this.settings = settings; + this.context = context; + this.rendererName = rendererName; + /// Just storing parameters + if (!settings) { + settings = {}; + } + this.context[rendererName] = {}; + if (!logger_) { + this.logger = T3D.Logger; + } + else { + this.logger = logger_; + } + } + /** + * Gets the output value object for a specified class within the context. + * + * @param {Class} otherClass The class to fetch the output value object for. + * If not specified the class of this instance will be used. + * @return {Object} The output value object for this class within the context. + */ + getOutput(otherClass) { + return this.context[otherClass ? otherClass.rendererName : this.rendererName]; + } + /** + * Basic rendering of unknown files. Output fileds generated: + * + * - *fileId* The fileId passed in the settings parameter when constructing this instance. + * + * - *rawData* An ArrayBuffer containg the infalted binary data of the loaded file. + * + * - *rawString* A string representation of the rawData + * + * - *image* A value object witht he fields 'width', 'height' and 'data' describing a RGBA bitmap + * image. Only set if the loaded file was a texture. + * + * - *file* A FileParser representation of the loaded file. Only set if the loaded file was a Pack File. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + const self = this; + this.localReader.loadFile(this.settings.id, function (inflatedData) { + /// Set fileId so callers can identify this VO + self.getOutput().fileId = self.settings.id; + /// Share inflated data + self.getOutput().rawData = inflatedData; + /// Construct raw string + const uarr = new Uint8Array(inflatedData); + const rawStrings = []; + const chunksize = 0xffff; + const len = Math.min(uarr.length, 10000); + // There is a maximum stack size. We cannot call String.fromCharCode with as many arguments as we want + for (let i = 0; i * chunksize < len; i++) { + //@ts-ignore + rawStrings.push(String.fromCharCode.apply(null, uarr.subarray(i * chunksize, (i + 1) * chunksize))); + } + if (len < uarr.length) { + rawStrings.push("T3D Ignored the last " + (uarr.length - len) + " bytes when generating this raw output"); + } + self.getOutput().rawString = rawStrings.join(); + /// Check if this is an PF or ATEX file + // Binareis are MZ + const dataView = new DataView(inflatedData); + const first4 = String.fromCharCode(dataView.getUint8(0), dataView.getUint8(1), dataView.getUint8(2), dataView.getUint8(3)); + /// Do special stuff for different fcc signatures + /// + /// fourcc != fcc::ATEX && fourcc != fcc::ATEC && fourcc != fcc::ATEP && + /// fourcc != fcc::ATET && fourcc != fcc::ATEU && fourcc != fcc::ATTX) + /// + if (first4 === "ATEX" || + first4 === "ATEC" || + first4 === "ATEP" || + first4 === "ATET" || + first4 === "ATEU" || + first4 === "ATTX") { + /// TODO: MOVE TO GW2 texture file!! + /// Load file using LocalReader. + self.localReader.loadFile(self.settings.id, function (inflatedData, dxtType, imageWidth, imageHeigth) { + /// Create image using returned data. + const image = { + data: new Uint8Array(inflatedData), + width: imageWidth, + height: imageHeigth, + }; + self.getOutput().image = image; + callback(); + }, true); + } + else if (first4.indexOf("PF") === 0) { + self.getOutput().file = new t3dParser.FileParser(inflatedData); + callback(); + } + else { + self.getOutput().file = null; + callback(); + } + }); + } + } + + /* + guid 1683952224941671000 is fucked up floor in SAB HUB + materialFilename for that mesh is 564821, shared with lots of stuff + lod 1 and 2 are both 0 + material flags is 2056 + */ + /** + * Builds a custom vertex shader for a given number of uv cannels. + * WIP not implemented yet! + * + * @memberof MaterialUtils + * @param {Number} numUv Number of UV channels used by this shader + * @return {String} Genereted vertex shader source + */ + function buildVS(numUv) { + let vdefs = ""; + let adefs = ""; + let reads = ""; + for (let i = 0; i < numUv; i++) { + vdefs += "varying vec2 vUv_" + (i + 1) + ";\n"; + /// uv and uv2 are defined by THREE + if (i > 1) + adefs += "attribute vec2 uv" + (i + 1) + ";\n"; + reads += "vUv_" + (i + 1) + " = uv" + (i > 0 ? i + 1 : "") + ";\n"; + } + return (adefs + + vdefs + + "void main()\n" + + "{\n" + + reads + + "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n" + + "gl_Position = projectionMatrix * mvPosition;\n" + + "}"); + } + /** + * Generate a texture of a specified color, used to be part of THREEjs + * + * @memberof MaterialUtils + * @param {Number} width + * @param {Number} height + * @param {THREE.Color} color + * @returns {THREE.DataTexture} + */ + function generateDataTexture(width, height, color) { + // create a buffer with color data + const size = width * height; + const data = new Uint8Array(4 * size); + const r = Math.floor(color.r * 255); + const g = Math.floor(color.g * 255); + const b = Math.floor(color.b * 255); + const a = 255; + for (let i = 0; i < size; i++) { + const stride = i * 4; + data[stride] = r; + data[stride + 1] = g; + data[stride + 2] = b; + data[stride + 3] = a; + } + // used the buffer to create a DataTexture + return new THREE.DataTexture(data, width, height, THREE.RGBAFormat); + } + /** + * Builds a custom pixel shader for a given number of uv cannels. + * WIP not implemented yet! + * + * @memberof MaterialUtils + * @param {Array} textures THREE textures + * @param {Number} numUv Number of UV channels used by this shader + * @param {Number} alphaTest Texture see-trough alpha treshold + * @param {any} lightMap TODO + * @returns {string} + */ + function buildPS(textures, numUv, alphaTest, lightMap) { + const t1uv = "vUv_" + (textures[0].uvIdx + 1); + let discard = ""; + if (alphaTest) { + discard = " if (c1.a < 0.5) \n" + " discard;\n"; + } + /// Color from 1st text or lighted by 2nd? + let writeColor = "gl_FragColor = c1;\n"; + if (lightMap) { + const texIdx = 0; + // var t2uv = "vUv_4";//+(3-textures[texIdx].uvIdx+1); + const t2uv = "vUv_1"; // + (textures[texIdx].uvIdx+1); + // console.log("t2uv",t2uv); + writeColor = " vec4 c2 = texture2D( texture" + (texIdx + 1) + ", " + t2uv + " );\n" + " gl_FragColor = c2;\n"; + // " gl_FragColor = vec4(c2.rgb * c1.r/.5, c2.a);\n"; + } + let uniforms = ""; + textures.forEach(function (t, idx) { + uniforms += "uniform sampler2D texture" + (idx + 1) + ";\n"; + }); + /* uniforms += "uniform sampler2D texture1;\n"; + if(lightMap) + uniforms += "uniform sampler2D texture2;\n"; */ + let varyings = ""; + for (let i = 0; i < numUv; i++) { + varyings += "varying vec2 vUv_" + (i + 1) + ";\n"; + } + return (uniforms + + varyings + + "void main( void ) {\n" + + " vec4 c1 = texture2D( texture1, " + + t1uv + + " );\n" + + discard + + writeColor + + "}"); + } + /** + * WIP, concept for generatin materials to render multi UV chanelled meshes. + * + * @memberof MaterialUtils + * @param {Array} textures THREE texture + * @param {Number} numUV Number of UV channels used by this shader + * @param {Number} alphaTest Texture see-trough alpha treshold + * @return {THREE.ShaderMaterial} Generated shader + */ + function getUVMat(textures, numUV, alphaTest) { + let lightMap = false; + const uniforms = {}; + textures.forEach(function (t, idx) { + uniforms["texture" + idx] = { type: "t", value: t }; + }); + if (textures.length > 1) { + lightMap = true; + } + const attributes = {}; + for (let i = 2; i < numUV; i++) { + attributes["uv" + (i + 1)] = { type: "v2", value: [] }; + } + const vs = buildVS(numUV); + return new THREE.ShaderMaterial({ + uniforms: uniforms, + vertexShader: vs, + fragmentShader: buildPS(textures, numUV, alphaTest, lightMap), + // @ts-ignore + attributes: attributes, + side: THREE.FrontSide, + }); + } + /** + * Builds a THREE texture from a ModelMaterialData by reading settings and + * loading any required data from the localReader. Uses sharedTextures for + * texture caching. + * + * This method is full of guesses and estimations, and could be improved on + * a lot, allowing rendering of multi UV channeled materials, or special + * materials like custom color chanelled gear. + * + * @memberof MaterialUtils + * @param {ModelMaterialData} material + * @param {FileParser} materialFile A FileParser instance, must be of type AMAT + * @param {LocalReader} localReader The LocalReader to load the file contents from. + * @param {Object} sharedTextures Value Object for keeping the texture cache + * @return {THREE.Material} A THREE Material with the generated contents and settings. + */ + function getMaterial(material, materialFile, localReader, sharedTextures) { + if (!materialFile) + return; + const dxChunk = materialFile.getChunk("dx9s"); + let grChunk = materialFile.getChunk("grmt"); + if (!dxChunk) { + return getSimpleMaterial(material, materialFile, localReader, sharedTextures); + } + /// Append all textures to the custom material + const finalTextures = []; + // Some materials don't use textures.. + if (material && material.textures.length && dxChunk.data.techniques.length > 0) { + /// TODO: check for flags! + /// + /// techinques[] -> passes[] -> effects[] -> samplerIndex[] + /// + // console.log("num effects",dxChunk.data.techniques[0].passes[0].effects.length); + // if(grChunk.data.flags!=76) + // return; + /// 3 teqs : high medium low GRAPHICS LEVEL SETTINGS + /// 1 passes DON'T CARE + /// 15 effects Each effect has a pixel shader HOW?? + /// 1 or 2 sampler indices USE ALL! (Multi material) + const effects = dxChunk.data.techniques[0].passes[0].effects; + // var effect = effects[10]; + const effect = effects[0]; + //let shader = dxChunk.data.shaders[effect.pixelShader]; + /* effects.forEach(function (eff) { + if(eff.samplerIndex.length > effect.samplerIndex.length) + effect = eff; + }); */ + // var samplerIdx = effect.samplerIndex[0]; + const samplerTextures = []; + let textureToken; // UINT64 + let samplerTex; + for (let i = 0; i < effect.samplerIndex.length; i++) { + const samplerIdx = effect.samplerIndex[i]; + const sampler = dxChunk.data.samplers[samplerIdx]; + /// SHOULD NEVER HAPPEN, hide mesh! + if (!sampler) + continue; // return; + textureToken = sampler && Number(grChunk.data.texTokens[sampler.textureIndex]); + if (!textureToken) + textureToken = 0; + /* else + textureToken =textureToken.val; */ + /// Find the texture reffered by this sampler + samplerTex = null; + material.textures.forEach(function (tex /*, index*/) { + /// Seems like only 1st part of token is used... + if (!samplerTex && Number(tex.token) === textureToken) { + // console.log("TEX match",tex.token, textureToken) + samplerTex = tex; + } + }); + /// Add this sampler's texture to the collection of all textures + if (samplerTex) { + samplerTextures.push(samplerTex); + } + else { + /// FALLBACK, just guess what texture we should use + if (sampler) { + samplerTextures.push(material.textures[sampler.textureIndex]); + } + else if (material.textures.length > 0) { + samplerTextures.push(material.textures[0]); + } + else { + return; + } + } + } /// END for each sampler index in effect + /// We now have all textures + // console.log("textures from sampler", samplerTextures); + /// Fallback to using whatever texture there is. + if (samplerTextures.length <= 0) { + return; + // mainTex = material.textures[0]; + } + // console.log("num samplers ",samplerTextures.length); + samplerTextures.forEach(function (texture, idx) { + if (!texture) + return; + /// Set texture "URL" + const texURL = texture && texture.filename; + /// Load texture from RAM or local reader: + finalTextures[idx] = getTexture(texURL, localReader, sharedTextures); + if (finalTextures[idx]) { + finalTextures[idx].uvIdx = texture.uvPSInputIndex; + } + }); + } /// End if material and texture + let finalMaterial; + /// Create custom shader material if there are textures + if (finalTextures) { + // TODO: make this work! + // eslint-disable-next-line no-constant-condition, no-constant-binary-expression + { + let ft; + let nt; + material.textures.forEach(function (t) { + // Flag for diffuse map + if (!ft && Number(t.token) === 1733499172) + ft = t; + // Flag for normal map + if (!nt && Number(t.token) === 404146670) + nt = t; + }); + if (!ft || ft.filename <= 0) + return; + finalMaterial = new THREE.MeshPhongMaterial({ + side: THREE.FrontSide, + map: getTexture(ft.filename, localReader, sharedTextures), + }); + if (nt) { + const normalMap = getTexture(nt.filename, localReader, sharedTextures); + normalMap.flipY = true; + finalMaterial.normalMap = normalMap; + } + finalMaterial.textureFilename = ft.filename; + if (grChunk.data.flags !== 16460) { + // console.log("Setting alpha flag for ",grChunk.data.flags) + finalMaterial.alphaTest = 0.05; + } + } + } + /// Fallback material is monocolored red + else { + finalMaterial = new THREE.MeshBasicMaterial({ + side: THREE.FrontSide, + color: 0xff0000, + flatShading: true, + }); + } + finalMaterial.needsUpdate = true; + /// Set material props + /// disable for now in order for custom shaders not to fuck up + if (material) { + const alphaMask0 = 0x0001; // + 0x0100 + 0x0200; + const alphaMask1 = 0x0010; + const alphaMask2 = 0x0100 + 0x0200; + //let alphaMask2b = 0x0200; + grChunk = materialFile.getChunk("grmt"); + // Enable alpha test for transparent flags + if (material.materialFlags & alphaMask0 || + material.materialFlags & alphaMask1 || + material.materialFlags & alphaMask2 // && solidColor != null + ) ; + /// GRCHUNK -> DATA -> FLAGS + /// HAS LIGHT - TEX - ? - EMISSIVE16460 + /// + /// 56533 LOD FOR TOMBSTONE? + // 16460 0100 0000 0100 1100 "standard" stuff rendering OK in SAB (no alpha test) + // + // 16452(SAB) 0100 0000 0100 0100 yellow numbers in sab signs + // 16448(SAB) 0100 0000 0100 0000 faces on rocks, cloudmen, skybox portal images, holes in walls, floor plates... + // no lighting?? + // + // 8268 0010 0000 0100 1100 + // 3392 0000 1101 0100 0000 Moto machine light bulbs + // 2380 0000 1001 0100 1100 + // 2368 0000 1001 0100 0000 Fountain water with rings, portal border and circular "light" + // 332 0000 0001 0100 1100 + // 324 0000 0001 0100 0100 Moto face sprites + // + // 320(SAB) 0000 0001 0100 0000 portal textures (normal maps ish) + // + // 76 0000 0000 0100 1100 LOTS OF STUFF + // Tree leaves, ground, hills, some roofs, flags, street lights + // sheild textures, some fences, water tops, waterfall + // + // IN KHYLO "everything with alpha" + // + // + // 68 0000 0000 0100 0100 Some flowers (lo res?) fountain edges foam + // + // 64(SAB) 0000 0000 0100 0000 clouds, sun iamge + const lightMask = 8; + const knownFileFlags = [24652, 16460, 16452, 16448, 8268, 3392, 2380, 2368, 332, 324, 320, 76, 68, 64]; + if (knownFileFlags.indexOf(grChunk.data.flags) < 0) { + T3D.Logger.log(T3D.Logger.TYPE_WARNING, "unknown GR flag", grChunk.data.flags); + } + if (!(grChunk.data.flags & lightMask)) { + // debugger; + // console.log("no light"); + finalMaterial = new THREE.MeshBasicMaterial({ + side: THREE.FrontSide, + map: finalMaterial.map, + }); + } + if (grChunk.data.flags !== 16460) { + finalMaterial.alphaTest = 0.05; + } + } /// End if material + return finalMaterial; + } + function getSimpleMaterial(material, materialFile, localReader, sharedTextures) { + if (!materialFile) + return; + const grChunk = materialFile.getChunk("grmt"); + let ft; + let nt; + material.textures.forEach(function (t) { + console.log(t); + // Flag for diffuse map + if (!ft && Number(t.token) === 1733499172) + ft = t; + if (!ft && t.token === 27219515885689124n) + ft = t; + // Flag for normal map + if (!nt && Number(t.token) === 404146670) + nt = t; + if (!nt && t.token === 850610087184878n) + nt = t; + }); + console.log(ft); + if (!ft || ft.filename <= 0) { + return; + } + const finalMaterial = new THREE.MeshPhongMaterial({ + side: THREE.FrontSide, + map: getTexture(ft.filename, localReader, sharedTextures), + }); + if (nt) { + const normalMap = getTexture(nt.filename, localReader, sharedTextures); + normalMap.flipY = true; + finalMaterial.normalMap = normalMap; + } + finalMaterial.textureFilename = ft.filename; + if (grChunk.data.flags !== 16460) { + finalMaterial.alphaTest = 0.05; + } + finalMaterial.needsUpdate = true; + return finalMaterial; + } + /** + * Load image data into a THREE.Texture from a texture file in the .dat file, using a LocalReader. + * Any loaded tetures are added to sharedTextures, allowing for texture caching and fewer reads. + * + * @memberof MaterialUtils + * @param {Number} texURL The fileId or baseId of the file to load image data from. + * @param {LocalReader} localReader The LocalReader to load the file contents from. + * @param {Object} sharedTextures Value Object for keeping the texture cache + * @return {THREE.Texture} A texture that will be populated by the file data when it is loaded. + */ + function getTexture(texURL, localReader, sharedTextures) { + let finalTexture; + /// Read texture from shared array of loaded textures + /// or read it from URL and add to shared ones! + if (texURL && sharedTextures[texURL]) { + /// Just read from already loaded textures. + finalTexture = sharedTextures[texURL]; + } + else if (texURL) { + /// Load and add to shared array. + finalTexture = loadLocalTexture(localReader, texURL); + /// Set standard texture functionality. + finalTexture.wrapT = THREE.RepeatWrapping; + finalTexture.wrapS = THREE.RepeatWrapping; + finalTexture.flipY = false; + sharedTextures[texURL] = finalTexture; + } + return finalTexture; + } + /** + * Load image data into a THREE.Texture from a texture file in the .dat file, using a LocalReader. + * If you're loading multiple textures, make sure to use + * {{#crossLink "MaterialUtils/getTexture"}}{{/crossLink}} that allows you to cache textures. + * + * @memberof MaterialUtils + * @param {LocalReader} localReader - The LocalReader to load the file contents from. + * @param {Number} fileId - The fileId or baseId of the file to load image data from. + * @param {Number} mapping - What THREE mapping the returned texture will use, not implemented. + + * @return {THREE.Texture} A texture that will be populated by the file data when it is loaded. + */ + function loadLocalTexture(localReader, fileId, mapping, defaultColor, onerror) { + if (defaultColor === undefined) { + defaultColor = Math.floor(0xffffff * Math.random()); + } + /// Temporary texture that will be returned by the function. + /// Color is randomized in order to differentiate different textures during loading. + const texture = generateDataTexture(1, // Width + 1, // Height + new THREE.Color(defaultColor) // Color + ); + // Threejs r71 is using these settings by default, r72+ changed it + texture.minFilter = THREE.LinearMipMapLinearFilter; + texture.magFilter = THREE.LinearFilter; + texture.generateMipmaps = true; + texture.flipY = true; + /// Only allow non-zero fileId, otherwise jsut return static texture + if (parseInt(String(fileId)) <= 0) { + if (onerror) + onerror(); + return texture; + } + /// Load file using LocalReader. + localReader.loadFile(fileId, function (inflatedData, dxtType, imageWidth, imageHeigth) { + /// Require infalted data to be returned. + if (!inflatedData) { + if (onerror) + onerror(); + return; + } + /// Create image using returned data. + const image = { + data: new Uint8Array(inflatedData), + width: imageWidth, + height: imageHeigth, + }; + /// Use RGBA for all textures for now... + /// TODO: don't use alpha for some formats! + texture.format = + //eslint-disable-next-line no-constant-condition + dxtType === 3 || dxtType === 5 || true ? THREE.RGBAFormat : THREE.RGBFormat; + /// Update texture with the loaded image. + //@ts-ignore + texture.image = image; + texture.needsUpdate = true; + }, true); + /// Return texture with temporary content. + return texture; + } + + var MaterialUtils = /*#__PURE__*/Object.freeze({ + __proto__: null, + buildPS: buildPS, + buildVS: buildVS, + generateDataTexture: generateDataTexture, + getMaterial: getMaterial, + getSimpleMaterial: getSimpleMaterial, + getTexture: getTexture, + getUVMat: getUVMat, + loadLocalTexture: loadLocalTexture + }); + + /** + * + * A renderer that generates some of the environment objects of a map. + * + * @class EnvironmentRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "mapFile", a FileParser. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class EnvironmentRenderer extends DataRenderer { + static rendererName = "EnvironmentRenderer"; + mapFile; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "EnvironmentRenderer"); + this.mapFile = this.settings.mapFile; + } + getMat(tex) { + return new THREE.MeshBasicMaterial({ + map: tex, + side: THREE.BackSide, + fog: false, + depthWrite: false, + }); + } + loadTextureWithFallback(targetMatIndices, materialArray, filename, fallbackFilename, hazeColorAsInt) { + const self = this; + function writeMat(mat) { + targetMatIndices.forEach(function (i) { + materialArray[i] = mat; + }); + } + function loadFallback() { + const mat = self.getMat(new THREE.TextureLoader().load(fallbackFilename)); + writeMat(mat); + } + function errorCallback() { + setTimeout(loadFallback, 1); + } + const mat = self.getMat(loadLocalTexture(this.localReader, filename, undefined, hazeColorAsInt, errorCallback)); + writeMat(mat); + } + getHazeColor(environmentChunkData) { + const hazes = environmentChunkData && environmentChunkData.dataGlobal.haze; + if (!hazes || hazes.length <= 0) { + return [190, 160, 60]; + } + else { + return hazes[0].farColor; + } + } + parseLights(environmentChunkData) { + const self = this; + /// Set up output array + self.getOutput().lights = []; + const lights = environmentChunkData + ? environmentChunkData.dataGlobal.lighting + : [ + { + lights: [], + backlightIntensity: 1.0, + backlightColor: [255, 255, 255], + }, + ]; + let ambientLight; + // var light = lights[0]; + // + let hasLight = false; + lights.forEach(function (light /*, idx*/) { + if (hasLight) + return; + /// Directional lights + // eslint-disable-next-line @typescript-eslint/no-unused-vars + let sumDirLightIntensity = 0; + light.lights.forEach(function (dirLightData /*, idx*/) { + hasLight = true; + const color = new THREE.Color(dirLightData.color[2] / 255.0, dirLightData.color[1] / 255.0, dirLightData.color[0] / 255.0); + const directionalLight = new THREE.DirectionalLight(color.getHex(), dirLightData.intensity); + directionalLight.position + .set(-dirLightData.direction[0], dirLightData.direction[2], dirLightData.direction[1]) + .normalize(); + sumDirLightIntensity += dirLightData.intensity; + self.getOutput().lights.push(directionalLight); + }); // END for each directional light in light + /// Add some random directional lighting if there was no, in order to se SOME depth on models + if (!light.lights || light.lights.length === 0) { + const directions = [ + [0, 1, 0, 0.3], + [1, 2, 1, 0.3], + [-1, -2, -1, 0.3], + ]; + directions.forEach(function (lightDir) { + const color = new THREE.Color(1, 1, 1); + const intensity = lightDir[3]; + const directionalLight = new THREE.DirectionalLight(color.getHex(), intensity); + directionalLight.position.set(lightDir[0], lightDir[1], lightDir[2]).normalize(); + sumDirLightIntensity += intensity; + self.getOutput().lights.push(directionalLight); + }); + } + /// Ambient light + // light.backlightIntensity /= sumDirLightIntensity +light.backlightIntensity; + // light.backlightIntensity = light.backlightIntensity; + const color = new THREE.Color((light.backlightIntensity * (255.0 - light.backlightColor[2])) / 255.0, (light.backlightIntensity * (255.0 - light.backlightColor[1])) / 255.0, (light.backlightIntensity * (255.0 - light.backlightColor[0])) / 255.0); + ambientLight = new THREE.AmbientLight(color); + }); // END for each light in lighting + let ambientTotal = 0; + if (ambientLight) { + ambientTotal = ambientLight.color.r + ambientLight.color.g + ambientLight.color.b; + this.getOutput().lights.push(ambientLight); + } + /// Parsing done, set hasLight flag and return + this.getOutput().hasLight = hasLight || ambientTotal > 0; + } + parseSkybox(environmentChunkData, parameterChunkData, hazeColorAsInt) { + /// set up output array + this.getOutput().skyCubeTexture = null; + this.getOutput().skyBox = null; + /// Grab sky texture. + /// index 0 and 1 day + /// index 2 and 3 evening + let skyModeTex = environmentChunkData && environmentChunkData.dataGlobal.skyModeTex[0]; + /// Fallback skyboxfrom dat. + if (!skyModeTex) { + skyModeTex = { + texPathNE: 187554, + texPathSW: 187556, + texPathT: 187558, + }; + } + /// Calculate bounds + const bounds = parameterChunkData.rect; + Math.abs(bounds[0] - bounds[2]); + Math.abs(bounds[1] - bounds[3]); + const materialArray = []; + /// Load skybox textures, fallback to hosted png files. + this.loadTextureWithFallback([1, 4], materialArray, skyModeTex.texPathNE + 1, "img/193068.png", hazeColorAsInt); + this.loadTextureWithFallback([0, 5], materialArray, skyModeTex.texPathSW + 1, "img/193070.png", hazeColorAsInt); + this.loadTextureWithFallback([2], materialArray, skyModeTex.texPathT + 1, "img/193072.png", hazeColorAsInt); + materialArray[3] = new THREE.MeshBasicMaterial({ visible: false }); + /// Create skybox geometry + const boxSize = 1024; // boundSide * 2; + const skyGeometry = new THREE.BoxGeometry(boxSize, boxSize / 2, boxSize); // Width Height Depth + /// Ugly way of fixing UV maps for the skybox (I think) + skyGeometry.faceVertexUvs[0].forEach((vecs, idx) => { + const face = Math.floor(idx / 2); + // PX NX + // PY NY + // PZ NZ + /// PX - WEST NX - EAST + if (face === 0 || face === 1) { + vecs.forEach((vec2) => { + vec2.x = 1 - vec2.x; + vec2.y /= 2.0; + vec2.y += 0.5; + }); + } + /// NZ - SOUTH PZ - NORTH + else if (face === 5 || face === 4) { + vecs.forEach((vec2) => { + vec2.y /= -2.0; + vec2.y += 0.5; + }); + } + else { + vecs.forEach((vec2) => { + vec2.x = 1 - vec2.x; + }); + } + }); + skyGeometry.uvsNeedUpdate = true; + /// Generate final skybox + const skyBox = new THREE.Mesh(skyGeometry, materialArray); + /// Put horizon in camera center + // skyBox.translateY(-(boxSize / 8)); + // skyBox.translateY( -environmentChunk.data.dataGlobal.sky.verticalOffset ); + /// Write to output + this.getOutput().skyBox = skyBox; + } + /** + * Output fileds generated: + * + * - *hazeColor* Array of RGBA values describing the global haze color of the map. + * - *lights* An array of THREE.DirectionalLight and THREE.AmbientLight objects. + * - *hasLight* Boolean is false if no directional lights were added to "lights". + * - *skyBox* A textured THREE.Mesh skybox. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + if (!this.mapFile) { + throw new Error("No map file available for EnvironmentRenderer"); + } + const environmentChunkData = this.mapFile.getChunk("env").data; + const parameterChunkData = this.mapFile.getChunk("parm").data; + /// Set renderer clear color from environment haze + const hazeColor = this.getHazeColor(environmentChunkData); + const hazeColorAsInt = hazeColor[2] * 256 * 256 + hazeColor[1] * 256 + hazeColor[0]; + this.getOutput().hazeColor = hazeColor; + /// Add directional lights to output. Also write hasLight flag + this.parseLights(environmentChunkData); + /// Generate skybox + this.parseSkybox(environmentChunkData, parameterChunkData, hazeColorAsInt); + /// All parsing is synchronous, just fire callback + callback(); + } + } + + /** + * + * A renderer that generates meshes describing the collisions of a map. + * + * @class HavokRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "mapFile", a FileParser. If "visible" is specified and true, the generated meshes will be textured + * with a MeshNormalMaterial, otherwise they will not be visible. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class HavokRenderer extends DataRenderer { + static rendererName = "HavokRenderer"; + mapFile; + lastP; + seed; + meshes; + geometries; + animations; + havokChunkData; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "HavokRenderer"); + this.mapFile = this.settings.mapFile; + this.lastP = -1; + this.seed = 1; + this.meshes = []; + } + /** + * TODO + * + * @param {Function} callback [description] + * @async + */ + renderModels(models, title, callback) { + let mat; + if (this.settings && this.settings.visible) { + mat = new THREE.MeshNormalMaterial({ side: THREE.DoubleSide }); + } + else if (this.settings && this.settings.export) { + mat = new THREE.MeshBasicMaterial({ visible: true }); + } + else { + mat = new THREE.MeshBasicMaterial({ visible: false }); + } + this.parseAllModels(models, mat, title, 200, 0, callback); + } + /** + * TODO + * + * @param {*} animation [description] + * @param {*} collisions [description] + * @return {*} [description] + */ + getCollisionsForAnimation(animation, collisions) { + const ret = []; + for (let i = 0; i < animation.collisionIndices.length; i++) { + const index = animation.collisionIndices[i]; + const collision = collisions[index]; + collision.index = index; + ret.push(collision); + } + return ret; + } + /** + * TODO + * + * @param {*} models [description] + * @param {*} mat [description] + * @param {*} title [description] + * @param {*} chunkSize [description] + * @param {*} offset [description] + * @return {*} callback [description] + * @async + */ + parseAllModels(models, mat, title, chunkSize, offset, callback) { + let i = offset; + for (; i < offset + chunkSize && i < models.length; i++) { + const p = Math.round((i * 100) / models.length); + if (p !== this.lastP) { + this.logger.log(T3D.Logger.TYPE_PROGRESS, "Loading Collision Models (" + title + ")", p); + this.lastP = p; + } + /// Get animation object + const animation = this.animationFromGeomIndex(models[i].geometryIndex, this.geometries, this.animations); + const collisions = this.getCollisionsForAnimation(animation, this.havokChunkData.collisions); + for (let j = 0; j < collisions.length; j++) { + const collision = collisions[j]; + this.renderMesh(collision, models[i], mat); + } + } + if (i < models.length) { + setTimeout(this.parseAllModels.bind(this, models, mat, title, chunkSize, offset + chunkSize, callback), 10 /* time in ms to next call */); + } + else { + callback(); + } + } + /** + * TODO + * + * @param {*} propGeomIndex [description] + * @param {*} geometries [description] + * @param {*} animations [description] + * @return {*} [description] + */ + animationFromGeomIndex(propGeomIndex, geometries, animations) { + // geometries is just list of all geometries.animations[end] for now + const l = geometries[propGeomIndex].animations.length; + return animations[geometries[propGeomIndex].animations[l - 1]]; + // return animations[ geometries[propGeomIndex].animations[0] ]; + } + /** + * TODO + * + * @param {*} collision [description] + * @param {*} model [description] + * @param {*} mat [description] + * @return {*} [description] + */ + renderMesh(collision, model, mat) { + const pos = model.translate; + const rot = model.rotate; + const scale = 32 * model.scale; + /// Generate mesh + const mesh = this.parseHavokMesh(collision, mat); + /// Position mesh + /// "x","float32","z","float32","y","float32" + mesh.position.set(pos[0], -pos[2], -pos[1]); + /// Scale mesh + if (scale) + mesh.scale.set(scale, scale, scale); + /// Rotate mesh + if (rot) { + mesh.rotation.order = "ZXY"; + // ["x","float32","z","float32","y","float32"], + mesh.rotation.set(rot[0], -rot[2], -rot[1]); + } + /// Add mesh to scene and collisions + this.getOutput().meshes.push(mesh); + } + /** + * TODO + * + * @return {*} [description] + */ + seedRandom() { + const x = Math.sin(this.seed++) * 10000; + return x - Math.floor(x); + } + /** + * TODO + * + * @param {*} collision [description] + * @param {*} mat [description] + * @return {*} [description] + */ + parseHavokMesh(collision, mat) { + const index = collision.index; + if (!this.meshes[index]) { + const geom = new THREE.Geometry(); + /// Pass vertices + for (let i = 0; i < collision.vertices.length; i++) { + const v = collision.vertices[i]; + // "x","float32","z","float32","y","float32"] + geom.vertices.push(new THREE.Vector3(v[0], v[2], -v[1])); + } + /// Pass faces + for (let i = 0; i < collision.indices.length; i += 3) { + const f1 = collision.indices[i]; + const f2 = collision.indices[i + 1]; + const f3 = collision.indices[i + 2]; + if (f1 <= collision.vertices.length && f2 <= collision.vertices.length && f3 <= collision.vertices.length) { + geom.faces.push(new THREE.Face3(f1, f2, f3)); + } + else { + this.logger.log(T3D.Logger.TYPE_ERROR, "Errorus index in havok model geometry."); + } + } + /// Prepare geometry and pass new mesh + geom.computeFaceNormals(); + // geom.computeVertexNormals(); + this.meshes[index] = new THREE.Mesh(geom, mat); + return this.meshes[index]; + } + else { + return this.meshes[index].clone(); + } + } + /** + * Output fileds generated: + * + * - *boundingBox* Array of values describing the bounding box of all collision. + * - *meshes* An array of THREE.Mesh objects visualizing all collision in the map. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + const self = this; + // TODO:The design of this method pretty much requires one instance + // of the class per parallel async render. Should probably fix this + // at some point... + /// Get required chunks + this.havokChunkData = this.mapFile.getChunk("havk").data; + /// Set static bounds to the bounds of the havk models + this.getOutput().boundingBox = this.havokChunkData.boundsMax; + /// Clear old meshes + this.meshes = []; + /// Set up output array + this.getOutput().meshes = []; + /// Grab model raw data from the chunk. + /// Add missing scale value to obs models. + const propModels = this.havokChunkData.propModels; + const zoneModels = this.havokChunkData.zoneModels; + const obsModels = this.havokChunkData.obsModels; + obsModels.forEach(function (mdl) { + mdl.scale = 1; + }); + /// Store geoms and animations from the file in hte instance so we don't + /// have to pass them arround too much. (fix this later) + this.geometries = this.havokChunkData.geometries; + this.animations = this.havokChunkData.animations; + /// Render "prop", "zone" and "obs" models in that order. + const renderZoneModelsCB = function () { + self.renderModels(obsModels, "obs", callback); + }; + const renderPropModelsCB = function () { + self.renderModels(zoneModels, "zone", renderZoneModelsCB); + }; + self.renderModels(propModels, "prop", renderPropModelsCB); + } + } + + const base32Max = Math.pow(2, 32); + /** + * Collection Math and sorting methods + * @namespace MathUtils + */ + /** + * Takes an integer and calculates what the 16 bit float + * representation of the binary data used to read the integer is. + * + * @memberof MathUtils + * @param {Number} h Integer value + * @return {Number} Float value + */ + function f16(h) { + const s = (h & 0x8000) >> 15; + const e = (h & 0x7c00) >> 10; + const f = h & 0x03ff; + if (e === 0) { + return (s ? -1 : 1) * Math.pow(2, -14) * (f / Math.pow(2, 10)); + } + else if (e === 0x1f) { + return f ? NaN : (s ? -1 : 1) * Infinity; + } + return (s ? -1 : 1) * Math.pow(2, e - 15) * (1 + f / Math.pow(2, 10)); + } + /** + * Calculates the number of binary ones present in the data used to + * generate the input integer. + * + * @memberof MathUtils + * @param {Number} bits Integer + * @return {Number} Number of binary ones in the data + */ + function popcount(bits) { + const SK5 = 0x55555555; + const SK3 = 0x33333333; + const SKF0 = 0x0f0f0f0f; + // let SKFF = 0xff00ff + bits -= (bits >> 1) & SK5; + bits = (bits & SK3) + ((bits >> 2) & SK3); + bits = (bits & SKF0) + ((bits >> 4) & SKF0); + bits += bits >> 8; + return (bits + (bits >> 15)) & 63; + } + /** + * Calculates the 64 bit integer value of two 32 bit integers. Only works up to + * the limit of the javascript Number maximum value. + * + * @memberof MathUtils + * @param {Number[]} arr Input integers, length should be 2. + * @return {Number} 64 bit representation of the two integers. + */ + function arr32To64(arr) { + /// Re-read as uint64 (still little endian) + /// Warn: this will not work for ~50+ bit longs cus all JS numbers are 64 bit floats... + return base32Max * arr[1] + arr[0]; + } + /** + * Sorts an array and returns unique values only. + * + * @memberof MathUtils + * @param {Array} arr_in Input array + * @param {Function} comparator A comparator function between the objects in arr_in + * @return {Array} Sorted and unique value. + */ + function sort_unique(arr_in, comparator) { + const arr = Array.prototype.sort.call(arr_in, comparator); + const u = {}; + const a = []; + for (let i = 0, l = arr.length; i < l; ++i) { + // eslint-disable-next-line no-prototype-builtins + if (u.hasOwnProperty(arr[i])) { + continue; + } + a.push(arr[i]); + //@ts-ignore + u[arr[i]] = 1; + } + return a; + } + + var MathUtils = /*#__PURE__*/Object.freeze({ + __proto__: null, + arr32To64: arr32To64, + f16: f16, + popcount: popcount, + sort_unique: sort_unique + }); + + // TODO: Remove this local cache!! + const matFiles = {}; + /** + * Object describing the meaning of the bits in fvf integers. + * @property fvfFormat + * @private + * @type {Object} + */ + const fvfFormat = { + Position: 0x00000001 /** < 12 bytes. Position as three 32-bit floats in the order x, y, z. */, + Weights: 0x00000002 /** < 4 bytes. Contains bone weights. */, + Group: 0x00000004 /** < 4 bytes. Related to bone weights. */, + Normal: 0x00000008 /** < 12 bytes. Normal as three 32-bit floats in the order x, y, z. */, + Color: 0x00000010 /** < 4 bytes. Vertex color. */, + Tangent: 0x00000020 /** < 12 bytes. Tangent as three 32-bit floats in the order x, y, z. */, + Bitangent: 0x00000040 /** < 12 bytes. Bitangent as three 32-bit floats in the order x, y, z. */, + TangentFrame: 0x00000080 /** < 12 bytes. */, + UV32Mask: 0x0000ff00 /** < 8 bytes for each set bit. Contains UV-coords as two 32-bit floats in the order u, v. */, + UV16Mask: 0x00ff0000 /** < 4 bytes for each set bit. Contains UV-coords as two 16-bit floats in the order u, v. */, + Unknown1: 0x01000000 /** < 48 bytes. Unknown data. */, + Unknown2: 0x02000000 /** < 4 bytes. Unknown data. */, + Unknown3: 0x04000000 /** < 4 bytes. Unknown data. */, + Unknown4: 0x08000000 /** < 16 bytes. Unknown data. */, + PositionCompressed: 0x10000000 /** < 6 bytes. Position as three 16-bit floats in the order x, y, z. */, + Unknown5: 0x20000000 /** < 12 bytes. Unknown data. **/, + }; + /** + * Collection of methods used for generating THREE meshes from Guild Wars 2 data formats. + * @namespace RenderUtils + */ + /** + * Creates a mesh representing a single plane. + * + * @memberof RenderUtils + * @param {Object} rect An object with x1,x2,y1 and y2 properties. + * @param {Number} yPos Vertical position of the rectangle. + * @param {THREE.Material} material Mesh material to apply. + * @param {Number} dy Mesh height. + * @return {THREE.Mesh} The generated mesh. + */ + function renderRect(rect, yPos, material, dy) { + const dx = rect.x1 - rect.x2; + const dz = rect.y1 - rect.y2; + if (!dy) + dy = 1; + const cx = (rect.x1 + rect.x2) / 2; + const cz = (rect.y1 + rect.y2) / 2; + const cy = yPos; + const geometry = new THREE.BoxGeometry(dx, dy, dz); + material = + material || + new THREE.MeshBasicMaterial({ + color: 0xff0000, + wireframe: true, + }); + const plane = new THREE.Mesh(geometry, material); + //@ts-ignore + plane.overdraw = true; + plane.position.x = cx; + plane.position.y = cy; + plane.position.z = cz; + return plane; + } + /** + * Returns a THREE representation of the data contained by a GW2 model file. + * The data is read using a LocalReader reference into the GW2 .dat. + * + * @memberof RenderUtils + * @param {LocalReader} localReader The LocalReader to load the file contents from. + * @param {Object} chunk Model GEOM chunk. + * @param {Object} modelDataChunk Model MODL chunk. + * @param {Object} sharedTextures Value Object for keeping the texture cache. + * @param {boolean} showUnmaterialed If false does not render any models with missing materials. + * + * @return {Array} Each geometry in the model file represented by a textured THREE.Mesh object + */ + function renderGeomChunk(localReader, chunk, modelDataChunk, sharedTextures, showUnmaterialed) { + const rawMeshes = chunk.data.meshes; + const meshes = []; + const mats = modelDataChunk.data.permutations[0].materials; + rawMeshes.forEach(function (rawMesh) { + const rawGeom = rawMesh.geometry; + const fvf = rawGeom.verts.mesh.fvf; // rawGeom.fvf; + const numVerts = rawGeom.verts.vertexCount; // rawGeom.vertexCount; + const rawVerts = rawGeom.verts.mesh.vertices; // rawGeom.vertices + const indices = rawGeom.indices.indices; + const geom = new THREE.BufferGeometry(); + const vertsDataView = new DataView(rawVerts.buffer); + // Dirty step length for now: + const stride = rawVerts.length / numVerts; + // Each vertex + // DO UV as well + const vertices = new Float32Array(numVerts * 3); + const uvs = []; + /// Calculate the distance to the first pair of UV data from the + /// start of the vertex entry + /// + const distToNormals = + //@ts-ignore + !!(fvf & fvfFormat.Position) * 12 + !!(fvf & fvfFormat.Weights) * 4 + !!(fvf & fvfFormat.Group) * 4; + //@ts-ignore + const distToTangent = distToNormals + !!(fvf & fvfFormat.Normal) * 12 + !!(fvf & fvfFormat.Color) * 4; + //@ts-ignore + const distToBittangent = distToTangent + !!(fvf & fvfFormat.Tangent) * 12; + //@ts-ignore + const distToTangentFrame = distToBittangent + !!(fvf & fvfFormat.Bitangent) * 12; + //@ts-ignore + const distToUV = distToTangentFrame + !!(fvf & fvfFormat.TangentFrame) * 12; + /// Check if the UV is 32 bit float or 16 bit float. + const uv32Flag = (fvf & fvfFormat.UV32Mask) >> 8; + const uv16Flag = (fvf & fvfFormat.UV16Mask) >> 16; + const isUV32 = !!uv32Flag; + const hasUV = !!uv16Flag || !!uv32Flag; + /// Popcount (count the number of binary 1's) in the UV flag + /// to get the number of UV pairs used in this vertex format. + const masked = isUV32 ? uv32Flag : uv16Flag; + let numUV = popcount(masked); + numUV = Math.min(numUV, 1.0); + /// Create typed UV arrays + if (hasUV) { + for (let i = 0; i < numUV; i++) { + uvs[i] = new Float32Array(numVerts * 2); + } + } + /// Read data from each vertex data entry + for (let i = 0; i < numVerts; i++) { + /// Go to vertex memory position + let cursor = i * stride; + /// Read position data + /// (we just hope all meshes has 32 bit position...) + const x = vertsDataView.getFloat32(cursor, true); + const z = vertsDataView.getFloat32(cursor + 4, true); + const y = vertsDataView.getFloat32(cursor + 8, true); + /// Write position data, transformed to Tyria3D coordinate system. + vertices[i * 3 + 0] = x; // - c.x; + vertices[i * 3 + 1] = -y; // + c.y; + vertices[i * 3 + 2] = -z; // + c.z; + /// Read data at UV position + if (hasUV) { + for (let uvIdx = 0; uvIdx < numUV; uvIdx++) { + cursor = i * stride + distToUV + uvIdx * (isUV32 ? 8 : 4); + /// Add one UV pair: + let u, v; + if (isUV32) { + u = vertsDataView.getFloat32(cursor, true); + v = vertsDataView.getFloat32(cursor + 4, true); + } + else { + u = f16(vertsDataView.getUint16(cursor, true)); + v = f16(vertsDataView.getUint16(cursor + 2, true)); + } + /// Push to correct UV array + uvs[uvIdx][i * 2 + 0] = u; + uvs[uvIdx][i * 2 + 1] = v; + } + } /// End if has UV + } /// End each vertex + /// Each face descripbed in indices + const faces = new Uint16Array(indices.length); + for (let i = 0; i < indices.length; i += 3) { + // This is ONE face + faces[i + 0] = indices[i + 2]; + faces[i + 1] = indices[i + 1]; + faces[i + 2] = indices[i + 0]; + } // End each index aka "face" + /// Add position, index and uv props to buffered geometry + geom.setAttribute("position", new THREE.BufferAttribute(vertices, 3)); + // geom.setAttribute( 'index', new THREE.BufferAttribute( faces, 1) ); + geom.setIndex(new THREE.BufferAttribute(faces, 1)); + { + /// Calculate normals + geom.computeVertexNormals(); + } + if (hasUV) { + for (let uvIdx = 0; uvIdx < numUV; uvIdx++) { + /// Names are "uv", "uv2", "uv3", ... , "uvN" + const uvName = "uv" + (uvIdx > 0 ? uvIdx + 1 : ""); + /// Set "custom" attribute uvN + geom.setAttribute(uvName, new THREE.BufferAttribute(uvs[uvIdx], 2)); + /// Flag for update + geom.attributes[uvName].needsUpdate = true; + } + /// Not needed anymore? + //@ts-ignore + geom.uvsNeedUpdate = true; + } + /// Tell geometry to update its UVs and buffers + //@ts-ignore + geom.buffersNeedUpdate = true; + /// DONE READING VERTEX DATA + /// Get material used for this mesh + const matIdx = rawMesh.materialIndex; + const mat = mats[matIdx]; + let materialFile = null; + if (mat && matFiles[mat.filename]) { + materialFile = matFiles[mat.filename]; + } + console.log(`material file:`, materialFile); + let finalMaterial = getMaterial(mat, materialFile, localReader, sharedTextures); + /// IF we could not find a material abort OR use a wireframe placeholder. + if (!finalMaterial) { + if (showUnmaterialed) { + finalMaterial = new THREE.MeshLambertMaterial({ + color: 0x5bb1e8, + wireframe: false, + side: THREE.DoubleSide, + }); + } + else { + return; + } + } + /// Create the final mesh from the BufferedGeometry and MeshBasicMaterial + const finalMesh = new THREE.Mesh(geom, finalMaterial); + /// Set material info on the returned mesh + if (mat) { + finalMesh.materialFlags = mat.materialFlags; + finalMesh.materialFilename = mat.filename; + } + finalMesh.materialName = rawMesh.materialName; + /// Use materialFilename, materialName, and material.textureFilename in order to build export + /// Set lod info on the returned mesh + finalMesh.numLods = rawMesh.geometry.lods.length; + finalMesh.lodOverride = modelDataChunk.data.lodOverride; + /// Set flag and UV info on the returned mehs + finalMesh.flags = rawMesh.flags; + finalMesh.numUV = numUV; + /// Add mesh to returned Array + meshes.push(finalMesh); + }); /// End rawMeshes for Each + return meshes; + } + /** + * Merge multiple meshes together and return an instancedMesh for it + * @param {Array} meshes Three Meshes to be merged into a single mesh + * @param {Number} size Size of the instanced mesh + * @param {Number} filterFlags When undefined, it will render all LODs. When using 0, only show most detailed LOD + * @returns {Mesh} a Three instanced mesh + */ + function getInstancedMesh(meshes, size, filterFlags) { + const meshMaterials = []; + const mergedGeometry = new THREE.Geometry(); + meshes.forEach((mesh, index) => { + // If filterFlags is set, we ignore any mesh without the correct flag + if (filterFlags !== undefined && mesh.flags !== filterFlags) { + return; + } + meshMaterials.push(mesh.material); + // It's only possible to merge geometries of the same type + const meshGeometry = new THREE.Geometry().fromBufferGeometry(mesh.geometry); + mergedGeometry.merge(meshGeometry, mesh.matrix, index); + }); + const finalMesh = new THREE.InstancedMesh(mergedGeometry, meshMaterials, size); + finalMesh.updateMatrix(); + finalMesh.matrixAutoUpdate = false; + return finalMesh; + } + /** + * Loads mesh array from Model file and sends as argument to callback. + * + * @memberof RenderUtils + * @async + * @param {Number} filename Name of the model file to load data from. + * @param {Array} solidColor RGBA array of 4 integers + * @param {LocalReader} localReader The LocalReader to load the file contents from. + * @param {Object} sharedTextures Value Object for keeping the texture cache. + * @param {boolean} showUnmaterialed If false does not render any models with missing materials. + + * @param {Function} callback Fired once all meshes have been loaded. + * two arguments are passed to the callback function. + * + * The first argument is an Array with each textured THREE.Mesh objects. + * + * The second argument is the bounding spehere of this model file. + * + */ + function loadMeshFromModelFile(filename, solidColor, localReader, sharedTextures, showUnmaterialed, callback) { + // Short handles prop attributes + const finalMeshes = []; + /// Load file + localReader.loadFile(filename, function (inflatedData) { + try { + if (!inflatedData) { + throw "Could not find MFT entry for " + filename; + } + const modelFile = new t3dParser.FileParser(inflatedData); + // MODL for materials -> textures + const modelDataChunk = modelFile.getChunk("modl"); + // GEOM for geometry + const geometryDataChunk = modelFile.getChunk("geom"); + /// Hacky fix for not being able to adjust for position + const boundingSphere = modelDataChunk.data.boundingSphere; + const bsc = boundingSphere.center; + if (bsc) { + boundingSphere.radius += Math.sqrt(bsc[0] * bsc[0] + Math.sqrt(bsc[1] * bsc[1] + bsc[2] * bsc[2])); + } + /// Load all material files + const allMats = modelDataChunk.data.permutations[0].materials; + function loadMaterialIndex(mIdx, matCallback) { + if (mIdx >= allMats.length) { + matCallback(); + return; + } + const mat = allMats[mIdx]; + /// Skip if file is loaded + if (matFiles[mat.filename]) { + loadMaterialIndex(mIdx + 1, matCallback); + return; + } + localReader.loadFile(mat.filename, function (inflatedData) { + if (inflatedData) { + const materialFile = new t3dParser.FileParser(inflatedData); + matFiles[mat.filename] = materialFile; + } + loadMaterialIndex(mIdx + 1, matCallback); + }); + } + loadMaterialIndex(0, function () { + /// Create meshes + const meshes = renderGeomChunk(localReader, geometryDataChunk, modelDataChunk, sharedTextures, showUnmaterialed); + // Build mesh group + meshes.forEach(function (mesh) { + /// Material flags + const knownflags = [ + /* + 1-5 + Has Tex? IDK Light? Alpha? + + 5-8 + 0 0 IDK Water? + + 9-12 + Has Tex? 0 Alpha? Alpha? + + 13 + IDK KEV + */ + 0, // 0 0000 0000 0000 Ground / Wall splashes + 8, // 0 0000 0000 1000 Broken Khylo roof DDS + 9, // 0 0000 0000 1001 Tree leaves + 520, // 0 0010 0000 1000 Some LOD modules, fires, smoke, inside of tents (some DSS textures) + 2056, // 0 1000 0000 1000 Solid objects, also broken animations + /// Solids here are unhappy, or are they? could be animations etc + 2057, // 0 1000 0000 1001 Windmill sails, bushes, trees, but also a statue and a few pieces of wall + 2060, // 0 1000 0000 1100 A few solid objects, like wooden barricades, one(!) painting + 2061, // 0 1000 0000 1101 A few bushes, two paintings + 2312, // 0 1001 0000 1000 Opaque Clock tower main walls AND IVY + 2316, // 0 1001 0000 1100 Bushes, inner flower walkway a ramp and a box + // Number 10 + 2568, // 0 1010 0000 1000 Lots of solids; walls, tents also some tent details WITH alpa + // Number 11 + 2569, // 0 1010 0000 1001 Solids like walls and roofs and appernt non solids like ropes + 2572, // 0 1010 0000 1100 Solid wooden beems, lamp posts + 2573, // 0 1010 0000 1101 Lamp holders, bushes, fences, apparent non solids + 2584, // 0 1010 0001 1000 Fountain Well water + 2824, // 0 1011 0000 1000 Windows, sign arrows, cloth roofs (non solids) BUT straw roofs + 2828, // 0 1011 0000 1100 A few fence post (non solids) + 2840, // 0 1011 0001 1000 Fountain running water + pipe water + 4617, // 1 0010 0000 1001 Found nothing + 6664, // 1 1010 0000 1000 Two groups of solid boxes + ]; + // let alphaMask0 = 0x0001 // + 0x0100 + 0x0200; + // let alphaMask1 = 0x0010 + // let alphaMask2 = 0x0100 + 0x0200 + // let alphaMask2b = 0x0200 + const texMask = 0x8 + 0x0800; + if (knownflags.indexOf(mesh.materialFlags) !== 11) { + // return; + } + // No smoke etc + if (mesh.materialFlags === 520) { + // return; + } + // Must have texture + if (!showUnmaterialed && !(mesh.materialFlags & texMask)) { + return; + } + // NO lods + if (mesh.flags === 4 || mesh.flags === 1 || mesh.flags === 0) { + // return; + } + // Add to final colection + finalMeshes.push(mesh); + }); /// END FOR EACH meshes + callback(finalMeshes, boundingSphere); + }); /// END LOAD MATERIALS CALLBACK + } + catch (e) { + console.warn("Failed rendering model " + filename, e); + const mesh = new THREE.Mesh(new THREE.BoxGeometry(200, 2000, 200), new THREE.MeshNormalMaterial()); + //@ts-ignore + mesh.flags = 4; + //@ts-ignore + mesh.materialFlags = 2056; + //@ts-ignore + mesh.lodOverride = [1000000, 1000000]; + finalMeshes.push(mesh); + /// Send the final meshes to callback function + callback(finalMeshes); + } + }); /// END FILE LOADED CALLBACK FUNCTION + } + /** + * Gets a mesh array from Model file and sends as argument to callback. Uses a cache of meshes in order + * to never read the same model file twice. + * + * @memberof RenderUtils + * @async + * @param {Number} filename The fileId or baseId of the Model file to load + * @param {Array} color RGBA array of 4 integers + * @param {LocalReader} localReader The LocalReader object used to read data from the GW2 .dat file. + * @param {Object} sharedMeshes Value Object for keeping the texture cache. + * @param {Object} sharedTextures Value Object for keeping the texture cache. + * @param {boolean} showUnmaterialed If false does not render any models with missing materials. + * @param {Function} callback Fired once all meshes have been loaded. + * three arguments are passed to the callback function. + * + * The first argument is an Array with each textured THREE.Mesh objects. + * + * The second argument is a boolean, true indicates that these meshes were not + * loaded from the dat file, but retrieved from the run time cache. + * + * The third argument is the bounding spehere of this model file. + */ + function getMeshesForFilename(filename, color, localReader, sharedMeshes, sharedTextures, showUnmaterialed, callback) { + /// If this file has already been loaded, just return a reference to the meshes. + /// isCached will be set to true to inform the caller the meshes will probably + /// have to be cloned in some way. + if (sharedMeshes[filename]) { + callback(sharedMeshes[filename].meshes, true, sharedMeshes[filename].boundingSphere); + } + /// If this file has never been loaded, load it using loadMeshFromModelFile + /// the resulting mesh array will be cached within this model's scope. + else { + loadMeshFromModelFile(filename, color, localReader, sharedTextures, showUnmaterialed, function (meshes, boundingSphere) { + /// Cache result if any. + if (meshes) { + sharedMeshes[filename] = { + meshes: meshes, + boundingSphere: boundingSphere, + }; + } + /// Allways fire callback. + callback(meshes, false, boundingSphere); + }); + } + } + /** + * WIP, Tries to find all fileIds refered by a model file. + * + * @memberof RenderUtils + * @async + * @param {Number} filename Model file Id + * @param {LocalReader} localReader LocalReader instance to read from + * @param {Function} callback First argument is list of used file IDs + */ + function getFilesUsedByModel(filename, localReader, callback) { + const fileIds = [filename]; + /// Load model file + localReader.loadFile(filename, function (inflatedData) { + try { + if (!inflatedData) { + throw "Could not find MFT entry for " + filename; + } + const modelFile = new t3dParser.FileParser(inflatedData); + // MODL for materials -> textures + const modelDataChunk = modelFile.getChunk("modl"); + /// Get materials used by model + const mats = modelDataChunk.data.permutations[0].materials; + /// Add each material file AND referenced TEXTURES + mats.forEach(function (mat) { + /// Add material file id + const matFileName = mat.filename; + fileIds.push(matFileName); + /// Add each texture file id + mat.textures.forEach(function (tex) { + fileIds.push(tex.filename); + }); + }); + } + catch (e) { + console.warn("Could not export any data", e); + } + callback(fileIds); + }); + } + + var RenderUtils = /*#__PURE__*/Object.freeze({ + __proto__: null, + getFilesUsedByModel: getFilesUsedByModel, + getInstancedMesh: getInstancedMesh, + getMeshesForFilename: getMeshesForFilename, + loadMeshFromModelFile: loadMeshFromModelFile, + renderGeomChunk: renderGeomChunk, + renderRect: renderRect + }); + + /** + * A Logger class for T3D + * + * This satic class defines severity levels of messages and provides + * basic logging functionality. Replacing the reference to + * + * @namespace + * @static + */ + class Logger { + TYPE_ERROR = 4; + TYPE_WARNING = 3; + TYPE_MESSAGE = 2; + TYPE_PROGRESS = 1; + TYPE_DEBUG = 0; + logFunctions = new Array(5); + constructor() { + this.logFunctions[this.TYPE_ERROR] = function (...args) { + console.error(...args); + }; + this.logFunctions[this.TYPE_WARNING] = function (...args) { + console.warn(...args); + }; + this.logFunctions[this.TYPE_MESSAGE] = function (...args) { + console.log(...args); + }; + this.logFunctions[this.TYPE_PROGRESS] = function (...args) { + const argArr = args; + argArr.unshift("Progress: "); + console.log(...argArr); + }; + this.logFunctions[this.TYPE_DEBUG] = function (...args) { + const argArr = args; + console.debug(...argArr); + }; + } + /** + * Main logging method. Takes 1 to N arguments. If there are more than 1 arguments + * the first argument is interpreted as severity. If there is only one argument + * severity defaults to + * {{#crossLink "Logger/TYPE_MESSAGE:property"}}{{/crossLink}}. + * + * The following arguments are passed to a logging function matching the + * severity. + * + + * + */ + log(...args) { + /// Require at least 1 argument + if (arguments.length === 0) { + return; + } + /// Parse arguments to an actual array + const argArr = args; + /// Default to message if just one argument was passed + if (argArr.length === 1) { + argArr.unshift(this.TYPE_MESSAGE); + } + /// Otherwise 1st arg is severity, log/warn/error + const severity = Math.max(0, Math.min(this.logFunctions.length, argArr.shift())); + const logFunc = this.logFunctions[severity]; + /// Ouput the rest of the arguments + logFunc.apply(this, argArr); + } + } + const logger = new Logger(); + + // A progress cache is needed to debounce logs at the same percentage + const progressCache = {}; + /** + * This utility function is a helper for showing loading progress of dataRenderers. + * It automatically generates progress logs which can be used outside of the library to show progress bars. + * Must be used on loop implementations where the maximum index is known in advance + * + * @param {Object} logger The default logger or given one + * @param {Number} currentIndex Current index of the item being loaded + * @param {Number} maxIndex Maximum index of items to load + * @param {String} progressName Name of the resource being loaded + */ + function progress(logger$1, currentIndex, maxIndex, progressName) { + const percent = Math.round((1000.0 * currentIndex) / maxIndex) / 10.0; + // Make sure we don't spam logs + if (progressCache[progressName] !== percent) { + const consistentPercent = percent + (percent.toString().indexOf(".") < 0 ? ".0" : ""); + logger$1.log(logger.TYPE_PROGRESS, progressName, consistentPercent); + progressCache[progressName] = percent; + } + // Clean cache on last item + if (currentIndex === maxIndex) { + progressCache[progressName] = undefined; + } + } + + /** + * + * A renderer that generates property models for a map. + * + * @class PropertiesRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "mapFile", a FileParser. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class PropertiesRenderer extends DataRenderer { + static rendererName = "PropertiesRenderer"; + showUnmaterialized; + mapFile; + meshCache; + textureCache; + models; + modelsList = []; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "PropertiesRenderer"); + this.mapFile = this.settings.mapFile; + this.showUnmaterialized = this.settings.showUnmaterialized || false; + this.meshCache = {}; + this.textureCache = {}; + this.models = {}; + } + /** + * Renders all property meshes in a GW2 map described by the map's PROP chunk. + * Output fileds generated: + * + * - *meshes* An array of THREE.Mesh objects visualizing all property models refered by this map. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + this.getOutput().meshes = []; + const propertiesChunkData = this.mapFile.getChunk("prp2").data; + if (!propertiesChunkData) { + return callback(); + } + // Get all different prop types + const props = [] + .concat(propertiesChunkData.propArray) + .concat(propertiesChunkData.propAnimArray) + .concat(propertiesChunkData.propInstanceArray) + .concat(propertiesChunkData.propMetaArray); + /// Build an object containing all the data we need for each prop + this.models = props.reduce((models, prop) => { + const propSize = prop.transforms ? prop.transforms.length + 1 : 1; + if (models[prop.filename]) { + models[prop.filename].props.push(prop); + models[prop.filename].size += propSize; + } + else { + models[prop.filename] = { + props: [prop], + size: propSize, + }; + } + return models; + }, {}); + this.modelsList = Object.keys(this.models); + this.renderModel(0, callback); + } + getFileIdsAsync(callback) { + this.logger.log(T3D.Logger.TYPE_WARNING, "PropertiesRenderer.getFileIdsAsync is not implemented"); + callback([]); + } + /** + * PRIVATE METHODS + */ + /** + * To optimize the rendering on the GPU we render each model only once and use instances for + * any other place using the same model. This allows us to have a much lower amount of draw calls + * and usage of GPU memory compared to a naive approach having a mesh for each model. + */ + renderModel(index, callback) { + if (index >= this.modelsList.length) { + this.meshCache = {}; + this.textureCache = {}; + this.models = {}; + return callback(); + } + progress(this.logger, index, this.modelsList.length, "Loading 3D Models (Props)"); + const modelName = parseInt(this.modelsList[index]); + getMeshesForFilename(modelName, this.models[modelName].props[0].color, this.localReader, this.meshCache, this.textureCache, this.showUnmaterialized, + // We don't care about cached meshes since we know we only ask for each meshes once. + (meshes) => { + if (meshes) { + this.placeModelOnScene(modelName, meshes /*, boundingSphere*/); + } + this.renderModel(index + 1, callback); + }); + } + /** + * Gets the meshes of a specific model, merge them together as an instanced mesh + * and place them in the scene where they are referenced by the props. + * @param {number} modelName The baseId of the model + * @param {*} meshes The 3d models of the model + */ + placeModelOnScene(modelName, meshes) { + const model = this.models[modelName]; + const instancedMesh = getInstancedMesh(meshes, model.size); + let instancedIndex = 0; + for (const prop of model.props) { + instancedMesh.setMatrixAt(instancedIndex, getMatrixForProp(prop)); + instancedIndex += 1; + for (const transform of prop.transforms || []) { + instancedMesh.setMatrixAt(instancedIndex, getMatrixForProp(transform)); + instancedIndex += 1; + } + } + this.getOutput().meshes.push(instancedMesh); + } + } + /** + * Return a Matrix4 for a given prop defining the Scale Rotation and Location of a model + * @param {Object} propData + * @returns {THREE.Matrix4} + */ + function getMatrixForProp(propData) { + const matrix = new THREE.Matrix4(); + matrix.makeRotationFromEuler(new THREE.Euler(propData.rotation[0], -propData.rotation[2], -propData.rotation[1], "ZXY")); + matrix.scale(new THREE.Vector3(propData.scale, propData.scale, propData.scale)); + matrix.setPosition(propData.position[0], -propData.position[2], -propData.position[1]); + return matrix; + } + + /** + * + * A renderer that generates meshes for a single model file. + * + * @class SingleModelRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "id" the base ID or file ID of the model to generate meshes for. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class SingleModelRenderer extends DataRenderer { + static rendererName = "SingleModelRenderer"; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "SingleModelRenderer"); + } + /** + * Output fileds generated: + * + * - *meshes* An array of THREE.Mesh objects visualizing this model file. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + const self = this; + /// Get file id + const fileId = this.settings.id; + const showUnmaterialed = true; + /// Load the model file + let meshCache = {}; + const textureCache = {}; + /// Set up output array + self.getOutput().meshes = []; + getMeshesForFilename(fileId, 0x00ff00, self.localReader, meshCache, textureCache, showUnmaterialed, function (meshes, isCached, boundingSphere) { + if (meshes) { + meshes.forEach(function (mesh) { + mesh.boundingSphere = boundingSphere; + self.getOutput().meshes.push(mesh); + }); + } + /// Fire callback after all meshes have been added. + meshCache = {}; + callback(); + }); + } + } + + /// TODO: port fog from in-engine + function getFragmentShader() { + return [ + "uniform vec2 uvScale;", + "uniform vec2 offset;", + "uniform sampler2D texturePicker;", + "uniform sampler2D texturePicker2;", + "uniform sampler2D texture1;", + "uniform sampler2D texture2;", + "uniform sampler2D texture3;", + "uniform sampler2D texture4;", + "#include ", + "#include ", + "varying vec2 vUv;", + "varying vec3 vecNormal;", + "vec3 blend(", + "vec4 texture1, float a1, vec4 texture2, float a2,", + "vec4 texture3, float a3, vec4 texture4, float a4)", + "{", + "float depth = 2.0;", + "float alphaMult = 1.0;", + "float alphaAdd = 0.0;", + "a1 *= 4.0;", + "a2 *= 4.0;", + "a3 *= 4.0;", + "a4 *= 4.0;", + "a1 = a1+(1.5+texture1.a);", + "a2 = a2+(1.5+texture2.a);", + "a3 = a3+(1.5+texture3.a);", + "a4 = a4+(1.5+texture4.a);", + "float ma = max(a1,a2);", + "ma = max(ma,a3);", + "ma = max(ma,a4);", + "ma -= depth;", + "float b1 = max(a1 - ma, 0.0);", + "float b2 = max(a2 - ma, 0.0);", + "float b3 = max(a3 - ma, 0.0);", + "float b4 = max(a4 - ma, 0.0);", + "return (", + "texture1.rgb * b1 + texture2.rgb * b2 +", + "texture3.rgb * b3 + texture4.rgb * b4 ", + ") / (b1 + b2 + b3 + b4);", + "}", + "void main( void ) {", + "vec2 position = vUv*uvScale;", + "float edge = 1.0/1024.0;", + "vec2 compPos = edge + (vUv*0.25 + offset) * (1.0-edge*2.0);", + "vec4 tp1 = texture2D( texturePicker, compPos);", + "vec4 tp2 = texture2D( texturePicker2, compPos);", + "vec4 composite = tp1;", + "vec4 t1 = texture2D( texture1, position );", + "vec4 t2 = texture2D( texture2, position );", + "vec4 t3 = texture2D( texture3, position );", + "vec4 t4 = texture2D( texture4, position );", + "vec3 color = blend(", + "t1, tp1.a,", + "t2, tp1.b,", + "t3, tp1.g,", + "t4, tp1.r", + ");", + "color *= 0.5+tp2.r;", + "gl_FragColor = vec4(color,1.0);", + "#include ", + "}", + ].join("\n"); + } + function getVertexShader() { + return [ + "varying vec2 vUv;", + "varying vec3 vecNormal;", + "#include ", + "#include ", + "void main()", + "{", + "vUv = uv;", + "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", + "vecNormal = (modelMatrix * vec4(normal, 0.0)).xyz;", + "gl_Position = projectionMatrix * mvPosition;", + "#include ", + "}", + ].join("\n"); + } + + /** + * + * A renderer that generates the meshes for the terrain of a map. + * + * + * Requires a context previously populated by a + * {{#crossLink "EnvironmentRenderer"}}{{/crossLink}}. + * + * @class TerrainRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "mapFile", a FileParser. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class TerrainRenderer extends DataRenderer { + static rendererName = "TerrainRenderer"; + mapFile; + mapRect; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "TerrainRenderer"); + this.mapFile = this.settings.mapFile; + } + drawWater(rect) { + /// Add Water + const material = new THREE.MeshBasicMaterial({ + color: 0x5bb1e8, + wireframe: false, + opacity: 0.35, + }); + material.transparent = true; + return renderRect(rect, 0, material); + } + parseNumChunks(terrainData) { + terrainData.numChunksD_1 = Math.sqrt((terrainData.dims[0] * terrainData.chunkArray.length) / terrainData.dims[1]); + terrainData.numChunksD_2 = terrainData.chunkArray.length / terrainData.numChunksD_1; + } + loadPagedImageCallback(callback, inflatedBuffer) { + const self = this; + // Prep output array + self.getOutput().terrainTiles = []; + const pimgFile = new t3dParser.FileParser(inflatedBuffer); + const pimgTableDataChunk = pimgFile.getChunk("pgtb"); + const pimgData = pimgTableDataChunk && pimgTableDataChunk.data; + this.mapRect = null; + /// Fetch chunks + const terrainData = this.mapFile.getChunk("trn").data; + const parameterData = this.mapFile.getChunk("parm").data; + /// Read settings + const maxAnisotropy = this.settings.anisotropy ? this.settings.anisotropy : 1; + //let chunks = []; + const chunkW = 35; + /// Calculate numChunksD_1 and _2 + this.parseNumChunks(terrainData); + const xChunks = terrainData.numChunksD_1; + const yChunks = terrainData.numChunksD_2; + const allMaterials = terrainData.materials.materials; + const allTextures = terrainData.materials.texFileArray; + // Total map dx and dy + /* + old parameter data definition: + "x1", "float32", + "y1", "float32", + "x2", "float32", + "y2", "float32" + */ + // var dx = parameterData.rect.x2 - parameterData.rect.x1; + // var dy = parameterData.rect.y2 - parameterData.rect.y1; + const dx = parameterData.rect[2] - parameterData.rect[0]; + const dy = parameterData.rect[3] - parameterData.rect[1]; + // Each chunk dx and dy + const cdx = (dx / terrainData.numChunksD_1) * 1; // 35/33; + const cdy = (dy / terrainData.numChunksD_2) * 1; // 35/33; + let n = 0; + const customMaterial = new THREE.MeshLambertMaterial({ + side: THREE.DoubleSide, + color: 0x666666, + flatShading: true, + }); + //let texMats = {}; + /// Load textures from PIMG and inject as material maps (textures) + const chunkTextures = {}; + /// Load textures + if (pimgData) { + const strippedPages = pimgData.strippedPages; + /// Only use layer 0 + strippedPages.forEach(function (page) { + /// Only load layer 0 and 1 + if (page.layer <= 1) { + const filename = page.filename; + //let color = page.solidColor; + const coord = page.coord; + let matName = coord[0] + "," + coord[1]; + if (page.layer === 1) + matName += "-2"; + /// Add texture to list, note that coord name is used, not actual file name + if (!chunkTextures[matName]) { + /// Load local texture, here we use file name! + const chunkTex = loadLocalTexture(self.localReader, filename); + if (chunkTex) { + /// Set repeat, antistropy and repeat Y + chunkTex.anisotropy = maxAnisotropy; + chunkTex.wrapS = THREE.RepeatWrapping; + chunkTex.wrapT = THREE.RepeatWrapping; + } + /// ...But store in coord name + chunkTextures[matName] = chunkTex; + } + } + }); /// end for each stripped page in pimgData + } + /// Render Each chunk + /// We'll make this async in order for the screen to be able to update + const renderChunk = function (cx, cy) { + const chunkIndex = cy * xChunks + cx; + const pageX = Math.floor(cx / 4); + const pageY = Math.floor(cy / 4); + // TODO: Terrain texture LOD ? + const chunkTextureIndices = allMaterials[chunkIndex].loResMaterial.texIndexArray; + // let matFileName = allMaterials[chunkIndex].loResMaterial.materialFile; + // let chunkTextureIndices = allMaterials[chunkIndex].hiResMaterial.texIndexArray; + // let matFileName = allMaterials[chunkIndex].hiResMaterial.materialFile; + // let chunkData = terrainData.chunkArray[chunkIndex]; + // let mainTex = allTextures[chunkTextureIndices[0]]; + let mat = customMaterial; + /// TODO: just tick invert y = false...? + const pageOffetX = (cx % 4) / 4.0; + const pageOffetY = 0.75 - (cy % 4) / 4.0; + // offset 0 -> 0.75 + // Make sure we have shared textures + /// Load and store all tiled textures + const fileNames = []; + for (let gi = 0; gi < chunkTextureIndices.length / 2; gi++) { + const textureFileName = allTextures[chunkTextureIndices[gi]].filename; + fileNames.push(textureFileName); + /// If the texture is not already loaded, read it from the .dat! + if (!chunkTextures[textureFileName]) { + /// Load local texture + const chunkTex = loadLocalTexture(self.localReader, textureFileName); + if (chunkTex) { + /// Set repeat, antistropy and repeat Y + chunkTex.anisotropy = maxAnisotropy; + chunkTex.wrapS = THREE.RepeatWrapping; + chunkTex.wrapT = THREE.RepeatWrapping; + } + chunkTextures[textureFileName] = chunkTex; + } + } /// End for each chunkTextureIndices + /// Create Composite texture material, refering the shared textures + const pageTexName = pageX + "," + pageY; + const pageTexName2 = pageX + "," + pageY + "-2"; + /// Get haze color from environment rednerer + const envOutput = self.getOutput(T3D.EnvironmentRenderer); + if (envOutput.hazeColor) { + envOutput.hazeColor[2] / 255.0; + envOutput.hazeColor[1] / 255.0; + envOutput.hazeColor[0] / 255.0; + } + const uniforms = THREE.UniformsUtils.merge([THREE.UniformsLib["lights"]]); + /// TODO: READ FROM VO, don't default to hard coded scale + uniforms.uvScale = { type: "v2", value: new THREE.Vector2(8.0, 8.0) }; + uniforms.offset = { + type: "v2", + value: new THREE.Vector2(pageOffetX, pageOffetY), + }; + uniforms.texturePicker = { + type: "t", + value: chunkTextures[pageTexName], + }; + uniforms.texturePicker2 = { + type: "t", + value: chunkTextures[pageTexName2], + }; + uniforms.texture1 = { type: "t", value: chunkTextures[fileNames[0]] }; + uniforms.texture2 = { type: "t", value: chunkTextures[fileNames[1]] }; + uniforms.texture3 = { type: "t", value: chunkTextures[fileNames[2]] }; + uniforms.texture4 = { type: "t", value: chunkTextures[fileNames[3]] }; + if (self.settings && self.settings.export) { + mat = new THREE.MeshBasicMaterial({ visible: true }); + } + else { + mat = new THREE.ShaderMaterial({ + uniforms: uniforms, + fragmentShader: getFragmentShader(), + vertexShader: getVertexShader(), + }); + } + /// -1 for faces -> vertices , -2 for ignoring outer faces + const chunkGeo = new THREE.PlaneBufferGeometry(cdx, cdy, chunkW - 3, chunkW - 3); + let cn = 0; + /// Render chunk + /// Each chunk vertex + for (let y = 0; y < chunkW; y++) { + for (let x = 0; x < chunkW; x++) { + if (x !== 0 && x !== chunkW - 1 && y !== 0 && y !== chunkW - 1) { + //@ts-ignore + chunkGeo.getAttribute("position").array[cn * 3 + 2] = terrainData.heightMapArray[n]; + cn++; + } + n++; + } + } // End each chunk vertex + /// Flip the plane to fit wonky THREE js world axes + const mS = new THREE.Matrix4().identity(); + mS.elements[5] = -1; + chunkGeo.applyMatrix4(mS); + /// Compute face normals for lighting, not used when textured + //@ts-ignore + chunkGeo.computeFaceNormals(); + chunkGeo.computeVertexNormals(); + /// Build chunk mesh! + let chunk; + chunk = new THREE.Mesh(chunkGeo, customMaterial); + if (Array.isArray(mat)) { + chunk = THREE.SceneUtils.createMultiMaterialObject(chunkGeo, mat); + } + else { + chunk = new THREE.Mesh(chunkGeo, mat); + } + /// Move and rotate Mesh to fit in place + chunk.rotation.set(Math.PI / 2, 0, 0); + /// Last term is the new one: -cdx*(2/35) + const globalOffsetX = parameterData.rect[0] + cdx / 2; + const chunkOffsetX = cx * cdx; + chunk.position.x = globalOffsetX + chunkOffsetX; + /// Adjust for odd / even number of chunks + if (terrainData.numChunksD_2 % 2 === 0) { + /// Last term is the new one: -cdx*(2/35) + const globalOffsetY = parameterData.rect[1] + cdy / 2 - 0; // -cdy*(1/35); + const chunkOffsetY = cy * cdy * 1; // 33/35; + chunk.position.z = chunkOffsetY + globalOffsetY; + } + else { + const globalOffsetY = parameterData.rect[1] - cdy / 2 + 0; // cdy*(1/35); + const chunkOffsetY = cy * cdy * 1; // 33/35; + chunk.position.z = globalOffsetY + chunkOffsetY; + } + const px = chunk.position.x; + const py = chunk.position.z; + if (!self.mapRect) { + self.mapRect = { + x1: px - cdx / 2, + x2: px + cdx / 2, + y1: py - cdy / 2, + y2: py + cdy / 2, + }; + } + self.mapRect.x1 = Math.min(self.mapRect.x1, px - cdx / 2); + self.mapRect.x2 = Math.max(self.mapRect.x2, px + cdx / 2); + self.mapRect.y1 = Math.min(self.mapRect.y1, py - cdy / 2); + self.mapRect.y2 = Math.max(self.mapRect.y2, py + cdy / 2); + chunk.updateMatrix(); + chunk.updateMatrixWorld(); + /// Add to list of stuff to render + /// TODO: Perhaps use some kind of props for each entry instead? + self.getOutput().terrainTiles.push(chunk); + }; /// End render chunk function + const stepChunk = function (cx, cy) { + if (cx >= xChunks) { + cx = 0; + cy++; + } + if (cy >= yChunks) { + /// Draw water surface using map bounds + self.getOutput().water = self.drawWater(self.mapRect); + /// Set bounds in output VO + self.getOutput().bounds = self.mapRect; + /// Fire call back, we're done rendering. + callback(); + return; + } + const pct = Math.floor((100 * (cy * xChunks + cx)) / (xChunks * yChunks)); + self.logger.log(T3D.Logger.TYPE_PROGRESS, "Loading Terrain", pct); + renderChunk(cx, cy); + setTimeout(stepChunk, 1, cx + 1, cy); + }; + stepChunk(0, 0); + } + /** + * Output fileds generated: + * + * - *terrainTiles* An array of THREE.Mesh objects visualizing terrain of the map. + * + * - *water* A THREE.Mesh object visualizing the bounds of the map. + * + * - *bounds* An object wiht x1, x2, y1, and y2 properties specifying the bounds of the map. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + /// Load all paged Images, requires inflation of other pack files! + const pagedImageId = this.mapFile.getChunk("trn").data.materials.pagedImage; + //@ts-ignore + this.localReader.loadFile(pagedImageId, this.loadPagedImageCallback.bind(this, callback)); + } + /** + * TODO: write description. Used for export feature + * + * @param {Function} callback [description] + * @return {*} [description] + */ + getFileIdsAsync( /* callback */) { + const terrainChunk = this.mapFile.getChunk("trn"); + const pimgTableDataChunk = this.mapFile.getChunk("pimg"); + const fileIds = []; + /// ------------ SPLASH TEXTURES ------------ + const pimgData = pimgTableDataChunk && pimgTableDataChunk.data; + const strippedPages = pimgData.strippedPages; + /// Only use layer 0 + strippedPages.forEach(function (page) { + /// Only load layer 0 and 1 + if (page.layer <= 1 && page.filename > 0) { + fileIds.push(page.filename); + } + }); + /// ------------ END SPLASH TEXTURES ------------ + /// ------------ TILED IMAGES ------------ + const terrainData = terrainChunk.data; + const allTextures = terrainData.materials.texFileArray; + allTextures.forEach(function (texture) { + if (texture.filename > 0) + fileIds.push(texture.filename); + }); + /// ------------ END TILED IMAGES ------------ + return fileIds; + } + } + + /** + * + * A renderer that generates zone models for a map. + * + * @class ZoneRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "mapFile", a FileParser. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class ZoneRenderer extends DataRenderer { + static rendererName = "ZoneRenderer"; + meshCache; + textureCache; + mapFile; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "ZoneRenderer"); + this.mapFile = this.settings.mapFile; + } + /** + * TODO + * + * @param {*} zone [description] + * @param {*} zoneDefs [description] + * @param {*} mapRect [description] + * @param {*} renderZoneCallback [description] + * @return {*} [description] + */ + renderZone(zone, zoneDefs, mapRect, renderZoneCallback) { + const self = this; + /// Get Zone Definition + let zoneDef = null; + zoneDefs.forEach(function (zd) { + if (!zoneDef && zd.token === zone.defToken) + zoneDef = zd; + }); + /// Create array of all models to add: + // let models = [] + const modelGroups = this.getModelGroups(zone, zoneDef, mapRect); + /// Create empty mesh cache + self.meshCache = {}; + self.textureCache = {}; + /* + * ---Keeping this out of the doc for now--- + * Steps trough each model and renders it to the scene, allowing for efficient caching. + * @param {Number} i - Current index within the models array + */ + // var lastPct = -1; + const groupKeys = Object.keys(modelGroups); + function stepModels(i) { + /* var pct = Math.round(100.0*i / groupKeys.length); + if(lastPct!=pct){ + console.log("Rendering ZONE models "+pct); + lastPct = pct; + } */ + if (i >= groupKeys.length) { + /// Empty mesh cache + self.meshCache = {}; + self.textureCache = {}; + /// Tell caller this zone is done loading + renderZoneCallback(); + return; + } + /// Read model at index + /// var model = models[i]; + const key = groupKeys[i]; /// key is model filename + const group = modelGroups[key]; + const meshGroups = []; + /// Get model just once for this group + const showUnmaterialed = false; + getMeshesForFilename(key, null, self.localReader, self.meshCache, self.textureCache, showUnmaterialed, function (meshes /*, isCached*/) { + /// If there were meshes, add them to the scene with correct scaling rotation etc. + if (meshes /* && meshes.length == 3 */) { + /// Add one copy per model instance + /// TODO: add rotation! + /// TODO: fine tune position? + /// TODO: POTIMIZE! + group.forEach(function (model, instanceIdx) { + //let isCached = true; + //let scale = 1.0; + /// For each Mesh in the model + meshes.forEach(function (mesh, meshIdx) { + if (mesh.materialFlags === 525 /* || mesh.materialFlags == 520 || mesh.materialFlags == 521 */) { + // console.log("Skipping lod"); + return; + } + const move = { x: 0, y: 0, z: 0 }; + /// Add to big mesh + if (!meshGroups[meshIdx]) { + const mg = mesh.geometry.clone(); + meshGroups[meshIdx] = { + readVerts: mg.getAttribute("position").array, + verts: new Float32Array(group.length * mg.getAttribute("position").array.length), + readIndices: mg.getIndex().array, + indices: new Uint32Array(group.length * mg.getIndex().array.length), + readUVs: mg.getAttribute("uv").array, + uvs: new Float32Array(group.length * mg.getAttribute("uv").array.length), + readNormals: mg.getAttribute("normal").array, + normals: new Float32Array(group.length * mg.getAttribute("normal").array.length), + material: mesh.material, + // material:new THREE.MeshBasicMaterial( {color: 0xffcccc, wireframe:true} ), + /* material : new THREE.PointCloudMaterial ({ + color: 0xFF0000, + size: 20 + }), */ + position: { x: model.x, y: model.y, z: model.z }, + }; + } + else { + /// Translate + move.x = model.x - meshGroups[meshIdx].position.x; + move.y = model.z - meshGroups[meshIdx].position.z; + move.z = model.y - meshGroups[meshIdx].position.y; + } + /// Add geom verts + const readVerts = meshGroups[meshIdx].readVerts; + const writeVerts = meshGroups[meshIdx].verts; + const stride = readVerts.length; + for (let i = 0, j = instanceIdx * stride; i < stride; i += 3, j += 3) { + writeVerts[j + 0] = readVerts[i + 0] + move.x; + writeVerts[j + 1] = readVerts[i + 1] + move.y; + writeVerts[j + 2] = readVerts[i + 2] + move.z; + } + const readIndices = meshGroups[meshIdx].readIndices; + const writeIndices = meshGroups[meshIdx].indices; + const strideIndices = readIndices.length; + const shift = (stride * instanceIdx) / 3; + for (let i = 0, j = instanceIdx * strideIndices; i < strideIndices; i++, j++) { + writeIndices[j] = readIndices[i] + shift; + } + const readUVs = meshGroups[meshIdx].readUVs; + const writeUvs = meshGroups[meshIdx].uvs; + const uvStride = readUVs.length; + for (let i = 0, j = instanceIdx * uvStride; i < uvStride; i++, j++) { + writeUvs[j] = readUVs[i]; + } + const readNormals = meshGroups[meshIdx].readNormals; + const writeNormals = meshGroups[meshIdx].normals; + const normalStride = readNormals.length; + for (let i = 0, j = instanceIdx * normalStride; i < normalStride; i++, j++) { + writeNormals[j] = readNormals[i]; + } + }); + }); // End for each model in group + } /// End if meshes + /// Add each cluster of merged meshes to scene + meshGroups.forEach(function (meshGroup) { + const mergedGeom = new THREE.BufferGeometry(); + mergedGeom.setAttribute("position", new THREE.BufferAttribute(meshGroup.verts, 3)); + // mergedGeom.setAttribute( 'index', new THREE.BufferAttribute( meshGroup.indices, 1) ); + mergedGeom.setIndex(new THREE.BufferAttribute(meshGroup.indices, 1)); + mergedGeom.setAttribute("normal", new THREE.BufferAttribute(meshGroup.normals, 3)); + mergedGeom.setAttribute("uv", new THREE.BufferAttribute(meshGroup.uvs, 2)); + //@ts-ignore + mergedGeom.buffersNeedUpdate = true; + const mesh = new THREE.Mesh(mergedGeom, meshGroup.material); + mesh.position.set(meshGroup.position.x, meshGroup.position.z, meshGroup.position.y); + self.getOutput().meshes.push(mesh); + }); // End for each meshgroup + /// Rendering is done, render next. + stepModels(i + 1); + }); + } /// End function stepModels + /// Begin stepping trough the models, rendering them. + stepModels(0); + } + /** + * TODO + * + * @param {*} zone [description] + * @param {*} zoneDef [description] + * @param {*} mapRect [description] + * @return {*} [description] + */ + getModelGroups(zone, zoneDef, mapRect) { + /// Calculate rect in global coordinates + // let zPos = zone.zPos; + const mapX = mapRect[0]; + const mapY = mapRect[1]; + const c = 32 + 16; + // ["x1","uint32","y1","uint32","x2","uint32", "y2", "uint32"] + const zoneRect = { + x1: zone.vertRect[0] * c + mapX, + x2: zone.vertRect[2] * c + mapX, + y1: zone.vertRect[1] * -c - mapY, + y2: zone.vertRect[3] * -c - mapY, + }; + /// Zone width and depth in local corrdinates + /* var zdx = zone.vertRect.x1-zone.vertRect.x2; + var zdy = zone.vertRect.y1-zone.vertRect.y2; */ + /// These zones seems to overflow :/ + if (zone.encodeData.length === 0) { + return {}; + } + // console.log("Get mdl groups", zone); + /// Testing: Render Zone Vert Rect + // RenderUtils.renderRect(zoneRect, -zPos); + const zdx = zone.vertRect[0] - zone.vertRect[2]; + // let zdy = zone.vertRect[1] - zone.vertRect[3]; + /// Zone Flags increases a linear position, used to step trough the Zone. + let linearPos = 0; + const modelGroups = {}; + const terrainTiles = this.getOutput(T3D.TerrainRenderer).terrainTiles; + for (let i = 0; i < zone.flags.length; i += 2) { + /// Step forward + linearPos += zone.flags[i]; + /// Check if a model should be placed + const flag = zone.flags[i + 1]; + if (flag !== 0) { + /// Extract flag data + /// Layer is written in the last 4 bytes + const zoneDefLayer = flag >> 4; + /// Get Zone Definition Layer + const layer = zoneDef.layerDefArray[zoneDefLayer - 1]; + /// TESTING Only show layers with height >= 3 + if (layer /* && layer.height >= 0 */) { + /// Get X and Y from linear position + const modelX = (linearPos % zdx) * c + zoneRect.x1; + const modelY = Math.floor(linearPos / zdx) * c + zoneRect.y1; + /// Get Z from intersection with terrain + let modelZ = null; + const startZ = 100000; + const raycaster = new THREE.Raycaster(new THREE.Vector3(modelX, startZ, modelY), new THREE.Vector3(0, -1, 0)); + /// TODO: OPT? + terrainTiles.forEach(function (chunk) { + if (modelZ === null) { + const intersections = raycaster.intersectObject(chunk); + if (intersections.length > 0) { + modelZ = startZ - intersections[0].distance; + } + } + }); + /// Get model id + /// TODO: check with modelIdx = flag & 0xf; + const modelIdx = 0; + const model = layer.modelArray[modelIdx]; + const modelFilename = model.filename; + // let zOffsets = model.zOffsets; + // let layerFlags = layer.layerFlags; // NOrmaly 128, 128 + // TODO: flip z,y? + const rotRangeX = layer.rotRangeX; // max min + const rotRangeY = layer.rotRangeY; // max min + const rotRangeZ = layer.rotRangeZ; // max min + const scaleRange = layer.scaleRange; // max min + const fadeRange = layer.fadeRange; // max min + // Unused + // tiling: 3 + // type: 1 + // width: 2 + // radiusGround: 2 + /// Create modelGroup (this zone only) + if (!modelGroups[modelFilename]) { + modelGroups[modelFilename] = []; + } + /// Add entry to model group + modelGroups[modelFilename].push({ + x: modelX, + y: modelY, + z: modelZ, + rotRangeX: rotRangeX, + rotRangeY: rotRangeY, + rotRangeZ: rotRangeZ, + scaleRange: scaleRange, + fadeRange: fadeRange, + }); + } /// End if layer + } /// End if flag != 0 + } /// End for each flag + return modelGroups; + } + /** + * Renders all zone meshes in a GW2 map described by the map's "zon2" chunk. + * Output fileds generated: + * + * - *meshes* An array of THREE.Mesh objects visualizing all zone models refered by this map. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + const self = this; + /// Set up output array + self.getOutput().meshes = []; + const zoneChunkData = this.mapFile.getChunk("zon2").data; + const parameterChunkData = this.mapFile.getChunk("parm").data; + // let terrainChunkData = this.mapFile.getChunk("trn").data; + const mapRect = parameterChunkData.rect; + /// Zone data + const zones = zoneChunkData.zoneArray; + const zoneDefs = zoneChunkData.zoneDefArray; + /// Render each zone + let lastPct = -1; + /// Main render loop, render each zone + function stepZone(i) { + const pct = Math.round((100.0 * i) / zones.length); + if (lastPct !== pct) { + self.logger.log(T3D.Logger.TYPE_PROGRESS, "Loading 3D Models (Zone)", pct); + lastPct = pct; + } + if (i >= zones.length) { + callback(); + return; + } + /// Main zone render function call + self.renderZone(zones[i], zoneDefs, mapRect, stepZone.bind(self, i + 1)); + } + stepZone(0); + } + } + /* + /// NOT USED?? + // eslint-disable-next-line no-unused-vars + function addZoneMeshesToScene(meshes, isCached, position, scale, rotation) { + /// Called for each mesh in the zone + /// TODO: Opt opt opt... + + meshes.forEach(function (mesh) { + /// Create new mesh if we got back a cached original. + if (isCached) mesh = new THREE.Mesh(mesh.geometry, mesh.material); + + /// Scale, position and rotate. + mesh.scale.set(scale, scale, scale); + if (rotation) { + mesh.rotation.order = "ZXY"; + mesh.rotation.set(rotation.x, rotation.y, rotation.z); + } + mesh.position.set(position.x, position.y, position.z); + + /// Add to export + this.getOutput().meshes.push(mesh); + }); + } + */ + /// / Not used: zone defintion per chunk data "images" 32*32 points + /* + //Total map dx and dy + var d = terrainChunkHeader.data; + var pd = parameterChunkHeader.data; + var dx = (pd.rect.x2-pd.rect.x1); + var dy = (pd.rect.y2-pd.rect.y1); + + //Each chunk dx and dy + + var c =1; + var cdx = c*dx/d.dims.dim1; + + var cdy = c*dy/d.dims.dim2; + + var cdx = dx/(d.numChunksD_1*2); + var cdy =dy/(d.numChunksD_2*2); + + for(var i=0; i0){ + // console.log("Found flag",flags[j],"@ zoneDef",zoneDef.token,"coord",coord,"index",j); + // } + //} + }); + + } + + } */ + + /** + * + * A renderer that generates a list of readable strings from a "strs" file. + * + * @class StringRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "id" the base ID or file ID of the string file to read strings from. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class StringRenderer extends DataRenderer { + static rendererName = "StringRenderer"; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "StringRenderer"); + } + /** + * Output fileds generated: + * + * - *strings* An array of objects. Each object has a "recid"-property specifing on what index within the file + * a given string was found, and a "value"-property specigying the string value. + * + * - *language* An integer specifing the language of the loaded file. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + const self = this; + /// Get file id + // const fileId = this.settings.id; + /// Load the string file + /// Set up output array + this.getOutput().strings = []; + this.localReader.loadFile(this.settings.id, function (inflatedData) { + const dataView = new DataView(inflatedData); + const end = dataView.byteLength - 2; + /// skip past fcc + let cursor = 4; + let entryIndex = 0; + while (end - cursor > 6) { + const size = dataView.getUint16(cursor, true); + cursor += 2; + const decryptionOffset = dataView.getUint16(cursor, true); + cursor += 2; + const bitsPerSymbol = dataView.getUint16(cursor, true); + cursor += 2; + const entry = { size, decryptionOffset, bitsPerSymbol }; + entry.size -= 6; + if (entry.size > 0) { + const isEncrypted = entry.decryptionOffset !== 0 || entry.bitsPerSymbol !== 0x10; + /// UTF-16 + if (!isEncrypted) { + const value = new Uint16Array(inflatedData, cursor, entry.size / 2); + cursor += entry.size; + self.getOutput().strings.push({ value: String.fromCharCode(...value), recid: entryIndex }); + } + } + entryIndex++; + } + self.getOutput().language = dataView.getUint16(end, true); + callback(); + }); + } + } + + var version = "3.0.0"; + + /* INCLUDES */ + /* PRIVATE VARS */ + const _settings = { + t3dtoolsWorker: "modules/t3dtools/t3dworker.js", + concurrentTasks: typeof navigator !== "undefined" ? navigator.hardwareConcurrency : 1, + }; + // eslint-disable-next-line prefer-const + T3D = { + version: version, + DataRenderer: DataRenderer, + EnvironmentRenderer: EnvironmentRenderer, + HavokRenderer: HavokRenderer, + PropertiesRenderer: PropertiesRenderer, + SingleModelRenderer: SingleModelRenderer, + TerrainRenderer: TerrainRenderer, + ZoneRenderer: ZoneRenderer, + StringRenderer: StringRenderer, + Logger: logger, + MapFileList: mapMap, + MaterialUtils: MaterialUtils, + MathUtils: MathUtils, + RenderUtils: RenderUtils, + PersistantStore: PersistantStore, + FileTypes: FileTypes, + /** + * Creates a new instance of LocalReader with an pNaCl inflater connected to it. + */ + getLocalReader: function (file, callback, t3dtoolsWorker, noIndexedDB) { + const path = t3dtoolsWorker || _settings.t3dtoolsWorker; + // Create the instance and init the threads + const lrInstance = new LocalReader({ + workerPath: path, + workersNb: _settings.concurrentTasks, + noIndexedDB, + }); + /// Callback with the lrInstance + lrInstance.openArchive(file).then(() => { + callback(lrInstance); + }); + return lrInstance; + }, + /** + * Utility method for acceccing a list containing information about all files + * in the .dat connected to the provided LocalReader instance. This method first + * tries to read a local indexing list from the client's localstorage and + * fallbacks to generating the list by scanning the MFT indices of the .dat + * and peeking each file in order to find out what filetype it has. + * + * Note that peeking the files is the time consuming task, so if you don't want + * yout application to spend time indexing the .dat and have a priori knowledge + * about the required file Id's you should not use this method. + **/ + getFileListAsync: function (localReader, callback) { + localReader.readFileList().then((result) => { + const returnObj = {}; + for (const fileEntry of result) { + if (returnObj[fileEntry.fileType] === undefined) { + returnObj[fileEntry.fileType] = []; + } + returnObj[fileEntry.fileType].push(fileEntry.mftId); + } + callback(returnObj); + }); + }, + /** + * Utility method for acceccing a list containing information about all map files + * in the .dat connected to the provided LocalReader instance. This method first + * tries to read a local indexing list from the client's localstorage and + * fallbacks to generating the list by scanning the MFT indices of the .dat + * and peeking each file in order to find out what filetype it has. + * + * If the searchAll flag is not set to true, this process will only scan files + * from the "T3D/MapFileList" property. + **/ + getMapListAsync: function (localReader, callback, searchAll) { + function restoreOuput(array) { + const returnArray = []; + for (const elt of array) { + let category = returnArray.findIndex((i) => i.name === elt.category); + if (category === -1) { + category = returnArray.push({ name: elt.category, maps: [] }) - 1; + } + returnArray[category].maps.push({ + fileName: elt.baseId, + name: elt.name, + }); + } + // And resort it in order + returnArray.sort((i, j) => { + if (i.name < j.name) + return -1; + if (i.name > j.name) + return 1; + return 0; + }); + return { maps: returnArray }; + } + /// If seachAll flag is true, force a deep search + if (searchAll) { + localReader.readFileList().then(() => { + localReader.getMapList().then((result) => { + callback(restoreOuput(result)); + }); + }); + return; + } + else { + localReader.getMapList().then((result) => { + callback(restoreOuput(result)); + }); + } + }, + /** + * Utility method used for rendering map files. Loads a map file and applies + * the provided renderers to it. + **/ + renderMapContentsAsync: function (localReader, fileName, renderers, callback, logger) { + /// VO for storing result from renderers + const context = {}; + let runAllRenderers; + /// Make sure we got an actuall ID number + if (parseInt(fileName)) { + /// File name is baseId, load using local reader. + localReader.loadFile(parseInt(fileName), function (arrayBuffer) { + /// Initiate Map file object. Connect callback + const mapFile = new t3dParser.FileParser(arrayBuffer); + /// Populate VO by running the renderers + runAllRenderers = function (i) { + /// Run each renderer + if (i < renderers.length) { + T3D.runRenderer(renderers[i].renderClass, localReader, Object.assign(renderers[i].settings, { mapFile: mapFile }), context, () => runAllRenderers(i + 1)); + } + /// Fire callback with VO when done + else { + callback(context); + } + }; + /// Starting point for running each renderer + runAllRenderers(0); + }); + } + /// Primitive error message... + else { + const outputLogger = logger || T3D.Logger; + outputLogger.log(T3D.Logger.TYPE_ERROR, "Map id must be an integer!, was:", fileName); + } + }, + /** + * Utility method for applying a single renderer to a LocalReader insatnce. + **/ + runRenderer: function (renderClass, localReader, settings, context, cb) { + const r = new renderClass(localReader, settings, context, undefined, renderClass.rendererName); + r.renderAsync(cb); + }, + getContextValue: function (context, clazz, propName, defaultValue) { + const output = context[clazz.rendererName]; + if (output) { + return output[propName] ? output[propName] : defaultValue; + } + return defaultValue; + }, + /** + * Check if the client web browser can render WebGL 3D content. + * + * @private + * @param {boolean} return_context flag making this method return the canvas object instead of true + * @return {boolean} true if the client is WebGL enabled, false otherwise + */ + hasWebGL: function (return_context) { + if (window.WebGLRenderingContext) { + const canvas = document.createElement("canvas"); + const names = ["webgl", "experimental-webgl", "moz-webgl", "webkit-3d"]; + let context = false; + for (let i = 0; i < 4; i++) { + try { + context = canvas.getContext(names[i]); + if (context && typeof context.getParameter === "function") { + // WebGL is enabled + if (return_context) { + // return WebGL object if the function's argument is present + return { name: names[i], gl: context }; + } + // else, return just true + return true; + } + } + catch { + //continue + } + } + // WebGL is supported, but disabled + return false; + } + // WebGL not supported + return false; + }, + }; + var T3D$1 = T3D; + globalThis.T3D = T3D; + /* PRIVATE METHODS */ + /** + * Performs checks for required browser capabilities and required third party libraries. + * Loggs any warnings or error messages. + * + * @private + * @return {Number} The ammount of errors and warnings generated. + */ + function checkRequirements() { + let numErrors = 0; + if (!globalThis.window || !window.indexedDB) { + T3D.Logger.log(T3D.Logger.TYPE_ERROR, "T3D persistant storing and loading requires indexedDB support."); + numErrors++; + } + if (typeof t3dParser.FileParser === "undefined") { + T3D.Logger.log(T3D.Logger.TYPE_ERROR, "T3D core functionality requires t3d-parser library."); + numErrors++; + } + if (typeof THREE === "undefined") { + T3D.Logger.log(T3D.Logger.TYPE_WARNING, "T3D mesh generation requires three.js library."); + numErrors++; + } + if (numErrors < 1) { + T3D.Logger.log(T3D.Logger.TYPE_MESSAGE, "Tyria 3D API v" + T3D.version + " initialized."); + } + return numErrors; + } + /// Library checks requirements on startup + checkRequirements(); + + return T3D$1; + +})(T3DParser); +//# sourceMappingURL=T3D.js.map diff --git a/examples/static/T3D.js.map b/examples/static/T3D.js.map new file mode 100644 index 0000000..335a7eb --- /dev/null +++ b/examples/static/T3D.js.map @@ -0,0 +1 @@ +{"version":3,"file":"T3D.js","sources":["../src/LocalReader/PersistantStore.ts","../src/LocalReader/DataReader.ts","../src/MapFileList.ts","../src/LocalReader/FileTypes.ts","../src/LocalReader/LocalReader.ts","../src/dataRenderer/DataRenderer.ts","../src/util/MaterialUtils.ts","../src/dataRenderer/EnvironmentRenderer.ts","../src/dataRenderer/HavokRenderer.ts","../src/util/MathUtils.ts","../src/util/RenderUtils.ts","../src/Logger.ts","../src/util/Logs.ts","../src/dataRenderer/PropertiesRenderer.ts","../src/dataRenderer/SingleModelRenderer.ts","../src/util/TerrainShader.ts","../src/dataRenderer/TerrainRenderer.ts","../src/dataRenderer/ZoneRenderer.ts","../src/dataRenderer/StringRenderer.ts","../src/T3DLib.ts"],"sourcesContent":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"names":["FileParser","ArchiveParser","ParsingUtils","MapFileList","FileTypes.getFileType","MaterialUtils.loadLocalTexture","MathUtils.popcount","MathUtils.f16","MaterialUtils.getMaterial","logger","Logger","LogsUtils.progress","RenderUtils.getMeshesForFilename","RenderUtils.getInstancedMesh","RenderUtils.renderRect","TerrainShader.getFragmentShader","TerrainShader.getVertexShader","_version"],"mappings":"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"} \ No newline at end of file diff --git a/examples/static/empty.js b/examples/static/empty.js new file mode 100644 index 0000000..31dfeb9 --- /dev/null +++ b/examples/static/empty.js @@ -0,0 +1,6 @@ +(function () { + 'use strict'; + + + +})(); diff --git a/examples/static/jquery.js b/examples/static/jquery.js new file mode 100644 index 0000000..2170756 --- /dev/null +++ b/examples/static/jquery.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.0 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-04-10T15:07Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && 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 #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 elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +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.5.0", + + // 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; + }, + + // 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 ); + }, + + // 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; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // 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: http://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" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = 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" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://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; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + 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 + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( 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; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// 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: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( 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, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + 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 ) || rcombinators.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. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } 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( rtrim, "$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 Issue #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 Sizzle + * @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; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "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 + /* jshint -W018 */ + 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 Sizzle 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; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, 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; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // 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 ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // 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 ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // 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" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // 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 + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // 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: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + 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 && + 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 && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( 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 Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.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 contains( context, elem ); +}; + +Sizzle.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 (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = 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 += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // 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 ] ) { + Sizzle.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 ] ) { + Sizzle.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 nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "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 = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "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, uniqueCache, 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 ? + node.nodeName.toLowerCase() === 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 + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ 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 ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ 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 ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ 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 + // http://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() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle 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( 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( rtrim, "$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 (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( 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." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.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 === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || 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 + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://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 ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // 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 = argument < 0 ? + argument + length : + argument > length ? + length : + 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(); + +tokenize = Sizzle.tokenize = function( 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 = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + 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 + return parseOnly ? + soFar.length : + soFar ? + Sizzle.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, uniqueCache, 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 ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ 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 + uniqueCache[ 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++ ) { + Sizzle( 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, + 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, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // 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( 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( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #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( rtrim, "$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: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + 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 ) ) { + results.push( 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 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( 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 Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( 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 + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// 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; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +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; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +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 to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#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 Sizzle + 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+ + // 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.stackTrace ); + } + + // 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 stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = 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 master Deferred + master = 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 ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.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$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // 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, stack ); + } +}; + + + + +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 #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 (#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 = Object.create( null ); + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #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 (#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 (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#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 = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#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 or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _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, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#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 (#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 + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +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 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 (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #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 (#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", returnTrue ); + } + + // 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, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + 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 notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // 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 + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // 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.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +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 (#504, #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: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // 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; + }, + + delegateType: delegateType + }; +} ); + +// 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 = /\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 (#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; + + // Reenable 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 { + 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 Sizzle 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 getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #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 (#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! + 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"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // 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, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + 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]).+)/, + rcustomProp = /^--/, + 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; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += 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; +} + +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, + "columnCount": true, + "fillOpacity": 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, + "widows": true, + "zIndex": true, + "zoom": 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 (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#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 )` (#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. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +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 + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#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 classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( 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 (#14686, #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 (#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 + + +support.focusin = "onfocusin" in window; + + +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 (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#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 (#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 ); + } + } +} ); + + +// 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 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + 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 ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +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, + + // #7653, #8125, #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 (#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 #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 (#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 #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 (#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; + + // #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 + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + 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 (#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 + // #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 #8605, #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 ) { + + // #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( " + + + + + + + + + + + diff --git a/explorer/index.js b/explorer/index.js new file mode 100644 index 0000000..20a5660 --- /dev/null +++ b/explorer/index.js @@ -0,0 +1,671 @@ +(function () { + 'use strict'; + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + var src = {}; + + const CANVAS_CLEAR_COLOR = 0x342920; + const FOG_LENGTH = 5000; + + let AppRenderer$1 = class AppRenderer { + constructor(stats) { + this.localReader = undefined; + this._threeContext = {}; + this._mapMeshes = []; + this._mapContext = undefined; + this._renderOptions = undefined; + this.stats = stats; + + // Defaults + this.fog = 25000; + this.movementSpeed = 10000; + this.lightIntensity = 0.5; + this.loadedMapID = undefined; + this.controllerType = "fly"; + + this.webGLRendererOptions = { + sortObjects: false, + logarithmicDepthBuffer: true, + stencil: false, + premultipliedAlpha: false, + antialiasing: true, + }; + } + + /** PUBLIC methods */ + createLocalReader(file, callback) { + this.localReader = T3D.getLocalReader(file, callback, "./static/t3dworker.js"); + } + + getMapList() { + return this.localReader.getMapList(); + } + + scanArchiveForMaps() { + return this.localReader.readFileList(); + } + + loadMap(mapId, renderOptions, callback) { + if (this.loadedMapID) { + this.cleanupMap(); + } + + this.loadedMapID = mapId; + this._renderOptions = renderOptions; + + const renderers = [ + { renderClass: T3D.EnvironmentRenderer, settings: {} }, + { renderClass: T3D.TerrainRenderer, settings: {} }, + ]; + + if (renderOptions.zone) { + renderers.push({ renderClass: T3D.ZoneRenderer, settings: { visible: true } }); + } + if (renderOptions.props) { + renderers.push({ renderClass: T3D.PropertiesRenderer, settings: { visible: true } }); + } + if (renderOptions.collisions) { + renderers.push({ renderClass: T3D.HavokRenderer, settings: { visible: true } }); + } + + T3D.renderMapContentsAsync(this.localReader, this.loadedMapID, renderers, (context) => { + this._loadMapCallback(context, renderOptions, callback); + }); + } + + setFogDistance(value) { + this.fog = value; + if (this._threeContext.scene && this._threeContext.scene.fog) { + this._threeContext.scene.fog.near = this.fog; + this._threeContext.scene.fog.far = this.fog + FOG_LENGTH; + } + if (this._threeContext.camera) { + this._threeContext.camera.far = this.fog + FOG_LENGTH; + this._threeContext.camera.updateProjectionMatrix(); + } + } + + setMovementSpeed(value) { + this.movementSpeed = value; + if (this._threeContext.controls) { + this._threeContext.controls.movementSpeed = value; + } + } + + move(x, y, z) { + if (x) { + this._threeContext.controls.object.position.x = x; + } + if (y) { + this._threeContext.controls.object.position.y = y; + } + if (z) { + this._threeContext.controls.object.position.z = z; + } + } + + rotate(rx, ry, rz) { + if (rx) { + this._threeContext.controls.object.rotation.x = rx; + } + if (ry) { + this._threeContext.controls.object.rotation.y = ry; + } + if (rz) { + this._threeContext.controls.object.rotation.z = rz; + } + } + + setLightIntensity(value) { + this.lightIntensity = value; + if (this._threeContext.sceneLights) { + for (const light of this._threeContext.sceneLights) { + light.intensity = value; + } + } + } + + takeScreenShot() { + const newWindow = window.open("", ""); + newWindow.document.title = "T3D Explorer Screenshot"; + const image = new Image(); + + this._threeContext.renderer.clear(this._threeContext.renderer.getClearColor()); + // Render first skyCamera + this._threeContext.renderer.render(this._threeContext.skyScene, this._threeContext.skyCamera); + this._threeContext.renderer.render(this._threeContext.scene, this._threeContext.camera); + image.src = this._threeContext.renderer.domElement.toDataURL(); + newWindow.document.body.appendChild(image); + } + + setupController(controllerType = "fly") { + if (this._threeContext.controls) { + this._threeContext.controls.dispose(); + } + + if (controllerType === "orbital") { + this._threeContext.controls = new THREE.OrbitControls( + this._threeContext.camera, + this._threeContext.renderer.domElement + ); + + this._threeContext.controls.enableZoom = true; + } else if (controllerType === "fly") { + this._threeContext.controls = new THREE.FlyControls( + this._threeContext.camera, + this._threeContext.renderer.domElement + ); + + this._threeContext.controls.movementSpeed = this.movementSpeed; + this._threeContext.controls.rollSpeed = Math.PI / 6; + this._threeContext.controls.autoForward = false; + this._threeContext.controls.dragToLook = true; + } else { + throw new Error("Invalid controller type"); + } + + this.controllerType = controllerType; + } + + cleanupMap() { + this._mapContext = undefined; + this._renderOptions = undefined; + this.loadedMapID = undefined; + for (const mesh of this._mapMeshes) { + this._threeContext.scene.remove(mesh); + } + for (const skyBox of this._threeContext.skyScene.children) { + this._threeContext.skyScene.remove(skyBox); + } + this._mapMeshes = []; + } + + setupScene() { + const { _threeContext: context } = this; + + context.camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 100000); + context.skyCamera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 100000); + context.scene = new THREE.Scene(); + context.skyScene = new THREE.Scene(); + context.clock = new THREE.Clock(); + + context.ambientLight = new THREE.AmbientLight(0x555555); + context.scene.add(context.ambientLight); + + context.sceneLights = [ + new THREE.DirectionalLight(0xffffff, this.lightIntensity), + new THREE.DirectionalLight(0xffffff, this.lightIntensity), + new THREE.DirectionalLight(0xffffff, this.lightIntensity), + ]; + context.sceneLights[0].position.set(0, 0, 1); + context.sceneLights[0].position.set(0, 1, 0); + context.sceneLights[0].position.set(1, 0, 0); + for (const light of context.sceneLights) { + context.scene.add(light); + } + + context.scene.fog = new THREE.Fog(0xffffff, this.fog, this.fog + FOG_LENGTH); + context.camera.far = this.fog + FOG_LENGTH; + context.camera.updateProjectionMatrix(); + + this.setupWebGLRenderer(true); + this.setupController(); + this._render(); + } + + onWindowResize() { + const { _threeContext: context } = this; + if (context.renderer && context.camera && context.skyCamera) { + context.camera.aspect = window.innerWidth / window.innerHeight; + context.camera.updateProjectionMatrix(); + context.renderer.setSize(window.innerWidth, window.innerHeight); + context.skyCamera.aspect = window.innerWidth / window.innerHeight; + context.skyCamera.updateProjectionMatrix(); + } + } + + // This function is safe to be called whenever the active webgl context is not rendering on screen + setupWebGLRenderer(hidden) { + const { _threeContext: context } = this; + const oldRenderer = context.renderer; + context.renderer = new THREE.WebGLRenderer(this.webGLRendererOptions); + context.renderer.autoClear = false; + context.renderer.setSize(window.innerWidth, window.innerHeight); + context.renderer.setClearColor(CANVAS_CLEAR_COLOR); + if (hidden) { + $(context.renderer.domElement).hide(); + } + if (oldRenderer) { + $(oldRenderer.domElement).remove(); + } + $("#explorer").append(context.renderer.domElement); + } + + getUrlData() { + const controls = this._threeContext.controls; + const pos = controls.object.position; + const rot = controls.object.rotation; + return { + map: this.loadedMapID, + x: Math.round(pos.x * 1000) / 1000, + y: Math.round(pos.y * 1000) / 1000, + z: Math.round(pos.z * 1000) / 1000, + rx: Math.round(rot.x * 10000) / 10000, + ry: Math.round(rot.y * 10000) / 10000, + rz: Math.round(rot.z * 10000) / 10000, + cameraType: this.controllerType, + loadZone: !!this._renderOptions.zone, + loadProp: !!this._renderOptions.props, + showHavok: !!this._renderOptions.collisions, + fog: this.fog, + }; + } + + /** PRIVATE methods */ + _render() { + this.stats.update(); + window.requestAnimationFrame(() => this._render()); + this._threeContext.controls.update(this._threeContext.clock.getDelta()); + + this._threeContext.renderer.clear(this._threeContext.renderer.getClearColor()); + + // Render first skyCamera + this._threeContext.skyCamera.quaternion.copy(this._threeContext.camera.quaternion); + this._threeContext.renderer.render(this._threeContext.skyScene, this._threeContext.skyCamera); + + this._threeContext.renderer.render(this._threeContext.scene, this._threeContext.camera); + } + + _loadMapCallback(context, renderOptions, externalCallback) { + this._mapContext = context; + + // Add all the data from the context to the threejs scene + for (const tile of T3D.getContextValue(context, T3D.TerrainRenderer, "terrainTiles")) { + this._threeContext.scene.add(tile); + this._mapMeshes.push(tile); + } + const water = T3D.getContextValue(context, T3D.TerrainRenderer, "water"); + this._threeContext.scene.add(water); + this._mapMeshes.push(water); + + const skyBox = T3D.getContextValue(context, T3D.EnvironmentRenderer, "skyBox"); + this._threeContext.skyScene.add(skyBox); + const hazeColor = T3D.getContextValue(context, T3D.EnvironmentRenderer, "hazeColor"); + if (hazeColor) { + this._threeContext.renderer.setClearColor( + new THREE.Color(hazeColor[2] / 255, hazeColor[1] / 255, hazeColor[0] / 255) + ); + } + + if (renderOptions.zone) { + for (const zoneModel of T3D.getContextValue(context, T3D.ZoneRenderer, "meshes")) { + this._threeContext.scene.add(zoneModel); + this._mapMeshes.push(zoneModel); + } + } + if (renderOptions.props) { + for (const propModel of T3D.getContextValue(context, T3D.PropertiesRenderer, "meshes")) { + this._threeContext.scene.add(propModel); + this._mapMeshes.push(propModel); + } + } + if (renderOptions.collisions) { + for (const collModel of T3D.getContextValue(context, T3D.HavokRenderer, "meshes")) { + this._threeContext.scene.add(collModel); + this._mapMeshes.push(collModel); + } + } + + // Move camera + const bounds = T3D.getContextValue(context, T3D.TerrainRenderer, "bounds"); + this._resetCameraLocation(bounds); + + // If set fog is too small to see the map we increase it + if (this.fog < bounds.y2 * 1.5) { + this.setFogDistance(bounds.y2 * 2); + } + + return externalCallback(); + } + + _resetCameraLocation(bounds) { + if (this.controllerType === "fly") { + this._threeContext.camera.position.x = 0; + this._threeContext.camera.position.y = bounds ? bounds.y2 : 0; + this._threeContext.camera.position.z = 0; + this._threeContext.camera.rotation.x = (-90 * Math.PI) / 180; + } else { + this._threeContext.camera.position.x = 0; + this._threeContext.camera.position.y = 0; + this._threeContext.camera.position.z = 0; + } + } + }; + + var renderer = AppRenderer$1; + + let UI$1 = class UI { + constructor(appRenderer) { + this.appRenderer = appRenderer; + + this.showingProgress = false; + this.archiveLoaded = false; + this.mapFileList = []; + this.autoLoad = undefined; + this.shouldUpdateUrl = false; + + this.urlUpdateInterval = setInterval(() => this.updateUrl(), 100); + this.lastUrlData = ""; + } + + init() { + this.appRenderer.setupScene(); + + T3D.Logger.logFunctions[T3D.Logger.TYPE_PROGRESS] = (name, value) => { + console.log(name, value); + if (this.showingProgress) { + $("#loadingName").text(name); + $("#loadingValue").text(`${value}%`); + } + }; + + T3D.Logger.logFunctions[T3D.Logger.TYPE_ERROR] = (error) => { + console.error(error); + // If we receive an error before the archive is loaded that means that parsing the archive failed + if (!this.archiveLoaded) { + $("#intro").fadeIn(); + } + }; + + this.setupIntro(); + this.setupMapChoice(); + this.setupMapExplorer(); + + this.appRenderer.setMovementSpeed(parseInt($("#mvntSpeedRange").val(), 10)); + this.appRenderer.setFogDistance(parseInt($("#fogRange").val(), 10)); + this.appRenderer.renderHook = (data) => this.updateUrl(data); + + $("canvas").on("wheel", (event) => this.onMouseWheel(event)); + + this.checkAutoLoad(); + } + + /* + * SETUPS + */ + setupIntro() { + $("#filePickerInput").on("change", (event) => this.onFileSelected(event)); + $("#filePickerButton").on("click", () => $("#filePickerInput").trigger("click")); + } + setupMapChoice() { + $("#categorySelect").on("change", () => this.genMapSelect()); + $("#mapLoadButton").on("click", () => this.onMapLoadClick()); + $("#scanMapLink").on("click", () => this.onScanMapClick()); + } + setupMapExplorer() { + $("#switchControllerType").on("click", () => { + if (this.appRenderer.controllerType === "fly") { + this.appRenderer.setupController("orbital"); + } else { + this.appRenderer.setupController("fly"); + } + }); + $("#goToMapSelectButton").on("click", () => this.onBackToMapSelect()); + $("#takeScreenshot").on("click", () => this.appRenderer.takeScreenShot()); + $("#mvntSpeedRange").on("change", (event) => this.appRenderer.setMovementSpeed(event.target.valueAsNumber)); + $("#fogRange").on("change", (event) => this.appRenderer.setFogDistance(event.target.valueAsNumber)); + + window.addEventListener("resize", () => this.appRenderer.onWindowResize()); + } + + /* + * HANDLERS + */ + onFileSelected(event) { + const file = event.target.files[0]; + $("#intro").slideUp(() => { + this.appRenderer.createLocalReader(file, async () => { + this.archiveLoaded = true; + this.mapFileList = await this.appRenderer.getMapList(); + this.fillMapChoiceSelect(); + // User might enter an non-existant ID so we only trigger autoload if we find the map + if (this.autoLoad && this.mapFileList.find((i) => i.baseId === this.autoLoad.map)) { + return this.onAutoLoad(); + } + $("#choose-map").fadeIn(); + }); + }); + } + + onAutoLoad() { + const mapId = this.autoLoad.map; + const renderOptions = { + zone: this.autoLoad.loadZone === undefined ? false : this.autoLoad.loadZone, + props: this.autoLoad.loadProp === undefined ? true : this.autoLoad.loadProp, + collisions: this.autoLoad.showHavok === undefined ? false : this.autoLoad.showHavok, + }; + this.showingProgress = true; + $("#loading-ui").fadeIn(); + this.appRenderer.loadMap(mapId, renderOptions, () => { + this.appRenderer.setupController(this.autoLoad.cameraType || "fly"); + this.appRenderer.move(this.autoLoad.x, this.autoLoad.y, this.autoLoad.z); + this.appRenderer.rotate(this.autoLoad.rx, this.autoLoad.ry, this.autoLoad.rz); + // Don't forget to cleanup autoLoad, if not it might break map choice UI + this.autoLoad = undefined; + this.onMapLoaded(); + }); + } + + onMapLoadClick() { + // Anti aliasing option can only be enabled when creating the webgl context + // So we update that first if needed + const aaEnabled = $("#enableAA").is(":checked"); + if (this.appRenderer.webGLRendererOptions.antialiasing !== aaEnabled) { + this.appRenderer.webGLRendererOptions.antialiasing = aaEnabled; + this.appRenderer.setupWebGLRenderer(true); + } + + const mapId = $("#mapSelect").val(); + const renderOptions = { + zone: $("#loadZone").is(":checked"), + props: $("#loadProps").is(":checked"), + collisions: $("#loadColl").is(":checked"), + }; + $("#choose-map").slideUp(() => { + this.showingProgress = true; + $("#loading-ui").fadeIn(); + }); + this.appRenderer.loadMap(mapId, renderOptions, () => { + // Reset the position of the camera if we already loaded a previous map + this.appRenderer.setupController(); + this.onMapLoaded(); + }); + } + + onMapLoaded() { + this.showingProgress = false; + $("#loading-ui").slideUp(() => { + $("canvas").fadeIn(); + $("#controls").fadeIn(); + $("#loadingName").text("Loading..."); + $("#loadingValue").text(""); + }); + // Sync the input ranges with their value in the appRenderer + $("#fogRange").val(this.appRenderer.fog); + $("#mvntSpeedRange").val(this.appRenderer.movementSpeed); + this.shouldUpdateUrl = true; + } + + onBackToMapSelect() { + $("#controls").slideUp(() => { + $("canvas").hide(0); + $("#choose-map").fadeIn(); + this.appRenderer.cleanupMap(); + this.updateUrl(true); + this.shouldUpdateUrl = false; + }); + } + + onFileScanDone() { + this.showingProgress = false; + $("#loading-ui").slideUp(() => { + $("#choose-map").fadeIn(); + $("#loadingName").text("Loading..."); + $("#loadingValue").text(""); + }); + } + + onScanMapClick() { + $("#choose-map").slideUp(() => { + $("#loadingName").text("Scanning..."); + this.showingProgress = true; + $("#loading-ui").fadeIn(async () => { + await this.appRenderer.scanArchiveForMaps(); + this.mapFileList = await this.appRenderer.getMapList(); + this.fillMapChoiceSelect(); + this.onFileScanDone(); + }); + }); + } + + onMouseWheel(event) { + const newSpeed = + event.originalEvent.deltaY < 0 + ? Math.min(this.appRenderer.movementSpeed + 100, 10000) + : Math.max(this.appRenderer.movementSpeed - 100, 500); + + this.appRenderer.setMovementSpeed(newSpeed); + $("#mvntSpeedRange").val(newSpeed); + } + + /* UTILS */ + + /** + * This function generates the content of the map selector + * and NOT the category one + */ + genMapSelect() { + const category = $("#categorySelect").val(); + $("#mapSelect").empty(); + for (const map of this.mapFileList) { + if (map.category === category) { + const opt = document.createElement("option"); + opt.value = map.baseId; + opt.innerHTML = map.name; + $("#mapSelect").append(opt); + } + } + } + + /** + * This function generates the content of the category selector + * and NOT the map one + */ + fillMapChoiceSelect() { + const categoryList = this.mapFileList + .sort((a, b) => a.categoryIndex - b.categoryIndex) + .reduce((categories, map) => { + if (categories.indexOf(map.category) === -1) { + categories.push(map.category); + } + return categories; + }, []); + for (const category of categoryList) { + const opt = document.createElement("option"); + opt.value = category; + opt.innerHTML = category; + $("#categorySelect").append(opt); + } + this.genMapSelect(); + } + + updateUrl(shouldClear = false) { + if (this.shouldUpdateUrl) { + if (shouldClear) { + window.location.hash = ""; + } else { + const urlData = $.param(this.appRenderer.getUrlData()); + if (this.lastUrlData !== urlData) { + window.location.hash = urlData; + this.lastUrlData = urlData; + } + } + } + } + + checkAutoLoad() { + const urlData = getParsedUrl(); + if (urlData.map) { + this.autoLoad = urlData; + } + } + }; + + function getParsedUrl() { + const data = deparam(window.location.hash.slice(1)); + data.map = data.map ? parseInt(data.map) : undefined; + data.x = data.x ? parseInt(data.x) : undefined; + data.y = data.y ? parseInt(data.y) : undefined; + data.z = data.z ? parseInt(data.z) : undefined; + data.rx = data.rx ? parseFloat(data.rx) : undefined; + data.ry = data.ry ? parseFloat(data.ry) : undefined; + data.rz = data.rz ? parseFloat(data.rz) : undefined; + data.loadZone = data.loadZone ? data.loadZone === "true" : undefined; + data.loadProp = data.loadProp ? data.loadProp === "true" : undefined; + data.showHavok = data.showHavok ? data.showHavok === "true" : undefined; + data.fog = data.fog ? parseInt(data.fog) : undefined; + + // Backward compatibility with Tyria3DApp + if (data.pitch && data.yaw) { + const pitch = parseFloat(data.pitch); + const yaw = parseFloat(data.yaw); + // convert pitch yaw to xyz rotations: + data.rx = -Math.cos(yaw) * Math.cos(pitch); + data.ry = Math.sin(yaw) * Math.cos(pitch); + data.rz = -Math.sin(pitch); + } + + return data; + } + + function deparam(queryString) { + try { + const parameters = {}; + const chunks = queryString.split("&"); + for (const chunk of chunks) { + const [key, value] = chunk.split("="); + parameters[decodeURIComponent(key)] = decodeURIComponent(value); + } + return parameters; + } catch (error) { + console.error(error); + return {}; + } + } + + var ui$1 = UI$1; + + const AppRenderer = renderer; + const UI = ui$1; + + const stats = new Stats(); + $("body").append(stats.domElement); + $(stats.domElement).hide(); + stats.toggle = () => $(stats.domElement).toggle(); + + const appRenderer = new AppRenderer(stats); + const ui = new UI(appRenderer); + + ui.init(); + + // Allow user to access appRenderer + // This is not used by the app itself + commonjsGlobal.appRenderer = appRenderer; + commonjsGlobal.ui = ui; + commonjsGlobal.stats = stats; + + return src; + +})(); +//# sourceMappingURL=index.js.map diff --git a/explorer/index.js.map b/explorer/index.js.map new file mode 100644 index 0000000..f5da29d --- /dev/null +++ b/explorer/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sources":["../src/renderer.js","../src/ui.js","../src/index.js"],"sourcesContent":["const CANVAS_CLEAR_COLOR = 0x342920;\nconst FOG_LENGTH = 5000;\n\nclass AppRenderer {\n constructor(stats) {\n this.localReader = undefined;\n this._threeContext = {};\n this._mapMeshes = [];\n this._mapContext = undefined;\n this._renderOptions = undefined;\n this.stats = stats;\n\n // Defaults\n this.fog = 25000;\n this.movementSpeed = 10000;\n this.lightIntensity = 0.5;\n this.loadedMapID = undefined;\n this.controllerType = \"fly\";\n\n this.webGLRendererOptions = {\n sortObjects: false,\n logarithmicDepthBuffer: true,\n stencil: false,\n premultipliedAlpha: false,\n antialiasing: true,\n };\n }\n\n /** PUBLIC methods */\n createLocalReader(file, callback) {\n this.localReader = T3D.getLocalReader(file, callback, \"./static/t3dworker.js\");\n }\n\n getMapList() {\n return this.localReader.getMapList();\n }\n\n scanArchiveForMaps() {\n return this.localReader.readFileList();\n }\n\n loadMap(mapId, renderOptions, callback) {\n if (this.loadedMapID) {\n this.cleanupMap();\n }\n\n this.loadedMapID = mapId;\n this._renderOptions = renderOptions;\n\n const renderers = [\n { renderClass: T3D.EnvironmentRenderer, settings: {} },\n { renderClass: T3D.TerrainRenderer, settings: {} },\n ];\n\n if (renderOptions.zone) {\n renderers.push({ renderClass: T3D.ZoneRenderer, settings: { visible: true } });\n }\n if (renderOptions.props) {\n renderers.push({ renderClass: T3D.PropertiesRenderer, settings: { visible: true } });\n }\n if (renderOptions.collisions) {\n renderers.push({ renderClass: T3D.HavokRenderer, settings: { visible: true } });\n }\n\n T3D.renderMapContentsAsync(this.localReader, this.loadedMapID, renderers, (context) => {\n this._loadMapCallback(context, renderOptions, callback);\n });\n }\n\n setFogDistance(value) {\n this.fog = value;\n if (this._threeContext.scene && this._threeContext.scene.fog) {\n this._threeContext.scene.fog.near = this.fog;\n this._threeContext.scene.fog.far = this.fog + FOG_LENGTH;\n }\n if (this._threeContext.camera) {\n this._threeContext.camera.far = this.fog + FOG_LENGTH;\n this._threeContext.camera.updateProjectionMatrix();\n }\n }\n\n setMovementSpeed(value) {\n this.movementSpeed = value;\n if (this._threeContext.controls) {\n this._threeContext.controls.movementSpeed = value;\n }\n }\n\n move(x, y, z) {\n if (x) {\n this._threeContext.controls.object.position.x = x;\n }\n if (y) {\n this._threeContext.controls.object.position.y = y;\n }\n if (z) {\n this._threeContext.controls.object.position.z = z;\n }\n }\n\n rotate(rx, ry, rz) {\n if (rx) {\n this._threeContext.controls.object.rotation.x = rx;\n }\n if (ry) {\n this._threeContext.controls.object.rotation.y = ry;\n }\n if (rz) {\n this._threeContext.controls.object.rotation.z = rz;\n }\n }\n\n setLightIntensity(value) {\n this.lightIntensity = value;\n if (this._threeContext.sceneLights) {\n for (const light of this._threeContext.sceneLights) {\n light.intensity = value;\n }\n }\n }\n\n takeScreenShot() {\n const newWindow = window.open(\"\", \"\");\n newWindow.document.title = \"T3D Explorer Screenshot\";\n const image = new Image();\n\n this._threeContext.renderer.clear(this._threeContext.renderer.getClearColor());\n // Render first skyCamera\n this._threeContext.renderer.render(this._threeContext.skyScene, this._threeContext.skyCamera);\n this._threeContext.renderer.render(this._threeContext.scene, this._threeContext.camera);\n image.src = this._threeContext.renderer.domElement.toDataURL();\n newWindow.document.body.appendChild(image);\n }\n\n setupController(controllerType = \"fly\") {\n if (this._threeContext.controls) {\n this._threeContext.controls.dispose();\n }\n\n if (controllerType === \"orbital\") {\n this._threeContext.controls = new THREE.OrbitControls(\n this._threeContext.camera,\n this._threeContext.renderer.domElement\n );\n\n this._threeContext.controls.enableZoom = true;\n } else if (controllerType === \"fly\") {\n this._threeContext.controls = new THREE.FlyControls(\n this._threeContext.camera,\n this._threeContext.renderer.domElement\n );\n\n this._threeContext.controls.movementSpeed = this.movementSpeed;\n this._threeContext.controls.rollSpeed = Math.PI / 6;\n this._threeContext.controls.autoForward = false;\n this._threeContext.controls.dragToLook = true;\n } else {\n throw new Error(\"Invalid controller type\");\n }\n\n this.controllerType = controllerType;\n }\n\n cleanupMap() {\n this._mapContext = undefined;\n this._renderOptions = undefined;\n this.loadedMapID = undefined;\n for (const mesh of this._mapMeshes) {\n this._threeContext.scene.remove(mesh);\n }\n for (const skyBox of this._threeContext.skyScene.children) {\n this._threeContext.skyScene.remove(skyBox);\n }\n this._mapMeshes = [];\n }\n\n setupScene() {\n const { _threeContext: context } = this;\n\n context.camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 100000);\n context.skyCamera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 100000);\n context.scene = new THREE.Scene();\n context.skyScene = new THREE.Scene();\n context.clock = new THREE.Clock();\n\n context.ambientLight = new THREE.AmbientLight(0x555555);\n context.scene.add(context.ambientLight);\n\n context.sceneLights = [\n new THREE.DirectionalLight(0xffffff, this.lightIntensity),\n new THREE.DirectionalLight(0xffffff, this.lightIntensity),\n new THREE.DirectionalLight(0xffffff, this.lightIntensity),\n ];\n context.sceneLights[0].position.set(0, 0, 1);\n context.sceneLights[0].position.set(0, 1, 0);\n context.sceneLights[0].position.set(1, 0, 0);\n for (const light of context.sceneLights) {\n context.scene.add(light);\n }\n\n context.scene.fog = new THREE.Fog(0xffffff, this.fog, this.fog + FOG_LENGTH);\n context.camera.far = this.fog + FOG_LENGTH;\n context.camera.updateProjectionMatrix();\n\n this.setupWebGLRenderer(true);\n this.setupController();\n this._render();\n }\n\n onWindowResize() {\n const { _threeContext: context } = this;\n if (context.renderer && context.camera && context.skyCamera) {\n context.camera.aspect = window.innerWidth / window.innerHeight;\n context.camera.updateProjectionMatrix();\n context.renderer.setSize(window.innerWidth, window.innerHeight);\n context.skyCamera.aspect = window.innerWidth / window.innerHeight;\n context.skyCamera.updateProjectionMatrix();\n }\n }\n\n // This function is safe to be called whenever the active webgl context is not rendering on screen\n setupWebGLRenderer(hidden) {\n const { _threeContext: context } = this;\n const oldRenderer = context.renderer;\n context.renderer = new THREE.WebGLRenderer(this.webGLRendererOptions);\n context.renderer.autoClear = false;\n context.renderer.setSize(window.innerWidth, window.innerHeight);\n context.renderer.setClearColor(CANVAS_CLEAR_COLOR);\n if (hidden) {\n $(context.renderer.domElement).hide();\n }\n if (oldRenderer) {\n $(oldRenderer.domElement).remove();\n }\n $(\"#explorer\").append(context.renderer.domElement);\n }\n\n getUrlData() {\n const controls = this._threeContext.controls;\n const pos = controls.object.position;\n const rot = controls.object.rotation;\n return {\n map: this.loadedMapID,\n x: Math.round(pos.x * 1000) / 1000,\n y: Math.round(pos.y * 1000) / 1000,\n z: Math.round(pos.z * 1000) / 1000,\n rx: Math.round(rot.x * 10000) / 10000,\n ry: Math.round(rot.y * 10000) / 10000,\n rz: Math.round(rot.z * 10000) / 10000,\n cameraType: this.controllerType,\n loadZone: !!this._renderOptions.zone,\n loadProp: !!this._renderOptions.props,\n showHavok: !!this._renderOptions.collisions,\n fog: this.fog,\n };\n }\n\n /** PRIVATE methods */\n _render() {\n this.stats.update();\n window.requestAnimationFrame(() => this._render());\n this._threeContext.controls.update(this._threeContext.clock.getDelta());\n\n this._threeContext.renderer.clear(this._threeContext.renderer.getClearColor());\n\n // Render first skyCamera\n this._threeContext.skyCamera.quaternion.copy(this._threeContext.camera.quaternion);\n this._threeContext.renderer.render(this._threeContext.skyScene, this._threeContext.skyCamera);\n\n this._threeContext.renderer.render(this._threeContext.scene, this._threeContext.camera);\n }\n\n _loadMapCallback(context, renderOptions, externalCallback) {\n this._mapContext = context;\n\n // Add all the data from the context to the threejs scene\n for (const tile of T3D.getContextValue(context, T3D.TerrainRenderer, \"terrainTiles\")) {\n this._threeContext.scene.add(tile);\n this._mapMeshes.push(tile);\n }\n const water = T3D.getContextValue(context, T3D.TerrainRenderer, \"water\");\n this._threeContext.scene.add(water);\n this._mapMeshes.push(water);\n\n const skyBox = T3D.getContextValue(context, T3D.EnvironmentRenderer, \"skyBox\");\n this._threeContext.skyScene.add(skyBox);\n const hazeColor = T3D.getContextValue(context, T3D.EnvironmentRenderer, \"hazeColor\");\n if (hazeColor) {\n this._threeContext.renderer.setClearColor(\n new THREE.Color(hazeColor[2] / 255, hazeColor[1] / 255, hazeColor[0] / 255)\n );\n }\n\n if (renderOptions.zone) {\n for (const zoneModel of T3D.getContextValue(context, T3D.ZoneRenderer, \"meshes\")) {\n this._threeContext.scene.add(zoneModel);\n this._mapMeshes.push(zoneModel);\n }\n }\n if (renderOptions.props) {\n for (const propModel of T3D.getContextValue(context, T3D.PropertiesRenderer, \"meshes\")) {\n this._threeContext.scene.add(propModel);\n this._mapMeshes.push(propModel);\n }\n }\n if (renderOptions.collisions) {\n for (const collModel of T3D.getContextValue(context, T3D.HavokRenderer, \"meshes\")) {\n this._threeContext.scene.add(collModel);\n this._mapMeshes.push(collModel);\n }\n }\n\n // Move camera\n const bounds = T3D.getContextValue(context, T3D.TerrainRenderer, \"bounds\");\n this._resetCameraLocation(bounds);\n\n // If set fog is too small to see the map we increase it\n if (this.fog < bounds.y2 * 1.5) {\n this.setFogDistance(bounds.y2 * 2);\n }\n\n return externalCallback();\n }\n\n _resetCameraLocation(bounds) {\n if (this.controllerType === \"fly\") {\n this._threeContext.camera.position.x = 0;\n this._threeContext.camera.position.y = bounds ? bounds.y2 : 0;\n this._threeContext.camera.position.z = 0;\n this._threeContext.camera.rotation.x = (-90 * Math.PI) / 180;\n } else {\n this._threeContext.camera.position.x = 0;\n this._threeContext.camera.position.y = 0;\n this._threeContext.camera.position.z = 0;\n }\n }\n}\n\nmodule.exports = AppRenderer;\n","class UI {\n constructor(appRenderer) {\n this.appRenderer = appRenderer;\n\n this.showingProgress = false;\n this.archiveLoaded = false;\n this.mapFileList = [];\n this.autoLoad = undefined;\n this.shouldUpdateUrl = false;\n\n this.urlUpdateInterval = setInterval(() => this.updateUrl(), 100);\n this.lastUrlData = \"\";\n }\n\n init() {\n this.appRenderer.setupScene();\n\n T3D.Logger.logFunctions[T3D.Logger.TYPE_PROGRESS] = (name, value) => {\n console.log(name, value);\n if (this.showingProgress) {\n $(\"#loadingName\").text(name);\n $(\"#loadingValue\").text(`${value}%`);\n }\n };\n\n T3D.Logger.logFunctions[T3D.Logger.TYPE_ERROR] = (error) => {\n console.error(error);\n // If we receive an error before the archive is loaded that means that parsing the archive failed\n if (!this.archiveLoaded) {\n $(\"#intro\").fadeIn();\n }\n };\n\n this.setupIntro();\n this.setupMapChoice();\n this.setupMapExplorer();\n\n this.appRenderer.setMovementSpeed(parseInt($(\"#mvntSpeedRange\").val(), 10));\n this.appRenderer.setFogDistance(parseInt($(\"#fogRange\").val(), 10));\n this.appRenderer.renderHook = (data) => this.updateUrl(data);\n\n $(\"canvas\").on(\"wheel\", (event) => this.onMouseWheel(event));\n\n this.checkAutoLoad();\n }\n\n /*\n * SETUPS\n */\n setupIntro() {\n $(\"#filePickerInput\").on(\"change\", (event) => this.onFileSelected(event));\n $(\"#filePickerButton\").on(\"click\", () => $(\"#filePickerInput\").trigger(\"click\"));\n }\n setupMapChoice() {\n $(\"#categorySelect\").on(\"change\", () => this.genMapSelect());\n $(\"#mapLoadButton\").on(\"click\", () => this.onMapLoadClick());\n $(\"#scanMapLink\").on(\"click\", () => this.onScanMapClick());\n }\n setupMapExplorer() {\n $(\"#switchControllerType\").on(\"click\", () => {\n if (this.appRenderer.controllerType === \"fly\") {\n this.appRenderer.setupController(\"orbital\");\n } else {\n this.appRenderer.setupController(\"fly\");\n }\n });\n $(\"#goToMapSelectButton\").on(\"click\", () => this.onBackToMapSelect());\n $(\"#takeScreenshot\").on(\"click\", () => this.appRenderer.takeScreenShot());\n $(\"#mvntSpeedRange\").on(\"change\", (event) => this.appRenderer.setMovementSpeed(event.target.valueAsNumber));\n $(\"#fogRange\").on(\"change\", (event) => this.appRenderer.setFogDistance(event.target.valueAsNumber));\n\n window.addEventListener(\"resize\", () => this.appRenderer.onWindowResize());\n }\n\n /*\n * HANDLERS\n */\n onFileSelected(event) {\n const file = event.target.files[0];\n $(\"#intro\").slideUp(() => {\n this.appRenderer.createLocalReader(file, async () => {\n this.archiveLoaded = true;\n this.mapFileList = await this.appRenderer.getMapList();\n this.fillMapChoiceSelect();\n // User might enter an non-existant ID so we only trigger autoload if we find the map\n if (this.autoLoad && this.mapFileList.find((i) => i.baseId === this.autoLoad.map)) {\n return this.onAutoLoad();\n }\n $(\"#choose-map\").fadeIn();\n });\n });\n }\n\n onAutoLoad() {\n const mapId = this.autoLoad.map;\n const renderOptions = {\n zone: this.autoLoad.loadZone === undefined ? false : this.autoLoad.loadZone,\n props: this.autoLoad.loadProp === undefined ? true : this.autoLoad.loadProp,\n collisions: this.autoLoad.showHavok === undefined ? false : this.autoLoad.showHavok,\n };\n this.showingProgress = true;\n $(\"#loading-ui\").fadeIn();\n this.appRenderer.loadMap(mapId, renderOptions, () => {\n this.appRenderer.setupController(this.autoLoad.cameraType || \"fly\");\n this.appRenderer.move(this.autoLoad.x, this.autoLoad.y, this.autoLoad.z);\n this.appRenderer.rotate(this.autoLoad.rx, this.autoLoad.ry, this.autoLoad.rz);\n // Don't forget to cleanup autoLoad, if not it might break map choice UI\n this.autoLoad = undefined;\n this.onMapLoaded();\n });\n }\n\n onMapLoadClick() {\n // Anti aliasing option can only be enabled when creating the webgl context\n // So we update that first if needed\n const aaEnabled = $(\"#enableAA\").is(\":checked\");\n if (this.appRenderer.webGLRendererOptions.antialiasing !== aaEnabled) {\n this.appRenderer.webGLRendererOptions.antialiasing = aaEnabled;\n this.appRenderer.setupWebGLRenderer(true);\n }\n\n const mapId = $(\"#mapSelect\").val();\n const renderOptions = {\n zone: $(\"#loadZone\").is(\":checked\"),\n props: $(\"#loadProps\").is(\":checked\"),\n collisions: $(\"#loadColl\").is(\":checked\"),\n };\n $(\"#choose-map\").slideUp(() => {\n this.showingProgress = true;\n $(\"#loading-ui\").fadeIn();\n });\n this.appRenderer.loadMap(mapId, renderOptions, () => {\n // Reset the position of the camera if we already loaded a previous map\n this.appRenderer.setupController();\n this.onMapLoaded();\n });\n }\n\n onMapLoaded() {\n this.showingProgress = false;\n $(\"#loading-ui\").slideUp(() => {\n $(\"canvas\").fadeIn();\n $(\"#controls\").fadeIn();\n $(\"#loadingName\").text(\"Loading...\");\n $(\"#loadingValue\").text(\"\");\n });\n // Sync the input ranges with their value in the appRenderer\n $(\"#fogRange\").val(this.appRenderer.fog);\n $(\"#mvntSpeedRange\").val(this.appRenderer.movementSpeed);\n this.shouldUpdateUrl = true;\n }\n\n onBackToMapSelect() {\n $(\"#controls\").slideUp(() => {\n $(\"canvas\").hide(0);\n $(\"#choose-map\").fadeIn();\n this.appRenderer.cleanupMap();\n this.updateUrl(true);\n this.shouldUpdateUrl = false;\n });\n }\n\n onFileScanDone() {\n this.showingProgress = false;\n $(\"#loading-ui\").slideUp(() => {\n $(\"#choose-map\").fadeIn();\n $(\"#loadingName\").text(\"Loading...\");\n $(\"#loadingValue\").text(\"\");\n });\n }\n\n onScanMapClick() {\n $(\"#choose-map\").slideUp(() => {\n $(\"#loadingName\").text(\"Scanning...\");\n this.showingProgress = true;\n $(\"#loading-ui\").fadeIn(async () => {\n await this.appRenderer.scanArchiveForMaps();\n this.mapFileList = await this.appRenderer.getMapList();\n this.fillMapChoiceSelect();\n this.onFileScanDone();\n });\n });\n }\n\n onMouseWheel(event) {\n const newSpeed =\n event.originalEvent.deltaY < 0\n ? Math.min(this.appRenderer.movementSpeed + 100, 10000)\n : Math.max(this.appRenderer.movementSpeed - 100, 500);\n\n this.appRenderer.setMovementSpeed(newSpeed);\n $(\"#mvntSpeedRange\").val(newSpeed);\n }\n\n /* UTILS */\n\n /**\n * This function generates the content of the map selector\n * and NOT the category one\n */\n genMapSelect() {\n const category = $(\"#categorySelect\").val();\n $(\"#mapSelect\").empty();\n for (const map of this.mapFileList) {\n if (map.category === category) {\n const opt = document.createElement(\"option\");\n opt.value = map.baseId;\n opt.innerHTML = map.name;\n $(\"#mapSelect\").append(opt);\n }\n }\n }\n\n /**\n * This function generates the content of the category selector\n * and NOT the map one\n */\n fillMapChoiceSelect() {\n const categoryList = this.mapFileList\n .sort((a, b) => a.categoryIndex - b.categoryIndex)\n .reduce((categories, map) => {\n if (categories.indexOf(map.category) === -1) {\n categories.push(map.category);\n }\n return categories;\n }, []);\n for (const category of categoryList) {\n const opt = document.createElement(\"option\");\n opt.value = category;\n opt.innerHTML = category;\n $(\"#categorySelect\").append(opt);\n }\n this.genMapSelect();\n }\n\n updateUrl(shouldClear = false) {\n if (this.shouldUpdateUrl) {\n if (shouldClear) {\n window.location.hash = \"\";\n } else {\n const urlData = $.param(this.appRenderer.getUrlData());\n if (this.lastUrlData !== urlData) {\n window.location.hash = urlData;\n this.lastUrlData = urlData;\n }\n }\n }\n }\n\n checkAutoLoad() {\n const urlData = getParsedUrl();\n if (urlData.map) {\n this.autoLoad = urlData;\n }\n }\n}\n\nfunction getParsedUrl() {\n const data = deparam(window.location.hash.slice(1));\n data.map = data.map ? parseInt(data.map) : undefined;\n data.x = data.x ? parseInt(data.x) : undefined;\n data.y = data.y ? parseInt(data.y) : undefined;\n data.z = data.z ? parseInt(data.z) : undefined;\n data.rx = data.rx ? parseFloat(data.rx) : undefined;\n data.ry = data.ry ? parseFloat(data.ry) : undefined;\n data.rz = data.rz ? parseFloat(data.rz) : undefined;\n data.loadZone = data.loadZone ? data.loadZone === \"true\" : undefined;\n data.loadProp = data.loadProp ? data.loadProp === \"true\" : undefined;\n data.showHavok = data.showHavok ? data.showHavok === \"true\" : undefined;\n data.fog = data.fog ? parseInt(data.fog) : undefined;\n\n // Backward compatibility with Tyria3DApp\n if (data.pitch && data.yaw) {\n const pitch = parseFloat(data.pitch);\n const yaw = parseFloat(data.yaw);\n // convert pitch yaw to xyz rotations:\n data.rx = -Math.cos(yaw) * Math.cos(pitch);\n data.ry = Math.sin(yaw) * Math.cos(pitch);\n data.rz = -Math.sin(pitch);\n }\n\n return data;\n}\n\nfunction deparam(queryString) {\n try {\n const parameters = {};\n const chunks = queryString.split(\"&\");\n for (const chunk of chunks) {\n const [key, value] = chunk.split(\"=\");\n parameters[decodeURIComponent(key)] = decodeURIComponent(value);\n }\n return parameters;\n } catch (error) {\n console.error(error);\n return {};\n }\n}\n\nmodule.exports = UI;\n","const AppRenderer = require(\"./renderer\");\nconst UI = require(\"./ui\");\n\nconst stats = new Stats();\n$(\"body\").append(stats.domElement);\n$(stats.domElement).hide();\nstats.toggle = () => $(stats.domElement).toggle();\n\nconst appRenderer = new AppRenderer(stats);\nconst ui = new UI(appRenderer);\n\nui.init();\n\n// Allow user to access appRenderer\n// This is not used by the app itself\nglobal.appRenderer = appRenderer;\nglobal.ui = ui;\nglobal.stats = stats;\n"],"names":["AppRenderer","ui","UI","require$$0","require$$1","global"],"mappings":"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"} \ No newline at end of file diff --git a/explorer/static/Background1_2400_1200.jpg b/explorer/static/Background1_2400_1200.jpg new file mode 100644 index 0000000..ae2b39e Binary files /dev/null and b/explorer/static/Background1_2400_1200.jpg differ diff --git a/explorer/static/Background2_3840_2026.jpg b/explorer/static/Background2_3840_2026.jpg new file mode 100644 index 0000000..084afe5 Binary files /dev/null and b/explorer/static/Background2_3840_2026.jpg differ diff --git a/explorer/static/Background3_4096x2027.jpg b/explorer/static/Background3_4096x2027.jpg new file mode 100644 index 0000000..3d8b9f7 Binary files /dev/null and b/explorer/static/Background3_4096x2027.jpg differ diff --git a/explorer/static/Background4_2498x1403.png b/explorer/static/Background4_2498x1403.png new file mode 100644 index 0000000..6e4ab59 Binary files /dev/null and b/explorer/static/Background4_2498x1403.png differ diff --git a/explorer/static/FlyControls.js b/explorer/static/FlyControls.js new file mode 100644 index 0000000..253d987 --- /dev/null +++ b/explorer/static/FlyControls.js @@ -0,0 +1,307 @@ +THREE.FlyControls = function ( object, domElement ) { + + if ( domElement === undefined ) { + + console.warn( 'THREE.FlyControls: The second parameter "domElement" is now mandatory.' ); + domElement = document; + + } + + this.object = object; + this.domElement = domElement; + + if ( domElement ) this.domElement.setAttribute( 'tabindex', - 1 ); + + // API + + this.movementSpeed = 1.0; + this.rollSpeed = 0.005; + + this.dragToLook = false; + this.autoForward = false; + + // disable default target object behavior + + // internals + + var scope = this; + var changeEvent = { type: "change" }; + var EPS = 0.000001; + + this.tmpQuaternion = new THREE.Quaternion(); + + this.mouseStatus = 0; + + this.moveState = { up: 0, down: 0, left: 0, right: 0, forward: 0, back: 0, pitchUp: 0, pitchDown: 0, yawLeft: 0, yawRight: 0, rollLeft: 0, rollRight: 0 }; + this.moveVector = new THREE.Vector3( 0, 0, 0 ); + this.rotationVector = new THREE.Vector3( 0, 0, 0 ); + + this.keydown = function ( event ) { + + if ( event.altKey ) { + + return; + + } + + //event.preventDefault(); + + switch ( event.keyCode ) { + + case 16: /* shift */ this.movementSpeedMultiplier = .1; break; + + case 87: /*W*/ this.moveState.forward = 1; break; + case 83: /*S*/ this.moveState.back = 1; break; + + case 65: /*A*/ this.moveState.left = 1; break; + case 68: /*D*/ this.moveState.right = 1; break; + + case 82: /*R*/ this.moveState.up = 1; break; + case 70: /*F*/ this.moveState.down = 1; break; + + case 38: /*up*/ this.moveState.pitchUp = 1; break; + case 40: /*down*/ this.moveState.pitchDown = 1; break; + + case 37: /*left*/ this.moveState.yawLeft = 1; break; + case 39: /*right*/ this.moveState.yawRight = 1; break; + + case 81: /*Q*/ this.moveState.rollLeft = 1; break; + case 69: /*E*/ this.moveState.rollRight = 1; break; + + } + + this.updateMovementVector(); + this.updateRotationVector(); + + }; + + this.keyup = function ( event ) { + + switch ( event.keyCode ) { + + case 16: /* shift */ this.movementSpeedMultiplier = 1; break; + + case 87: /*W*/ this.moveState.forward = 0; break; + case 83: /*S*/ this.moveState.back = 0; break; + + case 65: /*A*/ this.moveState.left = 0; break; + case 68: /*D*/ this.moveState.right = 0; break; + + case 82: /*R*/ this.moveState.up = 0; break; + case 70: /*F*/ this.moveState.down = 0; break; + + case 38: /*up*/ this.moveState.pitchUp = 0; break; + case 40: /*down*/ this.moveState.pitchDown = 0; break; + + case 37: /*left*/ this.moveState.yawLeft = 0; break; + case 39: /*right*/ this.moveState.yawRight = 0; break; + + case 81: /*Q*/ this.moveState.rollLeft = 0; break; + case 69: /*E*/ this.moveState.rollRight = 0; break; + + } + + this.updateMovementVector(); + this.updateRotationVector(); + + }; + + this.mousedown = function ( event ) { + + if ( this.domElement !== document ) { + + this.domElement.focus(); + + } + + event.preventDefault(); + event.stopPropagation(); + + if ( this.dragToLook ) { + + this.mouseStatus ++; + + } else { + + switch ( event.button ) { + + case 0: this.moveState.forward = 1; break; + case 2: this.moveState.back = 1; break; + + } + + this.updateMovementVector(); + + } + + }; + + this.mousemove = function ( event ) { + + if ( ! this.dragToLook || this.mouseStatus > 0 ) { + + var container = this.getContainerDimensions(); + var halfWidth = container.size[ 0 ] / 2; + var halfHeight = container.size[ 1 ] / 2; + + this.moveState.yawLeft = - ( ( event.pageX - container.offset[ 0 ] ) - halfWidth ) / halfWidth; + this.moveState.pitchDown = ( ( event.pageY - container.offset[ 1 ] ) - halfHeight ) / halfHeight; + + this.updateRotationVector(); + + } + + }; + + this.mouseup = function ( event ) { + + event.preventDefault(); + event.stopPropagation(); + + if ( this.dragToLook ) { + + this.mouseStatus --; + + this.moveState.yawLeft = this.moveState.pitchDown = 0; + + } else { + + switch ( event.button ) { + + case 0: this.moveState.forward = 0; break; + case 2: this.moveState.back = 0; break; + + } + + this.updateMovementVector(); + + } + + this.updateRotationVector(); + + }; + + this.update = function () { + + var lastQuaternion = new THREE.Quaternion(); + var lastPosition = new THREE.Vector3(); + + return function ( delta ) { + + var moveMult = delta * scope.movementSpeed; + var rotMult = delta * scope.rollSpeed; + + scope.object.translateX( scope.moveVector.x * moveMult ); + scope.object.translateY( scope.moveVector.y * moveMult ); + scope.object.translateZ( scope.moveVector.z * moveMult ); + + scope.tmpQuaternion.set( scope.rotationVector.x * rotMult, scope.rotationVector.y * rotMult, scope.rotationVector.z * rotMult, 1 ).normalize(); + scope.object.quaternion.multiply( scope.tmpQuaternion ); + + if ( + lastPosition.distanceToSquared( scope.object.position ) > EPS || + 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS + ) { + + scope.dispatchEvent( changeEvent ); + lastQuaternion.copy( scope.object.quaternion ); + lastPosition.copy( scope.object.position ); + + } + + }; + + }(); + + this.updateMovementVector = function () { + + var forward = ( this.moveState.forward || ( this.autoForward && ! this.moveState.back ) ) ? 1 : 0; + + this.moveVector.x = ( - this.moveState.left + this.moveState.right ); + this.moveVector.y = ( - this.moveState.down + this.moveState.up ); + this.moveVector.z = ( - forward + this.moveState.back ); + + //console.log( 'move:', [ this.moveVector.x, this.moveVector.y, this.moveVector.z ] ); + + }; + + this.updateRotationVector = function () { + + this.rotationVector.x = ( - this.moveState.pitchDown + this.moveState.pitchUp ); + this.rotationVector.y = ( - this.moveState.yawRight + this.moveState.yawLeft ); + this.rotationVector.z = ( - this.moveState.rollRight + this.moveState.rollLeft ); + + //console.log( 'rotate:', [ this.rotationVector.x, this.rotationVector.y, this.rotationVector.z ] ); + + }; + + this.getContainerDimensions = function () { + + if ( this.domElement != document ) { + + return { + size: [ this.domElement.offsetWidth, this.domElement.offsetHeight ], + offset: [ this.domElement.offsetLeft, this.domElement.offsetTop ] + }; + + } else { + + return { + size: [ window.innerWidth, window.innerHeight ], + offset: [ 0, 0 ] + }; + + } + + }; + + function bind( scope, fn ) { + + return function () { + + fn.apply( scope, arguments ); + + }; + + } + + function contextmenu( event ) { + + event.preventDefault(); + + } + + this.dispose = function () { + + this.domElement.removeEventListener( 'contextmenu', contextmenu, false ); + this.domElement.removeEventListener( 'mousedown', _mousedown, false ); + this.domElement.removeEventListener( 'mousemove', _mousemove, false ); + this.domElement.removeEventListener( 'mouseup', _mouseup, false ); + + window.removeEventListener( 'keydown', _keydown, false ); + window.removeEventListener( 'keyup', _keyup, false ); + + }; + + var _mousemove = bind( this, this.mousemove ); + var _mousedown = bind( this, this.mousedown ); + var _mouseup = bind( this, this.mouseup ); + var _keydown = bind( this, this.keydown ); + var _keyup = bind( this, this.keyup ); + + this.domElement.addEventListener( 'contextmenu', contextmenu, false ); + + this.domElement.addEventListener( 'mousemove', _mousemove, false ); + this.domElement.addEventListener( 'mousedown', _mousedown, false ); + this.domElement.addEventListener( 'mouseup', _mouseup, false ); + + window.addEventListener( 'keydown', _keydown, false ); + window.addEventListener( 'keyup', _keyup, false ); + + this.updateMovementVector(); + this.updateRotationVector(); + +}; + +THREE.FlyControls.prototype = Object.create( THREE.EventDispatcher.prototype ); +THREE.FlyControls.prototype.constructor = THREE.FlyControls; diff --git a/explorer/static/GitHub-Mark-120px-plus.png b/explorer/static/GitHub-Mark-120px-plus.png new file mode 100644 index 0000000..ea6ff54 Binary files /dev/null and b/explorer/static/GitHub-Mark-120px-plus.png differ diff --git a/explorer/static/OrbitControls.js b/explorer/static/OrbitControls.js new file mode 100644 index 0000000..97b9396 --- /dev/null +++ b/explorer/static/OrbitControls.js @@ -0,0 +1,1207 @@ +// This set of controls performs orbiting, dollying (zooming), and panning. +// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). +// +// Orbit - left mouse / touch: one-finger move +// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish +// Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move + +THREE.OrbitControls = function ( object, domElement ) { + + if ( domElement === undefined ) console.warn( 'THREE.OrbitControls: The second parameter "domElement" is now mandatory.' ); + if ( domElement === document ) console.error( 'THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.' ); + + this.object = object; + this.domElement = domElement; + + // Set to false to disable this control + this.enabled = true; + + // "target" sets the location of focus, where the object orbits around + this.target = new THREE.Vector3(); + + // How far you can dolly in and out ( PerspectiveCamera only ) + this.minDistance = 0; + this.maxDistance = Infinity; + + // How far you can zoom in and out ( OrthographicCamera only ) + this.minZoom = 0; + this.maxZoom = Infinity; + + // How far you can orbit vertically, upper and lower limits. + // Range is 0 to Math.PI radians. + this.minPolarAngle = 0; // radians + this.maxPolarAngle = Math.PI; // radians + + // How far you can orbit horizontally, upper and lower limits. + // If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI ) + this.minAzimuthAngle = - Infinity; // radians + this.maxAzimuthAngle = Infinity; // radians + + // Set to true to enable damping (inertia) + // If damping is enabled, you must call controls.update() in your animation loop + this.enableDamping = false; + this.dampingFactor = 0.05; + + // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. + // Set to false to disable zooming + this.enableZoom = true; + this.zoomSpeed = 1.0; + + // Set to false to disable rotating + this.enableRotate = true; + this.rotateSpeed = 1.0; + + // Set to false to disable panning + this.enablePan = true; + this.panSpeed = 1.0; + this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up + this.keyPanSpeed = 7.0; // pixels moved per arrow key push + + // Set to true to automatically rotate around the target + // If auto-rotate is enabled, you must call controls.update() in your animation loop + this.autoRotate = false; + this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 + + // Set to false to disable use of the keys + this.enableKeys = true; + + // The four arrow keys + this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; + + // Mouse buttons + this.mouseButtons = { LEFT: THREE.MOUSE.ROTATE, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.PAN }; + + // Touch fingers + this.touches = { ONE: THREE.TOUCH.ROTATE, TWO: THREE.TOUCH.DOLLY_PAN }; + + // for reset + this.target0 = this.target.clone(); + this.position0 = this.object.position.clone(); + this.zoom0 = this.object.zoom; + + // + // public methods + // + + this.getPolarAngle = function () { + + return spherical.phi; + + }; + + this.getAzimuthalAngle = function () { + + return spherical.theta; + + }; + + this.saveState = function () { + + scope.target0.copy( scope.target ); + scope.position0.copy( scope.object.position ); + scope.zoom0 = scope.object.zoom; + + }; + + this.reset = function () { + + scope.target.copy( scope.target0 ); + scope.object.position.copy( scope.position0 ); + scope.object.zoom = scope.zoom0; + + scope.object.updateProjectionMatrix(); + scope.dispatchEvent( changeEvent ); + + scope.update(); + + state = STATE.NONE; + + }; + + // this method is exposed, but perhaps it would be better if we can make it private... + this.update = function () { + + var offset = new THREE.Vector3(); + + // so camera.up is the orbit axis + var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) ); + var quatInverse = quat.clone().invert(); + + var lastPosition = new THREE.Vector3(); + var lastQuaternion = new THREE.Quaternion(); + + var twoPI = 2 * Math.PI; + + return function update() { + + var position = scope.object.position; + + offset.copy( position ).sub( scope.target ); + + // rotate offset to "y-axis-is-up" space + offset.applyQuaternion( quat ); + + // angle from z-axis around y-axis + spherical.setFromVector3( offset ); + + if ( scope.autoRotate && state === STATE.NONE ) { + + rotateLeft( getAutoRotationAngle() ); + + } + + if ( scope.enableDamping ) { + + spherical.theta += sphericalDelta.theta * scope.dampingFactor; + spherical.phi += sphericalDelta.phi * scope.dampingFactor; + + } else { + + spherical.theta += sphericalDelta.theta; + spherical.phi += sphericalDelta.phi; + + } + + // restrict theta to be between desired limits + + var min = scope.minAzimuthAngle; + var max = scope.maxAzimuthAngle; + + if ( isFinite( min ) && isFinite( max ) ) { + + if ( min < - Math.PI ) min += twoPI; else if ( min > Math.PI ) min -= twoPI; + + if ( max < - Math.PI ) max += twoPI; else if ( max > Math.PI ) max -= twoPI; + + if ( min <= max ) { + + spherical.theta = Math.max( min, Math.min( max, spherical.theta ) ); + + } else { + + spherical.theta = ( spherical.theta > ( min + max ) / 2 ) ? + Math.max( min, spherical.theta ) : + Math.min( max, spherical.theta ); + + } + + } + + // restrict phi to be between desired limits + spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) ); + + spherical.makeSafe(); + + + spherical.radius *= scale; + + // restrict radius to be between desired limits + spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) ); + + // move target to panned location + + if ( scope.enableDamping === true ) { + + scope.target.addScaledVector( panOffset, scope.dampingFactor ); + + } else { + + scope.target.add( panOffset ); + + } + + offset.setFromSpherical( spherical ); + + // rotate offset back to "camera-up-vector-is-up" space + offset.applyQuaternion( quatInverse ); + + position.copy( scope.target ).add( offset ); + + scope.object.lookAt( scope.target ); + + if ( scope.enableDamping === true ) { + + sphericalDelta.theta *= ( 1 - scope.dampingFactor ); + sphericalDelta.phi *= ( 1 - scope.dampingFactor ); + + panOffset.multiplyScalar( 1 - scope.dampingFactor ); + + } else { + + sphericalDelta.set( 0, 0, 0 ); + + panOffset.set( 0, 0, 0 ); + + } + + scale = 1; + + // update condition is: + // min(camera displacement, camera rotation in radians)^2 > EPS + // using small-angle approximation cos(x/2) = 1 - x^2 / 8 + + if ( zoomChanged || + lastPosition.distanceToSquared( scope.object.position ) > EPS || + 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) { + + scope.dispatchEvent( changeEvent ); + + lastPosition.copy( scope.object.position ); + lastQuaternion.copy( scope.object.quaternion ); + zoomChanged = false; + + return true; + + } + + return false; + + }; + + }(); + + this.dispose = function () { + + scope.domElement.removeEventListener( 'contextmenu', onContextMenu, false ); + + scope.domElement.removeEventListener( 'pointerdown', onPointerDown, false ); + scope.domElement.removeEventListener( 'wheel', onMouseWheel, false ); + + scope.domElement.removeEventListener( 'touchstart', onTouchStart, false ); + scope.domElement.removeEventListener( 'touchend', onTouchEnd, false ); + scope.domElement.removeEventListener( 'touchmove', onTouchMove, false ); + + scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove, false ); + scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp, false ); + + scope.domElement.removeEventListener( 'keydown', onKeyDown, false ); + + //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here? + + }; + + // + // internals + // + + var scope = this; + + var changeEvent = { type: 'change' }; + var startEvent = { type: 'start' }; + var endEvent = { type: 'end' }; + + var STATE = { + NONE: - 1, + ROTATE: 0, + DOLLY: 1, + PAN: 2, + TOUCH_ROTATE: 3, + TOUCH_PAN: 4, + TOUCH_DOLLY_PAN: 5, + TOUCH_DOLLY_ROTATE: 6 + }; + + var state = STATE.NONE; + + var EPS = 0.000001; + + // current position in spherical coordinates + var spherical = new THREE.Spherical(); + var sphericalDelta = new THREE.Spherical(); + + var scale = 1; + var panOffset = new THREE.Vector3(); + var zoomChanged = false; + + var rotateStart = new THREE.Vector2(); + var rotateEnd = new THREE.Vector2(); + var rotateDelta = new THREE.Vector2(); + + var panStart = new THREE.Vector2(); + var panEnd = new THREE.Vector2(); + var panDelta = new THREE.Vector2(); + + var dollyStart = new THREE.Vector2(); + var dollyEnd = new THREE.Vector2(); + var dollyDelta = new THREE.Vector2(); + + function getAutoRotationAngle() { + + return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; + + } + + function getZoomScale() { + + return Math.pow( 0.95, scope.zoomSpeed ); + + } + + function rotateLeft( angle ) { + + sphericalDelta.theta -= angle; + + } + + function rotateUp( angle ) { + + sphericalDelta.phi -= angle; + + } + + var panLeft = function () { + + var v = new THREE.Vector3(); + + return function panLeft( distance, objectMatrix ) { + + v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix + v.multiplyScalar( - distance ); + + panOffset.add( v ); + + }; + + }(); + + var panUp = function () { + + var v = new THREE.Vector3(); + + return function panUp( distance, objectMatrix ) { + + if ( scope.screenSpacePanning === true ) { + + v.setFromMatrixColumn( objectMatrix, 1 ); + + } else { + + v.setFromMatrixColumn( objectMatrix, 0 ); + v.crossVectors( scope.object.up, v ); + + } + + v.multiplyScalar( distance ); + + panOffset.add( v ); + + }; + + }(); + + // deltaX and deltaY are in pixels; right and down are positive + var pan = function () { + + var offset = new THREE.Vector3(); + + return function pan( deltaX, deltaY ) { + + var element = scope.domElement; + + if ( scope.object.isPerspectiveCamera ) { + + // perspective + var position = scope.object.position; + offset.copy( position ).sub( scope.target ); + var targetDistance = offset.length(); + + // half of the fov is center to top of screen + targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 ); + + // we use only clientHeight here so aspect ratio does not distort speed + panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix ); + panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix ); + + } else if ( scope.object.isOrthographicCamera ) { + + // orthographic + panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix ); + panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix ); + + } else { + + // camera neither orthographic nor perspective + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' ); + scope.enablePan = false; + + } + + }; + + }(); + + function dollyOut( dollyScale ) { + + if ( scope.object.isPerspectiveCamera ) { + + scale /= dollyScale; + + } else if ( scope.object.isOrthographicCamera ) { + + scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) ); + scope.object.updateProjectionMatrix(); + zoomChanged = true; + + } else { + + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); + scope.enableZoom = false; + + } + + } + + function dollyIn( dollyScale ) { + + if ( scope.object.isPerspectiveCamera ) { + + scale *= dollyScale; + + } else if ( scope.object.isOrthographicCamera ) { + + scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) ); + scope.object.updateProjectionMatrix(); + zoomChanged = true; + + } else { + + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); + scope.enableZoom = false; + + } + + } + + // + // event callbacks - update the object state + // + + function handleMouseDownRotate( event ) { + + rotateStart.set( event.clientX, event.clientY ); + + } + + function handleMouseDownDolly( event ) { + + dollyStart.set( event.clientX, event.clientY ); + + } + + function handleMouseDownPan( event ) { + + panStart.set( event.clientX, event.clientY ); + + } + + function handleMouseMoveRotate( event ) { + + rotateEnd.set( event.clientX, event.clientY ); + + rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); + + var element = scope.domElement; + + rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height + + rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); + + rotateStart.copy( rotateEnd ); + + scope.update(); + + } + + function handleMouseMoveDolly( event ) { + + dollyEnd.set( event.clientX, event.clientY ); + + dollyDelta.subVectors( dollyEnd, dollyStart ); + + if ( dollyDelta.y > 0 ) { + + dollyOut( getZoomScale() ); + + } else if ( dollyDelta.y < 0 ) { + + dollyIn( getZoomScale() ); + + } + + dollyStart.copy( dollyEnd ); + + scope.update(); + + } + + function handleMouseMovePan( event ) { + + panEnd.set( event.clientX, event.clientY ); + + panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); + + pan( panDelta.x, panDelta.y ); + + panStart.copy( panEnd ); + + scope.update(); + + } + + function handleMouseUp( /*event*/ ) { + + // no-op + + } + + function handleMouseWheel( event ) { + + if ( event.deltaY < 0 ) { + + dollyIn( getZoomScale() ); + + } else if ( event.deltaY > 0 ) { + + dollyOut( getZoomScale() ); + + } + + scope.update(); + + } + + function handleKeyDown( event ) { + + var needsUpdate = false; + + switch ( event.keyCode ) { + + case scope.keys.UP: + pan( 0, scope.keyPanSpeed ); + needsUpdate = true; + break; + + case scope.keys.BOTTOM: + pan( 0, - scope.keyPanSpeed ); + needsUpdate = true; + break; + + case scope.keys.LEFT: + pan( scope.keyPanSpeed, 0 ); + needsUpdate = true; + break; + + case scope.keys.RIGHT: + pan( - scope.keyPanSpeed, 0 ); + needsUpdate = true; + break; + + } + + if ( needsUpdate ) { + + // prevent the browser from scrolling on cursor keys + event.preventDefault(); + + scope.update(); + + } + + + } + + function handleTouchStartRotate( event ) { + + if ( event.touches.length == 1 ) { + + rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + + rotateStart.set( x, y ); + + } + + } + + function handleTouchStartPan( event ) { + + if ( event.touches.length == 1 ) { + + panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + + panStart.set( x, y ); + + } + + } + + function handleTouchStartDolly( event ) { + + var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; + var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + + var distance = Math.sqrt( dx * dx + dy * dy ); + + dollyStart.set( 0, distance ); + + } + + function handleTouchStartDollyPan( event ) { + + if ( scope.enableZoom ) handleTouchStartDolly( event ); + + if ( scope.enablePan ) handleTouchStartPan( event ); + + } + + function handleTouchStartDollyRotate( event ) { + + if ( scope.enableZoom ) handleTouchStartDolly( event ); + + if ( scope.enableRotate ) handleTouchStartRotate( event ); + + } + + function handleTouchMoveRotate( event ) { + + if ( event.touches.length == 1 ) { + + rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + + rotateEnd.set( x, y ); + + } + + rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); + + var element = scope.domElement; + + rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height + + rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); + + rotateStart.copy( rotateEnd ); + + } + + function handleTouchMovePan( event ) { + + if ( event.touches.length == 1 ) { + + panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + + panEnd.set( x, y ); + + } + + panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); + + pan( panDelta.x, panDelta.y ); + + panStart.copy( panEnd ); + + } + + function handleTouchMoveDolly( event ) { + + var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; + var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + + var distance = Math.sqrt( dx * dx + dy * dy ); + + dollyEnd.set( 0, distance ); + + dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) ); + + dollyOut( dollyDelta.y ); + + dollyStart.copy( dollyEnd ); + + } + + function handleTouchMoveDollyPan( event ) { + + if ( scope.enableZoom ) handleTouchMoveDolly( event ); + + if ( scope.enablePan ) handleTouchMovePan( event ); + + } + + function handleTouchMoveDollyRotate( event ) { + + if ( scope.enableZoom ) handleTouchMoveDolly( event ); + + if ( scope.enableRotate ) handleTouchMoveRotate( event ); + + } + + function handleTouchEnd( /*event*/ ) { + + // no-op + + } + + // + // event handlers - FSM: listen for events and reset state + // + + function onPointerDown( event ) { + + if ( scope.enabled === false ) return; + + switch ( event.pointerType ) { + + case 'mouse': + case 'pen': + onMouseDown( event ); + break; + + // TODO touch + + } + + } + + function onPointerMove( event ) { + + if ( scope.enabled === false ) return; + + switch ( event.pointerType ) { + + case 'mouse': + case 'pen': + onMouseMove( event ); + break; + + // TODO touch + + } + + } + + function onPointerUp( event ) { + + switch ( event.pointerType ) { + + case 'mouse': + case 'pen': + onMouseUp( event ); + break; + + // TODO touch + + } + + } + + function onMouseDown( event ) { + + // Prevent the browser from scrolling. + event.preventDefault(); + + // Manually set the focus since calling preventDefault above + // prevents the browser from setting it automatically. + + scope.domElement.focus ? scope.domElement.focus() : window.focus(); + + var mouseAction; + + switch ( event.button ) { + + case 0: + + mouseAction = scope.mouseButtons.LEFT; + break; + + case 1: + + mouseAction = scope.mouseButtons.MIDDLE; + break; + + case 2: + + mouseAction = scope.mouseButtons.RIGHT; + break; + + default: + + mouseAction = - 1; + + } + + switch ( mouseAction ) { + + case THREE.MOUSE.DOLLY: + + if ( scope.enableZoom === false ) return; + + handleMouseDownDolly( event ); + + state = STATE.DOLLY; + + break; + + case THREE.MOUSE.ROTATE: + + if ( event.ctrlKey || event.metaKey || event.shiftKey ) { + + if ( scope.enablePan === false ) return; + + handleMouseDownPan( event ); + + state = STATE.PAN; + + } else { + + if ( scope.enableRotate === false ) return; + + handleMouseDownRotate( event ); + + state = STATE.ROTATE; + + } + + break; + + case THREE.MOUSE.PAN: + + if ( event.ctrlKey || event.metaKey || event.shiftKey ) { + + if ( scope.enableRotate === false ) return; + + handleMouseDownRotate( event ); + + state = STATE.ROTATE; + + } else { + + if ( scope.enablePan === false ) return; + + handleMouseDownPan( event ); + + state = STATE.PAN; + + } + + break; + + default: + + state = STATE.NONE; + + } + + if ( state !== STATE.NONE ) { + + scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove, false ); + scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp, false ); + + scope.dispatchEvent( startEvent ); + + } + + } + + function onMouseMove( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); + + switch ( state ) { + + case STATE.ROTATE: + + if ( scope.enableRotate === false ) return; + + handleMouseMoveRotate( event ); + + break; + + case STATE.DOLLY: + + if ( scope.enableZoom === false ) return; + + handleMouseMoveDolly( event ); + + break; + + case STATE.PAN: + + if ( scope.enablePan === false ) return; + + handleMouseMovePan( event ); + + break; + + } + + } + + function onMouseUp( event ) { + + scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove, false ); + scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp, false ); + + if ( scope.enabled === false ) return; + + handleMouseUp( event ); + + scope.dispatchEvent( endEvent ); + + state = STATE.NONE; + + } + + function onMouseWheel( event ) { + + if ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return; + + event.preventDefault(); + event.stopPropagation(); + + scope.dispatchEvent( startEvent ); + + handleMouseWheel( event ); + + scope.dispatchEvent( endEvent ); + + } + + function onKeyDown( event ) { + + if ( scope.enabled === false || scope.enableKeys === false || scope.enablePan === false ) return; + + handleKeyDown( event ); + + } + + function onTouchStart( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); // prevent scrolling + + switch ( event.touches.length ) { + + case 1: + + switch ( scope.touches.ONE ) { + + case THREE.TOUCH.ROTATE: + + if ( scope.enableRotate === false ) return; + + handleTouchStartRotate( event ); + + state = STATE.TOUCH_ROTATE; + + break; + + case THREE.TOUCH.PAN: + + if ( scope.enablePan === false ) return; + + handleTouchStartPan( event ); + + state = STATE.TOUCH_PAN; + + break; + + default: + + state = STATE.NONE; + + } + + break; + + case 2: + + switch ( scope.touches.TWO ) { + + case THREE.TOUCH.DOLLY_PAN: + + if ( scope.enableZoom === false && scope.enablePan === false ) return; + + handleTouchStartDollyPan( event ); + + state = STATE.TOUCH_DOLLY_PAN; + + break; + + case THREE.TOUCH.DOLLY_ROTATE: + + if ( scope.enableZoom === false && scope.enableRotate === false ) return; + + handleTouchStartDollyRotate( event ); + + state = STATE.TOUCH_DOLLY_ROTATE; + + break; + + default: + + state = STATE.NONE; + + } + + break; + + default: + + state = STATE.NONE; + + } + + if ( state !== STATE.NONE ) { + + scope.dispatchEvent( startEvent ); + + } + + } + + function onTouchMove( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); // prevent scrolling + event.stopPropagation(); + + switch ( state ) { + + case STATE.TOUCH_ROTATE: + + if ( scope.enableRotate === false ) return; + + handleTouchMoveRotate( event ); + + scope.update(); + + break; + + case STATE.TOUCH_PAN: + + if ( scope.enablePan === false ) return; + + handleTouchMovePan( event ); + + scope.update(); + + break; + + case STATE.TOUCH_DOLLY_PAN: + + if ( scope.enableZoom === false && scope.enablePan === false ) return; + + handleTouchMoveDollyPan( event ); + + scope.update(); + + break; + + case STATE.TOUCH_DOLLY_ROTATE: + + if ( scope.enableZoom === false && scope.enableRotate === false ) return; + + handleTouchMoveDollyRotate( event ); + + scope.update(); + + break; + + default: + + state = STATE.NONE; + + } + + } + + function onTouchEnd( event ) { + + if ( scope.enabled === false ) return; + + handleTouchEnd( event ); + + scope.dispatchEvent( endEvent ); + + state = STATE.NONE; + + } + + function onContextMenu( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); + + } + + // + + scope.domElement.addEventListener( 'contextmenu', onContextMenu, false ); + + scope.domElement.addEventListener( 'pointerdown', onPointerDown, false ); + scope.domElement.addEventListener( 'wheel', onMouseWheel, false ); + + scope.domElement.addEventListener( 'touchstart', onTouchStart, false ); + scope.domElement.addEventListener( 'touchend', onTouchEnd, false ); + scope.domElement.addEventListener( 'touchmove', onTouchMove, false ); + + scope.domElement.addEventListener( 'keydown', onKeyDown, false ); + + // force an update at start + + this.update(); + +}; + +THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype ); +THREE.OrbitControls.prototype.constructor = THREE.OrbitControls; + + +// This set of controls performs orbiting, dollying (zooming), and panning. +// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). +// This is very similar to OrbitControls, another set of touch behavior +// +// Orbit - right mouse, or left mouse + ctrl/meta/shiftKey / touch: two-finger rotate +// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish +// Pan - left mouse, or arrow keys / touch: one-finger move + +THREE.MapControls = function ( object, domElement ) { + + THREE.OrbitControls.call( this, object, domElement ); + + this.screenSpacePanning = false; // pan orthogonal to world-space direction camera.up + + this.mouseButtons.LEFT = THREE.MOUSE.PAN; + this.mouseButtons.RIGHT = THREE.MOUSE.ROTATE; + + this.touches.ONE = THREE.TOUCH.PAN; + this.touches.TWO = THREE.TOUCH.DOLLY_ROTATE; + +}; + +THREE.MapControls.prototype = Object.create( THREE.EventDispatcher.prototype ); +THREE.MapControls.prototype.constructor = THREE.MapControls; diff --git a/explorer/static/PointerLockControls.js b/explorer/static/PointerLockControls.js new file mode 100644 index 0000000..282d60d --- /dev/null +++ b/explorer/static/PointerLockControls.js @@ -0,0 +1,156 @@ +THREE.PointerLockControls = function ( camera, domElement ) { + + if ( domElement === undefined ) { + + console.warn( 'THREE.PointerLockControls: The second parameter "domElement" is now mandatory.' ); + domElement = document.body; + + } + + this.domElement = domElement; + this.isLocked = false; + + // Set to constrain the pitch of the camera + // Range is 0 to Math.PI radians + this.minPolarAngle = 0; // radians + this.maxPolarAngle = Math.PI; // radians + + // + // internals + // + + var scope = this; + + var changeEvent = { type: 'change' }; + var lockEvent = { type: 'lock' }; + var unlockEvent = { type: 'unlock' }; + + var euler = new THREE.Euler( 0, 0, 0, 'YXZ' ); + + var PI_2 = Math.PI / 2; + + var vec = new THREE.Vector3(); + + function onMouseMove( event ) { + + if ( scope.isLocked === false ) return; + + var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; + var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; + + euler.setFromQuaternion( camera.quaternion ); + + euler.y -= movementX * 0.002; + euler.x -= movementY * 0.002; + + euler.x = Math.max( PI_2 - scope.maxPolarAngle, Math.min( PI_2 - scope.minPolarAngle, euler.x ) ); + + camera.quaternion.setFromEuler( euler ); + + scope.dispatchEvent( changeEvent ); + + } + + function onPointerlockChange() { + + if ( scope.domElement.ownerDocument.pointerLockElement === scope.domElement ) { + + scope.dispatchEvent( lockEvent ); + + scope.isLocked = true; + + } else { + + scope.dispatchEvent( unlockEvent ); + + scope.isLocked = false; + + } + + } + + function onPointerlockError() { + + console.error( 'THREE.PointerLockControls: Unable to use Pointer Lock API' ); + + } + + this.connect = function () { + + scope.domElement.ownerDocument.addEventListener( 'mousemove', onMouseMove, false ); + scope.domElement.ownerDocument.addEventListener( 'pointerlockchange', onPointerlockChange, false ); + scope.domElement.ownerDocument.addEventListener( 'pointerlockerror', onPointerlockError, false ); + + }; + + this.disconnect = function () { + + scope.domElement.ownerDocument.removeEventListener( 'mousemove', onMouseMove, false ); + scope.domElement.ownerDocument.removeEventListener( 'pointerlockchange', onPointerlockChange, false ); + scope.domElement.ownerDocument.removeEventListener( 'pointerlockerror', onPointerlockError, false ); + + }; + + this.dispose = function () { + + this.disconnect(); + + }; + + this.getObject = function () { // retaining this method for backward compatibility + + return camera; + + }; + + this.getDirection = function () { + + var direction = new THREE.Vector3( 0, 0, - 1 ); + + return function ( v ) { + + return v.copy( direction ).applyQuaternion( camera.quaternion ); + + }; + + }(); + + this.moveForward = function ( distance ) { + + // move forward parallel to the xz-plane + // assumes camera.up is y-up + + vec.setFromMatrixColumn( camera.matrix, 0 ); + + vec.crossVectors( camera.up, vec ); + + camera.position.addScaledVector( vec, distance ); + + }; + + this.moveRight = function ( distance ) { + + vec.setFromMatrixColumn( camera.matrix, 0 ); + + camera.position.addScaledVector( vec, distance ); + + }; + + this.lock = function () { + + this.domElement.requestPointerLock(); + + }; + + this.unlock = function () { + + scope.domElement.ownerDocument.exitPointerLock(); + + }; + + this.connect(); + +}; + +THREE.PointerLockControls.prototype = Object.create( THREE.EventDispatcher.prototype ); +THREE.PointerLockControls.prototype.constructor = THREE.PointerLockControls; diff --git a/explorer/static/T3D.js b/explorer/static/T3D.js new file mode 100644 index 0000000..2a85d29 --- /dev/null +++ b/explorer/static/T3D.js @@ -0,0 +1,4271 @@ +/* +Copyright © 2024 T3D project contributors. + +This file is part of the T3D Library. + +T3D Library is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +T3D Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the T3D Library. If not, see . +*/ + +var T3D = (function (t3dParser) { + 'use strict'; + + /// Indexed DB versioning + const DB_VERSION = 4; + /** + * This class handles offline storage of the .dat indexes and files metadata + * @class PersistantStore + */ + class PersistantStore { + _dbConnection; + constructor() { + // They may be multiple connection request issued at the same time, but it's actually okay since + // as soon as they are registered, the not-used ones will get garbage collected + this._dbConnection = undefined; + this._getConnection(); + } + /** + * Initialize the IndexedDB connection and manages version changes. + * + * @async + * @private + * @returns {Promise} Promise to the Database connection + */ + _getConnection() { + const self = this; + return new Promise((resolve, reject) => { + if (self._dbConnection) + resolve(self._dbConnection); + // Let us open our database + const request = window.indexedDB.open("Tyria3DLibrary", DB_VERSION); + /// onblocked is fired when the db needs an upgrade but an older version is opened in another tab + request.onblocked = () => { + T3D.Logger.log(T3D.Logger.TYPE_ERROR, "The T3D persistant database cannot be upgraded while the app is opened somewhere else."); + }; + /// fired when the database needs to be upgraded (or the first time) + request.onupgradeneeded = (event) => { + // Probably bugged + //@ts-ignore + const db = event.target.result; + const currentVersion = event.oldVersion; + if (currentVersion < 2) { + db.createObjectStore("listings", { + autoIncrement: true, + }); + } + if (currentVersion < 3) { + const storeListing = event.currentTarget.transaction.objectStore("listings"); + storeListing.createIndex("filename", "filename", { unique: false }); + } + }; + request.onsuccess = (event) => { + self._dbConnection = event.target.result; + //@ts-ignore + self.isReady = true; + resolve(self._dbConnection); + }; + request.onerror = () => { + T3D.Logger.log(T3D.Logger.TYPE_ERROR, "The T3D persistant database could not be opened."); + reject(); + }; + }); + } + /** + * Add or update a listing into the database + * + * @async + * @param {number|undefined} id This ID doesn't really matter, it's just the index of the object in the database, can be undefined + * @param {Array} listing + * @param {string} fileName .dat file name, allows to have multiple listings for different .dat files. + * @param {boolean} isComplete Keep back the information if that was the last update on the current scan or not. + * @returns {Promise} On success, the number is the object key in the database + */ + putListing(id, listing, fileName, isComplete) { + const self = this; + return new Promise((resolve, reject) => { + self._getConnection().then((db) => { + const store = db.transaction(["listings"], "readwrite").objectStore("listings"); + const request = id + ? store.put({ array: listing, filename: fileName, complete: isComplete }, id) + : store.put({ array: listing, name: fileName }); + request.onsuccess = () => { + resolve(request.result); + }; + request.onerror = () => { + reject(); + }; + }); + }); + } + /** + * Returns the last valid listing in the database + * + * @async + * @param {string} fileName .dat file name, allows to have multiple listings for different .dat files. + * @returns {Promise<{array: Array, key: number, complete: boolean}>} + * array: the last listing + * key: the index of the last listing in the database + */ + getLastListing(fileName) { + const self = this; + return new Promise((resolve) => { + self._getConnection().then((db) => { + const listingsStore = db.transaction(["listings"], "readonly").objectStore("listings").index("filename"); + listingsStore.openCursor(IDBKeyRange.only(fileName), "prev").onsuccess = (event) => { + const cursor = event.target.result; + if (!cursor) + resolve({ array: [], key: undefined, complete: true }); + else { + resolve({ + array: cursor.value.array, + key: cursor.primaryKey, + complete: cursor.value.complete, + }); + } + }; + }); + }); + } + } + + /** + * Organized thread pool of extractors + */ + class DataReader { + settings; + _workerPool; + _workerLoad; + _inflateCallbacks; + constructor(settings) { + this.settings = settings; + this._workerPool = []; + this._workerLoad = []; + this._inflateCallbacks = []; + for (let i = 0; i < settings.workersNb; i++) { + this._startWorker(settings.workerPath); + } + } + inflate(buffer, size, mftId, isImage, capLength) { + return new Promise((resolve, reject) => { + const arrayBuffer = buffer; + // If no capLength then inflate the whole file + if (!capLength || capLength < 0) { + capLength = 0; + } + // Buffer length size check + if (arrayBuffer.byteLength < 12) { + T3D.Logger.log(T3D.Logger.TYPE_WARNING, `not inflating, length is too short (${arrayBuffer.byteLength})`, mftId); + reject(new Error("Couldn't inflate " + mftId + " (mftId)")); + return; + } + // Register the callback + if (this._inflateCallbacks[mftId]) { + this._inflateCallbacks[mftId].push({ + resolve: resolve, + reject: reject, + }); + /// No need to make another call, just wait for callback event to fire. + return; + } + else { + this._inflateCallbacks[mftId] = [{ resolve: resolve, reject: reject }]; + } + // Add the load to the worker + const workerId = this._getBestWorkerIndex(); + this._workerLoad[workerId] += 1; + this._workerPool[workerId].postMessage([mftId, arrayBuffer, isImage === true, capLength]); + }); + } + // Initialization function for creating a new worker (thread) + _startWorker(path) { + const self = this; + const worker = new Worker(path); + const selfWorkerId = this._workerPool.push(worker) - 1; + if (this._workerLoad.push(0) !== selfWorkerId + 1) { + throw new Error("WorkerLoad and WorkerPool don't have the same length"); + } + worker.onmessage = function (message_event) { + let mftId; + // Remove load + self._workerLoad[selfWorkerId] -= 1; + // If error + if (typeof message_event.data === "string") { + T3D.Logger.log(T3D.Logger.TYPE_WARNING, "Inflater threw an error", message_event.data); + mftId = parseInt(message_event.data.split(":")[0]); + for (const callback of self._inflateCallbacks[mftId]) { + callback.reject(); + } + } + else { + mftId = message_event.data[0]; + // On success + if (self._inflateCallbacks[mftId]) { + for (const callback of self._inflateCallbacks[mftId]) { + const data = message_event.data; + // Array buffer, dxtType, imageWidth, imageHeight + callback.resolve({ + buffer: data[1], + dxtType: data[2], + imageWidth: data[3], + imageHeight: data[4], + }); + } + // Remove triggered listeners + self._inflateCallbacks[mftId] = null; + } + // Unknown error + else { + T3D.Logger.log(T3D.Logger.TYPE_ERROR, "Inflater threw an error", message_event.data); + } + } + }; + } + // Get the worker with the less load + _getBestWorkerIndex() { + return this._workerLoad.indexOf(Math.min(...this._workerLoad)); + } + } + + const mapMap = { + /** + * @property maps + * @type {Array.<{name: String, maps: Array.<{fileName: String, name: String}>}>} + */ + maps: [ + { + name: "Core - Ascalon [Regrown]", + maps: [ + { fileName: "131944.data", name: "(City) Black Citadel" }, + { fileName: "196585.data", name: "(City) Black Citadel [MapRegrownCitadel]" }, + { fileName: "1968107.data", name: "(City) Black Citadel" }, + { fileName: "126118.data", name: "(1-15) Plains of Ashford" }, + { fileName: "188591.data", name: "(1-15) Plains of Ashford [MapRegrownAshford]" }, + { fileName: "127888.data", name: "(15-25) Diessa Plateau" }, + { fileName: "190490.data", name: "(15-25) Diessa Plateau [MapRegrownRange]" }, + { fileName: "283574.data", name: "(30-40) Fields of Ruin [MapRegrownHawke]" }, + { fileName: "282668.data", name: "(40-50) Iron Marches [MapRegrownGullet]" }, + { fileName: "280025.data", name: "(50-60) Blazeridge Steppes [MapRegrownBrand]" }, + { fileName: "281313.data", name: "(60-70) Fireheart Rise [MapRegrownFlame]" }, + ], + }, + { + name: "Core - Kryta [Valley]", + maps: [ + { fileName: "128151.data", name: "(City) Divinity's Reach" }, + { fileName: "191265.data", name: "(City) Divinity's Reach [MapValleyDivinity]" }, + { fileName: "1968748.data", name: "(City) Divinity's Reach" }, + { fileName: "129524.data", name: "(1-15) Queensdale" }, + { fileName: "192711.data", name: "(1-15) Queensdale [MapValleyHill]" }, + { fileName: "130970.data", name: "(15-25) Kessex Hills" }, + { fileName: "194288.data", name: "(15-25) Kessex Hills [MapValleyWilderness]" }, + { fileName: "861815.data", name: "(15-25) Kessex Hills [MapValleyWildernessFortSalma]" }, + { fileName: "2737234.data", name: "(15-25) Kessex Hills [MapValleyWildernessTower]" }, + { fileName: "289176.data", name: "(25-35) Gendarran Fields, Vigil Headquarters [MapValleySettlement]" }, + { fileName: "191000.data", name: "(City) Lion's Arch [MapValleyArch]" }, + { fileName: "1796999.data", name: "(City) Lion's Arch [MapValleyArchKiel]" }, + { fileName: "1968576.data", name: "(City) Lion's Arch" }, + { fileName: "287870.data", name: "(35-45) Harathi Hinterlands [MapValleyHeadland]" }, + { fileName: "286945.data", name: "(45-55) Bloodtide Coast [MapValleyCoast]" }, + { fileName: "295005.data", name: "(45-55) Chantry of Secrets [MapValleyWhisper]" }, + { fileName: "520479.data", name: "(80) Southsun Cove, Crab Toss, Southsun Survival [MapEventValleyLost]" }, + ], + }, + { + name: "Core - Shiverpeak Mountains [Alpine]", + maps: [ + { fileName: "132434.data", name: "(City) Hoelbrak, Keg Brawl" }, + { fileName: "197122.data", name: "(City) Hoelbrak, Keg Brawl [MapAlpineHall]" }, + { fileName: "1966018.data", name: "(City) Hoelbrak, Keg Brawl" }, + { fileName: "125199.data", name: "(1-15) Wayfarer Foothills" }, + { fileName: "187611.data", name: "(1-15) Wayfarer Foothills [MapAlpineSnowline]" }, + { fileName: "124093.data", name: "(15-25) Snowden Drifts" }, + { fileName: "186397.data", name: "(15-25) Snowden Drifts [MapAlpinePowder]" }, + { fileName: "277587.data", name: "(25-40) Lornar's Pass, The Durmand Priory [MapAlpineSlope]" }, + { fileName: "275155.data", name: "(40-50) Dredgehaunt Cliffs [MapAlpineCrest]" }, + { fileName: "278717.data", name: "(50-60) Timberline Falls [MapAlpineTimberland]" }, + { fileName: "846866.data", name: "(50-60) Timberline Falls" }, + { fileName: "276252.data", name: "(70-80) Frostgorge Sound [MapAlpineGlacier]" }, + { fileName: "295282.data", name: "(HoM) Eye of the North [MapAlpineMonument]" }, + ], + }, + { + name: "Core - Tarnished Coast [Wetland]", + maps: [ + { fileName: "198272.data", name: "(City) Rata Sum [MapWetlandComplex]" }, + { fileName: "1968896.data", name: "(City) Rata Sum" }, + { fileName: "198076.data", name: "(City) The Grove [MapWetlandGrove]" }, + { fileName: "1969341.data", name: "(City) The Grove" }, + { fileName: "195149.data", name: "(1-15) Caledon Forest [MapWetlandBayou]" }, + { fileName: "195493.data", name: "(1-15) Metrica Province [MapWetlandRiverside]" }, + { fileName: "293307.data", name: "(15-25) Brisban Wildlands [MapWetlandGrotto]" }, + { fileName: "292254.data", name: "(55-65) Sparkfly Fen [MapWetlandGlade]" }, + { fileName: "291064.data", name: "(60-70) Mount Maelstrom [MapWetlandCape]" }, + ], + }, + { + name: "Core - Ruins of Orr [Risen]", + maps: [ + { fileName: "284829.data", name: "(70-75) Straits of Devastation [MapRisenBeachhead]" }, + { fileName: "285089.data", name: "(75-80) Malchor's Leap [MapRisenCliff]" }, + { fileName: "285634.data", name: "(80) Cursed Shore [MapRisenShore]" }, + ], + }, + { + name: "Core - Personal Story", + maps: [ + { + fileName: "295962.data", + name: "(20-60) A Vision of Darkness, A Light in the Darkness [MapWetlandDestiny]", + }, + { fileName: "1019669.data", name: "(40-60) Old Lion's Arch [MapValleyArchOrig]" }, + { fileName: "294938.data", name: "(60) Claw Island [MapValleyClaw]" }, + { + fileName: "1018612.data", + name: "(70) Forging the Pact [MapAlpineTimberlandBeforeConcordiaVines]", + }, + { + fileName: "295179.data", + name: "(80) Temple of the Forgotten God [MapRisenBeachheadAbaddon]", + }, + { fileName: "473765.data", name: "(80) Victory or Death [MapRisenDragonStory]" }, + ], + }, + { + name: "Core - Dungeon", + maps: [ + { fileName: "126840.data", name: "(30-35) Ascalonian Catacombs" }, + { fileName: "189364.data", name: "(30-35) Ascalonian Catacombs [MapRegrownCatacomb]" }, + { fileName: "287214.data", name: "(40-45) Caudecus's Manor [MapValleyEstate]" }, + { fileName: "291284.data", name: "(50) Twilight Arbor [MapWetlandGarden]" }, + { fileName: "645968.data", name: "(55-80) Twilight Arbor [MapWetlandGardenRepeat]" }, + { fileName: "275474.data", name: "(60-65) Sorrow's Embrace [MapAlpineFurnace]" }, + { fileName: "284039.data", name: "(70-75) Citadel of Flame [MapRegrownShaman]" }, + { fileName: "276520.data", name: "(76-80) Honor of the Waves [MapAlpineIceberg]" }, + { fileName: "293606.data", name: "(78-80) Crucible of Eternity [MapWetlandWeapon]" }, + { fileName: "473930.data", name: "(80) The Ruined City of Arah [MapRisenDragonRepeat]" }, + ], + }, + { + name: "(LW1) Living World Season 1: Scarlet's War - (SM) Strike Mission", + maps: [ + { + fileName: "2771534.data", + name: "(Lounge) Memory of Old Lion's Arch [MapValleyArchProbed]", + }, + { fileName: "568778.data", name: "(LW1.E1) Cragstead [MapAlpineEnclave]" }, + { fileName: "580061.data", name: "(LW1.E1) Molten Furnace [MapFlameFrost]" }, + { + fileName: "2690992.data", + name: "(LW1.E2) Memorials on the Pyre, The Scene of the Crime [MapValleyArchDragon]", + }, + { fileName: "595722.data", name: "(LW1.E2) Aetherblade Retreat [MapValleyArchDungeon]" }, + { fileName: "2711089.data", name: "(LW1.E3) Scarlet's Playhouse [MapJubileeArena-2]" }, + { + fileName: "672138.data", + name: "(LW1.E4) The Nightmare Unveiled [MapValleyWildernessKraitTowerInstance]", + }, + { fileName: "679089.data", name: "(LW1.E4) The Tower of Nightmares [MapValleyWildernessKraitTowerInterior]" }, + { + fileName: "2469960.data", + name: "(LW1.E5) The Twisted Marionette [MapAlpineSlopeMarionette]", + }, + { fileName: "2770873.data", name: "(LW1.E5) The Battle For Lion's Arch [MapValleyArch2]" }, + { + fileName: "2773298.data", + name: "(LW1.E5) North Evacuation Camp [MapValleySettlementFeb2014]", + }, + { fileName: "814803.data", name: "(LW1.E5) Lion's Arch: Honored Guests [MapValleyArch3]" }, + { fileName: "2771205.data", name: "(SM) Old Lion's Court [MapValleyArch2Strike]" }, + ], + }, + { + name: "(LW2) Living World Season 2: Glint's Prophecy", + maps: [ + { fileName: "836211.data", name: "(LW2.E1, LW2.E2, LW2.E4) Dry Top [MapDryTop]" }, + { fileName: "861770.data", name: "(LW2.E1, LW2.E2, LW2.E4) Dry Top [MapDryTopE2]" }, + { fileName: "909361.data", name: "(LW2.E5, LW2.E6, LW2.E7, LW2.E8) The Silverwastes [MapSandCastle]" }, + { fileName: "996202.data", name: "(LW2.E5, LW2.E6, LW2.E7, LW2.E8) The Silverwastes [MapSandcastleToFleet]" }, + { fileName: "908730.data", name: "(LW2.E5.4) Hidden Arcana [MapSandGrain]" }, + { + fileName: "922320.data", + name: "(LW2.E7.2) Meeting the Asura [MapWetlandRiversideAsuraFirstContact]", + }, + ], + }, + { + name: "(X1) Guild Wars 2: Heart of Thorns (HoT) - (Z) Zone - Maguuma Jungle [Jungle]", + maps: [ + { fileName: "969663.data", name: "(Z.1) Verdant Brink [MapJungleFleet]" }, + { fileName: "1263739.data", name: "(Z.2) Auric Basin [MapJungleGold]" }, + { fileName: "1264291.data", name: "(Z.3) Tangled Depths [MapJungleRoots]" }, + { fileName: "1262310.data", name: "(Z.4) Dragon's Stand [MapJungleArmy]" }, + { fileName: "1262460.data", name: "(X1.16) Hearts and Minds [MapJungleArmyNightmare]" }, + ], + }, + { + name: "(LW3) Living World Season 3: Glint's Legacy", + maps: [ + { fileName: "1472635.data", name: "(LW3.E1) Bloodstone Fen [MapJungleBloodstone]" }, + { fileName: "1498071.data", name: "(LW3.E2.1) Taimi's Game [MapHoloRoom]" }, + { fileName: "1498578.data", name: "(LW3.E2) Ember Bay [MapFireIsland]" }, + { fileName: "1605211.data", name: "(LW3.E3) Bitterfrost Frontier [MapAlpineTundra]" }, + { fileName: "1646520.data", name: "(LW3.E4) Lake Doric [MapValleyPort]" }, + { fileName: "1645474.data", name: "(LW3.E4.6) Confessor's End [MapValleyEstatePort]" }, + { fileName: "1682493.data", name: "(LW3.E5) Draconis Mons [MapLavaLamp]" }, + { fileName: "1682763.data", name: "(LW3.E5.5) Heart of the Volcano [MapLavaLampInstance2]" }, + { fileName: "1734839.data", name: "(LW3.E6.1) White Mantle Hideout [MapS0E6AspectHunt]" }, + { fileName: "1735440.data", name: "(LW3.E6.2) Shining Blade Headquarters [MapValleyBlade]" }, + { fileName: "1735346.data", name: "(LW3.E6) Siren's Landing [MapReclaimed]" }, + ], + }, + { + name: "(X2) Guild Wars 2: Path of Fire (PoF) - (Z) Zone - Crystal Desert [Desert]", + maps: [ + { fileName: "1794574.data", name: "(Z.1) Crystal Oasis [MapDesertOasis]" }, + { fileName: "1833034.data", name: "(Z.2) Desert Highlands [MapDesertHighlands]" }, + { + fileName: "1840368.data", + name: "(X2.7, X2.OS) Facing the Truth: The Sanctum, The Dark Library [MapDesertSanctum]", + }, + { fileName: "1840103.data", name: "(Z.3) Elon Riverlands [MapDesertRiver]" }, + { + fileName: "1833726.data", + name: "(X2.8, X2.9) The Way Forward, The Departing [MapDesertMists]", + }, + { fileName: "1842533.data", name: "(Z.4) The Desolation [MapDesertTorment]" }, + { fileName: "1839188.data", name: "(Z.5) Domain of Vabbi [MapDesertPalace]" }, + ], + }, + { + name: "(LW4) Living World Season 4: Rise of Kralkatorrik", + maps: [ + { + fileName: "1903523.data", + name: "(LW4.E1.1) Eye of the Brandstorm [MapDesertOasisInstanceS4E1]", + }, + { fileName: "1902235.data", name: "(LW4.E1) Domain of Istan [MapDesertJewel]" }, + { fileName: "1901428.data", name: "(LW4.E1.6) Fahranur, the First City [MapDesertCity]" }, + { + fileName: "1954984.data", + name: "(LW4.E2.1) Tracking the Scientist [MapDesertArchipelago_Chapter1]", + }, + { + fileName: "1955224.data", + name: "(LW4.E2.2) The Test Subject [MapDesertArchipelago_Chapter2]", + }, + { fileName: "1957526.data", name: "(LW4.E2) Sandswept Isles [MapDesertArchipelagoLargeMap]" }, + { fileName: "1955471.data", name: "(LW4.E2.5) The Charge [MapDesertArchipelago_Chapter5]" }, + { fileName: "1955642.data", name: "(LW4.E2.5) ??? [MapDesertArchipelago_Chapter5Boss_1]" }, + { fileName: "1955915.data", name: "(LW4.E2.5) ??? [MapDesertArchipelago_Chapter5Boss_2]" }, + { fileName: "1956140.data", name: "(LW4.E2.5) ??? [MapDesertArchipelago_Chapter5Boss_3]" }, + { fileName: "1956245.data", name: "(LW4.E2.5) ERROR: SIGNAL LOST [MapDesertArchipelago_Chapter5Boss_4]" }, + { fileName: "2005467.data", name: "(LW4.E3.1) Seized [MapDesertOasisS4E3]" }, + { fileName: "2004704.data", name: "(LW4.E3) Domain of Kourna [MapDesertMoon]" }, + { fileName: "2044320.data", name: "(LW4.E4) Jahai Bluffs, Sun's Refuge [MapDesertBluffs]" }, + { fileName: "2044502.data", name: "(LW4.E4.5) Storm Tracking [MapDesertBluffsCh5]" }, + { fileName: "2093791.data", name: "(LW4.E5.1) Scion & Champion [MapThe_Begining]" }, + { fileName: "2092435.data", name: "(LW4.E5) Thunderhead Peaks [MapAlpineKeep]" }, + { fileName: "2092812.data", name: "(LW4.E5.3) The Crystal Blooms [MapAlpineKeepInstance]" }, + { + fileName: "2093450.data", + name: "(LW4.E5.5) The Crystal Dragon [MapAlpineKeepInstanceKralk]", + }, + { fileName: "2124612.data", name: "(LW4.PP) Mists Rift [MapBrandedMistfight]" }, + { fileName: "2146312.data", name: "(LW4.E6.1) The End [MapDesertDragonfallCh01]" }, + { fileName: "2146346.data", name: "(LW4.E6.1) Dragonflight [MapDesertDragonfallCh02]" }, + { fileName: "2146125.data", name: "(LW4.E6) Dragonfall [MapDesertDragonfall]" }, + { fileName: "2146510.data", name: "(LW4.E6.5) Descent [MapDesertDragonfallFinalInstance]" }, + { fileName: "2146376.data", name: "(LW4.E6.5) Epilogue [MapDesertDragonfallEpilogue]" }, + ], + }, + { + name: "(LW5) Living World Season 5: The Icebrood Saga (IBS) - (SM) Strike Mission, (DRM) Dragon Response Missions", + maps: [ + { fileName: "2203371.data", name: "(LW5.E0, SM.1) Grothmar Valley, Shiverpeaks Pass [MapRegrownBlood]" }, + { fileName: "2251232.data", name: "(LW5.E1, LW5.E2) Bjora Marches [MapBjoraMarchesCombined]" }, + { fileName: "2224355.data", name: "(SM.2) Voice of the Fallen and Claw of the Fallen [MapKodanBNB]" }, + { fileName: "2224381.data", name: "(SM.3) Fraenir of Jormag [Mapshamanbnb]" }, + { fileName: "2224406.data", name: "(SM.4) Boneskinner [MapWendigoBNB]" }, + { fileName: "2249817.data", name: "(LW5.E2.5) Voice in the Deep [MapAlpineMarchesEp2FinalInstance]" }, + { fileName: "2251486.data", name: "(SM.5) Whisper of Jormag [MapWhisperofJormag]" }, + { fileName: "2251447.data", name: "(Lobby) Eye of the North [MapAlpineMonumentDragon]" }, + { fileName: "2272807.data", name: "(LW5.VotP.1, SM.6) Forging Steel [MapAlpineClimb]" }, + { fileName: "2273128.data", name: "(LW5.VotP.2) Darkrime Delves [MapAlpineDelves]" }, + { fileName: "2298865.data", name: "(LW5.E3) Drizzlewood Coast [MapAlpineCascades]" }, + { fileName: "2318029.data", name: "(LW5.E3, LW5.E4) Drizzlewood Coast [MapAlpineCascades02]" }, + { fileName: "2299088.data", name: "(SM.7) Cold War [MapAlpineCascadesStrike]" }, + { fileName: "2369582.data", name: "(LW5.E5.1) Primordus Rising [MapWetlandComplexE5Story]" }, + { + fileName: "2370614.data", + name: "(LW5.E5.3, DRM.1) Metrica Province [MapWetlandRiversideS5E5]", + }, + { + fileName: "2370017.data", + name: "(LW5.E5.3, DRM.2) Brisban Wildlands [MapWetlandGrottoS5E5]", + }, + { + fileName: "2369116.data", + name: "(LW5.E5.3, DRM.3) Gendarran Fields [MapValleySettlementS5E5]", + }, + { fileName: "2366776.data", name: "(LW5.E5.4, DRM.4) Fields of Ruin [MapRegrownHawkeS5E5]" }, + { + fileName: "2364032.data", + name: "(LW5.E5.4, DRM.5) Thunderhead Peaks [MapAlpineKeepS5E5]", + }, + { fileName: "2368400.data", name: "(LW5.E5.5, DRM.6) Lake Doric [MapValleyPortS5E5]" }, + { fileName: "2365787.data", name: "(LW5.E5.5, DRM.7) Snowden Drifts [MapAlpinePowderS5E5]" }, + { fileName: "2369398.data", name: "(LW5.E5.6, DRM.8) Caledon Forest [MapWetlandBayouS5E5]" }, + { fileName: "2414140.data", name: "(LW5.E5.7) Wildfire [MapLavaLampInstance_S5E5]" }, + { fileName: "2367211.data", name: "(LW5.E5.8, DRM.9) Bloodtide Coast [MapValleyCoastS5E5]" }, + { fileName: "2366368.data", name: "(LW5.E5.9, DRM.10) Fireheart Rise [MapRegrownFlameS5E5]" }, + { fileName: "2434582.data", name: "(LW5.E5) Dragonstorm [MapDragonFight]" }, + { fileName: "2434675.data", name: "(LW5.E5.11) Champion's End [MapDragonFightStoryInstance]" }, + ], + }, + { + name: "(X3) Guild Wars 2: End of Dragons (EoD) - (Z) Zone, (SM) Strike Mission - Cantha [Cantha]", + maps: [ + { fileName: "2669133.data", name: "(Lounge) Thousand Seas Pavilion [MapMTXLounge]" }, + { fileName: "2639738.data", name: "(X3.1) Old Friends [MapAlpineSlopeX03]" }, + { fileName: "2639795.data", name: "(X3.1) Aetherblade Armada [MapCanthaArmada]" }, + { fileName: "2647516.data", name: "(Z.1) Seitung Province [MapCanthaShingJea]" }, + { fileName: "2649141.data", name: "(SM.1) Aetherblade Hideout [MapMaiTrin]" }, + { fileName: "2645519.data", name: "(Z.2) New Kaineng City [MapCanthaKaineng]" }, + { fileName: "2645805.data", name: "(X3.7) Deepest Secrets: Yong Reactor [MapCanthaKainengCH5Reactor]" }, + { fileName: "2640407.data", name: "(Lobby) Arborstone [MapCanthaArborstone]" }, + { fileName: "2641850.data", name: "(Z.3) The Echovald Wilds [MapCanthaEchovald]" }, + { + fileName: "2642769.data", + name: "(SM.2) Xunlai Jade Junkyard [MapCanthaEchovaldStrikeMissions]", + }, + { fileName: "2646104.data", name: "(SM.3) Kaineng Overlook [MapCanthaKainengMinSecStrike]" }, + { fileName: "2644196.data", name: "(Z.4) Dragon's End [MapCanthaJadeSea]" }, + { fileName: "2702043.data", name: "(SM.4) Harvest Temple [MapCanthaJadeSeaStrikeMission]" }, + { fileName: "3012212.data", name: "(Z.5) Gyala Delve [MapCanthaDeep]" }, + { fileName: "3043972.data", name: "(Z.5) Gyala Delve [MapCanthaDeepQR2]" }, + { + fileName: "3100947.data", + name: "(X3.18) Forward [MapCanthaShingJeaExpac4AureneInstance]", + }, + ], + }, + { + name: "(X4) Guild Wars 2: Secrets of the Obscure (SotO) - (Z) Zone, (SM) Strike Mission - Skies of Tyria [Sky]", + maps: [ + { + fileName: "3134712.data", + name: "(X4.1) Commander without a Cause: Gendarran Fields [MapValleySettlementExpac4StealthMission]", + }, + { fileName: "3134778.data", name: "(Z.1) Skywatch Archipelago [MapSkyRise]" }, + { + fileName: "3135285.data", + name: "(SM.1) Cosmic Observatory [MapSkyRiseStrikeObservatory]", + }, + { fileName: "3135660.data", name: "(Lobby) The Wizard's Tower [MapSkyTower]" }, + { fileName: "3135805.data", name: "(Z.2) Amnytas [MapSkySpire]" }, + { fileName: "3136072.data", name: "(SM.2) Temple of Febe [MapCerusArena]" }, + { fileName: "3193573.data", name: "(?) Convergences [MapBountyIslands]" }, + { fileName: "3194054.data", name: "(Z.3) Inner Nayos [MapDream]" }, + { fileName: "3264516.data", name: "(Z.3) Inner Nayos [MapDream2]" }, + { fileName: "3316196.data", name: "(Z.3) Inner Nayos [MapDream3]" }, + ], + }, + { + name: "(GH) Guild Halls", + maps: [ + { fileName: "1255378.data", name: "(GH.1-2) Gilded Hollow [MapGuildCavern]" }, + { fileName: "1256064.data", name: "(GH.1-2) Lost Precipice [MapGuildHeights]" }, + { fileName: "1843274.data", name: "(GH.3) Windswept Haven [MapGuildPyramid]" }, + { fileName: "2648082.data", name: "(GH.4) Isle of Reflection [MapGuildIsle]" }, + ], + }, + { + name: "Cooperative - (FotM) Fractals of the Mists", + maps: [ + { fileName: "1733961.data", name: "(Lounge) Mistlock Sanctuary [MapInfiniteCosmicVIPLounge]" }, + { fileName: "1498016.data", name: "(FotM.0) Mistlock Observatory [MapInfiniteHub]" }, + { fileName: "519839.data", name: "(FotM.0-9) Fractals of the Mists [MapInfiniteIslands]" }, + { fileName: "2187042.data", name: "(FotM.0-9) Aquatic Ruins [MapInfiniteUnderwater]" }, + { fileName: "1426653.data", name: "(FotM.0-9) Cliffside [MapInfiniteCliffside]" }, + { fileName: "1472382.data", name: "(FotM.0-9) Snowblind [MapInfiniteSnowblind]" }, + { fileName: "1472406.data", name: "(FotM.0-9) Swampland [MapInfiniteSwamp]" }, + { + fileName: "1498798.data", + name: "(FotM.10-14) Aetherblade, Captain Mai Trin Boss [MapValleyArchDungeonUpdated02]", + }, + { + fileName: "1905739.data", + name: "(FotM.10-14) Molten Furnace, Molten Boss [MapFlameFrostFractalExtended]", + }, + { fileName: "697450.data", name: "(FotM.10-14) Thaumanova Reactor [MapInfiniteReactor]" }, + { fileName: "1472361.data", name: "(FotM.15) Chaos Isles [MapInfiniteChaos]" }, + { fileName: "1605344.data", name: "(FotM.16) Nightmare [MapInfiniteToxic]" }, + { fileName: "1733857.data", name: "(FotM.17) Shattered Observatory [MapInfiniteCosmic]" }, + { fileName: "1905889.data", name: "(FotM.18) Twilight Oasis [MapInfiniteMordant]" }, + { fileName: "2005713.data", name: "(FotM.19) Deepstone [MapInfiniteLabyrinth]" }, + { fileName: "2094098.data", name: "(FotM.20) Siren's Reef [MapInfiniteCove]" }, + { fileName: "2333932.data", name: "(FotM.21) Sunqua Peak [MapFractalElementalIslands]" }, + { fileName: "3100195.data", name: "(FotM.22) Silent Surf [MapLuxonFractal]" }, + { fileName: "3317434.data", name: "(FotM.23) Lonely Tower [MapSkyRiseFractalEparch]" }, + ], + }, + { + name: "Cooperative - (R) Raids", + maps: [ + { + fileName: "1427048.data", + name: "(Lobby, R.0) Lion's Arch Aerodrome, Special Forces Training Area [MapValleyArchRaidLobby]", + }, + { fileName: "1151420.data", name: "(R.1) Spirit Vale [MapRaidJungle01]" }, + { fileName: "1383309.data", name: "(R.2) Salvation Pass [MapE1R2]" }, + { fileName: "1454070.data", name: "(R.3) Stronghold of the Faithful [MapE1R3]" }, + { fileName: "1645215.data", name: "(R.4) Bastion of the Penitent [MapE1R4]" }, + { fileName: "1906329.data", name: "(R.5) Hall of Chains [MapE1R5]" }, + { fileName: "2045250.data", name: "(R.6) Mythwright Gambit [MapE2R2]" }, + { fileName: "2157962.data", name: "(R.7) The Key of Ahdashim [MapE2R3]" }, + ], + }, + { + name: "Competitive - Player vs. Player (PvP) - (CQ) Conquest, (MB) Murderball, (SH) Stronghold, (TDM) Team Deathmatch", + maps: [ + { fileName: "132570.data", name: "(Lobby) Heart of the Mists" }, + { fileName: "197249.data", name: "(Lobby) Heart of the Mists [MapPvPLobby]" }, + { fileName: "1713939.data", name: "(Lobby) Heart of the Mists [Mappvplobbyrework_cats]" }, + { fileName: "1734729.data", name: "(Lobby) Heart of the Mists [Mappvplobbyrework_catsMoreRoom]" }, + { fileName: "2129692.data", name: "(Lobby) Heart of the Mists [MapPvPLobby1016rework]" }, + { fileName: "132710.data", name: "(CQ.1-4) Battle of Khylo" }, + { fileName: "197402.data", name: "(CQ.1-4) Battle of Kyhlo [MapPvPConquestSiege]" }, + { fileName: "1644708.data", name: "(CQ.1-4) Battle of Khylo [MapPvPConquestSiege2]" }, + { fileName: "1666233.data", name: "(CQ.1-4) Battle of Khylo [MapPvPConquestSiege3]" }, + { fileName: "132837.data", name: "(CQ.1-4) Forest of Niflhel" }, + { fileName: "197545.data", name: "(CQ.1-4) Forest of Niflhel [MapPvPConquestForest]" }, + { fileName: "376916.data", name: "(CQ.1-4) Legacy of the Foefire [MapPvPConquestGuild]" }, + { fileName: "467374.data", name: "(CQ.1-4) Raid on the Capricorn" }, + { fileName: "520609.data", name: "(CQ.5) Temple of the Silent Storm [MapPvPConquestDojo]" }, + { fileName: "556199.data", name: "(CQ.6) Spirit Watch" }, + { fileName: "1473061.data", name: "(CQ.6) Spirit Watch [MapPVPConquestSpirit2]" }, + { fileName: "579383.data", name: "(CQ.7) Skyhammer" }, + { fileName: "677968.data", name: "(CQ.7) Skyhammer" }, + { fileName: "1426736.data", name: "(CQ.7) Skyhammer [MapPvPConquestCannonCapture]" }, + { fileName: "1934470.data", name: "(CQ.7) Skyhammer [MapPvPConquestCannonCapture2]" }, + { fileName: "1472979.data", name: "(CQ.8) Revenge of the Capricorn [MapPvPConquestCoastReturn]" }, + { fileName: "1644624.data", name: "(CQ.8) Revenge of the Capricorn [MapPvPConquestCoastReturnshrunk]" }, + { fileName: "1498174.data", name: "(CQ.9) Eternal Coliseum [MapPVPConquestArenaGods2]" }, + { fileName: "1704155.data", name: "(CQ.9) Eternal Coliseum [MapPVPConquestArenaGods4]" }, + { fileName: "2128880.data", name: "(CQ.9) Eternal Coliseum [MapPVPConquestArenaGodsTheme]" }, + { fileName: "2065760.data", name: "(CQ.10) Djinn's Dominion [Mapdesertconq]" }, + { fileName: "2128938.data", name: "(CQ.10) Djinn's Dominion [MapDesertConqWallMid]" }, + { fileName: "2175965.data", name: "(CQ.10) Djinn's Dominion [MapDesertConqWallMid2]" }, + { fileName: "791564.data", name: "(MB, TDM.2) Courtyard [MapDMCourtyard]" }, + { fileName: "1713054.data", name: "(MB, TDM.2) Courtyard [MapDMCourtyard2]" }, + { fileName: "870987.data", name: "(SH) Battle of Champion's Dusk [MapPvPStrongholdCity]" }, + { fileName: "871093.data", name: "(SH) Battle of Champion's Dusk [MapPvPStrongholdCityMercs]" }, + { fileName: "1712986.data", name: "(TDM.1) Hall of the Mists [MapHallway2v2]" }, + { fileName: "1712945.data", name: "(TDM.3) Asura Arena [Mapasura2v2]" }, + { fileName: "2187125.data", name: "(TDM.4) Auric Span [MapJungle2v2]" }, + ], + }, + { + name: "Competitive - World vs. World (WvW) - (MW) Mist War, (EotM) Edge of the Mists", + maps: [ + { fileName: "2113077.data", name: "(Lounge) Armistice Bastion [MapWvwLounge]" }, + { fileName: "131235.data", name: "(MW) Eternal Battlegrounds, Obsidian Sanctum" }, + { fileName: "195806.data", name: "(MW) Eternal Battlegrounds, Obsidian Sanctum [MapWvWCenter]" }, + { fileName: "1798709.data", name: "(MW) Eternal Battlegrounds, Obsidian Sanctum [MapWvWCenterGliding]" }, + { fileName: "1885693.data", name: "(MW) Eternal Battlegrounds, Obsidian Sanctum [MapWvWCenter4]" }, + { + fileName: "2263889.data", + name: "(MW) Eternal Battlegrounds, Obsidian Sanctum [MapWvWCenterWallChange10_19]", + }, + { fileName: "131574.data", name: "(MW) Alpine Borderlands" }, + { fileName: "641501.data", name: "(MW) Alpine Borderlands [MapWvWRedHomeLake01]" }, + { fileName: "1799855.data", name: "(MW) Alpine Borderlands [MapWvWRedHomeLake01gliding]" }, + { fileName: "1918037.data", name: "(MW) Alpine Borderlands [MapWvWRedHomeLake02]" }, + { fileName: "1427803.data", name: "(MW) Desert Borderlands [MapWvWDesertHomeUpdate]" }, + { fileName: "1647236.data", name: "(MW) Desert Borderlands [MapWvWDesertHomeUpdateMIDrework]" }, + { fileName: "1799442.data", name: "(MW) Desert Borderlands [MapWvWDesertHome4]" }, + { fileName: "2112733.data", name: "(MW) Desert Borderlands [MapWvWDesertHome]" }, + { fileName: "736241.data", name: "(EotM) Edge of the Mists [MapWvWIslands]" }, + ], + }, + { + name: "Festival - (LNY) Lunar New Year", + maps: [ + { fileName: "1625212.data", name: "(City) Divinity's Reach [MapValleyDivinityLNY]" }, + { fileName: "595582.data", name: "(LNY) Dragon Ball Arena [MapDragonBall]" }, + ], + }, + { + name: "Festival - (SAB) Super Adventure Festival - Super Adventure Box [SAB]", + maps: [ + { fileName: "1666365.data", name: "(City) Rata Sum [MapWetlandComplexSAB]" }, + { fileName: "569756.data", name: "(SAB) Super Adventure Box" }, + { fileName: "636133.data", name: "(Lobby) Hub [MapSABHub]" }, + { fileName: "635555.data", name: "(SAB.1) World 1 [MapSABWorld1]" }, + { fileName: "635960.data", name: "(SAB.2) World 2 [MapSABWorld2]" }, + { fileName: "3024941.data", name: "(SAB.3) World 3 [MapSABWorld3-0]" }, + { fileName: "3281398.data", name: "(SAB.3) World 3 [MapSABWorld3-1]" }, + ], + }, + { + name: "Festival - (DB) Dragon Bash", + maps: [{ fileName: "2164993.data", name: "(City) Hoelbrak [MapAlpineHallDragonBash]" }], + }, + { + name: "Festival - (FotFW) Festival of the Four Winds", + maps: [ + { fileName: "606255.data", name: "(FotFW) Labyrinthine Cliffs [MapEvenKiteCity]" }, + { fileName: "605983.data", name: "(FotFW) Sanctum Sprint [MapEvenTriathlonKiteCity]" }, + { fileName: "617120.data", name: "(FotFW) Aspect Arena [MapEvenPVPKiteCity]" }, + { fileName: "622681.data", name: "(FotFW) The Crown Pavilion [MapJubileeArena]" }, + ], + }, + { + name: "Festival - (HW) Halloween - Mad King's Realm [MadKing]", + maps: [ + { fileName: "1869665.data", name: "(City) Lion's Arch [MapValleyArchKielHalloween]" }, + { fileName: "506670.data", name: "(HW) Mad King's Labyrinth, Lunatic Inquisition [MapMadKingMaze]" }, + { fileName: "662436.data", name: "(HW) Mad King's Labyrinth, Lunatic Inquisition [MapMadKingMaze2013]" }, + { fileName: "2499169.data", name: "(HW) Mad King's Labyrinth, Lunatic Inquisition [MapMadKingMaze2021]" }, + { fileName: "506739.data", name: "(HW) Mad King's Clock Tower [MapMadKingTower]" }, + { fileName: "506539.data", name: "(HW) Mad King's Raceway, Reaper's Rumble [MapMadKingField]" }, + { fileName: "506592.data", name: "(HW) Ascent to Madness [MapMadKingBoss]" }, + ], + }, + { + name: "Festival - (WD) Wintersday - (SM) Strike Mission - Wintersday Celebration [Wintersday]", + maps: [ + { + fileName: "705746.data", + name: "(City) Divinity's Reach [MapWintersDayValleyDivinity2013]", + }, + { fileName: "1917775.data", name: "(City) Divinity's Reach [MapValleyDivinityholiday]" }, + { fileName: "529718.data", name: "(WD) Bell Choir Ensemble, Snowball Mayhem [MapWintersdaySnowGlobe]" }, + { fileName: "529896.data", name: "(WD) Tixx's Infinirarium, Toypocalypse [MapWintersdayAirship]" }, + { fileName: "529945.data", name: "(WD) Winter Wonderland [MapWintersdayFrostyland]" }, + { fileName: "2076921.data", name: "(SM) Secret Lair of the Snowmen [MapFrozenTyrant]" }, + ], + }, + { + name: "Miscellaneous", + maps: [ + { fileName: "122695.data", name: "(((Empty Plane)))" }, + { fileName: "129834.data", name: "Lake Doric" }, + { fileName: "132853.data", name: "(((Empty Box)))" }, + { fileName: "184799.data", name: "[MapDummy]" }, + { fileName: "193081.data", name: "Lake Doric [MapValleyReach]" }, + { fileName: "197562.data", name: "[MapPvPBlackBox]" }, + { fileName: "606030.data", name: "Basket Brawl [MapBasketBrawl]" }, + { fileName: "875614.data", name: "[MapTutorialChina]" }, + { fileName: "969964.data", name: "Verdant Brink [MapRootsAfterShip]" }, + { fileName: "1255516.data", name: "[MapGuildColiseum]" }, + { fileName: "1255634.data", name: "(((Unknown Town)))" }, + { fileName: "1282201.data", name: "(((WvW)))" }, + { fileName: "1498193.data", name: "[MapPvPConquestTemp]" }, + { fileName: "1513556.data", name: "[MapPvPInfection2]" }, + { fileName: "1513607.data", name: "[MapPvPConquestTest_01]" }, + { fileName: "1513620.data", name: "[MapPvPConquestTest_02]" }, + { fileName: "1513675.data", name: "[MapPvPConquestTest_04]" }, + { fileName: "1956299.data", name: "[MapDesertArchipelago_Instance]" }, + { fileName: "2204239.data", name: " [MapRegrownBloodCinematic]" }, + { fileName: "2224545.data", name: "Jaga Moraine [MapAlpinemoraine]" }, + { fileName: "2224624.data", name: "[MapAlpineMoraineFinalInstance]" }, + { fileName: "2257438.data", name: "[MapTest]" }, + { fileName: "2649061.data", name: " [MapRegrownBlood_CinematicEOD]" }, + { fileName: "2644298.data", name: "[MapJadeSeaWhirlpool]" }, + { fileName: "2689589.data", name: " [MapDesertHighlandsE3]" }, + ], + }, + ], + }; + + /** + * Parse the beginning of a file to find its type + * + * @memberof FileTypes + */ + function getFileType(buffer) { + const dataView = new DataView(buffer); + const first4 = String.fromCharCode(dataView.getUint8(0), dataView.getUint8(1), dataView.getUint8(2), dataView.getUint8(3)); + // Parse textures + switch (first4) { + case "ATEC": + return "TEXTURE_ATEC"; + case "ATEP": + return "TEXTURE_ATEP"; + case "ATET": + return "TEXTURE_ATET"; + case "ATEU": + return "TEXTURE_ATEU"; + case "ATEX": + return "TEXTURE_ATEX"; + case "ATTX": + return "TEXTURE_ATTX"; + } + if (first4.indexOf("DDS") === 0) + return "TEXTURE_DDS"; + if (first4.indexOf("PNG") === 1) + return "TEXTURE_PNG"; + if (first4.indexOf("RIFF") === 0) + return "TEXTURE_RIFF"; + if (first4.indexOf("YUI") === 0) + return "TEXT_YUI"; + // PackFiles + if (first4.indexOf("PF") === 0) { + const file = new t3dParser.FileParser(buffer, true); /// true for "plz no load chunkz" + return "PF_" + file.header.type; + } + // Binaries + if (first4.indexOf("MZ") === 0) + return "BINARIES"; + // Strings + if (first4.indexOf("strs") === 0) + return "STRINGS"; + // Raw asnd chunk (without pack file) + if (first4.indexOf("asnd") === 0) + return "CHUNK_ASND"; + // TODO: parse all buffers and if all bytes are valid unicode symbols then + // return TEXT_UNKNOWN; + // Unknown + return "UNKNOWN"; + } + + var FileTypes = /*#__PURE__*/Object.freeze({ + __proto__: null, + getFileType: getFileType + }); + + /** + * A statefull class that handles reading and inflating data from a local GW2 dat file. + */ + class LocalReader { + settings; + dataReader; + persistantStore; + file; + indexTable; + fileMetaTable; + persistantData = []; + _fileTypeCache; + constructor(settings) { + this.settings = settings; + this.dataReader = new DataReader(settings); + this.file = undefined; + this.indexTable = []; + this.fileMetaTable = []; + if (settings.noIndexedDB !== false) { + this.persistantStore = new PersistantStore(); + } + } + /** + * Asynchronously loads the archive by parsing its file index and header. + */ + async openArchive(file) { + const { metaTable, indexTable } = await t3dParser.ArchiveParser.readArchive(file); + this.fileMetaTable = metaTable; + this.indexTable = indexTable; + this.file = file; + } + /** + * Gets MFT index by baseId + */ + getFileIndex(baseId) { + return this.indexTable[baseId]; + } + /** + * Returns the metadata of a file stored in the archive + */ + getFileMeta(mftId) { + return this.fileMetaTable[mftId]; + } + /** + * Fetch a file and uncompress it if needed / required. + */ + async readFile(mftId, isImage, raw, fileLength, extractLength) { + if (!this.file) + throw new Error("No file loaded"); + //let buffer, dxtType, imageWidth, imageHeight; + const meta = this.getFileMeta(mftId); + if (!meta) + throw new Error("Unexistant file"); + // Slice up the data + const buffer = await t3dParser.ParsingUtils.sliceFile(this.file, Number(meta.offset), fileLength || meta.size); + // If needed we decompress, if not we keep raw + if (raw || meta.compressed) { + let data = { + buffer: undefined, + dxtType: undefined, + imageWidth: undefined, + imageHeight: undefined, + }; + await this.dataReader + .inflate(buffer, buffer.byteLength, mftId, isImage, extractLength || 0) + .then((result) => { + data = result; + }) + .catch(() => { + data = { + buffer: undefined, + dxtType: undefined, + imageWidth: undefined, + imageHeight: undefined, + }; + }); + return data; + } + else + return { buffer }; + } + /** + * Scans asynchronously the types of all the files listed in the archive. + * Uses persistant store to cache and speed up a rescan. + */ + async readFileList( + // This is a way for platforms not supporting indexDB to provide their own persistant storage. + oldFileList) { + if (!this.file) + throw new Error("No file loaded"); + const self = this; + let persistantList = oldFileList || []; + let persistantId; + // Load previously saved data + if (this.persistantStore) { + const lastListing = await this.persistantStore.getLastListing(this.file.name); + persistantList = lastListing.array; + // If the last scan was not completed then we will just update it.. + if (!lastListing.complete) { + persistantId = lastListing.key; + } + } + // Create a list of all the baseIds we need to inspect + const iterateList = Object.keys(self.indexTable).map((i) => Number(i)); + for (const index in persistantList) { + if (!(index in self.indexTable)) + iterateList.push(index); + } + // Spawn the decompression tasks + const taskArray = []; + for (let i = 0; i < 1; i++) { + taskArray[i] = Promise.resolve({ task: i }); + } + // Helps us to know when we need to update the persistant store + let persistantNeedsUpdate = false; + // Iterate through the array + for (const index in iterateList) { + const baseId = iterateList[index]; + // First use a synchronous function to know if we need to scan the file + const result = this._needsScan(baseId, persistantList); + if (result.scan === true) { + const taskId = (await Promise.race(taskArray)).task; + taskArray[taskId] = this._readFileType(baseId).then((scanResult) => { + // Put the result into our persistant storage + persistantList[baseId] = { + baseId: baseId, + size: scanResult.size, + crc: scanResult.crc, + fileType: scanResult.fileType, + }; + return { task: taskId }; + }); + } + if (result.change === "removed") { + // Update the persistant storage + delete persistantList[baseId]; + } + // Handle persistant storage update + if (result.change !== "none") + persistantNeedsUpdate = true; + // Tasks to do only every % + if (index % Math.floor(iterateList.length / 100) === 0) { + // Print progress + T3D.Logger.log(T3D.Logger.TYPE_PROGRESS, "Finding types", index / Math.floor(iterateList.length / 100)); + // Update the persistant storage if needed + if (self.persistantStore && persistantNeedsUpdate) { + persistantNeedsUpdate = false; + self.persistantStore + .putListing(persistantId, persistantList, self.file.name, false) + .then((res) => (persistantId = res)); + } + } + } + await Promise.all(taskArray).then(() => { + // Finally update the listing as complete + if (self.persistantStore) { + self.persistantStore.putListing(persistantId, persistantList, self.file.name, true); + } + }); + this.persistantData = persistantList; + return this.getFileList(); + } + /** + * Cheap version of the readFileList which will only scan files registered in the mapFileList + * This helps us being sure that we only return files that contain a mapc chunk when using + * the getMapList function + */ + async readMapList() { + const fileList = mapMap.maps.reduce((maps, category) => { + return maps.concat(category.maps.map((entry) => entry.fileName)); + }, []); + const temporaryStore = []; + for (const fileName of fileList) { + const baseId = fileName.split(".data")[0]; + if (this.indexTable[baseId]) { + const scanResult = await this._readFileType(baseId); + temporaryStore[baseId] = { + baseId: Number(baseId), + size: scanResult.size, + crc: scanResult.crc, + fileType: scanResult.fileType, + }; + } + } + // Fill the store without saving it to disk + this.persistantData = temporaryStore; + } + /** + * Returns a list of all the maps with their name and category. + * Uncategorized maps are available only if readFileList have been used before. + */ + async getMapList() { + const self = this; + const mapArray = []; + // If the archive hasn't been completely scanned we do a partial scan for the map files. + // It should be fast + if (this.persistantData.length === 0) { + await this.readMapList(); + } + // Filter the maps out of all our files + const reversedIndex = this.getReverseIndex(); + const maps = this.persistantData + .filter((file) => file.fileType === "PF_mapc") + .filter((id) => id.baseId === reversedIndex[self.getFileIndex(id.baseId)][0]); + for (const map of maps) { + let found = false; + // Try to see if we already have some informations on this map + for (const category of mapMap.maps) { + const fileMap = category.maps.find((item) => Number(item.fileName.split(".data")[0]) === map.baseId); + if (fileMap) { + mapArray.push({ + name: fileMap.name, + category: category.name, + baseId: map.baseId, + categoryIndex: mapMap.maps.indexOf(category), + }); + found = true; + break; + } + } + // If not we register it as Uncategorized + if (!found) { + mapArray.push({ + name: map.baseId.toString(), + category: "Uncategorized", + baseId: map.baseId, + categoryIndex: 99999, + }); + } + } + mapArray.sort((a, b) => a.category.localeCompare(b.category)); + return mapArray; + } + /** + * Return the meta table with extra information such as an array of baseIds and the file types. + * The filetype is available only if readFileList have been used before of course. + */ + getFileList() { + const typeList = this.persistantData ? this.persistantData.map((i) => i.fileType) : []; + const reverseBaseIdList = this.getReverseIndex(); + const fileList = this.fileMetaTable.map((meta, mftId) => { + const baseIds = reverseBaseIdList[mftId] ? reverseBaseIdList[mftId] : []; + const type = reverseBaseIdList[mftId] ? typeList[baseIds[0]] : "Non-Registered"; + return { + mftId: mftId, + baseIdList: baseIds, + size: meta.size, + crc: meta.crc, + fileType: type, + }; + }); + fileList[0] = { + mftId: 0, + baseIdList: [], + size: 0, + crc: 0, + fileType: "Non-Registered", + }; + return fileList; + } + /** + * @returns {Array>} + */ + getReverseIndex() { + return this.indexTable.reduce((reversed, mftId, baseId) => { + if (mftId in reversed) + reversed[mftId].push(baseId); + else + reversed[mftId] = [baseId]; + return reversed; + }, []); + } + // Callback wrapper + /** + * Reads data from a file in the dat. + * If `raw` is true, any infation is skipped and raw data is returned. + */ + loadFile(baseId, callback, isImage, raw) { + const mftId = this.getFileIndex(baseId); + if (mftId <= 0) + return callback(null); + this.readFile(mftId, isImage, raw).then((result) => { + if (result.buffer === undefined) + return callback(null); + callback(result.buffer, result.dxtType, result.imageWidth, result.imageHeight); + }); + } + // Private + _needsScan(baseId, persistantData) { + if (baseId <= 0) + return { change: "none", scan: false }; + const mftId = this.getFileIndex(baseId); + const metaData = this.getFileMeta(mftId); + // Nothing interesting + if (metaData === undefined && !(baseId in persistantData)) { + return { change: "none", scan: false }; + } + // If the file have been deleted + else if (metaData === undefined) { + return { change: "removed", scan: false }; + } + // If the file is new + else if (!(baseId in persistantData)) { + return { change: "added", scan: true }; + } + // If the size or crc don't match + else if (metaData.size !== persistantData[baseId].size || metaData.crc !== persistantData[baseId].crc) { + return { change: "modified", scan: true }; + } + // If everything is the same + else { + return { change: "none", scan: false }; + } + } + async _readFileType(baseId) { + if (!this._fileTypeCache) + this._fileTypeCache = []; + const mftId = this.getFileIndex(baseId); + const metaData = this.getFileMeta(mftId); + let fileType; + if (this._fileTypeCache[baseId] !== undefined) { + fileType = this._fileTypeCache[baseId]; + } + else { + const fileBuffer = (await this.readFile(mftId, false, false, Math.min(metaData.size, 1000), 32)).buffer; + if (fileBuffer === undefined) + return undefined; + fileType = getFileType(fileBuffer); + } + return { fileType: fileType, crc: metaData.crc, size: metaData.size }; + } + } + + /** + * Base class for data interpretors a.k.a. 'Renderers' + * + * Renderers are classes that collect and interpret data from the dat file. + * + * A {{#crossLink "LocalReader"}}{{/crossLink}} instance is used for accessing data from the dat. + * + * A {{#crossLink "Logger"}}{{/crossLink}} is used for posting progress output or error messages. + * + * The generated data, be it strings, numbers or meshes are put into a value object structure called + * the 'context'. The context can store data generated by multiple renderers and makes sure each + * renderer type, or class has it's own value object within the context. This enables one renderer + * to read data written by another renderer wihtout having to worry about overwriting existing data + * within the context. Keep in mind that you will have to manually pass and clean the conext object! + * + * A clean context object should just be the empty javasript object : {}. + * + * When a Renderer is done it will fire the callback and any view interrested in retrieving the generated + * data from the context can read it using + * {{#crossLink "T3D/getContextValue:method"}}{{/crossLink}}. + * + * + * + * + * @class DataRenderer + * @constructor + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class DataRenderer { + localReader; + settings; + context; + rendererName; + static rendererName = "DataRenderer"; + logger; + constructor(localReader, settings, context, logger_, rendererName = "DataRenderer") { + this.localReader = localReader; + this.settings = settings; + this.context = context; + this.rendererName = rendererName; + /// Just storing parameters + if (!settings) { + settings = {}; + } + this.context[rendererName] = {}; + if (!logger_) { + this.logger = T3D.Logger; + } + else { + this.logger = logger_; + } + } + /** + * Gets the output value object for a specified class within the context. + * + * @param {Class} otherClass The class to fetch the output value object for. + * If not specified the class of this instance will be used. + * @return {Object} The output value object for this class within the context. + */ + getOutput(otherClass) { + return this.context[otherClass ? otherClass.rendererName : this.rendererName]; + } + /** + * Basic rendering of unknown files. Output fileds generated: + * + * - *fileId* The fileId passed in the settings parameter when constructing this instance. + * + * - *rawData* An ArrayBuffer containg the infalted binary data of the loaded file. + * + * - *rawString* A string representation of the rawData + * + * - *image* A value object witht he fields 'width', 'height' and 'data' describing a RGBA bitmap + * image. Only set if the loaded file was a texture. + * + * - *file* A FileParser representation of the loaded file. Only set if the loaded file was a Pack File. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + const self = this; + this.localReader.loadFile(this.settings.id, function (inflatedData) { + /// Set fileId so callers can identify this VO + self.getOutput().fileId = self.settings.id; + /// Share inflated data + self.getOutput().rawData = inflatedData; + /// Construct raw string + const uarr = new Uint8Array(inflatedData); + const rawStrings = []; + const chunksize = 0xffff; + const len = Math.min(uarr.length, 10000); + // There is a maximum stack size. We cannot call String.fromCharCode with as many arguments as we want + for (let i = 0; i * chunksize < len; i++) { + //@ts-ignore + rawStrings.push(String.fromCharCode.apply(null, uarr.subarray(i * chunksize, (i + 1) * chunksize))); + } + if (len < uarr.length) { + rawStrings.push("T3D Ignored the last " + (uarr.length - len) + " bytes when generating this raw output"); + } + self.getOutput().rawString = rawStrings.join(); + /// Check if this is an PF or ATEX file + // Binareis are MZ + const dataView = new DataView(inflatedData); + const first4 = String.fromCharCode(dataView.getUint8(0), dataView.getUint8(1), dataView.getUint8(2), dataView.getUint8(3)); + /// Do special stuff for different fcc signatures + /// + /// fourcc != fcc::ATEX && fourcc != fcc::ATEC && fourcc != fcc::ATEP && + /// fourcc != fcc::ATET && fourcc != fcc::ATEU && fourcc != fcc::ATTX) + /// + if (first4 === "ATEX" || + first4 === "ATEC" || + first4 === "ATEP" || + first4 === "ATET" || + first4 === "ATEU" || + first4 === "ATTX") { + /// TODO: MOVE TO GW2 texture file!! + /// Load file using LocalReader. + self.localReader.loadFile(self.settings.id, function (inflatedData, dxtType, imageWidth, imageHeigth) { + /// Create image using returned data. + const image = { + data: new Uint8Array(inflatedData), + width: imageWidth, + height: imageHeigth, + }; + self.getOutput().image = image; + callback(); + }, true); + } + else if (first4.indexOf("PF") === 0) { + self.getOutput().file = new t3dParser.FileParser(inflatedData); + callback(); + } + else { + self.getOutput().file = null; + callback(); + } + }); + } + } + + /* + guid 1683952224941671000 is fucked up floor in SAB HUB + materialFilename for that mesh is 564821, shared with lots of stuff + lod 1 and 2 are both 0 + material flags is 2056 + */ + /** + * Builds a custom vertex shader for a given number of uv cannels. + * WIP not implemented yet! + * + * @memberof MaterialUtils + * @param {Number} numUv Number of UV channels used by this shader + * @return {String} Genereted vertex shader source + */ + function buildVS(numUv) { + let vdefs = ""; + let adefs = ""; + let reads = ""; + for (let i = 0; i < numUv; i++) { + vdefs += "varying vec2 vUv_" + (i + 1) + ";\n"; + /// uv and uv2 are defined by THREE + if (i > 1) + adefs += "attribute vec2 uv" + (i + 1) + ";\n"; + reads += "vUv_" + (i + 1) + " = uv" + (i > 0 ? i + 1 : "") + ";\n"; + } + return (adefs + + vdefs + + "void main()\n" + + "{\n" + + reads + + "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n" + + "gl_Position = projectionMatrix * mvPosition;\n" + + "}"); + } + /** + * Generate a texture of a specified color, used to be part of THREEjs + * + * @memberof MaterialUtils + * @param {Number} width + * @param {Number} height + * @param {THREE.Color} color + * @returns {THREE.DataTexture} + */ + function generateDataTexture(width, height, color) { + // create a buffer with color data + const size = width * height; + const data = new Uint8Array(4 * size); + const r = Math.floor(color.r * 255); + const g = Math.floor(color.g * 255); + const b = Math.floor(color.b * 255); + const a = 255; + for (let i = 0; i < size; i++) { + const stride = i * 4; + data[stride] = r; + data[stride + 1] = g; + data[stride + 2] = b; + data[stride + 3] = a; + } + // used the buffer to create a DataTexture + return new THREE.DataTexture(data, width, height, THREE.RGBAFormat); + } + /** + * Builds a custom pixel shader for a given number of uv cannels. + * WIP not implemented yet! + * + * @memberof MaterialUtils + * @param {Array} textures THREE textures + * @param {Number} numUv Number of UV channels used by this shader + * @param {Number} alphaTest Texture see-trough alpha treshold + * @param {any} lightMap TODO + * @returns {string} + */ + function buildPS(textures, numUv, alphaTest, lightMap) { + const t1uv = "vUv_" + (textures[0].uvIdx + 1); + let discard = ""; + if (alphaTest) { + discard = " if (c1.a < 0.5) \n" + " discard;\n"; + } + /// Color from 1st text or lighted by 2nd? + let writeColor = "gl_FragColor = c1;\n"; + if (lightMap) { + const texIdx = 0; + // var t2uv = "vUv_4";//+(3-textures[texIdx].uvIdx+1); + const t2uv = "vUv_1"; // + (textures[texIdx].uvIdx+1); + // console.log("t2uv",t2uv); + writeColor = " vec4 c2 = texture2D( texture" + (texIdx + 1) + ", " + t2uv + " );\n" + " gl_FragColor = c2;\n"; + // " gl_FragColor = vec4(c2.rgb * c1.r/.5, c2.a);\n"; + } + let uniforms = ""; + textures.forEach(function (t, idx) { + uniforms += "uniform sampler2D texture" + (idx + 1) + ";\n"; + }); + /* uniforms += "uniform sampler2D texture1;\n"; + if(lightMap) + uniforms += "uniform sampler2D texture2;\n"; */ + let varyings = ""; + for (let i = 0; i < numUv; i++) { + varyings += "varying vec2 vUv_" + (i + 1) + ";\n"; + } + return (uniforms + + varyings + + "void main( void ) {\n" + + " vec4 c1 = texture2D( texture1, " + + t1uv + + " );\n" + + discard + + writeColor + + "}"); + } + /** + * WIP, concept for generatin materials to render multi UV chanelled meshes. + * + * @memberof MaterialUtils + * @param {Array} textures THREE texture + * @param {Number} numUV Number of UV channels used by this shader + * @param {Number} alphaTest Texture see-trough alpha treshold + * @return {THREE.ShaderMaterial} Generated shader + */ + function getUVMat(textures, numUV, alphaTest) { + let lightMap = false; + const uniforms = {}; + textures.forEach(function (t, idx) { + uniforms["texture" + idx] = { type: "t", value: t }; + }); + if (textures.length > 1) { + lightMap = true; + } + const attributes = {}; + for (let i = 2; i < numUV; i++) { + attributes["uv" + (i + 1)] = { type: "v2", value: [] }; + } + const vs = buildVS(numUV); + return new THREE.ShaderMaterial({ + uniforms: uniforms, + vertexShader: vs, + fragmentShader: buildPS(textures, numUV, alphaTest, lightMap), + // @ts-ignore + attributes: attributes, + side: THREE.FrontSide, + }); + } + /** + * Builds a THREE texture from a ModelMaterialData by reading settings and + * loading any required data from the localReader. Uses sharedTextures for + * texture caching. + * + * This method is full of guesses and estimations, and could be improved on + * a lot, allowing rendering of multi UV channeled materials, or special + * materials like custom color chanelled gear. + * + * @memberof MaterialUtils + * @param {ModelMaterialData} material + * @param {FileParser} materialFile A FileParser instance, must be of type AMAT + * @param {LocalReader} localReader The LocalReader to load the file contents from. + * @param {Object} sharedTextures Value Object for keeping the texture cache + * @return {THREE.Material} A THREE Material with the generated contents and settings. + */ + function getMaterial(material, materialFile, localReader, sharedTextures) { + if (!materialFile) + return; + const dxChunk = materialFile.getChunk("dx9s"); + let grChunk = materialFile.getChunk("grmt"); + if (!dxChunk) { + return getSimpleMaterial(material, materialFile, localReader, sharedTextures); + } + /// Append all textures to the custom material + const finalTextures = []; + // Some materials don't use textures.. + if (material && material.textures.length && dxChunk.data.techniques.length > 0) { + /// TODO: check for flags! + /// + /// techinques[] -> passes[] -> effects[] -> samplerIndex[] + /// + // console.log("num effects",dxChunk.data.techniques[0].passes[0].effects.length); + // if(grChunk.data.flags!=76) + // return; + /// 3 teqs : high medium low GRAPHICS LEVEL SETTINGS + /// 1 passes DON'T CARE + /// 15 effects Each effect has a pixel shader HOW?? + /// 1 or 2 sampler indices USE ALL! (Multi material) + const effects = dxChunk.data.techniques[0].passes[0].effects; + // var effect = effects[10]; + const effect = effects[0]; + //let shader = dxChunk.data.shaders[effect.pixelShader]; + /* effects.forEach(function (eff) { + if(eff.samplerIndex.length > effect.samplerIndex.length) + effect = eff; + }); */ + // var samplerIdx = effect.samplerIndex[0]; + const samplerTextures = []; + let textureToken; // UINT64 + let samplerTex; + for (let i = 0; i < effect.samplerIndex.length; i++) { + const samplerIdx = effect.samplerIndex[i]; + const sampler = dxChunk.data.samplers[samplerIdx]; + /// SHOULD NEVER HAPPEN, hide mesh! + if (!sampler) + continue; // return; + textureToken = sampler && Number(grChunk.data.texTokens[sampler.textureIndex]); + if (!textureToken) + textureToken = 0; + /* else + textureToken =textureToken.val; */ + /// Find the texture reffered by this sampler + samplerTex = null; + material.textures.forEach(function (tex /*, index*/) { + /// Seems like only 1st part of token is used... + if (!samplerTex && Number(tex.token) === textureToken) { + // console.log("TEX match",tex.token, textureToken) + samplerTex = tex; + } + }); + /// Add this sampler's texture to the collection of all textures + if (samplerTex) { + samplerTextures.push(samplerTex); + } + else { + /// FALLBACK, just guess what texture we should use + if (sampler) { + samplerTextures.push(material.textures[sampler.textureIndex]); + } + else if (material.textures.length > 0) { + samplerTextures.push(material.textures[0]); + } + else { + return; + } + } + } /// END for each sampler index in effect + /// We now have all textures + // console.log("textures from sampler", samplerTextures); + /// Fallback to using whatever texture there is. + if (samplerTextures.length <= 0) { + return; + // mainTex = material.textures[0]; + } + // console.log("num samplers ",samplerTextures.length); + samplerTextures.forEach(function (texture, idx) { + if (!texture) + return; + /// Set texture "URL" + const texURL = texture && texture.filename; + /// Load texture from RAM or local reader: + finalTextures[idx] = getTexture(texURL, localReader, sharedTextures); + if (finalTextures[idx]) { + finalTextures[idx].uvIdx = texture.uvPSInputIndex; + } + }); + } /// End if material and texture + let finalMaterial; + /// Create custom shader material if there are textures + if (finalTextures) { + // TODO: make this work! + // eslint-disable-next-line no-constant-condition, no-constant-binary-expression + { + let ft; + let nt; + material.textures.forEach(function (t) { + // Flag for diffuse map + if (!ft && Number(t.token) === 1733499172) + ft = t; + // Flag for normal map + if (!nt && Number(t.token) === 404146670) + nt = t; + }); + if (!ft || ft.filename <= 0) + return; + finalMaterial = new THREE.MeshPhongMaterial({ + side: THREE.FrontSide, + map: getTexture(ft.filename, localReader, sharedTextures), + }); + if (nt) { + const normalMap = getTexture(nt.filename, localReader, sharedTextures); + normalMap.flipY = true; + finalMaterial.normalMap = normalMap; + } + finalMaterial.textureFilename = ft.filename; + if (grChunk.data.flags !== 16460) { + // console.log("Setting alpha flag for ",grChunk.data.flags) + finalMaterial.alphaTest = 0.05; + } + } + } + /// Fallback material is monocolored red + else { + finalMaterial = new THREE.MeshBasicMaterial({ + side: THREE.FrontSide, + color: 0xff0000, + flatShading: true, + }); + } + finalMaterial.needsUpdate = true; + /// Set material props + /// disable for now in order for custom shaders not to fuck up + if (material) { + const alphaMask0 = 0x0001; // + 0x0100 + 0x0200; + const alphaMask1 = 0x0010; + const alphaMask2 = 0x0100 + 0x0200; + //let alphaMask2b = 0x0200; + grChunk = materialFile.getChunk("grmt"); + // Enable alpha test for transparent flags + if (material.materialFlags & alphaMask0 || + material.materialFlags & alphaMask1 || + material.materialFlags & alphaMask2 // && solidColor != null + ) ; + /// GRCHUNK -> DATA -> FLAGS + /// HAS LIGHT - TEX - ? - EMISSIVE16460 + /// + /// 56533 LOD FOR TOMBSTONE? + // 16460 0100 0000 0100 1100 "standard" stuff rendering OK in SAB (no alpha test) + // + // 16452(SAB) 0100 0000 0100 0100 yellow numbers in sab signs + // 16448(SAB) 0100 0000 0100 0000 faces on rocks, cloudmen, skybox portal images, holes in walls, floor plates... + // no lighting?? + // + // 8268 0010 0000 0100 1100 + // 3392 0000 1101 0100 0000 Moto machine light bulbs + // 2380 0000 1001 0100 1100 + // 2368 0000 1001 0100 0000 Fountain water with rings, portal border and circular "light" + // 332 0000 0001 0100 1100 + // 324 0000 0001 0100 0100 Moto face sprites + // + // 320(SAB) 0000 0001 0100 0000 portal textures (normal maps ish) + // + // 76 0000 0000 0100 1100 LOTS OF STUFF + // Tree leaves, ground, hills, some roofs, flags, street lights + // sheild textures, some fences, water tops, waterfall + // + // IN KHYLO "everything with alpha" + // + // + // 68 0000 0000 0100 0100 Some flowers (lo res?) fountain edges foam + // + // 64(SAB) 0000 0000 0100 0000 clouds, sun iamge + const lightMask = 8; + const knownFileFlags = [24652, 16460, 16452, 16448, 8268, 3392, 2380, 2368, 332, 324, 320, 76, 68, 64]; + if (knownFileFlags.indexOf(grChunk.data.flags) < 0) { + T3D.Logger.log(T3D.Logger.TYPE_WARNING, "unknown GR flag", grChunk.data.flags); + } + if (!(grChunk.data.flags & lightMask)) { + // debugger; + // console.log("no light"); + finalMaterial = new THREE.MeshBasicMaterial({ + side: THREE.FrontSide, + map: finalMaterial.map, + }); + } + if (grChunk.data.flags !== 16460) { + finalMaterial.alphaTest = 0.05; + } + } /// End if material + return finalMaterial; + } + function getSimpleMaterial(material, materialFile, localReader, sharedTextures) { + if (!materialFile) + return; + const grChunk = materialFile.getChunk("grmt"); + let ft; + let nt; + material.textures.forEach(function (t) { + console.log(t); + // Flag for diffuse map + if (!ft && Number(t.token) === 1733499172) + ft = t; + if (!ft && t.token === 27219515885689124n) + ft = t; + // Flag for normal map + if (!nt && Number(t.token) === 404146670) + nt = t; + if (!nt && t.token === 850610087184878n) + nt = t; + }); + console.log(ft); + if (!ft || ft.filename <= 0) { + return; + } + const finalMaterial = new THREE.MeshPhongMaterial({ + side: THREE.FrontSide, + map: getTexture(ft.filename, localReader, sharedTextures), + }); + if (nt) { + const normalMap = getTexture(nt.filename, localReader, sharedTextures); + normalMap.flipY = true; + finalMaterial.normalMap = normalMap; + } + finalMaterial.textureFilename = ft.filename; + if (grChunk.data.flags !== 16460) { + finalMaterial.alphaTest = 0.05; + } + finalMaterial.needsUpdate = true; + return finalMaterial; + } + /** + * Load image data into a THREE.Texture from a texture file in the .dat file, using a LocalReader. + * Any loaded tetures are added to sharedTextures, allowing for texture caching and fewer reads. + * + * @memberof MaterialUtils + * @param {Number} texURL The fileId or baseId of the file to load image data from. + * @param {LocalReader} localReader The LocalReader to load the file contents from. + * @param {Object} sharedTextures Value Object for keeping the texture cache + * @return {THREE.Texture} A texture that will be populated by the file data when it is loaded. + */ + function getTexture(texURL, localReader, sharedTextures) { + let finalTexture; + /// Read texture from shared array of loaded textures + /// or read it from URL and add to shared ones! + if (texURL && sharedTextures[texURL]) { + /// Just read from already loaded textures. + finalTexture = sharedTextures[texURL]; + } + else if (texURL) { + /// Load and add to shared array. + finalTexture = loadLocalTexture(localReader, texURL); + /// Set standard texture functionality. + finalTexture.wrapT = THREE.RepeatWrapping; + finalTexture.wrapS = THREE.RepeatWrapping; + finalTexture.flipY = false; + sharedTextures[texURL] = finalTexture; + } + return finalTexture; + } + /** + * Load image data into a THREE.Texture from a texture file in the .dat file, using a LocalReader. + * If you're loading multiple textures, make sure to use + * {{#crossLink "MaterialUtils/getTexture"}}{{/crossLink}} that allows you to cache textures. + * + * @memberof MaterialUtils + * @param {LocalReader} localReader - The LocalReader to load the file contents from. + * @param {Number} fileId - The fileId or baseId of the file to load image data from. + * @param {Number} mapping - What THREE mapping the returned texture will use, not implemented. + + * @return {THREE.Texture} A texture that will be populated by the file data when it is loaded. + */ + function loadLocalTexture(localReader, fileId, mapping, defaultColor, onerror) { + if (defaultColor === undefined) { + defaultColor = Math.floor(0xffffff * Math.random()); + } + /// Temporary texture that will be returned by the function. + /// Color is randomized in order to differentiate different textures during loading. + const texture = generateDataTexture(1, // Width + 1, // Height + new THREE.Color(defaultColor) // Color + ); + // Threejs r71 is using these settings by default, r72+ changed it + texture.minFilter = THREE.LinearMipMapLinearFilter; + texture.magFilter = THREE.LinearFilter; + texture.generateMipmaps = true; + texture.flipY = true; + /// Only allow non-zero fileId, otherwise jsut return static texture + if (parseInt(String(fileId)) <= 0) { + if (onerror) + onerror(); + return texture; + } + /// Load file using LocalReader. + localReader.loadFile(fileId, function (inflatedData, dxtType, imageWidth, imageHeigth) { + /// Require infalted data to be returned. + if (!inflatedData) { + if (onerror) + onerror(); + return; + } + /// Create image using returned data. + const image = { + data: new Uint8Array(inflatedData), + width: imageWidth, + height: imageHeigth, + }; + /// Use RGBA for all textures for now... + /// TODO: don't use alpha for some formats! + texture.format = + //eslint-disable-next-line no-constant-condition + dxtType === 3 || dxtType === 5 || true ? THREE.RGBAFormat : THREE.RGBFormat; + /// Update texture with the loaded image. + //@ts-ignore + texture.image = image; + texture.needsUpdate = true; + }, true); + /// Return texture with temporary content. + return texture; + } + + var MaterialUtils = /*#__PURE__*/Object.freeze({ + __proto__: null, + buildPS: buildPS, + buildVS: buildVS, + generateDataTexture: generateDataTexture, + getMaterial: getMaterial, + getSimpleMaterial: getSimpleMaterial, + getTexture: getTexture, + getUVMat: getUVMat, + loadLocalTexture: loadLocalTexture + }); + + /** + * + * A renderer that generates some of the environment objects of a map. + * + * @class EnvironmentRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "mapFile", a FileParser. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class EnvironmentRenderer extends DataRenderer { + static rendererName = "EnvironmentRenderer"; + mapFile; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "EnvironmentRenderer"); + this.mapFile = this.settings.mapFile; + } + getMat(tex) { + return new THREE.MeshBasicMaterial({ + map: tex, + side: THREE.BackSide, + fog: false, + depthWrite: false, + }); + } + loadTextureWithFallback(targetMatIndices, materialArray, filename, fallbackFilename, hazeColorAsInt) { + const self = this; + function writeMat(mat) { + targetMatIndices.forEach(function (i) { + materialArray[i] = mat; + }); + } + function loadFallback() { + const mat = self.getMat(new THREE.TextureLoader().load(fallbackFilename)); + writeMat(mat); + } + function errorCallback() { + setTimeout(loadFallback, 1); + } + const mat = self.getMat(loadLocalTexture(this.localReader, filename, undefined, hazeColorAsInt, errorCallback)); + writeMat(mat); + } + getHazeColor(environmentChunkData) { + const hazes = environmentChunkData && environmentChunkData.dataGlobal.haze; + if (!hazes || hazes.length <= 0) { + return [190, 160, 60]; + } + else { + return hazes[0].farColor; + } + } + parseLights(environmentChunkData) { + const self = this; + /// Set up output array + self.getOutput().lights = []; + const lights = environmentChunkData + ? environmentChunkData.dataGlobal.lighting + : [ + { + lights: [], + backlightIntensity: 1.0, + backlightColor: [255, 255, 255], + }, + ]; + let ambientLight; + // var light = lights[0]; + // + let hasLight = false; + lights.forEach(function (light /*, idx*/) { + if (hasLight) + return; + /// Directional lights + // eslint-disable-next-line @typescript-eslint/no-unused-vars + let sumDirLightIntensity = 0; + light.lights.forEach(function (dirLightData /*, idx*/) { + hasLight = true; + const color = new THREE.Color(dirLightData.color[2] / 255.0, dirLightData.color[1] / 255.0, dirLightData.color[0] / 255.0); + const directionalLight = new THREE.DirectionalLight(color.getHex(), dirLightData.intensity); + directionalLight.position + .set(-dirLightData.direction[0], dirLightData.direction[2], dirLightData.direction[1]) + .normalize(); + sumDirLightIntensity += dirLightData.intensity; + self.getOutput().lights.push(directionalLight); + }); // END for each directional light in light + /// Add some random directional lighting if there was no, in order to se SOME depth on models + if (!light.lights || light.lights.length === 0) { + const directions = [ + [0, 1, 0, 0.3], + [1, 2, 1, 0.3], + [-1, -2, -1, 0.3], + ]; + directions.forEach(function (lightDir) { + const color = new THREE.Color(1, 1, 1); + const intensity = lightDir[3]; + const directionalLight = new THREE.DirectionalLight(color.getHex(), intensity); + directionalLight.position.set(lightDir[0], lightDir[1], lightDir[2]).normalize(); + sumDirLightIntensity += intensity; + self.getOutput().lights.push(directionalLight); + }); + } + /// Ambient light + // light.backlightIntensity /= sumDirLightIntensity +light.backlightIntensity; + // light.backlightIntensity = light.backlightIntensity; + const color = new THREE.Color((light.backlightIntensity * (255.0 - light.backlightColor[2])) / 255.0, (light.backlightIntensity * (255.0 - light.backlightColor[1])) / 255.0, (light.backlightIntensity * (255.0 - light.backlightColor[0])) / 255.0); + ambientLight = new THREE.AmbientLight(color); + }); // END for each light in lighting + let ambientTotal = 0; + if (ambientLight) { + ambientTotal = ambientLight.color.r + ambientLight.color.g + ambientLight.color.b; + this.getOutput().lights.push(ambientLight); + } + /// Parsing done, set hasLight flag and return + this.getOutput().hasLight = hasLight || ambientTotal > 0; + } + parseSkybox(environmentChunkData, parameterChunkData, hazeColorAsInt) { + /// set up output array + this.getOutput().skyCubeTexture = null; + this.getOutput().skyBox = null; + /// Grab sky texture. + /// index 0 and 1 day + /// index 2 and 3 evening + let skyModeTex = environmentChunkData && environmentChunkData.dataGlobal.skyModeTex[0]; + /// Fallback skyboxfrom dat. + if (!skyModeTex) { + skyModeTex = { + texPathNE: 187554, + texPathSW: 187556, + texPathT: 187558, + }; + } + /// Calculate bounds + const bounds = parameterChunkData.rect; + Math.abs(bounds[0] - bounds[2]); + Math.abs(bounds[1] - bounds[3]); + const materialArray = []; + /// Load skybox textures, fallback to hosted png files. + this.loadTextureWithFallback([1, 4], materialArray, skyModeTex.texPathNE + 1, "img/193068.png", hazeColorAsInt); + this.loadTextureWithFallback([0, 5], materialArray, skyModeTex.texPathSW + 1, "img/193070.png", hazeColorAsInt); + this.loadTextureWithFallback([2], materialArray, skyModeTex.texPathT + 1, "img/193072.png", hazeColorAsInt); + materialArray[3] = new THREE.MeshBasicMaterial({ visible: false }); + /// Create skybox geometry + const boxSize = 1024; // boundSide * 2; + const skyGeometry = new THREE.BoxGeometry(boxSize, boxSize / 2, boxSize); // Width Height Depth + /// Ugly way of fixing UV maps for the skybox (I think) + skyGeometry.faceVertexUvs[0].forEach((vecs, idx) => { + const face = Math.floor(idx / 2); + // PX NX + // PY NY + // PZ NZ + /// PX - WEST NX - EAST + if (face === 0 || face === 1) { + vecs.forEach((vec2) => { + vec2.x = 1 - vec2.x; + vec2.y /= 2.0; + vec2.y += 0.5; + }); + } + /// NZ - SOUTH PZ - NORTH + else if (face === 5 || face === 4) { + vecs.forEach((vec2) => { + vec2.y /= -2.0; + vec2.y += 0.5; + }); + } + else { + vecs.forEach((vec2) => { + vec2.x = 1 - vec2.x; + }); + } + }); + skyGeometry.uvsNeedUpdate = true; + /// Generate final skybox + const skyBox = new THREE.Mesh(skyGeometry, materialArray); + /// Put horizon in camera center + // skyBox.translateY(-(boxSize / 8)); + // skyBox.translateY( -environmentChunk.data.dataGlobal.sky.verticalOffset ); + /// Write to output + this.getOutput().skyBox = skyBox; + } + /** + * Output fileds generated: + * + * - *hazeColor* Array of RGBA values describing the global haze color of the map. + * - *lights* An array of THREE.DirectionalLight and THREE.AmbientLight objects. + * - *hasLight* Boolean is false if no directional lights were added to "lights". + * - *skyBox* A textured THREE.Mesh skybox. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + if (!this.mapFile) { + throw new Error("No map file available for EnvironmentRenderer"); + } + const environmentChunkData = this.mapFile.getChunk("env").data; + const parameterChunkData = this.mapFile.getChunk("parm").data; + /// Set renderer clear color from environment haze + const hazeColor = this.getHazeColor(environmentChunkData); + const hazeColorAsInt = hazeColor[2] * 256 * 256 + hazeColor[1] * 256 + hazeColor[0]; + this.getOutput().hazeColor = hazeColor; + /// Add directional lights to output. Also write hasLight flag + this.parseLights(environmentChunkData); + /// Generate skybox + this.parseSkybox(environmentChunkData, parameterChunkData, hazeColorAsInt); + /// All parsing is synchronous, just fire callback + callback(); + } + } + + /** + * + * A renderer that generates meshes describing the collisions of a map. + * + * @class HavokRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "mapFile", a FileParser. If "visible" is specified and true, the generated meshes will be textured + * with a MeshNormalMaterial, otherwise they will not be visible. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class HavokRenderer extends DataRenderer { + static rendererName = "HavokRenderer"; + mapFile; + lastP; + seed; + meshes; + geometries; + animations; + havokChunkData; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "HavokRenderer"); + this.mapFile = this.settings.mapFile; + this.lastP = -1; + this.seed = 1; + this.meshes = []; + } + /** + * TODO + * + * @param {Function} callback [description] + * @async + */ + renderModels(models, title, callback) { + let mat; + if (this.settings && this.settings.visible) { + mat = new THREE.MeshNormalMaterial({ side: THREE.DoubleSide }); + } + else if (this.settings && this.settings.export) { + mat = new THREE.MeshBasicMaterial({ visible: true }); + } + else { + mat = new THREE.MeshBasicMaterial({ visible: false }); + } + this.parseAllModels(models, mat, title, 200, 0, callback); + } + /** + * TODO + * + * @param {*} animation [description] + * @param {*} collisions [description] + * @return {*} [description] + */ + getCollisionsForAnimation(animation, collisions) { + const ret = []; + for (let i = 0; i < animation.collisionIndices.length; i++) { + const index = animation.collisionIndices[i]; + const collision = collisions[index]; + collision.index = index; + ret.push(collision); + } + return ret; + } + /** + * TODO + * + * @param {*} models [description] + * @param {*} mat [description] + * @param {*} title [description] + * @param {*} chunkSize [description] + * @param {*} offset [description] + * @return {*} callback [description] + * @async + */ + parseAllModels(models, mat, title, chunkSize, offset, callback) { + let i = offset; + for (; i < offset + chunkSize && i < models.length; i++) { + const p = Math.round((i * 100) / models.length); + if (p !== this.lastP) { + this.logger.log(T3D.Logger.TYPE_PROGRESS, "Loading Collision Models (" + title + ")", p); + this.lastP = p; + } + /// Get animation object + const animation = this.animationFromGeomIndex(models[i].geometryIndex, this.geometries, this.animations); + const collisions = this.getCollisionsForAnimation(animation, this.havokChunkData.collisions); + for (let j = 0; j < collisions.length; j++) { + const collision = collisions[j]; + this.renderMesh(collision, models[i], mat); + } + } + if (i < models.length) { + setTimeout(this.parseAllModels.bind(this, models, mat, title, chunkSize, offset + chunkSize, callback), 10 /* time in ms to next call */); + } + else { + callback(); + } + } + /** + * TODO + * + * @param {*} propGeomIndex [description] + * @param {*} geometries [description] + * @param {*} animations [description] + * @return {*} [description] + */ + animationFromGeomIndex(propGeomIndex, geometries, animations) { + // geometries is just list of all geometries.animations[end] for now + const l = geometries[propGeomIndex].animations.length; + return animations[geometries[propGeomIndex].animations[l - 1]]; + // return animations[ geometries[propGeomIndex].animations[0] ]; + } + /** + * TODO + * + * @param {*} collision [description] + * @param {*} model [description] + * @param {*} mat [description] + * @return {*} [description] + */ + renderMesh(collision, model, mat) { + const pos = model.translate; + const rot = model.rotate; + const scale = 32 * model.scale; + /// Generate mesh + const mesh = this.parseHavokMesh(collision, mat); + /// Position mesh + /// "x","float32","z","float32","y","float32" + mesh.position.set(pos[0], -pos[2], -pos[1]); + /// Scale mesh + if (scale) + mesh.scale.set(scale, scale, scale); + /// Rotate mesh + if (rot) { + mesh.rotation.order = "ZXY"; + // ["x","float32","z","float32","y","float32"], + mesh.rotation.set(rot[0], -rot[2], -rot[1]); + } + /// Add mesh to scene and collisions + this.getOutput().meshes.push(mesh); + } + /** + * TODO + * + * @return {*} [description] + */ + seedRandom() { + const x = Math.sin(this.seed++) * 10000; + return x - Math.floor(x); + } + /** + * TODO + * + * @param {*} collision [description] + * @param {*} mat [description] + * @return {*} [description] + */ + parseHavokMesh(collision, mat) { + const index = collision.index; + if (!this.meshes[index]) { + const geom = new THREE.Geometry(); + /// Pass vertices + for (let i = 0; i < collision.vertices.length; i++) { + const v = collision.vertices[i]; + // "x","float32","z","float32","y","float32"] + geom.vertices.push(new THREE.Vector3(v[0], v[2], -v[1])); + } + /// Pass faces + for (let i = 0; i < collision.indices.length; i += 3) { + const f1 = collision.indices[i]; + const f2 = collision.indices[i + 1]; + const f3 = collision.indices[i + 2]; + if (f1 <= collision.vertices.length && f2 <= collision.vertices.length && f3 <= collision.vertices.length) { + geom.faces.push(new THREE.Face3(f1, f2, f3)); + } + else { + this.logger.log(T3D.Logger.TYPE_ERROR, "Errorus index in havok model geometry."); + } + } + /// Prepare geometry and pass new mesh + geom.computeFaceNormals(); + // geom.computeVertexNormals(); + this.meshes[index] = new THREE.Mesh(geom, mat); + return this.meshes[index]; + } + else { + return this.meshes[index].clone(); + } + } + /** + * Output fileds generated: + * + * - *boundingBox* Array of values describing the bounding box of all collision. + * - *meshes* An array of THREE.Mesh objects visualizing all collision in the map. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + const self = this; + // TODO:The design of this method pretty much requires one instance + // of the class per parallel async render. Should probably fix this + // at some point... + /// Get required chunks + this.havokChunkData = this.mapFile.getChunk("havk").data; + /// Set static bounds to the bounds of the havk models + this.getOutput().boundingBox = this.havokChunkData.boundsMax; + /// Clear old meshes + this.meshes = []; + /// Set up output array + this.getOutput().meshes = []; + /// Grab model raw data from the chunk. + /// Add missing scale value to obs models. + const propModels = this.havokChunkData.propModels; + const zoneModels = this.havokChunkData.zoneModels; + const obsModels = this.havokChunkData.obsModels; + obsModels.forEach(function (mdl) { + mdl.scale = 1; + }); + /// Store geoms and animations from the file in hte instance so we don't + /// have to pass them arround too much. (fix this later) + this.geometries = this.havokChunkData.geometries; + this.animations = this.havokChunkData.animations; + /// Render "prop", "zone" and "obs" models in that order. + const renderZoneModelsCB = function () { + self.renderModels(obsModels, "obs", callback); + }; + const renderPropModelsCB = function () { + self.renderModels(zoneModels, "zone", renderZoneModelsCB); + }; + self.renderModels(propModels, "prop", renderPropModelsCB); + } + } + + const base32Max = Math.pow(2, 32); + /** + * Collection Math and sorting methods + * @namespace MathUtils + */ + /** + * Takes an integer and calculates what the 16 bit float + * representation of the binary data used to read the integer is. + * + * @memberof MathUtils + * @param {Number} h Integer value + * @return {Number} Float value + */ + function f16(h) { + const s = (h & 0x8000) >> 15; + const e = (h & 0x7c00) >> 10; + const f = h & 0x03ff; + if (e === 0) { + return (s ? -1 : 1) * Math.pow(2, -14) * (f / Math.pow(2, 10)); + } + else if (e === 0x1f) { + return f ? NaN : (s ? -1 : 1) * Infinity; + } + return (s ? -1 : 1) * Math.pow(2, e - 15) * (1 + f / Math.pow(2, 10)); + } + /** + * Calculates the number of binary ones present in the data used to + * generate the input integer. + * + * @memberof MathUtils + * @param {Number} bits Integer + * @return {Number} Number of binary ones in the data + */ + function popcount(bits) { + const SK5 = 0x55555555; + const SK3 = 0x33333333; + const SKF0 = 0x0f0f0f0f; + // let SKFF = 0xff00ff + bits -= (bits >> 1) & SK5; + bits = (bits & SK3) + ((bits >> 2) & SK3); + bits = (bits & SKF0) + ((bits >> 4) & SKF0); + bits += bits >> 8; + return (bits + (bits >> 15)) & 63; + } + /** + * Calculates the 64 bit integer value of two 32 bit integers. Only works up to + * the limit of the javascript Number maximum value. + * + * @memberof MathUtils + * @param {Number[]} arr Input integers, length should be 2. + * @return {Number} 64 bit representation of the two integers. + */ + function arr32To64(arr) { + /// Re-read as uint64 (still little endian) + /// Warn: this will not work for ~50+ bit longs cus all JS numbers are 64 bit floats... + return base32Max * arr[1] + arr[0]; + } + /** + * Sorts an array and returns unique values only. + * + * @memberof MathUtils + * @param {Array} arr_in Input array + * @param {Function} comparator A comparator function between the objects in arr_in + * @return {Array} Sorted and unique value. + */ + function sort_unique(arr_in, comparator) { + const arr = Array.prototype.sort.call(arr_in, comparator); + const u = {}; + const a = []; + for (let i = 0, l = arr.length; i < l; ++i) { + // eslint-disable-next-line no-prototype-builtins + if (u.hasOwnProperty(arr[i])) { + continue; + } + a.push(arr[i]); + //@ts-ignore + u[arr[i]] = 1; + } + return a; + } + + var MathUtils = /*#__PURE__*/Object.freeze({ + __proto__: null, + arr32To64: arr32To64, + f16: f16, + popcount: popcount, + sort_unique: sort_unique + }); + + // TODO: Remove this local cache!! + const matFiles = {}; + /** + * Object describing the meaning of the bits in fvf integers. + * @property fvfFormat + * @private + * @type {Object} + */ + const fvfFormat = { + Position: 0x00000001 /** < 12 bytes. Position as three 32-bit floats in the order x, y, z. */, + Weights: 0x00000002 /** < 4 bytes. Contains bone weights. */, + Group: 0x00000004 /** < 4 bytes. Related to bone weights. */, + Normal: 0x00000008 /** < 12 bytes. Normal as three 32-bit floats in the order x, y, z. */, + Color: 0x00000010 /** < 4 bytes. Vertex color. */, + Tangent: 0x00000020 /** < 12 bytes. Tangent as three 32-bit floats in the order x, y, z. */, + Bitangent: 0x00000040 /** < 12 bytes. Bitangent as three 32-bit floats in the order x, y, z. */, + TangentFrame: 0x00000080 /** < 12 bytes. */, + UV32Mask: 0x0000ff00 /** < 8 bytes for each set bit. Contains UV-coords as two 32-bit floats in the order u, v. */, + UV16Mask: 0x00ff0000 /** < 4 bytes for each set bit. Contains UV-coords as two 16-bit floats in the order u, v. */, + Unknown1: 0x01000000 /** < 48 bytes. Unknown data. */, + Unknown2: 0x02000000 /** < 4 bytes. Unknown data. */, + Unknown3: 0x04000000 /** < 4 bytes. Unknown data. */, + Unknown4: 0x08000000 /** < 16 bytes. Unknown data. */, + PositionCompressed: 0x10000000 /** < 6 bytes. Position as three 16-bit floats in the order x, y, z. */, + Unknown5: 0x20000000 /** < 12 bytes. Unknown data. **/, + }; + /** + * Collection of methods used for generating THREE meshes from Guild Wars 2 data formats. + * @namespace RenderUtils + */ + /** + * Creates a mesh representing a single plane. + * + * @memberof RenderUtils + * @param {Object} rect An object with x1,x2,y1 and y2 properties. + * @param {Number} yPos Vertical position of the rectangle. + * @param {THREE.Material} material Mesh material to apply. + * @param {Number} dy Mesh height. + * @return {THREE.Mesh} The generated mesh. + */ + function renderRect(rect, yPos, material, dy) { + const dx = rect.x1 - rect.x2; + const dz = rect.y1 - rect.y2; + if (!dy) + dy = 1; + const cx = (rect.x1 + rect.x2) / 2; + const cz = (rect.y1 + rect.y2) / 2; + const cy = yPos; + const geometry = new THREE.BoxGeometry(dx, dy, dz); + material = + material || + new THREE.MeshBasicMaterial({ + color: 0xff0000, + wireframe: true, + }); + const plane = new THREE.Mesh(geometry, material); + //@ts-ignore + plane.overdraw = true; + plane.position.x = cx; + plane.position.y = cy; + plane.position.z = cz; + return plane; + } + /** + * Returns a THREE representation of the data contained by a GW2 model file. + * The data is read using a LocalReader reference into the GW2 .dat. + * + * @memberof RenderUtils + * @param {LocalReader} localReader The LocalReader to load the file contents from. + * @param {Object} chunk Model GEOM chunk. + * @param {Object} modelDataChunk Model MODL chunk. + * @param {Object} sharedTextures Value Object for keeping the texture cache. + * @param {boolean} showUnmaterialed If false does not render any models with missing materials. + * + * @return {Array} Each geometry in the model file represented by a textured THREE.Mesh object + */ + function renderGeomChunk(localReader, chunk, modelDataChunk, sharedTextures, showUnmaterialed) { + const rawMeshes = chunk.data.meshes; + const meshes = []; + const mats = modelDataChunk.data.permutations[0].materials; + rawMeshes.forEach(function (rawMesh) { + const rawGeom = rawMesh.geometry; + const fvf = rawGeom.verts.mesh.fvf; // rawGeom.fvf; + const numVerts = rawGeom.verts.vertexCount; // rawGeom.vertexCount; + const rawVerts = rawGeom.verts.mesh.vertices; // rawGeom.vertices + const indices = rawGeom.indices.indices; + const geom = new THREE.BufferGeometry(); + const vertsDataView = new DataView(rawVerts.buffer); + // Dirty step length for now: + const stride = rawVerts.length / numVerts; + // Each vertex + // DO UV as well + const vertices = new Float32Array(numVerts * 3); + const uvs = []; + /// Calculate the distance to the first pair of UV data from the + /// start of the vertex entry + /// + const distToNormals = + //@ts-ignore + !!(fvf & fvfFormat.Position) * 12 + !!(fvf & fvfFormat.Weights) * 4 + !!(fvf & fvfFormat.Group) * 4; + //@ts-ignore + const distToTangent = distToNormals + !!(fvf & fvfFormat.Normal) * 12 + !!(fvf & fvfFormat.Color) * 4; + //@ts-ignore + const distToBittangent = distToTangent + !!(fvf & fvfFormat.Tangent) * 12; + //@ts-ignore + const distToTangentFrame = distToBittangent + !!(fvf & fvfFormat.Bitangent) * 12; + //@ts-ignore + const distToUV = distToTangentFrame + !!(fvf & fvfFormat.TangentFrame) * 12; + /// Check if the UV is 32 bit float or 16 bit float. + const uv32Flag = (fvf & fvfFormat.UV32Mask) >> 8; + const uv16Flag = (fvf & fvfFormat.UV16Mask) >> 16; + const isUV32 = !!uv32Flag; + const hasUV = !!uv16Flag || !!uv32Flag; + /// Popcount (count the number of binary 1's) in the UV flag + /// to get the number of UV pairs used in this vertex format. + const masked = isUV32 ? uv32Flag : uv16Flag; + let numUV = popcount(masked); + numUV = Math.min(numUV, 1.0); + /// Create typed UV arrays + if (hasUV) { + for (let i = 0; i < numUV; i++) { + uvs[i] = new Float32Array(numVerts * 2); + } + } + /// Read data from each vertex data entry + for (let i = 0; i < numVerts; i++) { + /// Go to vertex memory position + let cursor = i * stride; + /// Read position data + /// (we just hope all meshes has 32 bit position...) + const x = vertsDataView.getFloat32(cursor, true); + const z = vertsDataView.getFloat32(cursor + 4, true); + const y = vertsDataView.getFloat32(cursor + 8, true); + /// Write position data, transformed to Tyria3D coordinate system. + vertices[i * 3 + 0] = x; // - c.x; + vertices[i * 3 + 1] = -y; // + c.y; + vertices[i * 3 + 2] = -z; // + c.z; + /// Read data at UV position + if (hasUV) { + for (let uvIdx = 0; uvIdx < numUV; uvIdx++) { + cursor = i * stride + distToUV + uvIdx * (isUV32 ? 8 : 4); + /// Add one UV pair: + let u, v; + if (isUV32) { + u = vertsDataView.getFloat32(cursor, true); + v = vertsDataView.getFloat32(cursor + 4, true); + } + else { + u = f16(vertsDataView.getUint16(cursor, true)); + v = f16(vertsDataView.getUint16(cursor + 2, true)); + } + /// Push to correct UV array + uvs[uvIdx][i * 2 + 0] = u; + uvs[uvIdx][i * 2 + 1] = v; + } + } /// End if has UV + } /// End each vertex + /// Each face descripbed in indices + const faces = new Uint16Array(indices.length); + for (let i = 0; i < indices.length; i += 3) { + // This is ONE face + faces[i + 0] = indices[i + 2]; + faces[i + 1] = indices[i + 1]; + faces[i + 2] = indices[i + 0]; + } // End each index aka "face" + /// Add position, index and uv props to buffered geometry + geom.setAttribute("position", new THREE.BufferAttribute(vertices, 3)); + // geom.setAttribute( 'index', new THREE.BufferAttribute( faces, 1) ); + geom.setIndex(new THREE.BufferAttribute(faces, 1)); + { + /// Calculate normals + geom.computeVertexNormals(); + } + if (hasUV) { + for (let uvIdx = 0; uvIdx < numUV; uvIdx++) { + /// Names are "uv", "uv2", "uv3", ... , "uvN" + const uvName = "uv" + (uvIdx > 0 ? uvIdx + 1 : ""); + /// Set "custom" attribute uvN + geom.setAttribute(uvName, new THREE.BufferAttribute(uvs[uvIdx], 2)); + /// Flag for update + geom.attributes[uvName].needsUpdate = true; + } + /// Not needed anymore? + //@ts-ignore + geom.uvsNeedUpdate = true; + } + /// Tell geometry to update its UVs and buffers + //@ts-ignore + geom.buffersNeedUpdate = true; + /// DONE READING VERTEX DATA + /// Get material used for this mesh + const matIdx = rawMesh.materialIndex; + const mat = mats[matIdx]; + let materialFile = null; + if (mat && matFiles[mat.filename]) { + materialFile = matFiles[mat.filename]; + } + console.log(`material file:`, materialFile); + let finalMaterial = getMaterial(mat, materialFile, localReader, sharedTextures); + /// IF we could not find a material abort OR use a wireframe placeholder. + if (!finalMaterial) { + if (showUnmaterialed) { + finalMaterial = new THREE.MeshLambertMaterial({ + color: 0x5bb1e8, + wireframe: false, + side: THREE.DoubleSide, + }); + } + else { + return; + } + } + /// Create the final mesh from the BufferedGeometry and MeshBasicMaterial + const finalMesh = new THREE.Mesh(geom, finalMaterial); + /// Set material info on the returned mesh + if (mat) { + finalMesh.materialFlags = mat.materialFlags; + finalMesh.materialFilename = mat.filename; + } + finalMesh.materialName = rawMesh.materialName; + /// Use materialFilename, materialName, and material.textureFilename in order to build export + /// Set lod info on the returned mesh + finalMesh.numLods = rawMesh.geometry.lods.length; + finalMesh.lodOverride = modelDataChunk.data.lodOverride; + /// Set flag and UV info on the returned mehs + finalMesh.flags = rawMesh.flags; + finalMesh.numUV = numUV; + /// Add mesh to returned Array + meshes.push(finalMesh); + }); /// End rawMeshes for Each + return meshes; + } + /** + * Merge multiple meshes together and return an instancedMesh for it + * @param {Array} meshes Three Meshes to be merged into a single mesh + * @param {Number} size Size of the instanced mesh + * @param {Number} filterFlags When undefined, it will render all LODs. When using 0, only show most detailed LOD + * @returns {Mesh} a Three instanced mesh + */ + function getInstancedMesh(meshes, size, filterFlags) { + const meshMaterials = []; + const mergedGeometry = new THREE.Geometry(); + meshes.forEach((mesh, index) => { + // If filterFlags is set, we ignore any mesh without the correct flag + if (filterFlags !== undefined && mesh.flags !== filterFlags) { + return; + } + meshMaterials.push(mesh.material); + // It's only possible to merge geometries of the same type + const meshGeometry = new THREE.Geometry().fromBufferGeometry(mesh.geometry); + mergedGeometry.merge(meshGeometry, mesh.matrix, index); + }); + const finalMesh = new THREE.InstancedMesh(mergedGeometry, meshMaterials, size); + finalMesh.updateMatrix(); + finalMesh.matrixAutoUpdate = false; + return finalMesh; + } + /** + * Loads mesh array from Model file and sends as argument to callback. + * + * @memberof RenderUtils + * @async + * @param {Number} filename Name of the model file to load data from. + * @param {Array} solidColor RGBA array of 4 integers + * @param {LocalReader} localReader The LocalReader to load the file contents from. + * @param {Object} sharedTextures Value Object for keeping the texture cache. + * @param {boolean} showUnmaterialed If false does not render any models with missing materials. + + * @param {Function} callback Fired once all meshes have been loaded. + * two arguments are passed to the callback function. + * + * The first argument is an Array with each textured THREE.Mesh objects. + * + * The second argument is the bounding spehere of this model file. + * + */ + function loadMeshFromModelFile(filename, solidColor, localReader, sharedTextures, showUnmaterialed, callback) { + // Short handles prop attributes + const finalMeshes = []; + /// Load file + localReader.loadFile(filename, function (inflatedData) { + try { + if (!inflatedData) { + throw "Could not find MFT entry for " + filename; + } + const modelFile = new t3dParser.FileParser(inflatedData); + // MODL for materials -> textures + const modelDataChunk = modelFile.getChunk("modl"); + // GEOM for geometry + const geometryDataChunk = modelFile.getChunk("geom"); + /// Hacky fix for not being able to adjust for position + const boundingSphere = modelDataChunk.data.boundingSphere; + const bsc = boundingSphere.center; + if (bsc) { + boundingSphere.radius += Math.sqrt(bsc[0] * bsc[0] + Math.sqrt(bsc[1] * bsc[1] + bsc[2] * bsc[2])); + } + /// Load all material files + const allMats = modelDataChunk.data.permutations[0].materials; + function loadMaterialIndex(mIdx, matCallback) { + if (mIdx >= allMats.length) { + matCallback(); + return; + } + const mat = allMats[mIdx]; + /// Skip if file is loaded + if (matFiles[mat.filename]) { + loadMaterialIndex(mIdx + 1, matCallback); + return; + } + localReader.loadFile(mat.filename, function (inflatedData) { + if (inflatedData) { + const materialFile = new t3dParser.FileParser(inflatedData); + matFiles[mat.filename] = materialFile; + } + loadMaterialIndex(mIdx + 1, matCallback); + }); + } + loadMaterialIndex(0, function () { + /// Create meshes + const meshes = renderGeomChunk(localReader, geometryDataChunk, modelDataChunk, sharedTextures, showUnmaterialed); + // Build mesh group + meshes.forEach(function (mesh) { + /// Material flags + const knownflags = [ + /* + 1-5 + Has Tex? IDK Light? Alpha? + + 5-8 + 0 0 IDK Water? + + 9-12 + Has Tex? 0 Alpha? Alpha? + + 13 + IDK KEV + */ + 0, // 0 0000 0000 0000 Ground / Wall splashes + 8, // 0 0000 0000 1000 Broken Khylo roof DDS + 9, // 0 0000 0000 1001 Tree leaves + 520, // 0 0010 0000 1000 Some LOD modules, fires, smoke, inside of tents (some DSS textures) + 2056, // 0 1000 0000 1000 Solid objects, also broken animations + /// Solids here are unhappy, or are they? could be animations etc + 2057, // 0 1000 0000 1001 Windmill sails, bushes, trees, but also a statue and a few pieces of wall + 2060, // 0 1000 0000 1100 A few solid objects, like wooden barricades, one(!) painting + 2061, // 0 1000 0000 1101 A few bushes, two paintings + 2312, // 0 1001 0000 1000 Opaque Clock tower main walls AND IVY + 2316, // 0 1001 0000 1100 Bushes, inner flower walkway a ramp and a box + // Number 10 + 2568, // 0 1010 0000 1000 Lots of solids; walls, tents also some tent details WITH alpa + // Number 11 + 2569, // 0 1010 0000 1001 Solids like walls and roofs and appernt non solids like ropes + 2572, // 0 1010 0000 1100 Solid wooden beems, lamp posts + 2573, // 0 1010 0000 1101 Lamp holders, bushes, fences, apparent non solids + 2584, // 0 1010 0001 1000 Fountain Well water + 2824, // 0 1011 0000 1000 Windows, sign arrows, cloth roofs (non solids) BUT straw roofs + 2828, // 0 1011 0000 1100 A few fence post (non solids) + 2840, // 0 1011 0001 1000 Fountain running water + pipe water + 4617, // 1 0010 0000 1001 Found nothing + 6664, // 1 1010 0000 1000 Two groups of solid boxes + ]; + // let alphaMask0 = 0x0001 // + 0x0100 + 0x0200; + // let alphaMask1 = 0x0010 + // let alphaMask2 = 0x0100 + 0x0200 + // let alphaMask2b = 0x0200 + const texMask = 0x8 + 0x0800; + if (knownflags.indexOf(mesh.materialFlags) !== 11) { + // return; + } + // No smoke etc + if (mesh.materialFlags === 520) { + // return; + } + // Must have texture + if (!showUnmaterialed && !(mesh.materialFlags & texMask)) { + return; + } + // NO lods + if (mesh.flags === 4 || mesh.flags === 1 || mesh.flags === 0) { + // return; + } + // Add to final colection + finalMeshes.push(mesh); + }); /// END FOR EACH meshes + callback(finalMeshes, boundingSphere); + }); /// END LOAD MATERIALS CALLBACK + } + catch (e) { + console.warn("Failed rendering model " + filename, e); + const mesh = new THREE.Mesh(new THREE.BoxGeometry(200, 2000, 200), new THREE.MeshNormalMaterial()); + //@ts-ignore + mesh.flags = 4; + //@ts-ignore + mesh.materialFlags = 2056; + //@ts-ignore + mesh.lodOverride = [1000000, 1000000]; + finalMeshes.push(mesh); + /// Send the final meshes to callback function + callback(finalMeshes); + } + }); /// END FILE LOADED CALLBACK FUNCTION + } + /** + * Gets a mesh array from Model file and sends as argument to callback. Uses a cache of meshes in order + * to never read the same model file twice. + * + * @memberof RenderUtils + * @async + * @param {Number} filename The fileId or baseId of the Model file to load + * @param {Array} color RGBA array of 4 integers + * @param {LocalReader} localReader The LocalReader object used to read data from the GW2 .dat file. + * @param {Object} sharedMeshes Value Object for keeping the texture cache. + * @param {Object} sharedTextures Value Object for keeping the texture cache. + * @param {boolean} showUnmaterialed If false does not render any models with missing materials. + * @param {Function} callback Fired once all meshes have been loaded. + * three arguments are passed to the callback function. + * + * The first argument is an Array with each textured THREE.Mesh objects. + * + * The second argument is a boolean, true indicates that these meshes were not + * loaded from the dat file, but retrieved from the run time cache. + * + * The third argument is the bounding spehere of this model file. + */ + function getMeshesForFilename(filename, color, localReader, sharedMeshes, sharedTextures, showUnmaterialed, callback) { + /// If this file has already been loaded, just return a reference to the meshes. + /// isCached will be set to true to inform the caller the meshes will probably + /// have to be cloned in some way. + if (sharedMeshes[filename]) { + callback(sharedMeshes[filename].meshes, true, sharedMeshes[filename].boundingSphere); + } + /// If this file has never been loaded, load it using loadMeshFromModelFile + /// the resulting mesh array will be cached within this model's scope. + else { + loadMeshFromModelFile(filename, color, localReader, sharedTextures, showUnmaterialed, function (meshes, boundingSphere) { + /// Cache result if any. + if (meshes) { + sharedMeshes[filename] = { + meshes: meshes, + boundingSphere: boundingSphere, + }; + } + /// Allways fire callback. + callback(meshes, false, boundingSphere); + }); + } + } + /** + * WIP, Tries to find all fileIds refered by a model file. + * + * @memberof RenderUtils + * @async + * @param {Number} filename Model file Id + * @param {LocalReader} localReader LocalReader instance to read from + * @param {Function} callback First argument is list of used file IDs + */ + function getFilesUsedByModel(filename, localReader, callback) { + const fileIds = [filename]; + /// Load model file + localReader.loadFile(filename, function (inflatedData) { + try { + if (!inflatedData) { + throw "Could not find MFT entry for " + filename; + } + const modelFile = new t3dParser.FileParser(inflatedData); + // MODL for materials -> textures + const modelDataChunk = modelFile.getChunk("modl"); + /// Get materials used by model + const mats = modelDataChunk.data.permutations[0].materials; + /// Add each material file AND referenced TEXTURES + mats.forEach(function (mat) { + /// Add material file id + const matFileName = mat.filename; + fileIds.push(matFileName); + /// Add each texture file id + mat.textures.forEach(function (tex) { + fileIds.push(tex.filename); + }); + }); + } + catch (e) { + console.warn("Could not export any data", e); + } + callback(fileIds); + }); + } + + var RenderUtils = /*#__PURE__*/Object.freeze({ + __proto__: null, + getFilesUsedByModel: getFilesUsedByModel, + getInstancedMesh: getInstancedMesh, + getMeshesForFilename: getMeshesForFilename, + loadMeshFromModelFile: loadMeshFromModelFile, + renderGeomChunk: renderGeomChunk, + renderRect: renderRect + }); + + /** + * A Logger class for T3D + * + * This satic class defines severity levels of messages and provides + * basic logging functionality. Replacing the reference to + * + * @namespace + * @static + */ + class Logger { + TYPE_ERROR = 4; + TYPE_WARNING = 3; + TYPE_MESSAGE = 2; + TYPE_PROGRESS = 1; + TYPE_DEBUG = 0; + logFunctions = new Array(5); + constructor() { + this.logFunctions[this.TYPE_ERROR] = function (...args) { + console.error(...args); + }; + this.logFunctions[this.TYPE_WARNING] = function (...args) { + console.warn(...args); + }; + this.logFunctions[this.TYPE_MESSAGE] = function (...args) { + console.log(...args); + }; + this.logFunctions[this.TYPE_PROGRESS] = function (...args) { + const argArr = args; + argArr.unshift("Progress: "); + console.log(...argArr); + }; + this.logFunctions[this.TYPE_DEBUG] = function (...args) { + const argArr = args; + console.debug(...argArr); + }; + } + /** + * Main logging method. Takes 1 to N arguments. If there are more than 1 arguments + * the first argument is interpreted as severity. If there is only one argument + * severity defaults to + * {{#crossLink "Logger/TYPE_MESSAGE:property"}}{{/crossLink}}. + * + * The following arguments are passed to a logging function matching the + * severity. + * + + * + */ + log(...args) { + /// Require at least 1 argument + if (arguments.length === 0) { + return; + } + /// Parse arguments to an actual array + const argArr = args; + /// Default to message if just one argument was passed + if (argArr.length === 1) { + argArr.unshift(this.TYPE_MESSAGE); + } + /// Otherwise 1st arg is severity, log/warn/error + const severity = Math.max(0, Math.min(this.logFunctions.length, argArr.shift())); + const logFunc = this.logFunctions[severity]; + /// Ouput the rest of the arguments + logFunc.apply(this, argArr); + } + } + const logger = new Logger(); + + // A progress cache is needed to debounce logs at the same percentage + const progressCache = {}; + /** + * This utility function is a helper for showing loading progress of dataRenderers. + * It automatically generates progress logs which can be used outside of the library to show progress bars. + * Must be used on loop implementations where the maximum index is known in advance + * + * @param {Object} logger The default logger or given one + * @param {Number} currentIndex Current index of the item being loaded + * @param {Number} maxIndex Maximum index of items to load + * @param {String} progressName Name of the resource being loaded + */ + function progress(logger$1, currentIndex, maxIndex, progressName) { + const percent = Math.round((1000.0 * currentIndex) / maxIndex) / 10.0; + // Make sure we don't spam logs + if (progressCache[progressName] !== percent) { + const consistentPercent = percent + (percent.toString().indexOf(".") < 0 ? ".0" : ""); + logger$1.log(logger.TYPE_PROGRESS, progressName, consistentPercent); + progressCache[progressName] = percent; + } + // Clean cache on last item + if (currentIndex === maxIndex) { + progressCache[progressName] = undefined; + } + } + + /** + * + * A renderer that generates property models for a map. + * + * @class PropertiesRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "mapFile", a FileParser. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class PropertiesRenderer extends DataRenderer { + static rendererName = "PropertiesRenderer"; + showUnmaterialized; + mapFile; + meshCache; + textureCache; + models; + modelsList = []; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "PropertiesRenderer"); + this.mapFile = this.settings.mapFile; + this.showUnmaterialized = this.settings.showUnmaterialized || false; + this.meshCache = {}; + this.textureCache = {}; + this.models = {}; + } + /** + * Renders all property meshes in a GW2 map described by the map's PROP chunk. + * Output fileds generated: + * + * - *meshes* An array of THREE.Mesh objects visualizing all property models refered by this map. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + this.getOutput().meshes = []; + const propertiesChunkData = this.mapFile.getChunk("prp2").data; + if (!propertiesChunkData) { + return callback(); + } + // Get all different prop types + const props = [] + .concat(propertiesChunkData.propArray) + .concat(propertiesChunkData.propAnimArray) + .concat(propertiesChunkData.propInstanceArray) + .concat(propertiesChunkData.propMetaArray); + /// Build an object containing all the data we need for each prop + this.models = props.reduce((models, prop) => { + const propSize = prop.transforms ? prop.transforms.length + 1 : 1; + if (models[prop.filename]) { + models[prop.filename].props.push(prop); + models[prop.filename].size += propSize; + } + else { + models[prop.filename] = { + props: [prop], + size: propSize, + }; + } + return models; + }, {}); + this.modelsList = Object.keys(this.models); + this.renderModel(0, callback); + } + getFileIdsAsync(callback) { + this.logger.log(T3D.Logger.TYPE_WARNING, "PropertiesRenderer.getFileIdsAsync is not implemented"); + callback([]); + } + /** + * PRIVATE METHODS + */ + /** + * To optimize the rendering on the GPU we render each model only once and use instances for + * any other place using the same model. This allows us to have a much lower amount of draw calls + * and usage of GPU memory compared to a naive approach having a mesh for each model. + */ + renderModel(index, callback) { + if (index >= this.modelsList.length) { + this.meshCache = {}; + this.textureCache = {}; + this.models = {}; + return callback(); + } + progress(this.logger, index, this.modelsList.length, "Loading 3D Models (Props)"); + const modelName = parseInt(this.modelsList[index]); + getMeshesForFilename(modelName, this.models[modelName].props[0].color, this.localReader, this.meshCache, this.textureCache, this.showUnmaterialized, + // We don't care about cached meshes since we know we only ask for each meshes once. + (meshes) => { + if (meshes) { + this.placeModelOnScene(modelName, meshes /*, boundingSphere*/); + } + this.renderModel(index + 1, callback); + }); + } + /** + * Gets the meshes of a specific model, merge them together as an instanced mesh + * and place them in the scene where they are referenced by the props. + * @param {number} modelName The baseId of the model + * @param {*} meshes The 3d models of the model + */ + placeModelOnScene(modelName, meshes) { + const model = this.models[modelName]; + const instancedMesh = getInstancedMesh(meshes, model.size); + let instancedIndex = 0; + for (const prop of model.props) { + instancedMesh.setMatrixAt(instancedIndex, getMatrixForProp(prop)); + instancedIndex += 1; + for (const transform of prop.transforms || []) { + instancedMesh.setMatrixAt(instancedIndex, getMatrixForProp(transform)); + instancedIndex += 1; + } + } + this.getOutput().meshes.push(instancedMesh); + } + } + /** + * Return a Matrix4 for a given prop defining the Scale Rotation and Location of a model + * @param {Object} propData + * @returns {THREE.Matrix4} + */ + function getMatrixForProp(propData) { + const matrix = new THREE.Matrix4(); + matrix.makeRotationFromEuler(new THREE.Euler(propData.rotation[0], -propData.rotation[2], -propData.rotation[1], "ZXY")); + matrix.scale(new THREE.Vector3(propData.scale, propData.scale, propData.scale)); + matrix.setPosition(propData.position[0], -propData.position[2], -propData.position[1]); + return matrix; + } + + /** + * + * A renderer that generates meshes for a single model file. + * + * @class SingleModelRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "id" the base ID or file ID of the model to generate meshes for. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class SingleModelRenderer extends DataRenderer { + static rendererName = "SingleModelRenderer"; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "SingleModelRenderer"); + } + /** + * Output fileds generated: + * + * - *meshes* An array of THREE.Mesh objects visualizing this model file. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + const self = this; + /// Get file id + const fileId = this.settings.id; + const showUnmaterialed = true; + /// Load the model file + let meshCache = {}; + const textureCache = {}; + /// Set up output array + self.getOutput().meshes = []; + getMeshesForFilename(fileId, 0x00ff00, self.localReader, meshCache, textureCache, showUnmaterialed, function (meshes, isCached, boundingSphere) { + if (meshes) { + meshes.forEach(function (mesh) { + mesh.boundingSphere = boundingSphere; + self.getOutput().meshes.push(mesh); + }); + } + /// Fire callback after all meshes have been added. + meshCache = {}; + callback(); + }); + } + } + + /// TODO: port fog from in-engine + function getFragmentShader() { + return [ + "uniform vec2 uvScale;", + "uniform vec2 offset;", + "uniform sampler2D texturePicker;", + "uniform sampler2D texturePicker2;", + "uniform sampler2D texture1;", + "uniform sampler2D texture2;", + "uniform sampler2D texture3;", + "uniform sampler2D texture4;", + "#include ", + "#include ", + "varying vec2 vUv;", + "varying vec3 vecNormal;", + "vec3 blend(", + "vec4 texture1, float a1, vec4 texture2, float a2,", + "vec4 texture3, float a3, vec4 texture4, float a4)", + "{", + "float depth = 2.0;", + "float alphaMult = 1.0;", + "float alphaAdd = 0.0;", + "a1 *= 4.0;", + "a2 *= 4.0;", + "a3 *= 4.0;", + "a4 *= 4.0;", + "a1 = a1+(1.5+texture1.a);", + "a2 = a2+(1.5+texture2.a);", + "a3 = a3+(1.5+texture3.a);", + "a4 = a4+(1.5+texture4.a);", + "float ma = max(a1,a2);", + "ma = max(ma,a3);", + "ma = max(ma,a4);", + "ma -= depth;", + "float b1 = max(a1 - ma, 0.0);", + "float b2 = max(a2 - ma, 0.0);", + "float b3 = max(a3 - ma, 0.0);", + "float b4 = max(a4 - ma, 0.0);", + "return (", + "texture1.rgb * b1 + texture2.rgb * b2 +", + "texture3.rgb * b3 + texture4.rgb * b4 ", + ") / (b1 + b2 + b3 + b4);", + "}", + "void main( void ) {", + "vec2 position = vUv*uvScale;", + "float edge = 1.0/1024.0;", + "vec2 compPos = edge + (vUv*0.25 + offset) * (1.0-edge*2.0);", + "vec4 tp1 = texture2D( texturePicker, compPos);", + "vec4 tp2 = texture2D( texturePicker2, compPos);", + "vec4 composite = tp1;", + "vec4 t1 = texture2D( texture1, position );", + "vec4 t2 = texture2D( texture2, position );", + "vec4 t3 = texture2D( texture3, position );", + "vec4 t4 = texture2D( texture4, position );", + "vec3 color = blend(", + "t1, tp1.a,", + "t2, tp1.b,", + "t3, tp1.g,", + "t4, tp1.r", + ");", + "color *= 0.5+tp2.r;", + "gl_FragColor = vec4(color,1.0);", + "#include ", + "}", + ].join("\n"); + } + function getVertexShader() { + return [ + "varying vec2 vUv;", + "varying vec3 vecNormal;", + "#include ", + "#include ", + "void main()", + "{", + "vUv = uv;", + "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", + "vecNormal = (modelMatrix * vec4(normal, 0.0)).xyz;", + "gl_Position = projectionMatrix * mvPosition;", + "#include ", + "}", + ].join("\n"); + } + + /** + * + * A renderer that generates the meshes for the terrain of a map. + * + * + * Requires a context previously populated by a + * {{#crossLink "EnvironmentRenderer"}}{{/crossLink}}. + * + * @class TerrainRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "mapFile", a FileParser. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class TerrainRenderer extends DataRenderer { + static rendererName = "TerrainRenderer"; + mapFile; + mapRect; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "TerrainRenderer"); + this.mapFile = this.settings.mapFile; + } + drawWater(rect) { + /// Add Water + const material = new THREE.MeshBasicMaterial({ + color: 0x5bb1e8, + wireframe: false, + opacity: 0.35, + }); + material.transparent = true; + return renderRect(rect, 0, material); + } + parseNumChunks(terrainData) { + terrainData.numChunksD_1 = Math.sqrt((terrainData.dims[0] * terrainData.chunkArray.length) / terrainData.dims[1]); + terrainData.numChunksD_2 = terrainData.chunkArray.length / terrainData.numChunksD_1; + } + loadPagedImageCallback(callback, inflatedBuffer) { + const self = this; + // Prep output array + self.getOutput().terrainTiles = []; + const pimgFile = new t3dParser.FileParser(inflatedBuffer); + const pimgTableDataChunk = pimgFile.getChunk("pgtb"); + const pimgData = pimgTableDataChunk && pimgTableDataChunk.data; + this.mapRect = null; + /// Fetch chunks + const terrainData = this.mapFile.getChunk("trn").data; + const parameterData = this.mapFile.getChunk("parm").data; + /// Read settings + const maxAnisotropy = this.settings.anisotropy ? this.settings.anisotropy : 1; + //let chunks = []; + const chunkW = 35; + /// Calculate numChunksD_1 and _2 + this.parseNumChunks(terrainData); + const xChunks = terrainData.numChunksD_1; + const yChunks = terrainData.numChunksD_2; + const allMaterials = terrainData.materials.materials; + const allTextures = terrainData.materials.texFileArray; + // Total map dx and dy + /* + old parameter data definition: + "x1", "float32", + "y1", "float32", + "x2", "float32", + "y2", "float32" + */ + // var dx = parameterData.rect.x2 - parameterData.rect.x1; + // var dy = parameterData.rect.y2 - parameterData.rect.y1; + const dx = parameterData.rect[2] - parameterData.rect[0]; + const dy = parameterData.rect[3] - parameterData.rect[1]; + // Each chunk dx and dy + const cdx = (dx / terrainData.numChunksD_1) * 1; // 35/33; + const cdy = (dy / terrainData.numChunksD_2) * 1; // 35/33; + let n = 0; + const customMaterial = new THREE.MeshLambertMaterial({ + side: THREE.DoubleSide, + color: 0x666666, + flatShading: true, + }); + //let texMats = {}; + /// Load textures from PIMG and inject as material maps (textures) + const chunkTextures = {}; + /// Load textures + if (pimgData) { + const strippedPages = pimgData.strippedPages; + /// Only use layer 0 + strippedPages.forEach(function (page) { + /// Only load layer 0 and 1 + if (page.layer <= 1) { + const filename = page.filename; + //let color = page.solidColor; + const coord = page.coord; + let matName = coord[0] + "," + coord[1]; + if (page.layer === 1) + matName += "-2"; + /// Add texture to list, note that coord name is used, not actual file name + if (!chunkTextures[matName]) { + /// Load local texture, here we use file name! + const chunkTex = loadLocalTexture(self.localReader, filename); + if (chunkTex) { + /// Set repeat, antistropy and repeat Y + chunkTex.anisotropy = maxAnisotropy; + chunkTex.wrapS = THREE.RepeatWrapping; + chunkTex.wrapT = THREE.RepeatWrapping; + } + /// ...But store in coord name + chunkTextures[matName] = chunkTex; + } + } + }); /// end for each stripped page in pimgData + } + /// Render Each chunk + /// We'll make this async in order for the screen to be able to update + const renderChunk = function (cx, cy) { + const chunkIndex = cy * xChunks + cx; + const pageX = Math.floor(cx / 4); + const pageY = Math.floor(cy / 4); + // TODO: Terrain texture LOD ? + const chunkTextureIndices = allMaterials[chunkIndex].loResMaterial.texIndexArray; + // let matFileName = allMaterials[chunkIndex].loResMaterial.materialFile; + // let chunkTextureIndices = allMaterials[chunkIndex].hiResMaterial.texIndexArray; + // let matFileName = allMaterials[chunkIndex].hiResMaterial.materialFile; + // let chunkData = terrainData.chunkArray[chunkIndex]; + // let mainTex = allTextures[chunkTextureIndices[0]]; + let mat = customMaterial; + /// TODO: just tick invert y = false...? + const pageOffetX = (cx % 4) / 4.0; + const pageOffetY = 0.75 - (cy % 4) / 4.0; + // offset 0 -> 0.75 + // Make sure we have shared textures + /// Load and store all tiled textures + const fileNames = []; + for (let gi = 0; gi < chunkTextureIndices.length / 2; gi++) { + const textureFileName = allTextures[chunkTextureIndices[gi]].filename; + fileNames.push(textureFileName); + /// If the texture is not already loaded, read it from the .dat! + if (!chunkTextures[textureFileName]) { + /// Load local texture + const chunkTex = loadLocalTexture(self.localReader, textureFileName); + if (chunkTex) { + /// Set repeat, antistropy and repeat Y + chunkTex.anisotropy = maxAnisotropy; + chunkTex.wrapS = THREE.RepeatWrapping; + chunkTex.wrapT = THREE.RepeatWrapping; + } + chunkTextures[textureFileName] = chunkTex; + } + } /// End for each chunkTextureIndices + /// Create Composite texture material, refering the shared textures + const pageTexName = pageX + "," + pageY; + const pageTexName2 = pageX + "," + pageY + "-2"; + /// Get haze color from environment rednerer + const envOutput = self.getOutput(T3D.EnvironmentRenderer); + if (envOutput.hazeColor) { + envOutput.hazeColor[2] / 255.0; + envOutput.hazeColor[1] / 255.0; + envOutput.hazeColor[0] / 255.0; + } + const uniforms = THREE.UniformsUtils.merge([THREE.UniformsLib["lights"]]); + /// TODO: READ FROM VO, don't default to hard coded scale + uniforms.uvScale = { type: "v2", value: new THREE.Vector2(8.0, 8.0) }; + uniforms.offset = { + type: "v2", + value: new THREE.Vector2(pageOffetX, pageOffetY), + }; + uniforms.texturePicker = { + type: "t", + value: chunkTextures[pageTexName], + }; + uniforms.texturePicker2 = { + type: "t", + value: chunkTextures[pageTexName2], + }; + uniforms.texture1 = { type: "t", value: chunkTextures[fileNames[0]] }; + uniforms.texture2 = { type: "t", value: chunkTextures[fileNames[1]] }; + uniforms.texture3 = { type: "t", value: chunkTextures[fileNames[2]] }; + uniforms.texture4 = { type: "t", value: chunkTextures[fileNames[3]] }; + if (self.settings && self.settings.export) { + mat = new THREE.MeshBasicMaterial({ visible: true }); + } + else { + mat = new THREE.ShaderMaterial({ + uniforms: uniforms, + fragmentShader: getFragmentShader(), + vertexShader: getVertexShader(), + }); + } + /// -1 for faces -> vertices , -2 for ignoring outer faces + const chunkGeo = new THREE.PlaneBufferGeometry(cdx, cdy, chunkW - 3, chunkW - 3); + let cn = 0; + /// Render chunk + /// Each chunk vertex + for (let y = 0; y < chunkW; y++) { + for (let x = 0; x < chunkW; x++) { + if (x !== 0 && x !== chunkW - 1 && y !== 0 && y !== chunkW - 1) { + //@ts-ignore + chunkGeo.getAttribute("position").array[cn * 3 + 2] = terrainData.heightMapArray[n]; + cn++; + } + n++; + } + } // End each chunk vertex + /// Flip the plane to fit wonky THREE js world axes + const mS = new THREE.Matrix4().identity(); + mS.elements[5] = -1; + chunkGeo.applyMatrix4(mS); + /// Compute face normals for lighting, not used when textured + //@ts-ignore + chunkGeo.computeFaceNormals(); + chunkGeo.computeVertexNormals(); + /// Build chunk mesh! + let chunk; + chunk = new THREE.Mesh(chunkGeo, customMaterial); + if (Array.isArray(mat)) { + chunk = THREE.SceneUtils.createMultiMaterialObject(chunkGeo, mat); + } + else { + chunk = new THREE.Mesh(chunkGeo, mat); + } + /// Move and rotate Mesh to fit in place + chunk.rotation.set(Math.PI / 2, 0, 0); + /// Last term is the new one: -cdx*(2/35) + const globalOffsetX = parameterData.rect[0] + cdx / 2; + const chunkOffsetX = cx * cdx; + chunk.position.x = globalOffsetX + chunkOffsetX; + /// Adjust for odd / even number of chunks + if (terrainData.numChunksD_2 % 2 === 0) { + /// Last term is the new one: -cdx*(2/35) + const globalOffsetY = parameterData.rect[1] + cdy / 2 - 0; // -cdy*(1/35); + const chunkOffsetY = cy * cdy * 1; // 33/35; + chunk.position.z = chunkOffsetY + globalOffsetY; + } + else { + const globalOffsetY = parameterData.rect[1] - cdy / 2 + 0; // cdy*(1/35); + const chunkOffsetY = cy * cdy * 1; // 33/35; + chunk.position.z = globalOffsetY + chunkOffsetY; + } + const px = chunk.position.x; + const py = chunk.position.z; + if (!self.mapRect) { + self.mapRect = { + x1: px - cdx / 2, + x2: px + cdx / 2, + y1: py - cdy / 2, + y2: py + cdy / 2, + }; + } + self.mapRect.x1 = Math.min(self.mapRect.x1, px - cdx / 2); + self.mapRect.x2 = Math.max(self.mapRect.x2, px + cdx / 2); + self.mapRect.y1 = Math.min(self.mapRect.y1, py - cdy / 2); + self.mapRect.y2 = Math.max(self.mapRect.y2, py + cdy / 2); + chunk.updateMatrix(); + chunk.updateMatrixWorld(); + /// Add to list of stuff to render + /// TODO: Perhaps use some kind of props for each entry instead? + self.getOutput().terrainTiles.push(chunk); + }; /// End render chunk function + const stepChunk = function (cx, cy) { + if (cx >= xChunks) { + cx = 0; + cy++; + } + if (cy >= yChunks) { + /// Draw water surface using map bounds + self.getOutput().water = self.drawWater(self.mapRect); + /// Set bounds in output VO + self.getOutput().bounds = self.mapRect; + /// Fire call back, we're done rendering. + callback(); + return; + } + const pct = Math.floor((100 * (cy * xChunks + cx)) / (xChunks * yChunks)); + self.logger.log(T3D.Logger.TYPE_PROGRESS, "Loading Terrain", pct); + renderChunk(cx, cy); + setTimeout(stepChunk, 1, cx + 1, cy); + }; + stepChunk(0, 0); + } + /** + * Output fileds generated: + * + * - *terrainTiles* An array of THREE.Mesh objects visualizing terrain of the map. + * + * - *water* A THREE.Mesh object visualizing the bounds of the map. + * + * - *bounds* An object wiht x1, x2, y1, and y2 properties specifying the bounds of the map. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + /// Load all paged Images, requires inflation of other pack files! + const pagedImageId = this.mapFile.getChunk("trn").data.materials.pagedImage; + //@ts-ignore + this.localReader.loadFile(pagedImageId, this.loadPagedImageCallback.bind(this, callback)); + } + /** + * TODO: write description. Used for export feature + * + * @param {Function} callback [description] + * @return {*} [description] + */ + getFileIdsAsync( /* callback */) { + const terrainChunk = this.mapFile.getChunk("trn"); + const pimgTableDataChunk = this.mapFile.getChunk("pimg"); + const fileIds = []; + /// ------------ SPLASH TEXTURES ------------ + const pimgData = pimgTableDataChunk && pimgTableDataChunk.data; + const strippedPages = pimgData.strippedPages; + /// Only use layer 0 + strippedPages.forEach(function (page) { + /// Only load layer 0 and 1 + if (page.layer <= 1 && page.filename > 0) { + fileIds.push(page.filename); + } + }); + /// ------------ END SPLASH TEXTURES ------------ + /// ------------ TILED IMAGES ------------ + const terrainData = terrainChunk.data; + const allTextures = terrainData.materials.texFileArray; + allTextures.forEach(function (texture) { + if (texture.filename > 0) + fileIds.push(texture.filename); + }); + /// ------------ END TILED IMAGES ------------ + return fileIds; + } + } + + /** + * + * A renderer that generates zone models for a map. + * + * @class ZoneRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "mapFile", a FileParser. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class ZoneRenderer extends DataRenderer { + static rendererName = "ZoneRenderer"; + meshCache; + textureCache; + mapFile; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "ZoneRenderer"); + this.mapFile = this.settings.mapFile; + } + /** + * TODO + * + * @param {*} zone [description] + * @param {*} zoneDefs [description] + * @param {*} mapRect [description] + * @param {*} renderZoneCallback [description] + * @return {*} [description] + */ + renderZone(zone, zoneDefs, mapRect, renderZoneCallback) { + const self = this; + /// Get Zone Definition + let zoneDef = null; + zoneDefs.forEach(function (zd) { + if (!zoneDef && zd.token === zone.defToken) + zoneDef = zd; + }); + /// Create array of all models to add: + // let models = [] + const modelGroups = this.getModelGroups(zone, zoneDef, mapRect); + /// Create empty mesh cache + self.meshCache = {}; + self.textureCache = {}; + /* + * ---Keeping this out of the doc for now--- + * Steps trough each model and renders it to the scene, allowing for efficient caching. + * @param {Number} i - Current index within the models array + */ + // var lastPct = -1; + const groupKeys = Object.keys(modelGroups); + function stepModels(i) { + /* var pct = Math.round(100.0*i / groupKeys.length); + if(lastPct!=pct){ + console.log("Rendering ZONE models "+pct); + lastPct = pct; + } */ + if (i >= groupKeys.length) { + /// Empty mesh cache + self.meshCache = {}; + self.textureCache = {}; + /// Tell caller this zone is done loading + renderZoneCallback(); + return; + } + /// Read model at index + /// var model = models[i]; + const key = groupKeys[i]; /// key is model filename + const group = modelGroups[key]; + const meshGroups = []; + /// Get model just once for this group + const showUnmaterialed = false; + getMeshesForFilename(key, null, self.localReader, self.meshCache, self.textureCache, showUnmaterialed, function (meshes /*, isCached*/) { + /// If there were meshes, add them to the scene with correct scaling rotation etc. + if (meshes /* && meshes.length == 3 */) { + /// Add one copy per model instance + /// TODO: add rotation! + /// TODO: fine tune position? + /// TODO: POTIMIZE! + group.forEach(function (model, instanceIdx) { + //let isCached = true; + //let scale = 1.0; + /// For each Mesh in the model + meshes.forEach(function (mesh, meshIdx) { + if (mesh.materialFlags === 525 /* || mesh.materialFlags == 520 || mesh.materialFlags == 521 */) { + // console.log("Skipping lod"); + return; + } + const move = { x: 0, y: 0, z: 0 }; + /// Add to big mesh + if (!meshGroups[meshIdx]) { + const mg = mesh.geometry.clone(); + meshGroups[meshIdx] = { + readVerts: mg.getAttribute("position").array, + verts: new Float32Array(group.length * mg.getAttribute("position").array.length), + readIndices: mg.getIndex().array, + indices: new Uint32Array(group.length * mg.getIndex().array.length), + readUVs: mg.getAttribute("uv").array, + uvs: new Float32Array(group.length * mg.getAttribute("uv").array.length), + readNormals: mg.getAttribute("normal").array, + normals: new Float32Array(group.length * mg.getAttribute("normal").array.length), + material: mesh.material, + // material:new THREE.MeshBasicMaterial( {color: 0xffcccc, wireframe:true} ), + /* material : new THREE.PointCloudMaterial ({ + color: 0xFF0000, + size: 20 + }), */ + position: { x: model.x, y: model.y, z: model.z }, + }; + } + else { + /// Translate + move.x = model.x - meshGroups[meshIdx].position.x; + move.y = model.z - meshGroups[meshIdx].position.z; + move.z = model.y - meshGroups[meshIdx].position.y; + } + /// Add geom verts + const readVerts = meshGroups[meshIdx].readVerts; + const writeVerts = meshGroups[meshIdx].verts; + const stride = readVerts.length; + for (let i = 0, j = instanceIdx * stride; i < stride; i += 3, j += 3) { + writeVerts[j + 0] = readVerts[i + 0] + move.x; + writeVerts[j + 1] = readVerts[i + 1] + move.y; + writeVerts[j + 2] = readVerts[i + 2] + move.z; + } + const readIndices = meshGroups[meshIdx].readIndices; + const writeIndices = meshGroups[meshIdx].indices; + const strideIndices = readIndices.length; + const shift = (stride * instanceIdx) / 3; + for (let i = 0, j = instanceIdx * strideIndices; i < strideIndices; i++, j++) { + writeIndices[j] = readIndices[i] + shift; + } + const readUVs = meshGroups[meshIdx].readUVs; + const writeUvs = meshGroups[meshIdx].uvs; + const uvStride = readUVs.length; + for (let i = 0, j = instanceIdx * uvStride; i < uvStride; i++, j++) { + writeUvs[j] = readUVs[i]; + } + const readNormals = meshGroups[meshIdx].readNormals; + const writeNormals = meshGroups[meshIdx].normals; + const normalStride = readNormals.length; + for (let i = 0, j = instanceIdx * normalStride; i < normalStride; i++, j++) { + writeNormals[j] = readNormals[i]; + } + }); + }); // End for each model in group + } /// End if meshes + /// Add each cluster of merged meshes to scene + meshGroups.forEach(function (meshGroup) { + const mergedGeom = new THREE.BufferGeometry(); + mergedGeom.setAttribute("position", new THREE.BufferAttribute(meshGroup.verts, 3)); + // mergedGeom.setAttribute( 'index', new THREE.BufferAttribute( meshGroup.indices, 1) ); + mergedGeom.setIndex(new THREE.BufferAttribute(meshGroup.indices, 1)); + mergedGeom.setAttribute("normal", new THREE.BufferAttribute(meshGroup.normals, 3)); + mergedGeom.setAttribute("uv", new THREE.BufferAttribute(meshGroup.uvs, 2)); + //@ts-ignore + mergedGeom.buffersNeedUpdate = true; + const mesh = new THREE.Mesh(mergedGeom, meshGroup.material); + mesh.position.set(meshGroup.position.x, meshGroup.position.z, meshGroup.position.y); + self.getOutput().meshes.push(mesh); + }); // End for each meshgroup + /// Rendering is done, render next. + stepModels(i + 1); + }); + } /// End function stepModels + /// Begin stepping trough the models, rendering them. + stepModels(0); + } + /** + * TODO + * + * @param {*} zone [description] + * @param {*} zoneDef [description] + * @param {*} mapRect [description] + * @return {*} [description] + */ + getModelGroups(zone, zoneDef, mapRect) { + /// Calculate rect in global coordinates + // let zPos = zone.zPos; + const mapX = mapRect[0]; + const mapY = mapRect[1]; + const c = 32 + 16; + // ["x1","uint32","y1","uint32","x2","uint32", "y2", "uint32"] + const zoneRect = { + x1: zone.vertRect[0] * c + mapX, + x2: zone.vertRect[2] * c + mapX, + y1: zone.vertRect[1] * -c - mapY, + y2: zone.vertRect[3] * -c - mapY, + }; + /// Zone width and depth in local corrdinates + /* var zdx = zone.vertRect.x1-zone.vertRect.x2; + var zdy = zone.vertRect.y1-zone.vertRect.y2; */ + /// These zones seems to overflow :/ + if (zone.encodeData.length === 0) { + return {}; + } + // console.log("Get mdl groups", zone); + /// Testing: Render Zone Vert Rect + // RenderUtils.renderRect(zoneRect, -zPos); + const zdx = zone.vertRect[0] - zone.vertRect[2]; + // let zdy = zone.vertRect[1] - zone.vertRect[3]; + /// Zone Flags increases a linear position, used to step trough the Zone. + let linearPos = 0; + const modelGroups = {}; + const terrainTiles = this.getOutput(T3D.TerrainRenderer).terrainTiles; + for (let i = 0; i < zone.flags.length; i += 2) { + /// Step forward + linearPos += zone.flags[i]; + /// Check if a model should be placed + const flag = zone.flags[i + 1]; + if (flag !== 0) { + /// Extract flag data + /// Layer is written in the last 4 bytes + const zoneDefLayer = flag >> 4; + /// Get Zone Definition Layer + const layer = zoneDef.layerDefArray[zoneDefLayer - 1]; + /// TESTING Only show layers with height >= 3 + if (layer /* && layer.height >= 0 */) { + /// Get X and Y from linear position + const modelX = (linearPos % zdx) * c + zoneRect.x1; + const modelY = Math.floor(linearPos / zdx) * c + zoneRect.y1; + /// Get Z from intersection with terrain + let modelZ = null; + const startZ = 100000; + const raycaster = new THREE.Raycaster(new THREE.Vector3(modelX, startZ, modelY), new THREE.Vector3(0, -1, 0)); + /// TODO: OPT? + terrainTiles.forEach(function (chunk) { + if (modelZ === null) { + const intersections = raycaster.intersectObject(chunk); + if (intersections.length > 0) { + modelZ = startZ - intersections[0].distance; + } + } + }); + /// Get model id + /// TODO: check with modelIdx = flag & 0xf; + const modelIdx = 0; + const model = layer.modelArray[modelIdx]; + const modelFilename = model.filename; + // let zOffsets = model.zOffsets; + // let layerFlags = layer.layerFlags; // NOrmaly 128, 128 + // TODO: flip z,y? + const rotRangeX = layer.rotRangeX; // max min + const rotRangeY = layer.rotRangeY; // max min + const rotRangeZ = layer.rotRangeZ; // max min + const scaleRange = layer.scaleRange; // max min + const fadeRange = layer.fadeRange; // max min + // Unused + // tiling: 3 + // type: 1 + // width: 2 + // radiusGround: 2 + /// Create modelGroup (this zone only) + if (!modelGroups[modelFilename]) { + modelGroups[modelFilename] = []; + } + /// Add entry to model group + modelGroups[modelFilename].push({ + x: modelX, + y: modelY, + z: modelZ, + rotRangeX: rotRangeX, + rotRangeY: rotRangeY, + rotRangeZ: rotRangeZ, + scaleRange: scaleRange, + fadeRange: fadeRange, + }); + } /// End if layer + } /// End if flag != 0 + } /// End for each flag + return modelGroups; + } + /** + * Renders all zone meshes in a GW2 map described by the map's "zon2" chunk. + * Output fileds generated: + * + * - *meshes* An array of THREE.Mesh objects visualizing all zone models refered by this map. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + const self = this; + /// Set up output array + self.getOutput().meshes = []; + const zoneChunkData = this.mapFile.getChunk("zon2").data; + const parameterChunkData = this.mapFile.getChunk("parm").data; + // let terrainChunkData = this.mapFile.getChunk("trn").data; + const mapRect = parameterChunkData.rect; + /// Zone data + const zones = zoneChunkData.zoneArray; + const zoneDefs = zoneChunkData.zoneDefArray; + /// Render each zone + let lastPct = -1; + /// Main render loop, render each zone + function stepZone(i) { + const pct = Math.round((100.0 * i) / zones.length); + if (lastPct !== pct) { + self.logger.log(T3D.Logger.TYPE_PROGRESS, "Loading 3D Models (Zone)", pct); + lastPct = pct; + } + if (i >= zones.length) { + callback(); + return; + } + /// Main zone render function call + self.renderZone(zones[i], zoneDefs, mapRect, stepZone.bind(self, i + 1)); + } + stepZone(0); + } + } + /* + /// NOT USED?? + // eslint-disable-next-line no-unused-vars + function addZoneMeshesToScene(meshes, isCached, position, scale, rotation) { + /// Called for each mesh in the zone + /// TODO: Opt opt opt... + + meshes.forEach(function (mesh) { + /// Create new mesh if we got back a cached original. + if (isCached) mesh = new THREE.Mesh(mesh.geometry, mesh.material); + + /// Scale, position and rotate. + mesh.scale.set(scale, scale, scale); + if (rotation) { + mesh.rotation.order = "ZXY"; + mesh.rotation.set(rotation.x, rotation.y, rotation.z); + } + mesh.position.set(position.x, position.y, position.z); + + /// Add to export + this.getOutput().meshes.push(mesh); + }); + } + */ + /// / Not used: zone defintion per chunk data "images" 32*32 points + /* + //Total map dx and dy + var d = terrainChunkHeader.data; + var pd = parameterChunkHeader.data; + var dx = (pd.rect.x2-pd.rect.x1); + var dy = (pd.rect.y2-pd.rect.y1); + + //Each chunk dx and dy + + var c =1; + var cdx = c*dx/d.dims.dim1; + + var cdy = c*dy/d.dims.dim2; + + var cdx = dx/(d.numChunksD_1*2); + var cdy =dy/(d.numChunksD_2*2); + + for(var i=0; i0){ + // console.log("Found flag",flags[j],"@ zoneDef",zoneDef.token,"coord",coord,"index",j); + // } + //} + }); + + } + + } */ + + /** + * + * A renderer that generates a list of readable strings from a "strs" file. + * + * @class StringRenderer + * @constructor + * @extends DataRenderer + * @param {LocalReader} localReader The LocalReader instance to read data from. + * @param {Object} settings Any settings used by this renderer. + * *Must* specify "id" the base ID or file ID of the string file to read strings from. + * @param {Object} context Shared value object between renderers. + * @param {Logger} logger The logging class to use for progress, warnings, errors et cetera. + */ + class StringRenderer extends DataRenderer { + static rendererName = "StringRenderer"; + constructor(localReader, settings, context, logger) { + super(localReader, settings, context, logger, "StringRenderer"); + } + /** + * Output fileds generated: + * + * - *strings* An array of objects. Each object has a "recid"-property specifing on what index within the file + * a given string was found, and a "value"-property specigying the string value. + * + * - *language* An integer specifing the language of the loaded file. + * + * @async + * @param {Function} callback Fires when renderer is finished, does not take arguments. + */ + renderAsync(callback) { + const self = this; + /// Get file id + // const fileId = this.settings.id; + /// Load the string file + /// Set up output array + this.getOutput().strings = []; + this.localReader.loadFile(this.settings.id, function (inflatedData) { + const dataView = new DataView(inflatedData); + const end = dataView.byteLength - 2; + /// skip past fcc + let cursor = 4; + let entryIndex = 0; + while (end - cursor > 6) { + const size = dataView.getUint16(cursor, true); + cursor += 2; + const decryptionOffset = dataView.getUint16(cursor, true); + cursor += 2; + const bitsPerSymbol = dataView.getUint16(cursor, true); + cursor += 2; + const entry = { size, decryptionOffset, bitsPerSymbol }; + entry.size -= 6; + if (entry.size > 0) { + const isEncrypted = entry.decryptionOffset !== 0 || entry.bitsPerSymbol !== 0x10; + /// UTF-16 + if (!isEncrypted) { + const value = new Uint16Array(inflatedData, cursor, entry.size / 2); + cursor += entry.size; + self.getOutput().strings.push({ value: String.fromCharCode(...value), recid: entryIndex }); + } + } + entryIndex++; + } + self.getOutput().language = dataView.getUint16(end, true); + callback(); + }); + } + } + + var version = "3.0.0"; + + /* INCLUDES */ + /* PRIVATE VARS */ + const _settings = { + t3dtoolsWorker: "modules/t3dtools/t3dworker.js", + concurrentTasks: typeof navigator !== "undefined" ? navigator.hardwareConcurrency : 1, + }; + // eslint-disable-next-line prefer-const + T3D = { + version: version, + DataRenderer: DataRenderer, + EnvironmentRenderer: EnvironmentRenderer, + HavokRenderer: HavokRenderer, + PropertiesRenderer: PropertiesRenderer, + SingleModelRenderer: SingleModelRenderer, + TerrainRenderer: TerrainRenderer, + ZoneRenderer: ZoneRenderer, + StringRenderer: StringRenderer, + Logger: logger, + MapFileList: mapMap, + MaterialUtils: MaterialUtils, + MathUtils: MathUtils, + RenderUtils: RenderUtils, + PersistantStore: PersistantStore, + FileTypes: FileTypes, + /** + * Creates a new instance of LocalReader with an pNaCl inflater connected to it. + */ + getLocalReader: function (file, callback, t3dtoolsWorker, noIndexedDB) { + const path = t3dtoolsWorker || _settings.t3dtoolsWorker; + // Create the instance and init the threads + const lrInstance = new LocalReader({ + workerPath: path, + workersNb: _settings.concurrentTasks, + noIndexedDB, + }); + /// Callback with the lrInstance + lrInstance.openArchive(file).then(() => { + callback(lrInstance); + }); + return lrInstance; + }, + /** + * Utility method for acceccing a list containing information about all files + * in the .dat connected to the provided LocalReader instance. This method first + * tries to read a local indexing list from the client's localstorage and + * fallbacks to generating the list by scanning the MFT indices of the .dat + * and peeking each file in order to find out what filetype it has. + * + * Note that peeking the files is the time consuming task, so if you don't want + * yout application to spend time indexing the .dat and have a priori knowledge + * about the required file Id's you should not use this method. + **/ + getFileListAsync: function (localReader, callback) { + localReader.readFileList().then((result) => { + const returnObj = {}; + for (const fileEntry of result) { + if (returnObj[fileEntry.fileType] === undefined) { + returnObj[fileEntry.fileType] = []; + } + returnObj[fileEntry.fileType].push(fileEntry.mftId); + } + callback(returnObj); + }); + }, + /** + * Utility method for acceccing a list containing information about all map files + * in the .dat connected to the provided LocalReader instance. This method first + * tries to read a local indexing list from the client's localstorage and + * fallbacks to generating the list by scanning the MFT indices of the .dat + * and peeking each file in order to find out what filetype it has. + * + * If the searchAll flag is not set to true, this process will only scan files + * from the "T3D/MapFileList" property. + **/ + getMapListAsync: function (localReader, callback, searchAll) { + function restoreOuput(array) { + const returnArray = []; + for (const elt of array) { + let category = returnArray.findIndex((i) => i.name === elt.category); + if (category === -1) { + category = returnArray.push({ name: elt.category, maps: [] }) - 1; + } + returnArray[category].maps.push({ + fileName: elt.baseId, + name: elt.name, + }); + } + // And resort it in order + returnArray.sort((i, j) => { + if (i.name < j.name) + return -1; + if (i.name > j.name) + return 1; + return 0; + }); + return { maps: returnArray }; + } + /// If seachAll flag is true, force a deep search + if (searchAll) { + localReader.readFileList().then(() => { + localReader.getMapList().then((result) => { + callback(restoreOuput(result)); + }); + }); + return; + } + else { + localReader.getMapList().then((result) => { + callback(restoreOuput(result)); + }); + } + }, + /** + * Utility method used for rendering map files. Loads a map file and applies + * the provided renderers to it. + **/ + renderMapContentsAsync: function (localReader, fileName, renderers, callback, logger) { + /// VO for storing result from renderers + const context = {}; + let runAllRenderers; + /// Make sure we got an actuall ID number + if (parseInt(fileName)) { + /// File name is baseId, load using local reader. + localReader.loadFile(parseInt(fileName), function (arrayBuffer) { + /// Initiate Map file object. Connect callback + const mapFile = new t3dParser.FileParser(arrayBuffer); + /// Populate VO by running the renderers + runAllRenderers = function (i) { + /// Run each renderer + if (i < renderers.length) { + T3D.runRenderer(renderers[i].renderClass, localReader, Object.assign(renderers[i].settings, { mapFile: mapFile }), context, () => runAllRenderers(i + 1)); + } + /// Fire callback with VO when done + else { + callback(context); + } + }; + /// Starting point for running each renderer + runAllRenderers(0); + }); + } + /// Primitive error message... + else { + const outputLogger = logger || T3D.Logger; + outputLogger.log(T3D.Logger.TYPE_ERROR, "Map id must be an integer!, was:", fileName); + } + }, + /** + * Utility method for applying a single renderer to a LocalReader insatnce. + **/ + runRenderer: function (renderClass, localReader, settings, context, cb) { + const r = new renderClass(localReader, settings, context, undefined, renderClass.rendererName); + r.renderAsync(cb); + }, + getContextValue: function (context, clazz, propName, defaultValue) { + const output = context[clazz.rendererName]; + if (output) { + return output[propName] ? output[propName] : defaultValue; + } + return defaultValue; + }, + /** + * Check if the client web browser can render WebGL 3D content. + * + * @private + * @param {boolean} return_context flag making this method return the canvas object instead of true + * @return {boolean} true if the client is WebGL enabled, false otherwise + */ + hasWebGL: function (return_context) { + if (window.WebGLRenderingContext) { + const canvas = document.createElement("canvas"); + const names = ["webgl", "experimental-webgl", "moz-webgl", "webkit-3d"]; + let context = false; + for (let i = 0; i < 4; i++) { + try { + context = canvas.getContext(names[i]); + if (context && typeof context.getParameter === "function") { + // WebGL is enabled + if (return_context) { + // return WebGL object if the function's argument is present + return { name: names[i], gl: context }; + } + // else, return just true + return true; + } + } + catch { + //continue + } + } + // WebGL is supported, but disabled + return false; + } + // WebGL not supported + return false; + }, + }; + var T3D$1 = T3D; + globalThis.T3D = T3D; + /* PRIVATE METHODS */ + /** + * Performs checks for required browser capabilities and required third party libraries. + * Loggs any warnings or error messages. + * + * @private + * @return {Number} The ammount of errors and warnings generated. + */ + function checkRequirements() { + let numErrors = 0; + if (!globalThis.window || !window.indexedDB) { + T3D.Logger.log(T3D.Logger.TYPE_ERROR, "T3D persistant storing and loading requires indexedDB support."); + numErrors++; + } + if (typeof t3dParser.FileParser === "undefined") { + T3D.Logger.log(T3D.Logger.TYPE_ERROR, "T3D core functionality requires t3d-parser library."); + numErrors++; + } + if (typeof THREE === "undefined") { + T3D.Logger.log(T3D.Logger.TYPE_WARNING, "T3D mesh generation requires three.js library."); + numErrors++; + } + if (numErrors < 1) { + T3D.Logger.log(T3D.Logger.TYPE_MESSAGE, "Tyria 3D API v" + T3D.version + " initialized."); + } + return numErrors; + } + /// Library checks requirements on startup + checkRequirements(); + + return T3D$1; + +})(T3DParser); +//# sourceMappingURL=T3D.js.map diff --git a/explorer/static/T3D.js.map b/explorer/static/T3D.js.map new file mode 100644 index 0000000..335a7eb --- /dev/null +++ b/explorer/static/T3D.js.map @@ -0,0 +1 @@ +{"version":3,"file":"T3D.js","sources":["../src/LocalReader/PersistantStore.ts","../src/LocalReader/DataReader.ts","../src/MapFileList.ts","../src/LocalReader/FileTypes.ts","../src/LocalReader/LocalReader.ts","../src/dataRenderer/DataRenderer.ts","../src/util/MaterialUtils.ts","../src/dataRenderer/EnvironmentRenderer.ts","../src/dataRenderer/HavokRenderer.ts","../src/util/MathUtils.ts","../src/util/RenderUtils.ts","../src/Logger.ts","../src/util/Logs.ts","../src/dataRenderer/PropertiesRenderer.ts","../src/dataRenderer/SingleModelRenderer.ts","../src/util/TerrainShader.ts","../src/dataRenderer/TerrainRenderer.ts","../src/dataRenderer/ZoneRenderer.ts","../src/dataRenderer/StringRenderer.ts","../src/T3DLib.ts"],"sourcesContent":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"names":["FileParser","ArchiveParser","ParsingUtils","MapFileList","FileTypes.getFileType","MaterialUtils.loadLocalTexture","MathUtils.popcount","MathUtils.f16","MaterialUtils.getMaterial","logger","Logger","LogsUtils.progress","RenderUtils.getMeshesForFilename","RenderUtils.getInstancedMesh","RenderUtils.renderRect","TerrainShader.getFragmentShader","TerrainShader.getVertexShader","_version"],"mappings":"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"} \ No newline at end of file diff --git a/explorer/static/jquery.js b/explorer/static/jquery.js new file mode 100644 index 0000000..2170756 --- /dev/null +++ b/explorer/static/jquery.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.0 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-04-10T15:07Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && 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 #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 elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +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.5.0", + + // 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; + }, + + // 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 ); + }, + + // 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; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // 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: http://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" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = 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" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://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; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + 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 + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( 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; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// 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: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( 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, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + 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 ) || rcombinators.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. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } 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( rtrim, "$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 Issue #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 Sizzle + * @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; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "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 + /* jshint -W018 */ + 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 Sizzle 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; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, 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; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // 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 ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // 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 ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // 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" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // 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 + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // 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: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + 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 && + 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 && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( 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 Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.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 contains( context, elem ); +}; + +Sizzle.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 (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = 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 += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // 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 ] ) { + Sizzle.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 ] ) { + Sizzle.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 nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "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 = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "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, uniqueCache, 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 ? + node.nodeName.toLowerCase() === 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 + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ 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 ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ 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 ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ 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 + // http://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() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle 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( 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( rtrim, "$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 (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( 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." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.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 === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || 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 + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://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 ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // 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 = argument < 0 ? + argument + length : + argument > length ? + length : + 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(); + +tokenize = Sizzle.tokenize = function( 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 = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + 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 + return parseOnly ? + soFar.length : + soFar ? + Sizzle.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, uniqueCache, 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 ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ 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 + uniqueCache[ 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++ ) { + Sizzle( 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, + 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, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // 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( 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( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #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( rtrim, "$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: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + 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 ) ) { + results.push( 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 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( 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 Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( 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 + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// 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; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +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; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +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 to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#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 Sizzle + 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+ + // 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.stackTrace ); + } + + // 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 stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = 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 master Deferred + master = 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 ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.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$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // 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, stack ); + } +}; + + + + +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 #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 (#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 = Object.create( null ); + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #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 (#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 (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#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 = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#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 or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _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, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#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 (#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 + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +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 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 (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #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 (#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", returnTrue ); + } + + // 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, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + 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 notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // 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 + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // 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.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +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 (#504, #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: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // 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; + }, + + delegateType: delegateType + }; +} ); + +// 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 = /\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 (#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; + + // Reenable 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 { + 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 Sizzle 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 getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #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 (#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! + 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"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // 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, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + 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]).+)/, + rcustomProp = /^--/, + 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; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += 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; +} + +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, + "columnCount": true, + "fillOpacity": 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, + "widows": true, + "zIndex": true, + "zoom": 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 (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#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 )` (#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. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +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 + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#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 classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( 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 (#14686, #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 (#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 + + +support.focusin = "onfocusin" in window; + + +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 (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#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 (#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 ); + } + } +} ); + + +// 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 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + 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 ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +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, + + // #7653, #8125, #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 (#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 #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 (#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 #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 (#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; + + // #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 + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + 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 (#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 + // #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 #8605, #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 ) { + + // #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( "