From e9e19d6ee7f02767df1d8dc0a9d45b0f246cea35 Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Tue, 25 Jan 2022 13:55:25 -0500 Subject: [PATCH 1/4] listen only updates display on value change --- src/Controller.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Controller.js b/src/Controller.js index 282b281..c794284 100644 --- a/src/Controller.js +++ b/src/Controller.js @@ -318,7 +318,11 @@ export default class Controller { _listenCallback() { this._listenCallbackID = requestAnimationFrame( this._listenCallback ); - this.updateDisplay(); + const curValue = this.save(); + if ( curValue !== this._listenPrevValue ) { + this.updateDisplay(); + } + this._listenPrevValue = curValue; } /** From efb59789aba31f1e6c024b94cd32176cccb6a9d9 Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Wed, 26 Jan 2022 12:55:14 -0500 Subject: [PATCH 2/4] comment listen callback --- src/Controller.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Controller.js b/src/Controller.js index c794284..892aea1 100644 --- a/src/Controller.js +++ b/src/Controller.js @@ -317,12 +317,21 @@ export default class Controller { } _listenCallback() { + this._listenCallbackID = requestAnimationFrame( this._listenCallback ); + + // To prevent framerate loss, make sure the value has changed before updating the display. + // Note: save() is used here instead of getValue() only because of ColorController. The !== operator + // won't work for color objects or arrays, but ColorController.save() always returns a string. + const curValue = this.save(); + if ( curValue !== this._listenPrevValue ) { this.updateDisplay(); } + this._listenPrevValue = curValue; + } /** From 3dcaca392e518bdeb5c71be9abb26449e6810899 Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Wed, 26 Jan 2022 12:56:03 -0500 Subject: [PATCH 3/4] changelog --- Changelog.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Changelog.md b/Changelog.md index 1121b41..122df07 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,9 @@ +# 0.16.0-dev + +29.14kb, 8.31kb gzipped + +- Improved performance for GUI's that make heavy use of `listen()`. + # 0.16.0 29.05kb, 8.28kb gzipped From df827804e55c1d5e808ee0f802ff6faa1e0f22b3 Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Thu, 27 Jan 2022 10:37:47 -0500 Subject: [PATCH 4/4] listen stress test --- examples/listen-stress/index.html | 12 ++++ examples/listen-stress/listen-stress.js | 83 +++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 examples/listen-stress/index.html create mode 100644 examples/listen-stress/listen-stress.js diff --git a/examples/listen-stress/index.html b/examples/listen-stress/index.html new file mode 100644 index 0000000..44d8385 --- /dev/null +++ b/examples/listen-stress/index.html @@ -0,0 +1,12 @@ + + + + lil-gui - Basic Example + + + + + + + + diff --git a/examples/listen-stress/listen-stress.js b/examples/listen-stress/listen-stress.js new file mode 100644 index 0000000..94856b3 --- /dev/null +++ b/examples/listen-stress/listen-stress.js @@ -0,0 +1,83 @@ +/* global Stats */ +import GUI from '../../dist/lil-gui.esm.js'; + +const params = { + count: parseInt( location.search.substring( 1 ) ) || 10, + animateAll: false, + update() { + + let diff = params.count - folder.controllers.length; + + for ( ; diff < 0; diff++ ) { + folder.controllers.at( -1 ).destroy(); + } + + for ( ; diff > 0; diff-- ) { + const i = folder.controllers.length % dummyControllers.length; + const controller = dummyControllers[ i ](); + controller.listen(); + } + + folder.title( params.count + ' Listening Controllers' ); + + history.replaceState( {}, '', '?' + params.count ); + + } +}; + +const dummyControllers = [ + () => folder.add( dummyParams, 'options', { Small: 1, Medium: 10, Large: 100 } ), + () => folder.add( dummyParams, 'boolean' ), + () => folder.add( dummyParams, 'string' ), + () => folder.add( dummyParams, 'number', 0, 1 ), + () => folder.addColor( dummyParams, 'color' ) +]; + +const dummyParams = { + options: 10, + boolean: true, + string: 'lil-gui', + number: 0, + color: { r: 1, g: 0, b: 1 } +}; + +let frame = 0; +function animate() { + + stats.end(); + stats.begin(); + + if ( params.animateAll ) { + + const time = Date.now() / 1000; + + dummyParams.options = [ 1, 10, 100 ][ frame % 3 ]; + dummyParams.boolean = frame % 2; + dummyParams.string = time.toString(); + dummyParams.number = time % 1; + + dummyParams.color.r = Math.sin( time / 2 ) / 2 + 0.5; + dummyParams.color.g = Math.sin( time / 3 ) / 2 + 0.5; + dummyParams.color.b = Math.sin( time / 5 ) / 2 + 0.5; + + frame++; + + } + + requestAnimationFrame( animate ); + +} + +const gui = new GUI(); + +gui.add( params, 'animateAll' ); +gui.add( params, 'count' ).min( 0 ); +gui.add( params, 'update' ); + +const folder = gui.addFolder(); + +const stats = new Stats(); +document.body.appendChild( stats.dom ); + +params.update(); +animate();