/*global require*/
"use strict";
var defined = require("terriajs-cesium/Source/Core/defined").default;
var ScreenSpaceEventHandler = require("terriajs-cesium/Source/Core/ScreenSpaceEventHandler")
.default;
var ScreenSpaceEventType = require("terriajs-cesium/Source/Core/ScreenSpaceEventType")
.default;
var CustomDataSource = require("terriajs-cesium/Source/DataSources/CustomDataSource")
.default;
/**
* Callback for when a point is moved.
* @callback PointMovedCallback
* @param {CustomDataSource} customDataSource Contains all point entities that user has selected so far
*/
/**
* For letting user drag existing points in Cesium ViewerModes only.
*
* @alias CesiumDragPoints
* @constructor
*
* @param {Terria} terria The Terria instance.
* @param {PointMovedCallback} pointMovedCallback A function that is called when a point is moved.
*/
var CesiumDragPoints = function(terria, pointMovedCallback) {
this._terria = terria;
this._setUp = false;
this.type = "Cesium";
/**
* Callback that occurs when point is moved. Function takes a CustomDataSource which is a list of PointEntities.
* @type {PointMovedCallback}
* @default undefined
*/
this._pointMovedCallback = pointMovedCallback;
/**
* List of entities that can be dragged, which is populated with user-created points only.
* @type {CustomDataSource}
*/
this._draggableObjects = new CustomDataSource();
/**
* Whether user is currently dragging point.
* @type {Bool}
*/
this._dragInProgress = false;
/**
* For determining whether a drag has just occurred, to avoid deleting a point at the end of the drag.
* @type {Number}
*/
this.dragCount = 0;
};
/**
* Set up the drag point helper so that attempting to drag a point will move the point.
*/
CesiumDragPoints.prototype.setUp = function() {
if (this._setUp) {
return;
}
if (
!defined(this._terria.cesium) ||
!defined(this._terria.cesium.scene) ||
!defined(this._terria.cesium.viewer)
) {
// Test context or something has gone *so* badly wrong
return;
}
this._scene = this._terria.cesium.scene;
this._viewer = this._terria.cesium.viewer;
this._mouseHandler = new ScreenSpaceEventHandler(this._scene.canvas, false);
var that = this;
// Mousedown event. This is called for all mousedown events, not just mousedown on entity events like the Leaflet
// equivalent.
this._mouseHandler.setInputAction(function(click) {
if (
!defined(that._draggableObjects.entities) ||
that._draggableObjects.entities.length === 0
) {
return;
}
var pickedObject = that._scene.pick(click.position);
that._originalPosition = click.position;
if (defined(pickedObject)) {
var pickedEntity = pickedObject.id;
var draggedEntity = that._draggableObjects.entities.values.filter(
function(dragObjEntity) {
return dragObjEntity.id === pickedEntity.id;
}
)[0];
if (draggedEntity) {
that._dragInProgress = true;
that._entityDragged = draggedEntity;
that._setCameraMotion(false);
}
}
}, ScreenSpaceEventType.LEFT_DOWN);
// Mouse move event.
this._mouseHandler.setInputAction(function(move) {
if (!that._dragInProgress) {
return;
}
that.dragCount = that.dragCount + 1;
var cartesian = that._viewer.camera.pickEllipsoid(
move.endPosition,
that._scene.globe.ellipsoid
);
that._entityDragged.position = cartesian;
for (var i = 0; i < that._draggableObjects.entities.values.length; i++) {
if (
that._draggableObjects.entities.values[i].id === that._entityDragged.id
) {
that._draggableObjects.entities.values[i].position = cartesian;
}
}
}, ScreenSpaceEventType.MOUSE_MOVE);
// Mouse release event.
this._mouseHandler.setInputAction(function(mouseUp) {
if (that._dragInProgress && mouseUp.position !== that._originalPosition) {
that._pointMovedCallback(that._draggableObjects);
}
that._dragInProgress = false;
that._setCameraMotion(true);
}, ScreenSpaceEventType.LEFT_UP);
this._setUp = true;
};
/**
* Update the list of draggable objects with a new list of entities that are able to be dragged. We are only interested
* in entities that the user has drawn.
*
* @param {CustomDataSource} entities Entities that user has drawn on the map.
*/
CesiumDragPoints.prototype.updateDraggableObjects = function(entities) {
this._draggableObjects = entities;
};
/**
* A clean up function to call when destroying the object.
*/
CesiumDragPoints.prototype.destroy = function() {
if (defined(this._mouseHandler)) {
this._mouseHandler.destroy();
this._setUp = false;
}
};
/**
* Enable or disable camera motion, so that the user can drag a point rather than dragging the map.
* @param {Bool} state True to enable and false to disable camera motion.
* @private
*/
CesiumDragPoints.prototype._setCameraMotion = function(state) {
this._scene.screenSpaceCameraController.enableRotate = state;
this._scene.screenSpaceCameraController.enableZoom = state;
this._scene.screenSpaceCameraController.enableLook = state;
this._scene.screenSpaceCameraController.enableTilt = state;
this._scene.screenSpaceCameraController.enableTranslate = state;
};
module.exports = CesiumDragPoints;