var THREE = require('three');
const markerImage = new Image(128, 128);
markerImage.src = require("../assets/mapMarker.svg");
const texture = new THREE.Texture();
texture.image = markerImage;
texture.needsUpdate = true;
const size = [0.02, 0.03, 1];
const spriteMaterial = new THREE.SpriteMaterial({
map: texture,
alphaTest: 0.5,
transparent: true,
depthTest: false,
depthWrite: false,
sizeAttenuation: false
});
const createNewSpriteText = require('../utilities').createNewSpriteText;
/**
* A special graphics type with a tear drop shape.
* It is currently used to mark the location of a
* {@link zincObject}.
*
* @class
* @author Alan Wu
* @return {Marker}
*/
const Marker = function(zincObject) {
(require('./zincObject').ZincObject).call(this);
this.texture = texture;
let sprite = undefined;
let userTexture = undefined;
let userMaterial = undefined;
let userSprite = undefined;
let userUrl = undefined;
let defaultDisplay = true;
this.morph = new THREE.Group();
this.group = this.morph;
this.parent = zincObject;
this.isMarker = true;
let enabled = false;
this.ndc = new THREE.Vector3();
let number = undefined;
let label = undefined;
let initialise = () => {
sprite = new THREE.Sprite(spriteMaterial);
sprite.center.set(0.5, 0);
this.morph.add(sprite);
this.morph.position.set(0, 0, 0);
this.morph.renderOrder = 10000;
sprite.scale.set(size[0], size[1], size[2]);
sprite.userData = this;
}
this.updateVisual = (min, max) => {
let scale = 1;
let porportion = 0;
if (min !== max) {
porportion = (1 - (this.ndc.z - min) / (max - min));
scale = 0.6 + porportion * 0.4;
}
this.setSpriteSize(scale);
}
this.updateNDC = camera => {
this.ndc.copy(this.morph.position);
this.ndc.project(camera);
this.ndc.z = Math.min(Math.max(this.ndc.z, 0), 1);
return this.ndc;
}
/**
* Set the position of the marker.
*
* @param {Number} x - x coordinate to be set.
* @param {Number} y - y coordinate to be set.
* @param {Number} z - z coordinate to be set.
*/
this.setPosition = (x, y, z) => {
this.morph.position.set(x, y, z);
}
/**
* Set the size of the marker.
*
* @param {Number} size - size to be set.
*/
this.setSpriteSize = size => {
sprite.scale.set(0.015, 0.02, 1);
sprite.scale.multiplyScalar(size);
}
this.setUserSprite = () => {
if (userSprite) {
this.morph.add(userSprite);
if (defaultDisplay) {
this.morph.remove(sprite);
if (label) {
this.morph.remove(label);
}
defaultDisplay = false;
}
}
}
this.setImageForUserSprite = (image, size) => {
if (userSprite) {
this.morph.remove(userSprite);
userSprite = undefined;
}
if (userTexture) userTexture.dispose();
if (userMaterial) userMaterial.dispose();
userTexture = new THREE.Texture();
userTexture.image = image;
userTexture.needsUpdate = true;
userMaterial = new THREE.SpriteMaterial({
map: userTexture,
alphaTest: 0.5,
transparent: true,
depthTest: false,
depthWrite: false,
sizeAttenuation: false
});
if (!size) {
size = [0.05, 0.05, 1];
}
userSprite = new THREE.Sprite(userMaterial);
userSprite.center.set(0.5, 0);
userSprite.scale.set(size[0], size[1], size[2]);
userSprite.userData = this;
this.setUserSprite();
}
this.setDefaultSprite = () => {
if (!defaultDisplay) {
defaultDisplay = true;
this.morph.add(sprite);
if (userSprite) this.morph.remove(userSprite);
if (label) this.morph.add(label);
}
}
this.loadUserSprite = (url, size) => {
if (url) {
if (url !== userUrl) {
userUrl = url;
const userImage = new Image(128, 128);
userImage.crossOrigin = "anonymous"
userImage.onload = () => {
this.setImageForUserSprite(userImage, size);
};
userImage.src = url;
} else {
this.setUserSprite();
}
}
}
/**
* Clean up this object,
*/
this.dispose = () => {
if (this.morph) {
this.morph.clear();
}
if (sprite) {
sprite.clear();
sprite = undefined;
}
if (label) {
label.material.map.dispose();
label.material.dispose();
label = undefined;
}
}
this.isEnabled = () => {
return enabled;
}
this.setNumber = (numberIn) => {
if (!numberIn || (number != numberIn)) {
//remove label
if (label) {
this.morph.remove(label);
label.material.map.dispose();
label.material.dispose();
label = undefined;
}
}
if (!label && numberIn) {
label = createNewSpriteText(numberIn, 0.012, "black", "Asap", 120, 700);
this.morph.add(label);
}
number = numberIn;
}
this.getNumber = () => {
return number ? number : 1;
}
/**
* Set the visibility of this Geometry.
*
* @param {Boolean} visible - a boolean flag indicate the visibility to be set
*/
this.setVisibility = function(visible) {
if (visible !== this.visible) {
this.visible = visible;
this.group.visible = visible;
if (this.parent.region) this.parent.region.pickableUpdateRequired = true;
}
}
/**
* Enable and visualise the marker.
*/
this.enable = () => {
enabled = true;
this.morph.visible = true;
this.visible = true;
}
/**
* Disable and hide the marker.
*/
this.disable = () => {
enabled = false;
this.morph.visible = false;
this.visible = false;
}
initialise();
}
Marker.prototype = Object.create((require('./zincObject').ZincObject).prototype);
exports.Marker = Marker;