@yuebai008/cli
Version:
Command line interface for rapid qg-minigame development
1 lines • 11 kB
JavaScript
import*as Common from"../../core/common/common.js";import*as i18n from"../../core/i18n/i18n.js";import*as Platform from"../../core/platform/platform.js";import*as TimelineModel from"../../models/timeline_model/timeline_model.js";import*as TraceEngine from"../../models/trace/trace.js";import*as PerfUI from"../../ui/legacy/components/perf_ui/perf_ui.js";import*as UI from"../../ui/legacy/legacy.js";import{Events}from"./PerformanceModel.js";const UIStrings={jsHeap:"JS Heap",documents:"Documents",nodes:"Nodes",listeners:"Listeners",gpuMemory:"GPU Memory",ss:"[{PH1} – {PH2}]"},str_=i18n.i18n.registerUIStrings("panels/timeline/CountersGraph.ts",UIStrings),i18nString=i18n.i18n.getLocalizedString.bind(void 0,str_);export class CountersGraph extends UI.Widget.VBox{delegate;calculator;model;header;toolbar;graphsContainer;canvasContainer;canvas;timelineGrid;counters;counterUI;countersByName;gpuMemoryCounter;#e=null;currentValuesBar;markerXPosition;constructor(e){super(),this.element.id="memory-graphs-container",this.delegate=e,this.calculator=new Calculator,this.header=new UI.Widget.HBox,this.header.element.classList.add("timeline-memory-header"),this.header.show(this.element),this.toolbar=new UI.Toolbar.Toolbar("timeline-memory-toolbar"),this.header.element.appendChild(this.toolbar.element),this.graphsContainer=new UI.Widget.VBox,this.graphsContainer.show(this.element);const t=new UI.Widget.VBoxWithResizeCallback(this.resize.bind(this));t.show(this.graphsContainer.element),this.createCurrentValuesBar(),this.canvasContainer=t.element,this.canvasContainer.id="memory-graphs-canvas-container",this.canvas=document.createElement("canvas"),this.canvasContainer.appendChild(this.canvas),this.canvas.id="memory-counters-graph",this.canvasContainer.addEventListener("mouseover",this.onMouseMove.bind(this),!0),this.canvasContainer.addEventListener("mousemove",this.onMouseMove.bind(this),!0),this.canvasContainer.addEventListener("mouseleave",this.onMouseLeave.bind(this),!0),this.canvasContainer.addEventListener("click",this.onClick.bind(this),!0),this.timelineGrid=new PerfUI.TimelineGrid.TimelineGrid,this.canvasContainer.appendChild(this.timelineGrid.dividersElement),this.counters=[],this.counterUI=[],this.countersByName=new Map,this.countersByName.set("jsHeapSizeUsed",this.createCounter(i18nString(UIStrings.jsHeap),"hsl(220, 90%, 43%)",Platform.NumberUtilities.bytesToString)),this.countersByName.set("documents",this.createCounter(i18nString(UIStrings.documents),"hsl(0, 90%, 43%)")),this.countersByName.set("nodes",this.createCounter(i18nString(UIStrings.nodes),"hsl(120, 90%, 43%)")),this.countersByName.set("jsEventListeners",this.createCounter(i18nString(UIStrings.listeners),"hsl(38, 90%, 43%)")),this.gpuMemoryCounter=this.createCounter(i18nString(UIStrings.gpuMemory),"hsl(300, 90%, 43%)",Platform.NumberUtilities.bytesToString),this.countersByName.set("gpuMemoryUsedKB",this.gpuMemoryCounter)}setModel(e,t){if(this.#e=t,t){this.model!==e&&(this.model&&this.model.removeEventListener(Events.WindowChanged,this.onWindowChanged,this),this.model=e,this.model&&this.model.addEventListener(Events.WindowChanged,this.onWindowChanged,this)),this.calculator.setZeroTime(e?e.timelineModel().minimumRecordTime():0);for(let e=0;e<this.counters.length;++e)this.counters[e].reset(),this.counterUI[e].reset();this.scheduleRefresh();for(let e=0;e<t.length;++e){const i=t[e];if(i.name!==TimelineModel.TimelineModel.RecordType.UpdateCounters)continue;const s=i.args.data;if(!s)return;for(const e in s){const t=this.countersByName.get(e);if(t){const{startTime:n}=TraceEngine.Legacy.timesForEventInMilliseconds(i);t.appendSample(n,s[e])}}const n="gpuMemoryLimitKB";n in s&&this.gpuMemoryCounter.setLimit(s[n])}}}createCurrentValuesBar(){this.currentValuesBar=this.graphsContainer.element.createChild("div"),this.currentValuesBar.id="counter-values-bar"}createCounter(e,t,i){const s=new Counter;return this.counters.push(s),this.counterUI.push(new CounterUI(this,e,t,s,i)),s}resizerElement(){return this.header.element}resize(){const e=this.canvas.parentElement;this.canvas.width=e.clientWidth*window.devicePixelRatio,this.canvas.height=e.clientHeight*window.devicePixelRatio,this.calculator.setDisplayWidth(this.canvas.width),this.refresh()}onWindowChanged(e){const t=e.data.window;this.calculator.setWindow(t.left,t.right),this.scheduleRefresh()}scheduleRefresh(){UI.UIUtils.invokeOnceAfterBatchUpdate(this,this.refresh)}draw(){this.clear();for(const e of this.counters)e.calculateVisibleIndexes(this.calculator),e.calculateXValues(this.canvas.width);for(const e of this.counterUI)e.drawGraph(this.canvas)}onClick(e){const t=e.x-this.canvasContainer.getBoundingClientRect().left;let i,s=1/0;for(const e of this.counterUI){if(!e.counter.times.length)continue;const n=e.recordIndexAt(t),r=Math.abs(t*window.devicePixelRatio-e.counter.x[n]);r<s&&(s=r,i=e.counter.times[n])}void 0!==i&&this.#e&&this.delegate.selectEntryAtTime(this.#e,i)}onMouseLeave(e){delete this.markerXPosition,this.clearCurrentValueAndMarker()}clearCurrentValueAndMarker(){for(let e=0;e<this.counterUI.length;e++)this.counterUI[e].clearCurrentValueAndMarker()}onMouseMove(e){const t=e.x-this.canvasContainer.getBoundingClientRect().left;this.markerXPosition=t,this.refreshCurrentValues()}refreshCurrentValues(){if(void 0!==this.markerXPosition)for(let e=0;e<this.counterUI.length;++e)this.counterUI[e].updateCurrentValue(this.markerXPosition)}refresh(){this.timelineGrid.updateDividers(this.calculator),this.draw(),this.refreshCurrentValues()}clear(){const e=this.canvas.getContext("2d");if(!e)throw new Error("Unable to get canvas context");e.clearRect(0,0,e.canvas.width,e.canvas.height)}}export class Counter{times;values;x;minimumIndex;maximumIndex;maxTime;minTime;limitValue;constructor(){this.times=[],this.values=[],this.x=[],this.minimumIndex=0,this.maximumIndex=0,this.maxTime=0,this.minTime=0}appendSample(e,t){this.values.length&&this.values[this.values.length-1]===t||(this.times.push(e),this.values.push(t))}reset(){this.times=[],this.values=[]}setLimit(e){this.limitValue=e}calculateBounds(){let e,t;for(let i=this.minimumIndex;i<=this.maximumIndex;i++){const s=this.values[i];(void 0===t||s<t)&&(t=s),(void 0===e||s>e)&&(e=s)}return t=t||0,e=e||1,this.limitValue&&(e>.5*this.limitValue&&(e=Math.max(e,this.limitValue)),t=Math.min(t,this.limitValue)),{min:t,max:e}}calculateVisibleIndexes(e){const t=e.minimumBoundary(),i=e.maximumBoundary();this.minimumIndex=Platform.NumberUtilities.clamp(Platform.ArrayUtilities.upperBound(this.times,t,Platform.ArrayUtilities.DEFAULT_COMPARATOR)-1,0,this.times.length-1),this.maximumIndex=Platform.NumberUtilities.clamp(Platform.ArrayUtilities.lowerBound(this.times,i,Platform.ArrayUtilities.DEFAULT_COMPARATOR),0,this.times.length-1),this.minTime=t,this.maxTime=i}calculateXValues(e){if(!this.values.length)return;const t=e/(this.maxTime-this.minTime);this.x=new Array(this.values.length);for(let e=this.minimumIndex+1;e<=this.maximumIndex;e++)this.x[e]=t*(this.times[e]-this.minTime)}}export class CounterUI{countersPane;counter;formatter;setting;filter;range;value;graphColor;limitColor;graphYValues;verticalPadding;currentValueLabel;marker;constructor(e,t,i,s,n){this.countersPane=e,this.counter=s,this.formatter=n||Platform.NumberUtilities.withThousandsSeparator,this.setting=Common.Settings.Settings.instance().createSetting("timelineCountersGraph-"+t,!0),this.setting.setTitle(t),this.filter=new UI.Toolbar.ToolbarSettingCheckbox(this.setting,t),this.filter.inputElement.classList.add("-theme-preserve-input");const r=Common.Color.parse(i);if(r){const e=r.setAlpha(.5).asString("rgba"),t=this.filter.element;e&&(t.style.backgroundColor=e),t.style.borderColor="transparent"}this.filter.inputElement.addEventListener("click",this.toggleCounterGraph.bind(this)),e.toolbar.appendToolbarItem(this.filter),this.range=this.filter.element.createChild("span","range"),this.value=e.currentValuesBar.createChild("span","memory-counter-value"),this.value.style.color=i,this.graphColor=i,r&&(this.limitColor=r.setAlpha(.3).asString("rgba")),this.graphYValues=[],this.verticalPadding=10,this.currentValueLabel=t,this.marker=e.canvasContainer.createChild("div","memory-counter-marker"),this.marker.style.backgroundColor=i,this.clearCurrentValueAndMarker()}reset(){this.range.textContent=""}setRange(e,t){const i=this.formatter(e),s=this.formatter(t);this.range.textContent=i18nString(UIStrings.ss,{PH1:i,PH2:s})}toggleCounterGraph(){this.value.classList.toggle("hidden",!this.filter.checked()),this.countersPane.refresh()}recordIndexAt(e){return Platform.ArrayUtilities.upperBound(this.counter.x,e*window.devicePixelRatio,Platform.ArrayUtilities.DEFAULT_COMPARATOR,this.counter.minimumIndex+1,this.counter.maximumIndex+1)-1}updateCurrentValue(e){if(!this.visible()||!this.counter.values.length||!this.counter.x)return;const t=this.recordIndexAt(e),i=Platform.NumberUtilities.withThousandsSeparator(this.counter.values[t]);this.value.textContent=`${this.currentValueLabel}: ${i}`;const s=this.graphYValues[t]/window.devicePixelRatio;this.marker.style.left=e+"px",this.marker.style.top=s+"px",this.marker.classList.remove("hidden")}clearCurrentValueAndMarker(){this.value.textContent="",this.marker.classList.add("hidden")}drawGraph(e){const t=e.getContext("2d");if(!t)throw new Error("Unable to get canvas context");const i=e.width,s=e.height-2*this.verticalPadding;if(s<=0)return void(this.graphYValues=[]);const n=this.verticalPadding,r=this.counter,a=r.values;if(!a.length)return;const o=r.calculateBounds(),l=o.min,h=o.max;if(this.setRange(l,h),!this.visible())return;const m=this.graphYValues,u=h-l,c=u?s/u:1;t.save(),t.lineWidth=window.devicePixelRatio,t.lineWidth%2&&t.translate(.5,.5),t.beginPath();let d=a[r.minimumIndex],g=Math.round(n+s-(d-l)*c);t.moveTo(0,g);let p=r.minimumIndex;for(;p<=r.maximumIndex;p++){const e=Math.round(r.x[p]);t.lineTo(e,g);const i=a[p];void 0!==i&&(d=i),g=Math.round(n+s-(d-l)*c),t.lineTo(e,g),m[p]=g}if(m.length=p,t.lineTo(i,g),t.strokeStyle=this.graphColor,t.stroke(),r.limitValue){const e=Math.round(n+s-(r.limitValue-l)*c);t.moveTo(0,e),t.lineTo(i,e),this.limitColor&&(t.strokeStyle=this.limitColor),t.stroke()}t.closePath(),t.restore()}visible(){return this.filter.checked()}}export class Calculator{minimumBoundaryInternal;maximumBoundaryInternal;workingArea;zeroTimeInternal;constructor(){this.minimumBoundaryInternal=0,this.maximumBoundaryInternal=0,this.workingArea=0,this.zeroTimeInternal=0}setZeroTime(e){this.zeroTimeInternal=e}computePosition(e){return(e-this.minimumBoundaryInternal)/this.boundarySpan()*this.workingArea}setWindow(e,t){this.minimumBoundaryInternal=e,this.maximumBoundaryInternal=t}setDisplayWidth(e){this.workingArea=e}formatValue(e,t){return i18n.TimeUtilities.preciseMillisToString(e-this.zeroTime(),t)}maximumBoundary(){return this.maximumBoundaryInternal}minimumBoundary(){return this.minimumBoundaryInternal}zeroTime(){return this.zeroTimeInternal}boundarySpan(){return this.maximumBoundaryInternal-this.minimumBoundaryInternal}}