/**
* @module AxesHelperGui
* @description Adds <a href="../../AxesHelper/jsdoc/module-AxesHelper-AxesHelper.html" target="_blank">AxesHelper</a> settings folder into {@link https://github.com/anhr/dat.gui|dat.gui}.
* @see {@link https://github.com/anhr/AxesHelper|AxesHelper}
*
* @author [Andrej Hristoliubov]{@link https://github.com/anhr}
*
* @copyright 2011 Data Arts Team, Google Creative Lab
*
* @license under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
import ScaleController from '../ScaleController.js';
//import ScaleController from 'https://raw.githack.com/anhr/commonNodeJS/master/ScaleController.js';
import PositionController from '../PositionController.js';
//import PositionController from 'https://raw.githack.com/anhr/commonNodeJS/master/PositionController.js';
import { SpriteTextGui } from '../SpriteText/SpriteTextGui.js';
//import { SpriteTextGui } from 'https://raw.githack.com/anhr/commonNodeJS/master/SpriteText/SpriteTextGui.js';
import three from '../three.js'
import Options from '../Options.js'
/**
* Adds <a href="../../AxesHelper/jsdoc/module-AxesHelper-AxesHelper.html" target="_blank">AxesHelper</a> settings folder into {@link https://github.com/anhr/dat.gui|dat.gui}.
* An axis object to visualize axes.
* @param {Options} options Followed parameters is allowed.
* See the <b>options</b> parameter of the <a href="../../myThree/jsdoc/module-MyThree-MyThree.html" target="_blank">MyThree</a> class.
* @param {boolean} [options.dat.axesHelperGui] false - do not adds <b>AxesHelperGui</b> into [dat.gui]{@link https://github.com/dataarts/dat.gui}.
* @param {AxesHelper} [options.axesHelper is <a href="./module-AxesHelper-AxesHelper.html" target="_blank">AxesHelper</a> instance.
* @param {Function} [options.getLanguageCode=language code of your browser] Your custom getLanguageCode() function.
* <pre>
* returns the "primary language" subtag of the language version of the browser.
* Examples: "en" - English language, "ru" Russian.
* See the "Syntax" paragraph of RFC 4646 {@link https://tools.ietf.org/html/rfc4646#section-2.1|rfc4646 2.1 Syntax} for details.
* You can import { getLanguageCode } from '../../commonNodeJS/master/lang.js';
* </pre>
* @param {cookie} [options.cookie] Your custom cookie function for saving and loading of the AxesHelper settings.
* <pre>
* See [cookieNodeJS]{@link https://github.com/anhr/commonNodeJS/tree/master/cookieNodeJS}.
* Default cookie is not saving settings.
* </pre>
* @param {string} [options.cookieName] Name of the cookie is "AxesHelper" + options.cookieName.
* @param {GUI} [gui] is [new dat.GUI(...)]{@link https://github.com/anhr/dat.gui}.
*/
export default function AxesHelperGui( options, gui ) {
if ( !options.boOptions ) {
console.error( 'AxesHelperGui: call options = new Options( options ) first' );
return;
}
gui = gui || options.dat.gui;
if ( !gui || ( options.dat === false ) || ( options.dat.axesHelperGui === false ) )
return;
if ( options.axesHelper === false )
return;
if ( !options.axesHelper ) {
console.error( 'AxesHelperGui: create AxesHelper instance first' );
return;
}
const THREE = three.THREE, dat = three.dat;
const scalesDefault = JSON.parse( JSON.stringify( options.scales ) ),
groupAxesHelper = options.axesHelper.getGroup();
Object.freeze( scalesDefault );
options = options || {};
//Localization
const lang = {
axesHelper: 'Axes Helper',
scales: 'Scales',
displayScales: 'Display',
displayScalesTitle: 'Display or hide axes scales.',
precision: 'Precision',
precisionTitle: 'Formats a number to a specified length.',
min: 'Min',
max: 'Max',
marks: 'Marks',
marksTitle: 'Number of scale marks',
axesIntersection: 'Axes Intersection',
defaultButton: 'Default',
defaultTitle: 'Restore default Axes Helper settings.',
defaultAxesIntersectionTitle: 'Restore default axes intersection.',
};
switch ( options.getLanguageCode() ){
case 'ru'://Russian language
lang.axesHelper = 'Оси координат';
lang.scales = 'Шкалы';
lang.displayScales = 'Показать';
lang.displayScalesTitle = 'Показать или скрыть шкалы осей координат.';
lang.precision = 'Точность';
lang.precisionTitle = 'Ограничить количество цифр в числе.';
lang.min = 'Минимум';
lang.max = 'Максимум';
lang.marks = 'Риски';
lang.marksTitle = 'Количество отметок на шкале';
lang.axesIntersection = 'Начало координат',
lang.defaultButton = 'Восстановить';
lang.defaultTitle = 'Восстановить настройки осей координат по умолчанию.';
lang.defaultAxesIntersectionTitle = 'Восстановить начало координат по умолчанию.';
break;
default://Custom language
if ( ( options.lang === undefined ) || ( options.lang.languageCode != languageCode ) )
break;
Object.keys( options.lang ).forEach( function ( key ) {
if ( lang[key] === undefined )
return;
lang[key] = options.lang[key];
} );
}
const cookie = options.dat.cookie,
cookieName = options.dat.getCookieName( 'AxesHelper' );
cookie.getObject( cookieName, options.scales, options.scales );
function setSettings() {
cookie.setObject( cookieName, options.scales );
}
//AxesHelper folder
const fAxesHelper = gui.addFolder( lang.axesHelper );
//scales folder
const fScales = fAxesHelper.addFolder( lang.scales );
//display scales
const controllerDisplayScales = fScales.add( options.scales, 'display' ).onChange( function ( value ) {
groupAxesHelper.children.forEach( function ( group ) {
group.children.forEach( function ( group ) {
group.visible = value;
} );
} );
displayControllers();
setSettings();
} );
dat.controllerNameAndTitle( controllerDisplayScales, lang.displayScales, lang.displayScalesTitle );
var controllerPrecision;
if ( options.scales.text.precision !== undefined ) {
controllerPrecision = fScales.add( options.scales.text, 'precision', 2, 17, 1 ).onChange( function ( value ) {
function updateSpriteTextGroup( group ) {
group.children.forEach( function ( spriteItem ) {
if ( spriteItem instanceof THREE.Sprite ) {
if ( spriteItem.userData.updatePrecision !== undefined )
spriteItem.userData.updatePrecision();
} else if ( ( spriteItem instanceof THREE.Group ) || ( spriteItem instanceof THREE.Line ) )
updateSpriteTextGroup( spriteItem );
} );
}
updateSpriteTextGroup( groupAxesHelper );
setSettings();
} )
dat.controllerNameAndTitle( controllerPrecision, lang.precision, lang.precisionTitle );
}
const fSpriteText = typeof SpriteTextGui === "undefined" ? undefined : SpriteTextGui( groupAxesHelper, {
dat: {
gui: options.dat.gui,
cookieName: 'AxesHelper_' + options.dat.getCookieName(),
},
}, {
parentFolder: fScales,
} );
//Axes intersection folder
const fAxesIntersection = fAxesHelper.addFolder( lang.axesIntersection ),
axesIntersectionControllers = { x: {}, y: {}, z: {} };
function axesIntersection( axisName ) {
const scale = options.scales[axisName];
if ( !scale.isAxis() )
return;
const scaleControllers = axesIntersectionControllers[axisName];
scaleControllers.controller = fAxesIntersection.add( {
value: options.scales.posAxesIntersection[axisName],
}, 'value',
scale.min,
scale.max,
( scale.max - scale.min ) / 100 ).
onChange( function ( value ) {
options.scales.posAxesIntersection[axisName] = value;
options.axesHelper.updateAxes();
setSettings();
} );
dat.controllerNameAndTitle( scaleControllers.controller, scale.name );
}
axesIntersection( 'x' );
axesIntersection( 'y' );
axesIntersection( 'z' );
//default button Axes intersection
var defaultParams = {
defaultF: function ( value ) {
axesIntersectionControllers.x.controller.setValue( scalesDefault.posAxesIntersection.x );
axesIntersectionControllers.y.controller.setValue( scalesDefault.posAxesIntersection.y );
axesIntersectionControllers.z.controller.setValue( scalesDefault.posAxesIntersection.z );
},
};
dat.controllerNameAndTitle( fAxesIntersection.add( defaultParams, 'defaultF' ), lang.defaultButton, lang.defaultAxesIntersectionTitle );
fAxesHelper.add( new ScaleController(
function ( customController, action ) {
function zoom( zoom, action ) {
function axesZoom( axes, scaleControllers ) {
if ( axes === undefined )
return;//not 3D axesHelper
axes.min = action( axes.min, zoom );
scaleControllers.min.setValue( axes.min );
axes.max = action( axes.max, zoom );
scaleControllers.max.setValue( axes.max );
scaleControllers.onchangeWindowRange();
}
axesZoom( options.scales.x, scalesControllers.x );
axesZoom( options.scales.y, scalesControllers.y );
axesZoom( options.scales.z, scalesControllers.z );
}
zoom( customController.controller.getValue(), action );
}, {
settings: { zoomMultiplier: 1.1, },
getLanguageCode: options.getLanguageCode,
} ) ).onChange( function ( value ) {
console.warn( 'ScaleController.onChange' );
} );
function scale( axisName ) {
const axes = options.scales[axisName];
if ( axes === undefined )
return;
const scaleControllers = scalesControllers[axisName],
axesDefault = scalesDefault[axisName];
Object.freeze( axesDefault );
function updateAxis() {
groupAxesHelper.children.forEach( function ( group ) {
if ( group.userData.axisName !== axisName )
return;
groupAxesHelper.remove( group );
options.axesHelper.createAxis( axisName );
} );
}
scaleControllers.updateAxis = updateAxis;
function onchangeWindowRange() {
updateAxis();
setSettings();
}
scaleControllers.onchangeWindowRange = onchangeWindowRange;
function onclick( customController, action ) {
var zoom = customController.controller.getValue();
axes.min = action( axes.min, zoom );
scaleControllers.min.setValue( axes.min );
axes.max = action( axes.max, zoom );
scaleControllers.max.setValue( axes.max );
onchangeWindowRange( windowRange, axes );
}
scaleControllers.folder = fAxesHelper.addFolder( axes.name );
scaleControllers.scaleController = scaleControllers.folder.add( new ScaleController( onclick,
{ settings: axes, getLanguageCode: options.getLanguageCode, } ) ).onChange( function ( value ) {
axes.zoomMultiplier = value;
setSettings();
} );
var positionController = new PositionController( function ( shift ) {
onclick( positionController, function ( value, zoom ) {
value += shift;
return value;
} );
}, { settings: axes, getLanguageCode: options.getLanguageCode, } );
scaleControllers.positionController = scaleControllers.folder.add( positionController ).onChange( function ( value ) {
axes.offset = value;
setSettings();
} );
//min
scaleControllers.min = dat.controllerZeroStep( scaleControllers.folder, axes, 'min', function ( value ) {
onchangeWindowRange( windowRange );
} );
dat.controllerNameAndTitle( scaleControllers.min, lang.min );
//max
scaleControllers.max = dat.controllerZeroStep( scaleControllers.folder, axes, 'max', function ( value ) {
onchangeWindowRange( windowRange );
} );
dat.controllerNameAndTitle( scaleControllers.max, lang.max );
//marks
if ( axes.marks !== undefined ) {//w axis do not have marks
scaleControllers.marks = dat.controllerZeroStep( scaleControllers.folder, axes, 'marks', function ( value ) {
onchangeWindowRange( windowRange );
} );
dat.controllerNameAndTitle( scaleControllers.marks, axes.marksName === undefined ? lang.marks : axes.marksName,
axes.marksTitle === undefined ? lang.marksTitle : axes.marksTitle );
}
//Default button
scaleControllers.defaultButton = scaleControllers.folder.add( {
defaultF: function ( value ) {
axes.min = axesDefault.min;
scaleControllers.min.setValue( axes.min );
axes.max = axesDefault.max;
scaleControllers.max.setValue( axes.max );
axes.zoomMultiplier = axesDefault.zoomMultiplier;
scaleControllers.scaleController.setValue( axes.zoomMultiplier );
axes.offset = axesDefault.offset;
scaleControllers.positionController.setValue( axes.offset );
if ( axesDefault.marks !== undefined ) {
axes.marks = axesDefault.marks;
scaleControllers.marks.setValue( axes.marks );
}
onchangeWindowRange( windowRange, axes );
},
}, 'defaultF' );
dat.controllerNameAndTitle(scaleControllers.defaultButton , lang.defaultButton, lang.defaultTitle );
}
const scalesControllers = { x: {}, y: {}, z: {} };//, w: {} };//, t: {}, };
function windowRange() {
setSettings();
}
scale('x');
scale('y');
scale('z');
//default button
var defaultParams = {
defaultF: function ( value ) {
controllerDisplayScales.setValue( scalesDefault.display );
if ( controllerPrecision !== undefined )
controllerPrecision.setValue( scalesDefault.text.precision );
fSpriteText.userData.restore();
function defaulAxis( axisName ) {
if ( scalesControllers[axisName].defaultButton )
scalesControllers[axisName].defaultButton.object.defaultF();
}
defaulAxis( 'x' );
defaulAxis( 'y' );
defaulAxis( 'z' );
},
};
dat.controllerNameAndTitle( fAxesHelper.add( defaultParams, 'defaultF' ), lang.defaultButton, lang.defaultTitle );
function displayControllers() {
var display = options.scales.display ? 'block' : 'none';
if ( fSpriteText !== undefined )
fSpriteText.domElement.style.display = display;
if ( controllerPrecision !== undefined )
controllerPrecision.domElement.parentElement.parentElement.style.display = display;
}
displayControllers();
if ( scalesControllers.x.updateAxis ) scalesControllers.x.updateAxis();
if ( scalesControllers.y.updateAxis ) scalesControllers.y.updateAxis();
if ( scalesControllers.z.updateAxis ) scalesControllers.z.updateAxis();
}