NikLever / CanvasUI

A Three.JS WebXR UI. Enabling easy UI creation for immersive-vr sessions.
canvas-ui-eight.vercel.app
GNU General Public License v3.0
130 stars 22 forks source link

change: element/config refactor #30

Open eviltik opened 2 years ago

eviltik commented 2 years ago

First, we currently set positions, dimensions, font, colors, for each elements using attributes, but mixed with methods in the same object. Same thing for the config object which is a mix of different properties with differents usage (i.e element definition vs renderer, or panelSize vs an element name). This currently involves some filters when looping over object attributes in CanvasUI.

Let's take the current buttons example.

const config = {
    panelSize: { width: 2, height: 0.5 },
    height: 128,
    info: { type: "text", position:{ left: 6, top: 6 }, width: 500, height: 58, backgroundColor: "#aaa", fontColor: "#000" },
    prev: { type: "button", position:{ top: 64, left: 0 }, width: 64, fontColor: "#bb0", hover: "#ff0", onSelect: onPrev },
    stop: { type: "button", position:{ top: 64, left: 64 }, width: 64, fontColor: "#bb0", hover: "#ff0", onSelect: onStop },
    next: { type: "button", position:{ top: 64, left: 128 }, width: 64, fontColor: "#bb0", hover: "#ff0", onSelect: onNext },
    continue: { type: "button", position:{ top: 70, right: 10 }, width: 200, height: 52, fontColor: "#fff", backgroundColor: "#2659a4", hover: "#3df", onSelect: onContinue },
    renderer: this.renderer
}

First goal : elements objetct, only having elements declaration, rather than a mixed object.

const elements = {
    'info'': { type: 'text', value:'' },
    'prev': { type: 'button', value:'...', [ ... ] onSelect: onPrev },
    'stop': { type: 'button', value:'...', [ ... ] onSelect: onStop },
    'next': { type: 'button', value:'...', [ ... ] onSelect: onNext },
    'continue': { type: 'button', value:'Continue', [ ... ] onSelect: onContinue },
};

Everything which is not an element attribute should be moved to the config object,

const config = {

   /**        
   * CanvasUI start with a panel having a size of 1x1 meter. 
   * But you can define your own size.
   */
    panel: {

        size: {
            width: 2,
            height: 0.5
        }

    } ,

   /**        
   * CanvasUI use a Canvas HTML element to renderer widgets into a texture.
   */
    canvas: {
      /**    
       * size: canvas size (width, height) of the offscreencanvas, default 512 (pixels)
       */
        size: {
            height: 128
        }
    },

    threejs: {

        /**
        * threejs attribute value can be your threejs application instance, on which canvasui will look for a renderer,
        * camera and scene attributes.
        */

        /**        
         * renderer
         * 
         * NEEDED if you want to use WebXR controllers (renderer.xr, renderer.xr.isPresenting, getControllers ...)
         */
        renderer: this.renderer, 

        /**        
         * camera
         * 
         * NEEDED if you want to use the Mouse controller, because the raycaster is attached to the camera
         */
        camera: this.camera,

        /**        
         * camera
         * 
         * OPTIONAL if you want CanvasUI to be able to add some extra meshes (i.e raycaster intercept mesh, 
         * like in the panel scrolling example )
         */
        scene: this.scene 

    }

    controller: {

        drivers: {

           /**
           * Mouse driver
           * You can use mouse to interact with CanvasUI elements
           * this required a camera in threejs.camera config
           */
            mouse: {

               /**
               * enable: true | false, default true
               */
                enable: true,

               /**
               * handler: follow, default follow ('capture' mode not yet implemented)
               * 
               * follow mode just follow the mouse cursor.
               */
                handler:'follow'
            },

           /**
           * WebXR driver
           */

            webxr: {

                   /**
                   * enable: true | false, default true
                   */
                    enable: true, 

                   /**
                   * raycasterLinesLength: in meters, default 10
                   */
                    raycasterLinesLength:10
           },

           // @nik, do you see more drivers for later ? gamepad :) ?

        },*

        /**
         * Select behavior
         * 
         * Common settings for both WebXR driver and Mouse driver
         * For WebXR driver: selectstart, select, selectend controlller events
         * For Mouse driver: mouseup/mousedown/mousemove events
         */

        select: {

              /**
               * Raycaster(s) hover behavior while element is selected
               * 
               * hover : true | false, default false
               *
               * true:  trigger onSelect once (keyboard like behavior)
               * false: trigger onSelect while raycaster is moving (select+hover) on the element. Colorpicker or Slider like behavior.
               */
                hover: false, 

                /**
                 * Select repeater behavior 
                 * 
                 * Only when hover = false. 
                 * Usefull for repeating onSelect event while keeping a select WebXR button pressed or mouse down. 
                 * In keyboard example, it simulate multiple keydown event
                 */   
                repeater: {

                     * When pressing WebXR select button controller or clicking the mouse on a CanvasUI element,
                     * the onSelect method of the element is triggered a first time. And that's all when hover = true.
                     * 
                     * But if hover = false, after the first onSelect method has been triggered, it will optionally wait 
                     * for timeoutms milliseconds before triggering onSelect with a setInterval().
                     * 
                     * Then if specified, onSelect event will be triggered every repeatms millisecond until 
                     * the selectend or mouseup event is triggered
                     *
                     * enable or disable the repeter
                     * enable: true | false, default false
                     * 
                     * timeoutms
                     * 0 mean setTimeout 0 , i.e onSelect will be triggered in the next event loop, similare to setImmediate.
                     * null or undefined value will trigger onSelect on the same event loop without setTimeout().
                     * timeoutms:  default 100
                     * 
                     * repeatms
                     * 0 mean setInterval 0 , i.e onSelect will be triggered in the next event loop, similare to setImmediate. (use with caution)
                     * null or undefined value will disable the repeater.
                     * repeatms: default 20
                     */
                    timeoutms:100, 
                    repeatms:20
                }
          }
    }
}

Typical compact/minimal usage :

const config = {
    panel: { size: { width: 2, height: 0.5 } } ,
    canvas: { size : { height: 128 } },
    threejs: {
        renderer: this.renderer, 
        camera: this.camera
    }
}

Then, instantiate like this

new CanvasUI( elements , config );

Benefits:

NikLever commented 2 years ago

Like it.