// COMMON_CODE_BLOCK_BEGIN var xRotationEnabled = false; var yRotationEnabled = false; var zRotationEnabled = false; var rotationSpeedFactor = 1; var settingsShown = false; var labelsShown = true; var intervals = []; var timeouts = []; var explodingSpeed = 0.05; var explodeScale = 0; var XMLS = new XMLSerializer(); var svgElement; var render = function () { requestAnimationFrame(render); // comment in for automatic explosion // explode(updateFactor()); var phi = 0.02 * rotationSpeedFactor; if (xRotationEnabled){ scene.rotation.x += phi; } if(yRotationEnabled){ scene.rotation.y += phi; } if(zRotationEnabled){ scene.rotation.z += phi; } controls.update(); renderer.render(scene, camera); }; render(); function computeCentroid(geom) { centroid = new THREE.Vector3(); geom.vertices.forEach(function(v) { centroid.add(v); }); centroid.divideScalar(geom.vertices.length); return centroid; } function changeTransparency(event){ var opacity = 1-Number(event.currentTarget.value); for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ if (all_objects[i].children[j].material.type == "MultiMaterial") { for (var k=0; k<all_objects[i].children[j].material.materials.length; k++){ all_objects[i].children[j].material.materials[k].opacity = opacity; all_objects[i].children[j].material.materials[k].depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.materials[k].depthTest = opacity < 0.5 ? false : true; } } else if (all_objects[i].children[j].material.transparent && all_objects[i].children[j].material.type == "MeshBasicMaterial" && all_objects[i].children[j].geometry.type == "Geometry"){ all_objects[i].children[j].material.opacity = opacity; all_objects[i].children[j].material.depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.depthTest = opacity < 0.5 ? false : true; } } } } function changeRotationX(event){ xRotationEnabled = event.currentTarget.checked; } function changeRotationY(event){ yRotationEnabled = event.currentTarget.checked; } function changeRotationZ(event){ zRotationEnabled = event.currentTarget.checked; } function changeRotationSpeedFactor(event){ rotationSpeedFactor = Number(event.currentTarget.value); } function resetScene(){ scene.rotation.set(0,0,0); camera.position.set(0,0,5); camera.up.set(0,1,0); } function showSettings(event){ event.currentTarget.style.display = 'none'; document.getElementById('settings').style.display = 'inline-block'; document.getElementById('hideSettingsButton').style.display = 'inline'; var canvas = document.getElementsByTagName('canvas')[0]; canvas.style.right = '0px'; canvas.style.transform = 'translate(0,0)'; settingsShown = true; } function hideSettings(event){ event.currentTarget.style.display = 'none'; document.getElementById('settings').style.display = 'none'; document.getElementById('showSettingsButton').style.display = 'block'; var canvas = document.getElementsByTagName('canvas')[0]; canvas.style.right = '50%'; canvas.style.transform = 'translate(50%,0)'; settingsShown = false; } var pos = 150* Math.PI; function updateFactor() { pos++; return Math.sin(.01*pos)+1; } function makelabel(message, x, y, z, params) { var spritey = textSprite( message, params ); spritey.position.set(x, y, z); obj.add(spritey); } function textSprite(message, parameters) { if ( parameters === undefined ) parameters = {}; var fontface = "Helvetica"; var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 18; fontsize = fontsize*10; var canvas = document.createElement('canvas'); var size = 1000; canvas.width = size; canvas.height = size; var context = canvas.getContext('2d'); context.font = fontsize + "px " + fontface; // text color context.fillStyle = "rgba(0, 0, 0, 1.0)"; context.fillText(message, size/2, size/2); // canvas contents will be used for a texture var texture = new THREE.Texture(canvas); texture.needsUpdate = true; var spriteMaterial = new THREE.SpriteMaterial( {map: texture, useScreenCoordinates: false}); var sprite = new THREE.Sprite(spriteMaterial); return sprite; } function takeSvgScreenshot(){ if (labelsShown){ hideLabels(); } svgRenderer.render(scene,camera); svgElement = XMLS.serializeToString(svgRenderer.domElement); if (labelsShown){ displayLabels(); } if (document.getElementById('tab').checked){ //show in new tab var myWindow = window.open("",""); myWindow.document.body.innerHTML = svgElement; } else{ // download svg file download("screenshot.svg", svgElement); } } function showOrHideObject(event){ var nr = Number(event.currentTarget.name); all_objects[nr].visible = event.currentTarget.checked; } function displayOrHideOptions(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ if (all_objects[i].children[j].material.type == "MultiMaterial") { for (var k=0; k<all_objects[i].children[j].material.materials.length; k++){ if (all_objects[i].children[j].material.materials[k].transparent) { document.getElementById('transparency').style.display = 'block'; document.getElementById('transparencyRange').value = 1 - all_objects[i].children[j].material.materials[k].opacity; return; } } } else if (all_objects[i].children[j].material.transparent && all_objects[i].children[j].material.type == "MeshBasicMaterial" && all_objects[i].children[j].geometry.type == "Geometry"){ document.getElementById('transparency').style.display = 'block'; return; } } } } displayOrHideOptions() // ---------------------- EXPLOSION ------------------------------------------------ // --------------------------------------------------------------------------------- function explode(factor) { var obj, c; var c0 = centroids[0]; for (var i = 0; i<centroids.length; ++i) { c = centroids[i]; obj = all_objects[all_objects.length - centroids.length + i]; obj.position.set(c.x*factor, c.y*factor, c.z*factor); } } function triggerExplode(event){ explodeScale = Number(event.currentTarget.value); explode(explodeScale); } function setExplodingSpeed(event){ explodingSpeed = Number(event.currentTarget.value); } function triggerAutomaticExplode(event){ if (event.currentTarget.checked){ startExploding(); } else { clearIntervals(); } } function startExploding(){ intervals.push(setInterval(explodingInterval, 25)); } function explodingInterval(){ explodeScale += explodingSpeed; if (explodeScale <= 6){ explode(explodeScale); } else{ explode(6); explodeScale = 6; clearIntervals(); timeouts.push(setTimeout(startUnexploding, 3000)); } document.getElementById('explodeRange').value = explodeScale; } function startUnexploding(){ intervals.push(setInterval(unexplodingInterval, 25)); } function unexplodingInterval(){ explodeScale -= explodingSpeed; if (explodeScale >= 0){ explode(explodeScale); } else { explode(0); explodeScale = 0; clearIntervals(); timeouts.push(setTimeout(startExploding, 3000)); } document.getElementById('explodeRange').value = explodeScale; } function clearIntervals(){ intervals.forEach(function(interval){ clearInterval(interval); }); intervals = []; timeouts.forEach(function(timeout){ clearTimeout(timeout); }); timeouts = []; } // append checkboxes for displaying or hiding objects var shownObjectsList = document.getElementById('shownObjectsList'); for (var i=0; i<all_objects.length; i++){ var objNode = document.createElement('span'); objNode.innerHTML = objectnames[i] + '<br>'; var checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.checked = true; checkbox.name = String(i); checkbox.onchange = showOrHideObject; shownObjectsList.appendChild(checkbox); shownObjectsList.appendChild(objNode); } function displayLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = true; } } } } function hideLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = false; } } } } function displayOrHideLabels(event){ if (event.currentTarget.checked){ displayLabels(); labelsShown = true; } else { hideLabels(); labelsShown = false; } } function download(filename, text) { var element = document.createElement('a'); element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)); element.setAttribute('download', filename); element.style.display = 'none'; document.body.appendChild(element); element.click(); document.body.removeChild(element); } // ------------------ SHORTCUTS -------------------------------------------- // ------------------------------------------------------------------------- /** * http://www.openjs.com/scripts/events/keyboard_shortcuts/ * Version : 2.01.B * By Binny V A * License : BSD */ shortcut = { 'all_shortcuts':{},//All the shortcuts are stored in this array 'add': function(shortcut_combination,callback,opt) { //Provide a set of default options var default_options = { 'type':'keydown', 'propagate':false, 'disable_in_input':false, 'target':document, 'keycode':false } if(!opt) opt = default_options; else { for(var dfo in default_options) { if(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo]; } } var ele = opt.target; if(typeof opt.target == 'string') ele = document.getElementById(opt.target); var ths = this; shortcut_combination = shortcut_combination.toLowerCase(); //The function to be called at keypress var func = function(e) { e = e || window.event; if(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields var element; if(e.target) element=e.target; else if(e.srcElement) element=e.srcElement; if(element.nodeType==3) element=element.parentNode; if(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return; } //Find Which key is pressed if (e.keyCode) code = e.keyCode; else if (e.which) code = e.which; var character = String.fromCharCode(code).toLowerCase(); if(code == 188) character=","; //If the user presses , when the type is onkeydown if(code == 190) character="."; //If the user presses , when the type is onkeydown var keys = shortcut_combination.split("+"); //Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked var kp = 0; //Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken var shift_nums = { "`":"~", "1":"!", "2":"@", "3":"#", "4":"$", "5":"%", "6":"^", "7":"&", "8":"*", "9":"(", "0":")", "-":"_", "=":"+", ";":":", "'":"\"", ",":"<", ".":">", "/":"?", "\\":"|" } //Special Keys - and their codes var special_keys = { 'esc':27, 'escape':27, 'tab':9, 'space':32, 'return':13, 'enter':13, 'backspace':8, 'scrolllock':145, 'scroll_lock':145, 'scroll':145, 'capslock':20, 'caps_lock':20, 'caps':20, 'numlock':144, 'num_lock':144, 'num':144, 'pause':19, 'break':19, 'insert':45, 'home':36, 'delete':46, 'end':35, 'pageup':33, 'page_up':33, 'pu':33, 'pagedown':34, 'page_down':34, 'pd':34, 'left':37, 'up':38, 'right':39, 'down':40, 'f1':112, 'f2':113, 'f3':114, 'f4':115, 'f5':116, 'f6':117, 'f7':118, 'f8':119, 'f9':120, 'f10':121, 'f11':122, 'f12':123 } var modifiers = { shift: { wanted:false, pressed:false}, ctrl : { wanted:false, pressed:false}, alt : { wanted:false, pressed:false}, meta : { wanted:false, pressed:false} //Meta is Mac specific }; if(e.ctrlKey) modifiers.ctrl.pressed = true; if(e.shiftKey) modifiers.shift.pressed = true; if(e.altKey) modifiers.alt.pressed = true; if(e.metaKey) modifiers.meta.pressed = true; for(var i=0; k=keys[i],i<keys.length; i++) { //Modifiers if(k == 'ctrl' || k == 'control') { kp++; modifiers.ctrl.wanted = true; } else if(k == 'shift') { kp++; modifiers.shift.wanted = true; } else if(k == 'alt') { kp++; modifiers.alt.wanted = true; } else if(k == 'meta') { kp++; modifiers.meta.wanted = true; } else if(k.length > 1) { //If it is a special key if(special_keys[k] == code) kp++; } else if(opt['keycode']) { if(opt['keycode'] == code) kp++; } else { //The special keys did not match if(character == k) kp++; else { if(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase character = shift_nums[character]; if(character == k) kp++; } } } } if(kp == keys.length && modifiers.ctrl.pressed == modifiers.ctrl.wanted && modifiers.shift.pressed == modifiers.shift.wanted && modifiers.alt.pressed == modifiers.alt.wanted && modifiers.meta.pressed == modifiers.meta.wanted) { callback(e); if(!opt['propagate']) { //Stop the event //e.cancelBubble is supported by IE - this will kill the bubbling process. e.cancelBubble = true; e.returnValue = false; //e.stopPropagation works in Firefox. if (e.stopPropagation) { e.stopPropagation(); e.preventDefault(); } return false; } } } this.all_shortcuts[shortcut_combination] = { 'callback':func, 'target':ele, 'event': opt['type'] }; //Attach the function with the event if(ele.addEventListener) ele.addEventListener(opt['type'], func, false); else if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func); else ele['on'+opt['type']] = func; }, //Remove the shortcut - just specify the shortcut and I will remove the binding 'remove':function(shortcut_combination) { shortcut_combination = shortcut_combination.toLowerCase(); var binding = this.all_shortcuts[shortcut_combination]; delete(this.all_shortcuts[shortcut_combination]) if(!binding) return; var type = binding['event']; var ele = binding['target']; var callback = binding['callback']; if(ele.detachEvent) ele.detachEvent('on'+type, callback); else if(ele.removeEventListener) ele.removeEventListener(type, callback, false); else ele['on'+type] = false; } } shortcut.add("Alt+Left",function() { var event = new Event('click'); if (settingsShown){ document.getElementById('hideSettingsButton').dispatchEvent(event); } else{ document.getElementById('showSettingsButton').dispatchEvent(event); } }); if (foldable) moveToBaryCenter(); // COMMON_CODE_BLOCK_END