diff --git a/extensions/community/PerformanceMonitor.json b/extensions/community/PerformanceMonitor.json new file mode 100644 index 000000000..a33ba55d9 --- /dev/null +++ b/extensions/community/PerformanceMonitor.json @@ -0,0 +1,238 @@ +{ + "author": "Eldarduil", + "category": "Dev Tools", + "extensionNamespace": "PerformanceMonitor", + "fullName": "Performance Monitor", + "gdevelopVersion": "", + "helpPath": "", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0ibWRpLWNoYXJ0LWFyZWFzcGxpbmUtdmFyaWFudCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxwYXRoIGQ9Ik0yMiwyMUgyVjNINFYxNS41NEw5LjUsNkwxNiw5Ljc4TDIwLjI0LDIuNDVMMjEuOTcsMy40NUwyMiwyMVoiIC8+PC9zdmc+", + "name": "PerformanceMonitor", + "previewIconUrl": "https://asset-resources.gdevelop.io/public-resources/Icons/dd17a98775f56a7741e482ceff2bbfabec688812db8b2120f08cae8750c86345_chart-areaspline-variant.svg", + "shortDescription": "Adds performance info overlays on the screen.", + "version": "1.0.0", + "description": [ + "### Displays full performance overlay (FPS, MS, MB , Draw Calls, Triangles, Geometries, Texture) using stats.js in preview/HTML5.", + "", + "**FPS:** Frames rendered in the last second. The higher the number the better", + "**MS:** Milliseconds needed to render a frame. The lower the number the better", + "**MB:** MBytes of allocated memory (Run Chrome with --enable-precise-memory-info)", + "**CALLS:** The number of render calls since the app has been started", + "**TRIANGLES:** The number of rendered triangle primitives of the current frame", + "**GEOMETRIES:** The number of active geometries", + "**TEXTURE:** The number of active textures" + ], + "tags": [ + "debug", + "fps", + "performance", + "stat", + "statsjs", + "overlay" + ], + "authorIds": [ + "m8kleQHonagHWsvILDhyJhgVhuF2" + ], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [], + "eventsFunctions": [ + { + "description": "Starts the performance monitor.", + "fullName": "Start Performance Monitor", + "functionType": "Action", + "name": "StartPerformanceMonitor", + "sentence": "Start performance monitor in Expanded View: _PARAM1_ with Scale: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "runtimeScene._PerformanceMonitor = runtimeScene._PerformanceMonitor || {};", + "runtimeScene._PerformanceMonitor.customPanels = runtimeScene._PerformanceMonitor.customPanels || {};", + "", + "if (runtimeScene._PerformanceMonitor.instance || runtimeScene._PerformanceMonitor.loading) return;", + "runtimeScene._PerformanceMonitor.loading = true;", + "", + "const STATS_MIN_JS = \"/* stats.js - http://github.com/mrdoob/stats.js */(function(f,e){\\\"object\\\"===\\\"typeof exports\\\"&&\\\"undefined\\\"!==\\\"typeof module\\\"?module.exports=e():\\\"function\\\"===\\\"typeof define\\\"&&define.amd?define(e):f.Stats=e()})(this,function(){var f=function(){function e(a){c.appendChild(a.dom);return a}function u(a){for(var d=0;d=g+1E3&&(r.update(1E3*a/(c-g),100),g=c,a=0,t)){var d=performance.memory;t.update(d.usedJSHeapSize/1048576,d.jsHeapSizeLimit/1048576)}return c},update:function(){k=this.end()},domElement:c,setMode:u}};f.Panel=function(e,f,l){var c=Infinity,k=0,g=Math.round,a=g(window.devicePixelRatio||1),r=100*a,h=64*a,t=3*a,v=2*a,d=3*a,m=15*a,n=94*a,p=46*a,q=document.createElement(\\\"canvas\\\");q.width=r;q.height=h;q.style.cssText=\\\"width:100px;height:64px\\\";var b=q.getContext(\\\"2d\\\");b.font=\\\"bold \\\"+8*a+\\\"px Helvetica,Arial,sans-serif\\\";b.textBaseline=\\\"top\\\";b.fillStyle=l;b.fillRect(0,0,r,h);b.fillStyle=f;b.fillText(e,t,v);b.fillRect(d,m,n,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d,m,n,p);return{dom:q,update:function(h,w){c=Math.min(c,h);k=Math.max(k,h);b.fillStyle=l;b.globalAlpha=1;b.fillRect(0,0,r,m);b.fillStyle=f;b.fillText(g(h)+\\\" \\\"+e+\\\" (\\\"+g(c)+\\\"-\\\"+g(k)+\\\")\\\",t,v);b.drawImage(q,d+a,m,n-a,p,d,m,n-a,p);b.fillRect(d+n-a,m,a,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d+n-a,m,a,g((1-h/w)*p))}}};return f});\";", + "", + "const script = document.createElement('script');", + "script.textContent = STATS_MIN_JS;", + "document.head.appendChild(script);", + "", + "function initStats() {", + " const PanelConstructor = Stats ? Stats.Panel : null;", + "", + " if (typeof Stats === 'undefined' || !PanelConstructor) {", + " runtimeScene._PerformanceMonitor.loading = false;", + " return;", + " }", + "", + " const stats = new Stats();", + " stats.showPanel(0); // This creates the 3 default panels (FPS, MS, MB) inside stats.dom", + "", + " const expandedView = eventsFunctionContext.getArgument(\"ExpandedView\")", + " const scaleFactor = eventsFunctionContext.getArgument(\"ScaleFactor\")", + "", + " const actualScale = isFinite(scaleFactor) && scaleFactor > 0 ? scaleFactor : 1.0;", + "", + " stats.dom.style.position = 'fixed';", + " stats.dom.style.left = '0px';", + " stats.dom.style.top = '0px';", + " stats.dom.style.zIndex = '10000';", + " stats.dom.style.transform = `scale(${actualScale})`;;", + " stats.dom.style.transformOrigin = 'top left';", + "", + " document.body.appendChild(stats.dom);", + "", + " if (expandedView) {", + " stats.dom.style.top = '0px';", + " stats.dom.style.height = 'auto'; // Wrapper height is auto for stacking", + "", + " //Disable click events", + " stats.dom.style.pointerEvents = 'none';", + "", + " for (let i = 0; i < stats.dom.children.length; i++) {", + " const panelDom = stats.dom.children[i];", + " panelDom.style.display = 'block';", + " panelDom.style.position = 'absolute';", + " panelDom.style.top = `${i * 64}px`; // Stack them 64px apart", + "", + " }", + "", + " } else {", + " // Cycled mode default setup", + " stats.dom.style.height = '64px';", + " stats.dom.style.pointerEvents = 'auto'; // clicks are enabled for cycling", + " }", + "", + " if (PanelConstructor) {", + " // If cycled, currentOffset remains 0 (panels will be hidden and share the same spot)", + " let currentOffset = expandedView ? (stats.dom.children.length * 64) : 0;", + "", + " const createCustomPanel = (name, color, bgColor, topOffset) => {", + " const panel = stats.addPanel(new PanelConstructor(name, color, bgColor));", + "", + " if (expandedView) {", + " panel.dom.style.display = 'block';", + " panel.dom.style.position = 'absolute';", + " panel.dom.style.top = `${topOffset}px`;", + " } else {", + " panel.dom.style.display = 'none';", + " }", + "", + " return panel;", + " };", + "", + " // 1. render.calls (CALLS) - Purple", + " runtimeScene._PerformanceMonitor.customPanels.calls = createCustomPanel('CALLS', '#a0f', '#202', currentOffset);", + " currentOffset += 64;", + "", + " // 2. render.triangles (TRIS) - Orange", + " runtimeScene._PerformanceMonitor.customPanels.triangles = createCustomPanel('TRIS', '#f90', '#210', currentOffset);", + " currentOffset += 64;", + "", + " // 3. memory.geometries (GEOS) - Yellow", + " runtimeScene._PerformanceMonitor.customPanels.geometries = createCustomPanel('GEOS', '#ff0', '#220', currentOffset);", + " currentOffset += 64;", + "", + " // 4. memory.textures (TEXS) - Teal", + " runtimeScene._PerformanceMonitor.customPanels.textures = createCustomPanel('TEXS', '#0ff', '#022', currentOffset);", + " }", + "", + " runtimeScene._PerformanceMonitor.instance = stats;", + " runtimeScene._PerformanceMonitor.loading = false;", + "", + " (function loop() {", + " if (!runtimeScene._PerformanceMonitor.instance) return;", + "", + " runtimeScene._PerformanceMonitor.instance.update();", + "", + " const renderer = runtimeScene.getGame().getRenderer().getThreeRenderer();", + "", + " const renderInfo = renderer && renderer.info ? renderer.info.render : {};", + " const memoryInfo = renderer && renderer.info ? renderer.info.memory : {};", + "", + " // CALLS", + " if (runtimeScene._PerformanceMonitor.customPanels.calls) {", + " const calls = renderInfo.calls !== undefined ? renderInfo.calls : 0;", + " runtimeScene._PerformanceMonitor.customPanels.calls.update(calls, 1000);", + " }", + "", + " // TRIS", + " if (runtimeScene._PerformanceMonitor.customPanels.triangles) {", + " const triangles = renderInfo.triangles !== undefined ? renderInfo.triangles : 0;", + " runtimeScene._PerformanceMonitor.customPanels.triangles.update(triangles, 100000);", + " }", + "", + " // GEOS", + " if (runtimeScene._PerformanceMonitor.customPanels.geometries) {", + " const geometries = memoryInfo.geometries !== undefined ? memoryInfo.geometries : 0;", + " runtimeScene._PerformanceMonitor.customPanels.geometries.update(geometries, 1000);", + " }", + "", + " // TEXS", + " if (runtimeScene._PerformanceMonitor.customPanels.textures) {", + " const textures = memoryInfo.textures !== undefined ? memoryInfo.textures : 0;", + " runtimeScene._PerformanceMonitor.customPanels.textures.update(textures, 1000);", + " }", + "", + " requestAnimationFrame(loop);", + " })();", + "}", + "", + "initStats();" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Expanded View", + "name": "ExpandedView", + "type": "yesorno" + }, + { + "description": "Overlay Scale (default 1)", + "name": "ScaleFactor", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Stops and removes the Performance monitor.", + "fullName": "Stop Performance Monitor", + "functionType": "Action", + "name": "StopPerformanceMonitor", + "sentence": "Stop and remove the Performance monitor", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "runtimeScene._PerformanceMonitor = runtimeScene._PerformanceMonitor || {};", + "", + "if (runtimeScene._PerformanceMonitor.instance) {", + " const monitorDom = runtimeScene._PerformanceMonitor.instance.dom;", + "", + " if (monitorDom && document.body.contains(monitorDom)) {", + " document.body.removeChild(monitorDom);", + " }", + " ", + " runtimeScene._PerformanceMonitor.instance = null;", + " runtimeScene._PerformanceMonitor.loading = false;", + " ", + "}" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [], + "objectGroups": [] + } + ], + "eventsBasedBehaviors": [], + "eventsBasedObjects": [] +} \ No newline at end of file