(function(){ 'use strict'; var sharedFont, sharedTexture; var pendingQueue = []; /** * Sprite text based on {@link https://github.com/Jam3/three-bmfont-text} * @constructor * @param {string} text - Text to be displayed * @param {number} maxWidth - Max width * @param {number} color - Color in hexadecimal * @param {number} opacity - Text opacity * @param {object} options - Options to create text geometry */ PANOLENS.SpriteText = function ( text, maxWidth, color, opacity, options ) { THREE.Object3D.call( this ); this.text = text || ''; this.maxWidth = maxWidth || 2000; this.color = color || 0xffffff; this.opacity = opacity !== undefined ? opacity : 1; this.options = options || {}; this.animationDuration = 500; this.animationFadeOut = undefined; this.animationFadeIn = undefined; this.tweens = {}; this.addText( text ); } PANOLENS.SpriteText.prototype = Object.create( THREE.Object3D.prototype ); PANOLENS.SpriteText.prototype.constructor = PANOLENS.SpriteText; // Reference function will be overwritten by Bmfont.js PANOLENS.SpriteText.prototype.generateTextGeometry = function () {}; PANOLENS.SpriteText.prototype.generateSDFShader = function () {}; /** * Set BMFont * @param {Function} callback - Callback after font is loaded * @param {object} font - The font to be loaded * @param {THREE.Texture} texture - Font texture */ PANOLENS.SpriteText.prototype.setBMFont = function ( callback, font, texture ) { texture.needsUpdate = true; texture.minFilter = THREE.LinearMipMapLinearFilter; texture.magFilter = THREE.LinearFilter; texture.generateMipmaps = true; texture.anisotropy = 8; sharedFont = font; sharedTexture = texture; for ( var i = pendingQueue.length - 1; i >= 0; i-- ) { pendingQueue[ i ].target.addText( pendingQueue[ i ].text ); } while ( pendingQueue.length > 0 ) { pendingQueue.pop(); } callback && callback(); }; /** * Add text mesh * @param {string} text - Text to be displayed */ PANOLENS.SpriteText.prototype.addText = function ( text ) { if ( !sharedFont || !sharedTexture ) { pendingQueue.push( { target: this, text: text } ); return; } var textAnchor = new THREE.Object3D(); this.options.text = text; this.options.font = sharedFont; this.options.width = this.maxWidth; var geometry = this.generateTextGeometry( this.options ); geometry.computeBoundingBox(); geometry.computeBoundingSphere(); var material = new THREE.RawShaderMaterial(this.generateSDFShader({ map: sharedTexture, side: THREE.DoubleSide, transparent: true, color: this.color, opacity: this.opacity })); var layout = geometry.layout; var textMesh = new THREE.Mesh( geometry, material ); textMesh.entity = this; textMesh.position.x = -layout.width / 2; textMesh.position.y = layout.height * 1.035; textAnchor.scale.x = textAnchor.scale.y = -0.05; textAnchor.add( textMesh ); this.mesh = textMesh; this.add( textAnchor ); }; /** * Update text geometry * @param {object} options - Geometry options based on * https://github.com/Jam3/three-bmfont-text#geometry--createtextopt */ PANOLENS.SpriteText.prototype.update = function ( options ) { var mesh; options = options || {}; mesh = this.mesh; mesh.geometry.update( options ); mesh.position.x = -mesh.geometry.layout.width / 2; mesh.position.y = mesh.geometry.layout.height * 1.035; }; /** * Create a tween object for animation * based on - {@link https://github.com/tweenjs/tween.js} * @param {string} name - Name of the tween animation * @param {object} object - Object to be tweened * @param {object} toState - Final state of the object's properties * @param {number} duration - Tweening duration * @param {TWEEN.Easing} easing - Easing function * @param {number} delay - Animation delay time * @param {Function} onStart - On start function * @param {Function} onUpdate - On update function * @param {Function} onComplete - On complete function * @return {TWEEN.Tween} - Tween object */ PANOLENS.SpriteText.prototype.tween = function ( name, object, toState, duration, easing, delay, onStart, onUpdate, onComplete ) { object = object || this; toState = toState || {}; duration = duration || this.animationDuration; easing = easing || TWEEN.Easing.Exponential.Out; delay = delay !== undefined ? delay : 0; onStart = onStart ? onStart : null; onUpdate = onUpdate ? onUpdate : null; onComplete = onComplete ? onComplete : null; if ( !this.tweens[name] ) { this.tweens[name] = new TWEEN.Tween( object ) .to( toState, duration ) .easing( easing ) .delay( delay ) .onStart( onStart ) .onUpdate( onUpdate ) .onComplete( onComplete ); } return this.tweens[name]; }; /** * Get geometry layout * @return {object} Text geometry layout */ PANOLENS.SpriteText.prototype.getLayout = function () { return this.mesh && this.mesh.geometry && this.mesh.geometry.layout || {}; }; /** * Set entity if multiple objects are considered as one entity * @param {object} entity - Entity represents whole group structure */ PANOLENS.SpriteText.prototype.setEntity = function ( entity ) { this.entity = entity; }; })();