179 lines
4.6 KiB
JavaScript
179 lines
4.6 KiB
JavaScript
import { Tween, Easing } from './Tween.js';
|
|
|
|
class ThemeEditor {
|
|
|
|
constructor( game ) {
|
|
|
|
this.game = game;
|
|
|
|
this.editColor = 'R';
|
|
|
|
this.getPieceColor = this.getPieceColor.bind( this );
|
|
|
|
}
|
|
|
|
colorFromHSL( h, s, l ) {
|
|
|
|
h = Math.round( h );
|
|
s = Math.round( s );
|
|
l = Math.round( l );
|
|
|
|
return new THREE.Color( `hsl(${h}, ${s}%, ${l}%)` );
|
|
|
|
}
|
|
|
|
setHSL( color = null, animate = false ) {
|
|
|
|
this.editColor = ( color === null) ? 'R' : color;
|
|
|
|
const hsl = new THREE.Color( this.game.themes.getColors()[ this.editColor ] );
|
|
|
|
const { h, s, l } = hsl.getHSL( hsl );
|
|
const { hue, saturation, lightness } = this.game.preferences.ranges;
|
|
|
|
if ( animate ) {
|
|
|
|
const ho = hue.value / 360;
|
|
const so = saturation.value / 100;
|
|
const lo = lightness.value / 100;
|
|
|
|
const colorOld = this.colorFromHSL( hue.value, saturation.value, lightness.value );
|
|
|
|
if ( this.tweenHSL ) this.tweenHSL.stop()
|
|
|
|
this.tweenHSL = new Tween( {
|
|
duration: 200,
|
|
easing: Easing.Sine.Out(),
|
|
onUpdate: tween => {
|
|
|
|
hue.setValue( ( ho + ( h - ho ) * tween.value ) * 360 );
|
|
saturation.setValue( ( so + ( s - so ) * tween.value ) * 100 );
|
|
lightness.setValue( ( lo + ( l - lo ) * tween.value ) * 100 );
|
|
|
|
const colorTween = colorOld.clone().lerp( hsl, tween.value );
|
|
|
|
const colorTweenStyle = colorTween.getStyle();
|
|
const colorTweenHex = colorTween.getHSL( colorTween );
|
|
|
|
hue.handle.style.color = colorTweenStyle;
|
|
saturation.handle.style.color = colorTweenStyle;
|
|
lightness.handle.style.color = colorTweenStyle;
|
|
|
|
saturation.track.style.color =
|
|
this.colorFromHSL( colorTweenHex.h * 360, 100, 50 ).getStyle();
|
|
lightness.track.style.color =
|
|
this.colorFromHSL( colorTweenHex.h * 360, colorTweenHex.s * 100, 50 ).getStyle();
|
|
|
|
this.game.dom.theme.style.display = 'none';
|
|
this.game.dom.theme.offsetHeight;
|
|
this.game.dom.theme.style.display = '';
|
|
|
|
},
|
|
onComplete: () => {
|
|
|
|
this.updateHSL();
|
|
this.game.storage.savePreferences();
|
|
|
|
},
|
|
} );
|
|
|
|
} else {
|
|
|
|
hue.setValue( h * 360 );
|
|
saturation.setValue( s * 100 );
|
|
lightness.setValue( l * 100 );
|
|
|
|
this.updateHSL();
|
|
this.game.storage.savePreferences();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
updateHSL() {
|
|
|
|
const { hue, saturation, lightness } = this.game.preferences.ranges;
|
|
|
|
const h = hue.value;
|
|
const s = saturation.value;
|
|
const l = lightness.value;
|
|
|
|
const color = this.colorFromHSL( h, s, l ).getStyle();
|
|
|
|
hue.handle.style.color = color;
|
|
saturation.handle.style.color = color;
|
|
lightness.handle.style.color = color;
|
|
|
|
saturation.track.style.color = this.colorFromHSL( h, 100, 50 ).getStyle();
|
|
lightness.track.style.color = this.colorFromHSL( h, s, 50 ).getStyle();
|
|
|
|
this.game.dom.theme.style.display = 'none';
|
|
this.game.dom.theme.offsetHeight;
|
|
this.game.dom.theme.style.display = '';
|
|
|
|
const theme = this.game.themes.theme;
|
|
|
|
this.game.themes.colors[ theme ][ this.editColor ] = this.colorFromHSL( h, s, l ).getHex();
|
|
this.game.themes.setTheme();
|
|
|
|
}
|
|
|
|
colorPicker( enable ) {
|
|
|
|
if ( enable ) {
|
|
|
|
this.game.dom.game.addEventListener( 'click', this.getPieceColor, false );
|
|
|
|
} else {
|
|
|
|
this.game.dom.game.removeEventListener( 'click', this.getPieceColor, false );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
getPieceColor( event ) {
|
|
|
|
const clickEvent = event.touches
|
|
? ( event.touches[ 0 ] || event.changedTouches[ 0 ] )
|
|
: event;
|
|
|
|
const clickPosition = new THREE.Vector2( clickEvent.pageX, clickEvent.pageY );
|
|
|
|
let edgeIntersect = this.game.controls.getIntersect( clickPosition, this.game.cube.edges, true );
|
|
let pieceIntersect = this.game.controls.getIntersect( clickPosition, this.game.cube.cubes, true );
|
|
|
|
if ( edgeIntersect !== false ) {
|
|
|
|
const edge = edgeIntersect.object;
|
|
|
|
const position = edge.parent
|
|
.localToWorld( edge.position.clone() )
|
|
.sub( this.game.cube.object.position )
|
|
.sub( this.game.cube.animator.position );
|
|
|
|
const mainAxis = this.game.controls.getMainAxis( position );
|
|
if ( position.multiplyScalar( 2 ).round()[ mainAxis ] < 1 ) edgeIntersect = false;
|
|
|
|
}
|
|
|
|
const name = edgeIntersect ? edgeIntersect.object.name : pieceIntersect ? 'P' : 'G';
|
|
|
|
this.setHSL( name, true );
|
|
|
|
}
|
|
|
|
resetTheme() {
|
|
|
|
this.game.themes.colors[ this.game.themes.theme ] =
|
|
JSON.parse( JSON.stringify( this.game.themes.defaults[ this.game.themes.theme ] ) );
|
|
|
|
this.game.themes.setTheme();
|
|
|
|
this.setHSL( this.editColor, true );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
export { ThemeEditor }; |