1 |
- {"ast":null,"code":"import { EventState, Observable } from \"../observable.js\";\nimport { PrecisionDate } from \"../precisionDate.js\";\nimport { Tools } from \"../tools.js\";\nimport { DynamicFloat32Array } from \"./dynamicFloat32Array.js\";\n// the initial size of our array, should be a multiple of two!\nconst InitialArraySize = 1800;\n// three octets in a hexcode. #[AA][BB][CC], i.e. 24 bits of data.\nconst NumberOfBitsInHexcode = 24;\n// Allows single numeral hex numbers to be appended by a 0.\nconst HexPadding = \"0\";\n// header for the timestamp column\nconst TimestampColHeader = \"timestamp\";\n// header for the numPoints column\nconst NumPointsColHeader = \"numPoints\";\n// regex to capture all carriage returns in the string.\nconst CarriageReturnRegex = /\\r/g;\n// string to use as separator when exporting extra information along with the dataset id\nconst ExportedDataSeparator = \"@\";\n/**\n * The collector class handles the collection and storage of data into the appropriate array.\n * The collector also handles notifying any observers of any updates.\n */\nexport class PerformanceViewerCollector {\n /**\n * The offset for when actual data values start appearing inside a slice.\n */\n static get SliceDataOffset() {\n return 2;\n }\n /**\n * The offset for the value of the number of points inside a slice.\n */\n static get NumberOfPointsOffset() {\n return 1;\n }\n /**\n * Handles the creation of a performance viewer collector.\n * @param _scene the scene to collect on.\n * @param _enabledStrategyCallbacks the list of data to collect with callbacks for initialization purposes.\n */\n constructor(_scene, _enabledStrategyCallbacks) {\n this._scene = _scene;\n /**\n * Collects data for every dataset by using the appropriate strategy. This is called every frame.\n * This method will then notify all observers with the latest slice.\n */\n this._collectDataAtFrame = () => {\n const timestamp = PrecisionDate.Now - this._startingTimestamp;\n const numPoints = this.datasets.ids.length;\n // add the starting index for the slice\n const numberOfIndices = this.datasets.startingIndices.itemLength;\n let startingIndex = 0;\n if (numberOfIndices > 0) {\n const previousStartingIndex = this.datasets.startingIndices.at(numberOfIndices - 1);\n startingIndex = previousStartingIndex + this.datasets.data.at(previousStartingIndex + PerformanceViewerCollector.NumberOfPointsOffset) + PerformanceViewerCollector.SliceDataOffset;\n }\n this.datasets.startingIndices.push(startingIndex);\n // add the first 2 items in our slice.\n this.datasets.data.push(timestamp);\n this.datasets.data.push(numPoints);\n // add the values inside the slice.\n this.datasets.ids.forEach(id => {\n const strategy = this._strategies.get(id);\n if (!strategy) {\n return;\n }\n this.datasets.data.push(strategy.getData());\n });\n if (this.datasetObservable.hasObservers()) {\n const slice = [timestamp, numPoints];\n for (let i = 0; i < numPoints; i++) {\n slice.push(this.datasets.data.at(startingIndex + PerformanceViewerCollector.SliceDataOffset + i));\n }\n this.datasetObservable.notifyObservers(slice);\n }\n };\n this.datasets = {\n ids: [],\n data: new DynamicFloat32Array(InitialArraySize),\n startingIndices: new DynamicFloat32Array(InitialArraySize)\n };\n this._strategies = new Map();\n this._datasetMeta = new Map();\n this._eventRestoreSet = new Set();\n this._customEventObservable = new Observable();\n this.datasetObservable = new Observable();\n this.metadataObservable = new Observable(observer => observer.callback(this._datasetMeta, new EventState(0)));\n if (_enabledStrategyCallbacks) {\n this.addCollectionStrategies(..._enabledStrategyCallbacks);\n }\n }\n /**\n * Registers a custom string event which will be callable via sendEvent. This method returns an event object which will contain the id of the event.\n * The user can set a value optionally, which will be used in the sendEvent method. If the value is set, we will record this value at the end of each frame,\n * if not we will increment our counter and record the value of the counter at the end of each frame. The value recorded is 0 if no sendEvent method is called, within a frame.\n * @param name The name of the event to register\n * @param forceUpdate if the code should force add an event, and replace the last one.\n * @param category the category for that event\n * @returns The event registered, used in sendEvent\n */\n registerEvent(name, forceUpdate, category) {\n if (this._strategies.has(name) && !forceUpdate) {\n return;\n }\n if (this._strategies.has(name) && forceUpdate) {\n var _this$_strategies$get;\n (_this$_strategies$get = this._strategies.get(name)) === null || _this$_strategies$get === void 0 || _this$_strategies$get.dispose();\n this._strategies.delete(name);\n }\n const strategy = scene => {\n let counter = 0;\n let value = 0;\n const afterRenderObserver = scene.onAfterRenderObservable.add(() => {\n value = counter;\n counter = 0;\n });\n const stringObserver = this._customEventObservable.add(eventVal => {\n if (name !== eventVal.name) {\n return;\n }\n if (eventVal.value !== undefined) {\n counter = eventVal.value;\n } else {\n counter++;\n }\n });\n return {\n id: name,\n getData: () => value,\n dispose: () => {\n scene.onAfterRenderObservable.remove(afterRenderObserver);\n this._customEventObservable.remove(stringObserver);\n }\n };\n };\n const event = {\n name\n };\n this._eventRestoreSet.add(name);\n this.addCollectionStrategies({\n strategyCallback: strategy,\n category\n });\n return event;\n }\n /**\n * Lets the perf collector handle an event, occurences or event value depending on if the event.value params is set.\n * @param event the event to handle an occurence for\n */\n sendEvent(event) {\n this._customEventObservable.notifyObservers(event);\n }\n /**\n * This event restores all custom string events if necessary.\n */\n _restoreStringEvents() {\n if (this._eventRestoreSet.size !== this._customEventObservable.observers.length) {\n this._eventRestoreSet.forEach(event => {\n this.registerEvent(event, true);\n });\n }\n }\n /**\n * This method adds additional collection strategies for data collection purposes.\n * @param strategyCallbacks the list of data to collect with callbacks.\n */\n addCollectionStrategies(...strategyCallbacks) {\n // eslint-disable-next-line prefer-const\n for (let {\n strategyCallback,\n category,\n hidden\n } of strategyCallbacks) {\n const strategy = strategyCallback(this._scene);\n if (this._strategies.has(strategy.id)) {\n strategy.dispose();\n continue;\n }\n this.datasets.ids.push(strategy.id);\n if (category) {\n category = category.replace(new RegExp(ExportedDataSeparator, \"g\"), \"\");\n }\n this._datasetMeta.set(strategy.id, {\n color: this._getHexColorFromId(strategy.id),\n category,\n hidden\n });\n this._strategies.set(strategy.id, strategy);\n }\n this.metadataObservable.notifyObservers(this._datasetMeta);\n }\n /**\n * Gets a 6 character hexcode representing the colour from a passed in string.\n * @param id the string to get a hex code for.\n * @returns a hexcode hashed from the id.\n */\n _getHexColorFromId(id) {\n // this first bit is just a known way of hashing a string.\n let hash = 0;\n for (let i = 0; i < id.length; i++) {\n // (hash << 5) - hash is the same as hash * 31\n hash = id.charCodeAt(i) + ((hash << 5) - hash);\n }\n // then we build the string octet by octet.\n let hex = \"#\";\n for (let i = 0; i < NumberOfBitsInHexcode; i += 8) {\n const octet = hash >> i & 0xff;\n const toStr = HexPadding + octet.toString(16);\n hex += toStr.substring(toStr.length - 2);\n }\n return hex;\n }\n /**\n * Collects and then sends the latest slice to any observers by using the appropriate strategy when the user wants.\n * The slice will be of the form [timestamp, numberOfPoints, value1, value2...]\n * This method does not add onto the collected data accessible via the datasets variable.\n */\n getCurrentSlice() {\n const timestamp = PrecisionDate.Now - this._startingTimestamp;\n const numPoints = this.datasets.ids.length;\n const slice = [timestamp, numPoints];\n // add the values inside the slice.\n this.datasets.ids.forEach(id => {\n const strategy = this._strategies.get(id);\n if (!strategy) {\n return;\n }\n if (this.datasetObservable.hasObservers()) {\n slice.push(strategy.getData());\n }\n });\n if (this.datasetObservable.hasObservers()) {\n this.datasetObservable.notifyObservers(slice);\n }\n }\n /**\n * Updates a property for a dataset's metadata with the value provided.\n * @param id the id of the dataset which needs its metadata updated.\n * @param prop the property to update.\n * @param value the value to update the property with.\n */\n updateMetadata(id, prop, value) {\n const meta = this._datasetMeta.get(id);\n if (!meta) {\n return;\n }\n meta[prop] = value;\n this.metadataObservable.notifyObservers(this._datasetMeta);\n }\n /**\n * Completely clear, data, ids, and strategies saved to this performance collector.\n * @param preserveStringEventsRestore if it should preserve the string events, by default will clear string events registered when called.\n */\n clear(preserveStringEventsRestore) {\n this.datasets.data = new DynamicFloat32Array(InitialArraySize);\n this.datasets.ids.length = 0;\n this.datasets.startingIndices = new DynamicFloat32Array(InitialArraySize);\n this._datasetMeta.clear();\n this._strategies.forEach(strategy => strategy.dispose());\n this._strategies.clear();\n if (!preserveStringEventsRestore) {\n this._eventRestoreSet.clear();\n }\n this._hasLoadedData = false;\n }\n /**\n * Accessor which lets the caller know if the performance collector has data loaded from a file or not!\n * Call clear() to reset this value.\n * @returns true if the data is loaded from a file, false otherwise.\n */\n get hasLoadedData() {\n return this._hasLoadedData;\n }\n /**\n * Given a string containing file data, this function parses the file data into the datasets object.\n * It returns a boolean to indicate if this object was successfully loaded with the data.\n * @param data string content representing the file data.\n * @param keepDatasetMeta if it should use reuse the existing dataset metadata\n * @returns true if the data was successfully loaded, false otherwise.\n */\n loadFromFileData(data, keepDatasetMeta) {\n const lines = data.replace(CarriageReturnRegex, \"\").split(\"\\n\").map(line => line.split(\",\").filter(s => s.length > 0)).filter(line => line.length > 0);\n const timestampIndex = 0;\n const numPointsIndex = PerformanceViewerCollector.NumberOfPointsOffset;\n if (lines.length < 2) {\n return false;\n }\n const parsedDatasets = {\n ids: [],\n data: new DynamicFloat32Array(InitialArraySize),\n startingIndices: new DynamicFloat32Array(InitialArraySize)\n };\n // parse first line separately to populate ids!\n const [firstLine, ...dataLines] = lines;\n // make sure we have the correct beginning headers\n if (firstLine.length < 2 || firstLine[timestampIndex] !== TimestampColHeader || firstLine[numPointsIndex] !== NumPointsColHeader) {\n return false;\n }\n const idCategoryMap = new Map();\n // populate the ids.\n for (let i = PerformanceViewerCollector.SliceDataOffset; i < firstLine.length; i++) {\n const [id, category] = firstLine[i].split(ExportedDataSeparator);\n parsedDatasets.ids.push(id);\n idCategoryMap.set(id, category);\n }\n let startingIndex = 0;\n for (const line of dataLines) {\n if (line.length < 2) {\n return false;\n }\n const timestamp = parseFloat(line[timestampIndex]);\n const numPoints = parseInt(line[numPointsIndex]);\n if (isNaN(numPoints) || isNaN(timestamp)) {\n return false;\n }\n parsedDatasets.data.push(timestamp);\n parsedDatasets.data.push(numPoints);\n if (numPoints + PerformanceViewerCollector.SliceDataOffset !== line.length) {\n return false;\n }\n for (let i = PerformanceViewerCollector.SliceDataOffset; i < line.length; i++) {\n const val = parseFloat(line[i]);\n if (isNaN(val)) {\n return false;\n }\n parsedDatasets.data.push(val);\n }\n parsedDatasets.startingIndices.push(startingIndex);\n startingIndex += line.length;\n }\n this.datasets.ids = parsedDatasets.ids;\n this.datasets.data = parsedDatasets.data;\n this.datasets.startingIndices = parsedDatasets.startingIndices;\n if (!keepDatasetMeta) {\n this._datasetMeta.clear();\n }\n this._strategies.forEach(strategy => strategy.dispose());\n this._strategies.clear();\n // populate metadata.\n if (!keepDatasetMeta) {\n for (const id of this.datasets.ids) {\n const category = idCategoryMap.get(id);\n this._datasetMeta.set(id, {\n category,\n color: this._getHexColorFromId(id)\n });\n }\n }\n this.metadataObservable.notifyObservers(this._datasetMeta);\n this._hasLoadedData = true;\n return true;\n }\n /**\n * Exports the datasets inside of the collector to a csv.\n */\n exportDataToCsv() {\n let csvContent = \"\";\n // create the header line.\n csvContent += `${TimestampColHeader},${NumPointsColHeader}`;\n for (let i = 0; i < this.datasets.ids.length; i++) {\n csvContent += `,${this.datasets.ids[i]}`;\n if (this._datasetMeta) {\n const meta = this._datasetMeta.get(this.datasets.ids[i]);\n if (meta !== null && meta !== void 0 && meta.category) {\n csvContent += `${ExportedDataSeparator}${meta.category}`;\n }\n }\n }\n csvContent += \"\\n\";\n // create the data lines\n for (let i = 0; i < this.datasets.startingIndices.itemLength; i++) {\n const startingIndex = this.datasets.startingIndices.at(i);\n const timestamp = this.datasets.data.at(startingIndex);\n const numPoints = this.datasets.data.at(startingIndex + PerformanceViewerCollector.NumberOfPointsOffset);\n csvContent += `${timestamp},${numPoints}`;\n for (let offset = 0; offset < numPoints; offset++) {\n csvContent += `,${this.datasets.data.at(startingIndex + PerformanceViewerCollector.SliceDataOffset + offset)}`;\n }\n // add extra commas.\n for (let diff = 0; diff < this.datasets.ids.length - numPoints; diff++) {\n csvContent += \",\";\n }\n csvContent += \"\\n\";\n }\n const fileName = `${new Date().toISOString()}-perfdata.csv`;\n Tools.Download(new Blob([csvContent], {\n type: \"text/csv\"\n }), fileName);\n }\n /**\n * Starts the realtime collection of data.\n * @param shouldPreserve optional boolean param, if set will preserve the dataset between calls of start.\n */\n start(shouldPreserve) {\n if (!shouldPreserve) {\n this.datasets.data = new DynamicFloat32Array(InitialArraySize);\n this.datasets.startingIndices = new DynamicFloat32Array(InitialArraySize);\n this._startingTimestamp = PrecisionDate.Now;\n } else if (this._startingTimestamp === undefined) {\n this._startingTimestamp = PrecisionDate.Now;\n }\n this._scene.onAfterRenderObservable.add(this._collectDataAtFrame);\n this._restoreStringEvents();\n this._isStarted = true;\n }\n /**\n * Stops the collection of data.\n */\n stop() {\n this._scene.onAfterRenderObservable.removeCallback(this._collectDataAtFrame);\n this._isStarted = false;\n }\n /**\n * Returns if the perf collector has been started or not.\n */\n get isStarted() {\n return this._isStarted;\n }\n /**\n * Disposes of the object\n */\n dispose() {\n this._scene.onAfterRenderObservable.removeCallback(this._collectDataAtFrame);\n this._datasetMeta.clear();\n this._strategies.forEach(strategy => {\n strategy.dispose();\n });\n this.datasetObservable.clear();\n this.metadataObservable.clear();\n this._isStarted = false;\n this.datasets = null;\n }\n}","map":{"version":3,"names":["EventState","Observable","PrecisionDate","Tools","DynamicFloat32Array","InitialArraySize","NumberOfBitsInHexcode","HexPadding","TimestampColHeader","NumPointsColHeader","CarriageReturnRegex","ExportedDataSeparator","PerformanceViewerCollector","SliceDataOffset","NumberOfPointsOffset","constructor","_scene","_enabledStrategyCallbacks","_collectDataAtFrame","timestamp","Now","_startingTimestamp","numPoints","datasets","ids","length","numberOfIndices","startingIndices","itemLength","startingIndex","previousStartingIndex","at","data","push","forEach","id","strategy","_strategies","get","getData","datasetObservable","hasObservers","slice","i","notifyObservers","Map","_datasetMeta","_eventRestoreSet","Set","_customEventObservable","metadataObservable","observer","callback","addCollectionStrategies","registerEvent","name","forceUpdate","category","has","_this$_strategies$get","dispose","delete","scene","counter","value","afterRenderObserver","onAfterRenderObservable","add","stringObserver","eventVal","undefined","remove","event","strategyCallback","sendEvent","_restoreStringEvents","size","observers","strategyCallbacks","hidden","replace","RegExp","set","color","_getHexColorFromId","hash","charCodeAt","hex","octet","toStr","toString","substring","getCurrentSlice","updateMetadata","prop","meta","clear","preserveStringEventsRestore","_hasLoadedData","hasLoadedData","loadFromFileData","keepDatasetMeta","lines","split","map","line","filter","s","timestampIndex","numPointsIndex","parsedDatasets","firstLine","dataLines","idCategoryMap","parseFloat","parseInt","isNaN","val","exportDataToCsv","csvContent","offset","diff","fileName","Date","toISOString","Download","Blob","type","start","shouldPreserve","_isStarted","stop","removeCallback","isStarted"],"sources":["F:/workspace/202226701027/huinongbao-app/node_modules/@babylonjs/core/Misc/PerformanceViewer/performanceViewerCollector.js"],"sourcesContent":["import { EventState, Observable } from \"../observable.js\";\nimport { PrecisionDate } from \"../precisionDate.js\";\nimport { Tools } from \"../tools.js\";\nimport { DynamicFloat32Array } from \"./dynamicFloat32Array.js\";\n// the initial size of our array, should be a multiple of two!\nconst InitialArraySize = 1800;\n// three octets in a hexcode. #[AA][BB][CC], i.e. 24 bits of data.\nconst NumberOfBitsInHexcode = 24;\n// Allows single numeral hex numbers to be appended by a 0.\nconst HexPadding = \"0\";\n// header for the timestamp column\nconst TimestampColHeader = \"timestamp\";\n// header for the numPoints column\nconst NumPointsColHeader = \"numPoints\";\n// regex to capture all carriage returns in the string.\nconst CarriageReturnRegex = /\\r/g;\n// string to use as separator when exporting extra information along with the dataset id\nconst ExportedDataSeparator = \"@\";\n/**\n * The collector class handles the collection and storage of data into the appropriate array.\n * The collector also handles notifying any observers of any updates.\n */\nexport class PerformanceViewerCollector {\n /**\n * The offset for when actual data values start appearing inside a slice.\n */\n static get SliceDataOffset() {\n return 2;\n }\n /**\n * The offset for the value of the number of points inside a slice.\n */\n static get NumberOfPointsOffset() {\n return 1;\n }\n /**\n * Handles the creation of a performance viewer collector.\n * @param _scene the scene to collect on.\n * @param _enabledStrategyCallbacks the list of data to collect with callbacks for initialization purposes.\n */\n constructor(_scene, _enabledStrategyCallbacks) {\n this._scene = _scene;\n /**\n * Collects data for every dataset by using the appropriate strategy. This is called every frame.\n * This method will then notify all observers with the latest slice.\n */\n this._collectDataAtFrame = () => {\n const timestamp = PrecisionDate.Now - this._startingTimestamp;\n const numPoints = this.datasets.ids.length;\n // add the starting index for the slice\n const numberOfIndices = this.datasets.startingIndices.itemLength;\n let startingIndex = 0;\n if (numberOfIndices > 0) {\n const previousStartingIndex = this.datasets.startingIndices.at(numberOfIndices - 1);\n startingIndex =\n previousStartingIndex + this.datasets.data.at(previousStartingIndex + PerformanceViewerCollector.NumberOfPointsOffset) + PerformanceViewerCollector.SliceDataOffset;\n }\n this.datasets.startingIndices.push(startingIndex);\n // add the first 2 items in our slice.\n this.datasets.data.push(timestamp);\n this.datasets.data.push(numPoints);\n // add the values inside the slice.\n this.datasets.ids.forEach((id) => {\n const strategy = this._strategies.get(id);\n if (!strategy) {\n return;\n }\n this.datasets.data.push(strategy.getData());\n });\n if (this.datasetObservable.hasObservers()) {\n const slice = [timestamp, numPoints];\n for (let i = 0; i < numPoints; i++) {\n slice.push(this.datasets.data.at(startingIndex + PerformanceViewerCollector.SliceDataOffset + i));\n }\n this.datasetObservable.notifyObservers(slice);\n }\n };\n this.datasets = {\n ids: [],\n data: new DynamicFloat32Array(InitialArraySize),\n startingIndices: new DynamicFloat32Array(InitialArraySize),\n };\n this._strategies = new Map();\n this._datasetMeta = new Map();\n this._eventRestoreSet = new Set();\n this._customEventObservable = new Observable();\n this.datasetObservable = new Observable();\n this.metadataObservable = new Observable((observer) => observer.callback(this._datasetMeta, new EventState(0)));\n if (_enabledStrategyCallbacks) {\n this.addCollectionStrategies(..._enabledStrategyCallbacks);\n }\n }\n /**\n * Registers a custom string event which will be callable via sendEvent. This method returns an event object which will contain the id of the event.\n * The user can set a value optionally, which will be used in the sendEvent method. If the value is set, we will record this value at the end of each frame,\n * if not we will increment our counter and record the value of the counter at the end of each frame. The value recorded is 0 if no sendEvent method is called, within a frame.\n * @param name The name of the event to register\n * @param forceUpdate if the code should force add an event, and replace the last one.\n * @param category the category for that event\n * @returns The event registered, used in sendEvent\n */\n registerEvent(name, forceUpdate, category) {\n if (this._strategies.has(name) && !forceUpdate) {\n return;\n }\n if (this._strategies.has(name) && forceUpdate) {\n this._strategies.get(name)?.dispose();\n this._strategies.delete(name);\n }\n const strategy = (scene) => {\n let counter = 0;\n let value = 0;\n const afterRenderObserver = scene.onAfterRenderObservable.add(() => {\n value = counter;\n counter = 0;\n });\n const stringObserver = this._customEventObservable.add((eventVal) => {\n if (name !== eventVal.name) {\n return;\n }\n if (eventVal.value !== undefined) {\n counter = eventVal.value;\n }\n else {\n counter++;\n }\n });\n return {\n id: name,\n getData: () => value,\n dispose: () => {\n scene.onAfterRenderObservable.remove(afterRenderObserver);\n this._customEventObservable.remove(stringObserver);\n },\n };\n };\n const event = {\n name,\n };\n this._eventRestoreSet.add(name);\n this.addCollectionStrategies({ strategyCallback: strategy, category });\n return event;\n }\n /**\n * Lets the perf collector handle an event, occurences or event value depending on if the event.value params is set.\n * @param event the event to handle an occurence for\n */\n sendEvent(event) {\n this._customEventObservable.notifyObservers(event);\n }\n /**\n * This event restores all custom string events if necessary.\n */\n _restoreStringEvents() {\n if (this._eventRestoreSet.size !== this._customEventObservable.observers.length) {\n this._eventRestoreSet.forEach((event) => {\n this.registerEvent(event, true);\n });\n }\n }\n /**\n * This method adds additional collection strategies for data collection purposes.\n * @param strategyCallbacks the list of data to collect with callbacks.\n */\n addCollectionStrategies(...strategyCallbacks) {\n // eslint-disable-next-line prefer-const\n for (let { strategyCallback, category, hidden } of strategyCallbacks) {\n const strategy = strategyCallback(this._scene);\n if (this._strategies.has(strategy.id)) {\n strategy.dispose();\n continue;\n }\n this.datasets.ids.push(strategy.id);\n if (category) {\n category = category.replace(new RegExp(ExportedDataSeparator, \"g\"), \"\");\n }\n this._datasetMeta.set(strategy.id, {\n color: this._getHexColorFromId(strategy.id),\n category,\n hidden,\n });\n this._strategies.set(strategy.id, strategy);\n }\n this.metadataObservable.notifyObservers(this._datasetMeta);\n }\n /**\n * Gets a 6 character hexcode representing the colour from a passed in string.\n * @param id the string to get a hex code for.\n * @returns a hexcode hashed from the id.\n */\n _getHexColorFromId(id) {\n // this first bit is just a known way of hashing a string.\n let hash = 0;\n for (let i = 0; i < id.length; i++) {\n // (hash << 5) - hash is the same as hash * 31\n hash = id.charCodeAt(i) + ((hash << 5) - hash);\n }\n // then we build the string octet by octet.\n let hex = \"#\";\n for (let i = 0; i < NumberOfBitsInHexcode; i += 8) {\n const octet = (hash >> i) & 0xff;\n const toStr = HexPadding + octet.toString(16);\n hex += toStr.substring(toStr.length - 2);\n }\n return hex;\n }\n /**\n * Collects and then sends the latest slice to any observers by using the appropriate strategy when the user wants.\n * The slice will be of the form [timestamp, numberOfPoints, value1, value2...]\n * This method does not add onto the collected data accessible via the datasets variable.\n */\n getCurrentSlice() {\n const timestamp = PrecisionDate.Now - this._startingTimestamp;\n const numPoints = this.datasets.ids.length;\n const slice = [timestamp, numPoints];\n // add the values inside the slice.\n this.datasets.ids.forEach((id) => {\n const strategy = this._strategies.get(id);\n if (!strategy) {\n return;\n }\n if (this.datasetObservable.hasObservers()) {\n slice.push(strategy.getData());\n }\n });\n if (this.datasetObservable.hasObservers()) {\n this.datasetObservable.notifyObservers(slice);\n }\n }\n /**\n * Updates a property for a dataset's metadata with the value provided.\n * @param id the id of the dataset which needs its metadata updated.\n * @param prop the property to update.\n * @param value the value to update the property with.\n */\n updateMetadata(id, prop, value) {\n const meta = this._datasetMeta.get(id);\n if (!meta) {\n return;\n }\n meta[prop] = value;\n this.metadataObservable.notifyObservers(this._datasetMeta);\n }\n /**\n * Completely clear, data, ids, and strategies saved to this performance collector.\n * @param preserveStringEventsRestore if it should preserve the string events, by default will clear string events registered when called.\n */\n clear(preserveStringEventsRestore) {\n this.datasets.data = new DynamicFloat32Array(InitialArraySize);\n this.datasets.ids.length = 0;\n this.datasets.startingIndices = new DynamicFloat32Array(InitialArraySize);\n this._datasetMeta.clear();\n this._strategies.forEach((strategy) => strategy.dispose());\n this._strategies.clear();\n if (!preserveStringEventsRestore) {\n this._eventRestoreSet.clear();\n }\n this._hasLoadedData = false;\n }\n /**\n * Accessor which lets the caller know if the performance collector has data loaded from a file or not!\n * Call clear() to reset this value.\n * @returns true if the data is loaded from a file, false otherwise.\n */\n get hasLoadedData() {\n return this._hasLoadedData;\n }\n /**\n * Given a string containing file data, this function parses the file data into the datasets object.\n * It returns a boolean to indicate if this object was successfully loaded with the data.\n * @param data string content representing the file data.\n * @param keepDatasetMeta if it should use reuse the existing dataset metadata\n * @returns true if the data was successfully loaded, false otherwise.\n */\n loadFromFileData(data, keepDatasetMeta) {\n const lines = data\n .replace(CarriageReturnRegex, \"\")\n .split(\"\\n\")\n .map((line) => line.split(\",\").filter((s) => s.length > 0))\n .filter((line) => line.length > 0);\n const timestampIndex = 0;\n const numPointsIndex = PerformanceViewerCollector.NumberOfPointsOffset;\n if (lines.length < 2) {\n return false;\n }\n const parsedDatasets = {\n ids: [],\n data: new DynamicFloat32Array(InitialArraySize),\n startingIndices: new DynamicFloat32Array(InitialArraySize),\n };\n // parse first line separately to populate ids!\n const [firstLine, ...dataLines] = lines;\n // make sure we have the correct beginning headers\n if (firstLine.length < 2 || firstLine[timestampIndex] !== TimestampColHeader || firstLine[numPointsIndex] !== NumPointsColHeader) {\n return false;\n }\n const idCategoryMap = new Map();\n // populate the ids.\n for (let i = PerformanceViewerCollector.SliceDataOffset; i < firstLine.length; i++) {\n const [id, category] = firstLine[i].split(ExportedDataSeparator);\n parsedDatasets.ids.push(id);\n idCategoryMap.set(id, category);\n }\n let startingIndex = 0;\n for (const line of dataLines) {\n if (line.length < 2) {\n return false;\n }\n const timestamp = parseFloat(line[timestampIndex]);\n const numPoints = parseInt(line[numPointsIndex]);\n if (isNaN(numPoints) || isNaN(timestamp)) {\n return false;\n }\n parsedDatasets.data.push(timestamp);\n parsedDatasets.data.push(numPoints);\n if (numPoints + PerformanceViewerCollector.SliceDataOffset !== line.length) {\n return false;\n }\n for (let i = PerformanceViewerCollector.SliceDataOffset; i < line.length; i++) {\n const val = parseFloat(line[i]);\n if (isNaN(val)) {\n return false;\n }\n parsedDatasets.data.push(val);\n }\n parsedDatasets.startingIndices.push(startingIndex);\n startingIndex += line.length;\n }\n this.datasets.ids = parsedDatasets.ids;\n this.datasets.data = parsedDatasets.data;\n this.datasets.startingIndices = parsedDatasets.startingIndices;\n if (!keepDatasetMeta) {\n this._datasetMeta.clear();\n }\n this._strategies.forEach((strategy) => strategy.dispose());\n this._strategies.clear();\n // populate metadata.\n if (!keepDatasetMeta) {\n for (const id of this.datasets.ids) {\n const category = idCategoryMap.get(id);\n this._datasetMeta.set(id, { category, color: this._getHexColorFromId(id) });\n }\n }\n this.metadataObservable.notifyObservers(this._datasetMeta);\n this._hasLoadedData = true;\n return true;\n }\n /**\n * Exports the datasets inside of the collector to a csv.\n */\n exportDataToCsv() {\n let csvContent = \"\";\n // create the header line.\n csvContent += `${TimestampColHeader},${NumPointsColHeader}`;\n for (let i = 0; i < this.datasets.ids.length; i++) {\n csvContent += `,${this.datasets.ids[i]}`;\n if (this._datasetMeta) {\n const meta = this._datasetMeta.get(this.datasets.ids[i]);\n if (meta?.category) {\n csvContent += `${ExportedDataSeparator}${meta.category}`;\n }\n }\n }\n csvContent += \"\\n\";\n // create the data lines\n for (let i = 0; i < this.datasets.startingIndices.itemLength; i++) {\n const startingIndex = this.datasets.startingIndices.at(i);\n const timestamp = this.datasets.data.at(startingIndex);\n const numPoints = this.datasets.data.at(startingIndex + PerformanceViewerCollector.NumberOfPointsOffset);\n csvContent += `${timestamp},${numPoints}`;\n for (let offset = 0; offset < numPoints; offset++) {\n csvContent += `,${this.datasets.data.at(startingIndex + PerformanceViewerCollector.SliceDataOffset + offset)}`;\n }\n // add extra commas.\n for (let diff = 0; diff < this.datasets.ids.length - numPoints; diff++) {\n csvContent += \",\";\n }\n csvContent += \"\\n\";\n }\n const fileName = `${new Date().toISOString()}-perfdata.csv`;\n Tools.Download(new Blob([csvContent], { type: \"text/csv\" }), fileName);\n }\n /**\n * Starts the realtime collection of data.\n * @param shouldPreserve optional boolean param, if set will preserve the dataset between calls of start.\n */\n start(shouldPreserve) {\n if (!shouldPreserve) {\n this.datasets.data = new DynamicFloat32Array(InitialArraySize);\n this.datasets.startingIndices = new DynamicFloat32Array(InitialArraySize);\n this._startingTimestamp = PrecisionDate.Now;\n }\n else if (this._startingTimestamp === undefined) {\n this._startingTimestamp = PrecisionDate.Now;\n }\n this._scene.onAfterRenderObservable.add(this._collectDataAtFrame);\n this._restoreStringEvents();\n this._isStarted = true;\n }\n /**\n * Stops the collection of data.\n */\n stop() {\n this._scene.onAfterRenderObservable.removeCallback(this._collectDataAtFrame);\n this._isStarted = false;\n }\n /**\n * Returns if the perf collector has been started or not.\n */\n get isStarted() {\n return this._isStarted;\n }\n /**\n * Disposes of the object\n */\n dispose() {\n this._scene.onAfterRenderObservable.removeCallback(this._collectDataAtFrame);\n this._datasetMeta.clear();\n this._strategies.forEach((strategy) => {\n strategy.dispose();\n });\n this.datasetObservable.clear();\n this.metadataObservable.clear();\n this._isStarted = false;\n this.datasets = null;\n }\n}\n"],"mappings":"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","ignoreList":[]},"metadata":{},"sourceType":"module","externalDependencies":[]}
|