/*
█████╗ ██████╗████████╗██╗██╗ ██╗███████╗ ██╗ ██╗███████╗██╗ ██╗ █████╗ ██████╗ ██████╗ ███╗ ██╗
██╔══██╗██╔════╝╚══██╔══╝██║██║ ██║██╔════╝ ██║ ██║██╔════╝╚██╗██╔╝██╔══██╗██╔════╝ ██╔═══██╗████╗ ██║
███████║██║ ██║ ██║██║ ██║█████╗ ███████║█████╗ ╚███╔╝ ███████║██║ ███╗██║ ██║██╔██╗ ██║
██╔══██║██║ ██║ ██║╚██╗ ██╔╝██╔══╝ ██╔══██║██╔══╝ ██╔██╗ ██╔══██║██║ ██║██║ ██║██║╚██╗██║
██║ ██║╚██████╗ ██║ ██║ ╚████╔╝ ███████╗ ██║ ██║███████╗██╔╝ ██╗██║ ██║╚██████╔╝╚██████╔╝██║ ╚████║
╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═══╝ ╚══════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝
*/
// TODO: separate placing of additive prview hexagons
var active_hex_dummy = new THREE.Object3D();
active_hex_dummy.matrixAutoUpdate = false;
this.container.add( active_hex_dummy );
var active_hexagon = null;//
var extActiveHexagonHide;// External method to hide DOM element of the active hexagon
// ACTIVE HEXAGON
function activateHexagon( _location, mobile){
scope.deactivateHexagon();
main.controls.autoRotate = false;
scope.location_current = _location;
// Define an array of nearby locations to view
location_picked = _location;
_location.briefs = PlanetData.hasLocationAnyBriefs( location_picked, true );
_location.briefs_text = PlanetData.hasLocationAnyBriefTexts( location_picked, true );
_location.works_list = PlanetData.getWorkList( location_picked, true );
_location.more = PlanetData.getMoreText( location_picked, true );
;
var _locations = [ _location ];
// Hit an external method to show defined hexagons
if( kaspersky.getHexaspherePopup ) {
var o = kaspersky.getHexaspherePopup( _locations, moveToActiveHexagon, mobile);
active_hexagon = o.element;
extActiveHexagonHide = o.close;
var $active_hexagon = $(active_hexagon);
$active_hexagon.on( "mouseleave", onActiveHexagonMouseLeave );
function onActiveHexagonMouseLeave(){
scope.deactivateHexagon();
$active_hexagon.off( "mouseleave", onActiveHexagonMouseLeave );
}
}
active_hex_dummy.position.copy( _location.position );
// Disable Earth constant rotation
main.controls.autoRotate = false;
_location.light.visible = false;
// Hide current commentary
scope.commentToggle( false );
}
this.deactivateHexagon = function() {
if( !location_picked ) return;
if (typeof extActiveHexagonHide === "function") extActiveHexagonHide();
active_hexagon = null;
scope.location_current = null;
location_picked.light.visible = true;
location_picked = null;
main.controls.autoRotate = true;
// show a commentary
scope.commentToggle( true );
}
var camera_rotator = new THREE.Object3D();
camera_rotator.up = new THREE.Vector3(0,1,0);
main.scene.add(camera_rotator);
camera_rotator.matrixAutoUpdate = false;
function moveToActiveHexagon( location ) {
var navigateUrl;
var $info = location.years[PlanetData.YEAR_ID];
if ($info.type === "brief") {
navigateUrl = langUrl + $info.brief_id;
} else {
navigateUrl = langUrl + "locations/" + PlanetData.YEAR_ID + "/" + location.location_id;
}
scope.state = scope.ANIMATED;
main.controls.detach();
DOMElement.style.cursor = "default";
scope.deactivateHexagon();
// hide current commentary
scope.commentToggle( false );
// target rotation
camera_rotator.lookAt( location.position );
var qend = camera_rotator.quaternion.clone();
camera_rotator.lookAt( main.camera.position );
var qstart = camera_rotator.quaternion.clone();
camera_rotator.updateMatrix();
var d = main.camera.position.length();
camera_rotator.add( main.camera );
main.camera.position.set( 0,0,d );
main.camera.rotation.set( 0,0,0 );
scene.updateMatrixWorld();
// ANIMATE SPHERICAL ROTATION TO ACTIVE HEXAGON
camera_rotator._anim_progress_ = 0;
TweenLite.to( camera_rotator, 1.5, {
_anim_progress_: 1,
ease: Sine.easeInOut,
onUpdate: function () {
THREE.Quaternion.slerp( qstart, qend, camera_rotator.quaternion, camera_rotator._anim_progress_ );
camera_rotator.updateMatrix();
},
onComplete: function() {
TweenLite.to( main.camera.position, 1.2, {
z: radius*1.15,
ease: Sine.easeIn,
onComplete: function() {
}
});
// show Transition
setTimeout( kaspersky.Transition.fadeIn, 400);
setTimeout(function () {
kaspersky.navigateTo( navigateUrl );
}, 400);
}
});
}
// UTILS
this.isInFrontOfPlanet = function( position ) {
var dist = camera.position.distanceToSquared( position );
if( dist > camera_dist_to_center ) return false;
return true;
}
this.googlePosToUV = function( _u, _v ){
if( _u===undefined ) {
var a = ('40.705565,-74.1180857').split(",");
_u = a[0];
_v = a[1];
}
var u = 1-(parseFloat( _u ) + 90 )/180;
u += .014; if( u>1 ) u = u-1;
var v = (parseFloat( _v ) + 180 )/360;
v -= .031; if( v<0 ) v = 1+v;
return {u:u,v:v};
}
// INIT THE PLANET
var _first_year = window.currentYear || PlanetData.year_ids[0];
onReady();
main.animateOut( .05 , function(){
scope.showYear( _first_year, undefined, 6 );
});
}
Planet.prototype.getClosestLocation = function( intersection ) {
var _location_current;
var min = isMobile.any ? .15 : .04;
var _locations = this.planetLocations.current_locations;
for (var i = 0; i < _locations.length; i++) {
var l = _locations[i];
// if the location object has no briefs
if( !l.position ) continue;
if( !PlanetData.hasLocationAnyBriefs( l, true ) ) continue;
var d = intersection.distanceToSquared( l.position );
if( d<min ){
min = d;
_location_current = l;
break;
}
};
return _location_current;
}
Planet.prototype.getAnyClosestLocation = function( intersection, except_locations ) {
var _location_current;
var min = 10000;
var _locations = this.planetLocations.current_locations;
for (var i = 0; i < _locations.length; i++) {
var l = _locations[i];
if( except_locations && checkExceptions( l ) ) continue;
var d = intersection.distanceToSquared( l.position );
if( d<min ){
min = d;
_location_current = l;
}
};
function checkExceptions ( l ) {
for (var j = 0; j < except_locations.length; j++) {
if( except_locations[j] == l) return true;
};
return false;
}
return _location_current;
}
function Hexagon ( scene ) {
var active_color = new THREE.Color( 0xffffff );
var inactive_color = new THREE.Color( 0x507e50 );
var mesh = Utils.createHexagon( .5 );
// mesh.up = new THREE.Vector3(0,1,0);
var material = mesh.material;
material.transparent = true;
material.opacity = .4;
material.blending = THREE.AdditiveBlending;
material.depthWrite = false;
mesh._anim_progress = .001;
mesh.scale.set( mesh._anim_progress, mesh._anim_progress, mesh._anim_progress );
mesh.setToLocation = function ( l ) {
// console.log("setToTile: ", l);
mesh.location = l;
mesh.position.copy( l.position );
mesh.lookAt( new THREE.Vector3() );
material.color = active_color;
scene.add( mesh );
mesh.matrixAutoUpdate = true;
TweenLite.killTweensOf( mesh );
TweenLite.to( mesh, .2, {
_anim_progress: .8,// * .8,
// ease: Sine.easeOut,
onUpdate: function () {
mesh.scale.set( mesh._anim_progress, mesh._anim_progress, mesh._anim_progress );
},
onComplete:function() {
mesh.matrixAutoUpdate = false;
}
});
}
mesh.hide = function( _assets ) {
mesh.matrixAutoUpdate = true;
TweenLite.killTweensOf( mesh );
TweenLite.to( mesh, 1, {
_anim_progress: .001,
// ease: Sine.easeIn,
onUpdate: function () {
mesh.scale.set( mesh._anim_progress, mesh._anim_progress, mesh._anim_progress );
},
onComplete: function () {
scene.remove( mesh );
_assets.push( mesh );
mesh.matrixAutoUpdate = false;
}
});
}
/*
//
mesh.setActive = function() {
// console.log("setActive", mesh.tile);
if( !mesh.tile ) return;
mesh.is_active = true;
TweenLite.killTweensOf( mesh );
mesh._anim_progress = 0;
TweenLite.to( mesh, .2, {
_anim_progress: 1,
// ease: Sine.easeOut,
onUpdate: function () {
var scl = mesh._anim_progress*1+1;
mesh.scale.set( scl, scl, scl );
mesh.position.copy( mesh.tile.centerPoint ).multiplyScalar( 1 + scl*.05 );
}
});
}
mesh.setInactive = function( _assets ) {
// _assets.push( mesh );
mesh.is_active = false;
TweenLite.killTweensOf( mesh );
// mesh._anim_progress = 0;
TweenLite.to( mesh, .5, {
_anim_progress: .01,
// ease: Sine.easeOut,
onUpdate: function () {
mesh.scale.set( mesh._anim_progress, mesh._anim_progress, mesh._anim_progress );
},
onComplete: function () {
scene.remove( mesh );
_assets.push( mesh );
}
});
}
*/
return mesh;
}
function PlanetLocations ( planet ) {
var data = planet.data;
var data_locations = data.locations;
var current_container;
this.current_locations;// a list of locations corresponding to the current year
var max_opacity = .8;
var material_yellow = new THREE.MeshBasicMaterial({
transparent : true,
opacity : 0,
color : new THREE.Color( 0xffde00 ),
blending : THREE.AdditiveBlending,
side : THREE.DoubleSide,
depthWrite : false
});
var material_white = new THREE.MeshBasicMaterial({
transparent : true,
opacity : 0,
color : new THREE.Color( 0xffffff ),
blending : THREE.AdditiveBlending,
side : THREE.DoubleSide,
depthWrite : false,
});
// !!! fake locations
// get image links
var f_images = [];
for (var i = 0; i < data_locations.length; i++) {
f_images.push( data_locations[i].preview );
}
// make base location shape
var hex = Utils.createHexagon( .15, false, undefined );
// additional shape - the ring
var hex_ring = Utils.createHexagon( .2, false, undefined, .02 );
hex.add( hex_ring );
var r = planet.radius*1.005;
var zero = new THREE.Vector3();
// METHODS
this.init = function ( _year ){
var container = new THREE.Object3D();
container.matrixAutoUpdate = false;
var _locations = container._locations = [];
for (var i = 0; i < data_locations.length; i++) {
var l = data_locations[i];
_locations.push( l );/// All Locations are available in all Years
}
var geo;
var geo_yellow = new THREE.Geometry();//hex.geometry.clone();
var geo_white = new THREE.Geometry();//hex.geometry.clone();
for (var i = 0; i < _locations.length; i++) {
var l = _locations[i];
if(!!l.years[_year] === false) continue;
var l_year_data = l.years[_year];
// skip a point creation if the location doesn't have any briefs
if( !l_year_data.briefs ) continue;
// get shorthand to a country object of the location
l.country = data.countries_by_id[ l.country_id ];
var uv = planet.googlePosToUV( l.planet_u, l.planet_v );
Utils.setFromSpherical( r, uv.v, uv.u, hex.position );
hex.lookAt( zero );
hex.updateMatrix();
hex.updateMatrixWorld();
geo = l_year_data.works ? geo_yellow : geo_white;
geo.merge( hex.geometry, hex.matrixWorld );
geo.merge( hex_ring.geometry, hex_ring.matrixWorld );
l.position = hex.position.clone();
// and finaly the ray
l.light = addLightRay( hex.position, l_year_data.works );
container.add( l.light );
};
var hexs_yellow = new THREE.Mesh( geo_yellow, material_yellow );
container.add( hexs_yellow );
var hexs_white = new THREE.Mesh( geo_white, material_white );
container.add( hexs_white );
return container;
}
this.show = function( _year, t ){
var year_data = PlanetData.years[_year];
if( !year_data.locations_container ) year_data.locations_container = this.init( _year );
current_container = year_data.locations_container;
this.current_locations = current_container._locations;
planet.container.add( current_container );
_showMaterial( material_yellow, t );
_showMaterial( material_white, t );
showRays( t/2, t/2 );
}
function _showMaterial( mat, t ){
var _anim = 0;
var t1 = .3;
mat.opacity = 0;
TweenLite.killTweensOf( mat );
TweenLite.to( mat, t1, {
delay: t-t1,
ease: Sine.easeOut
,onUpdate:function(){
_anim += 1;
mat.opacity = Math.round( _anim%2 ) * max_opacity;
}
,onComplete: function(){
mat.opacity = max_opacity;
}
});
}
this.hide = function ( t ) {
_hideMaterial( material_yellow, t );
_hideMaterial( material_white, t );
hideRays( t/2 );
}
function _hideMaterial( mat, t ){
var _anim = 0;
TweenLite.killTweensOf( mat );
TweenLite.to( mat, .3, {
ease: Sine.easeInOut
,onUpdate:function(){
_anim += 1;
mat.opacity = Math.round( _anim%2 ) * max_opacity;
}
,onComplete: function(){
planet.container.remove( current_container );
}
});
}