⌈⌋ ⎇ branch:  Bitrhythm


Artifact Content

Artifact acf82a95476c120135b95e2b219a8b5865a260c8ff8ad7120f5d1ef6991e7e18:


'use strict';

import math from '../util/math';
import ToggleModel from '../models/toggle';


/*
how to use :

dial.interaction = new Handle('radial','relative',this.width,this.height);
// dial.interaction.mode = 'relative'
// dial.interaction.direction = 'radial'

on click:
dial.interaction.anchor = this.mouse;

on move:
dial.interaction.update(this.mouse);

console.log( dial.interaction.value ); should be a normalized value.

*/

/*
  absolute/relative are property: mode
  radial/vertical/horizontal/2d are property: direction

  plan :

  if relative --
  NO on click, get value offset between current value and click value.
  NO on move, use click value - offset
  INSTEAD
  use delta -- bc vertical motion on dial is impossible otherwise
  also allow to set sensitivity

*/

export class Handle {

  constructor(mode='absolute',direction='vertical',xbound=[0,100],ybound=[0,100]) {
    this.mode = mode;
    this.direction = direction;
    this.previous = 0;
    this.value = 0;
    this.sensitivity = 1;
    this.resize(xbound,ybound);
  }

  resize(xbound,ybound) {
    this.boundary = {
      min: {
        x: xbound[0],
        y: ybound[0]
      },
      max: {
        x: xbound[1],
        y: ybound[1]
      },
      center: {
        x: (xbound[1] - xbound[0])/2 + xbound[0],
        y: (ybound[1] - ybound[0])/2 + ybound[0]
      }
    };
  }

  set anchor(mouse) {
    this._anchor = this.convertPositionToValue(mouse);
  }

  get anchor() {
    return this._anchor;
  }


  update(mouse) {
    if (this.mode==='relative') {
      let increment = this.convertPositionToValue(mouse) - this.anchor;
      if (Math.abs(increment) > 0.5) { increment = 0; }
      this.anchor = mouse;
      this.value = this.value + increment * this.sensitivity;
    } else {
      this.value = this.convertPositionToValue(mouse);
    }
    this.value = math.clip(this.value,0,1);
  }

  convertPositionToValue(current) {
    switch(this.direction) {
      case 'radial':
        let position = math.toPolar(current.x - this.boundary.center.x, current.y - this.boundary.center.y);
        position = position.angle / (Math.PI*2);
        position = ((position - 0.25) + 1) % 1;
        return position;
      case 'vertical':
        return math.scale(current.y,this.boundary.min.y,this.boundary.max.y,0,1);
      case 'horizontal':
        return math.scale(current.x,this.boundary.min.x,this.boundary.max.x,0,1);
    }
  }

}


export class Button {

  constructor(mode='button') {
    this.mode = mode;
    this.state = new ToggleModel();
    this.paintbrush = false;
  }

  click() {
    switch (this.mode) {
      case 'impulse':
        this.state.on();
        if (this.timeout) {
          clearTimeout(this.timeout);
        }
        this.timeout = setTimeout(this.state.off.bind(this),30);
        this.emit('change',this.state);
        break;
      case 'button':
        this.turnOn();
        this.emit('change',this.state);
        break;
      case 'aftertouch':
        this.position = {
          x: math.clip(this.mouse.x / this.width,0,1),
          y: math.clip(1 - this.mouse.y / this.height,0,1)
        };
        this.turnOn();
        this.emit('change',{
          state: this.state,
          x: this.position.x,
          y: this.position.y,
        });
        break;
      case 'toggle':
        this.flip();
        this.emit('change',this.state);
        break;
    }

  }

  move() {
    if (this.mode==='aftertouch') {
      this.position = {
        x: math.clip(this.mouse.x / this.width,0,1),
        y: math.clip(1 - this.mouse.y / this.height,0,1)
      };
      this.emit('change',{
        state: this.state,
        x: this.position.x,
        y: this.position.y,
      });
      this.render();
    }
  }

  release() {
    switch (this.mode) {
      case 'button':
        this.turnOff();
        this.emit('change',this.state);
        break;
      case 'aftertouch':
        this.turnOff();
        this.position = {
          x: this.mouse.x / this.width,
          y: 1 - this.mouse.y / this.height
        };
        this.emit('change',{
          state: this.state,
          x: this.position.x,
          y: this.position.y,
        });
        break;
    }
  }
}