1044 lines
40 KiB
JavaScript
Executable File
1044 lines
40 KiB
JavaScript
Executable File
import {
|
|
creerTravee,
|
|
creerOuverture,
|
|
supprimerToutesOuvertures,
|
|
traitementCreationTravee,
|
|
traitementCreationOuverture,
|
|
selectionnerSolivage,
|
|
recreerTrappes
|
|
} from "./objects.js"
|
|
|
|
import {
|
|
createText,
|
|
glassMaterial,
|
|
doorMaterial,
|
|
garageDoorMaterial,
|
|
pignonMaterial,
|
|
wallMaterial,
|
|
roofMaterial,
|
|
MPL_Material,
|
|
MPE_Material,
|
|
MF1d_Material,
|
|
MF1g_Material,
|
|
MF2_Material,
|
|
MPEF_Material,
|
|
MPF_Material,
|
|
MPI_Material,
|
|
MPG1_Material,
|
|
MPG2_Material,
|
|
PEXT_Material,
|
|
CH1T_Material,
|
|
COLOR_ARRAY,
|
|
blankMaterial,
|
|
groundMaterial
|
|
}
|
|
from "./materials.js"
|
|
|
|
import {
|
|
URL_JSREPORT,
|
|
info,
|
|
alerte,
|
|
log,
|
|
retirerObjetModifiable,
|
|
extraireFace,
|
|
extraireNomTravee,
|
|
verifierContraintes,
|
|
showMainIncrustations,
|
|
hideMainIncrustations,
|
|
showPignonIncrustations,
|
|
hidePignonIncrustations,
|
|
incrusterCotes,
|
|
animate,
|
|
recalculerConstructions,
|
|
calculerTaillePoliceOptimale,
|
|
redimensionnerIncrustations,
|
|
changerCouleurTextes,
|
|
verifierControlesMetier,
|
|
modifierIncrustation,
|
|
restaurerPrefsUtilisateur,
|
|
importProjet,
|
|
exportProjet,
|
|
initObjetsSysteme,
|
|
updateClipboard
|
|
} from "./main.js"
|
|
|
|
import {
|
|
camera,
|
|
cameraOrtho,
|
|
canvas,
|
|
renderer,
|
|
aspectRatio,
|
|
initPositionCamera
|
|
} from "./environment.js"
|
|
|
|
|
|
export function unSelect() {
|
|
|
|
/* On masque le menu déroulant...
|
|
on déselectionne tous les objets à l'IHM,
|
|
puis on vide les variables */
|
|
|
|
$("#div-menu-contextuel").hide();
|
|
|
|
if (objetSelectionne) {
|
|
var objetTouche = scene.getObjectByName(objetSelectionne);
|
|
|
|
for (var i = 0; i < facesSelectionnees.length; i++) {
|
|
|
|
// Suivant l'objet touché...
|
|
if (!objetTouche.parent.name.includes('>')) { // Un mur
|
|
objetTouche.geometry.faces[facesSelectionnees[i]].color.set(COLOR_ARRAY['blanc']);
|
|
} else {
|
|
|
|
if (objetTouche.name.includes('Portique'))
|
|
objetTouche.geometry.faces[facesSelectionnees[i]].color.set(COLOR_ARRAY['blanc']);
|
|
|
|
if (objetTouche.name.includes('Vitre'))
|
|
objetTouche.material = glassMaterial;
|
|
|
|
if (objetTouche.name.includes('Porte')) {
|
|
if (objetTouche.name.includes('PG'))
|
|
objetTouche.material = garageDoorMaterial;
|
|
else
|
|
objetTouche.material = doorMaterial;
|
|
}
|
|
|
|
if (objetTouche.name.includes('PINT')) { // Pignon intérieur
|
|
for (var k = 0; k < 12; k++) {
|
|
objetTouche.geometry.faces[k].color.set(COLOR_ARRAY['blanc']);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
objetTouche.geometry.elementsNeedUpdate = true;
|
|
}
|
|
facesSelectionnees.length = 0;
|
|
objetSelectionne = '';
|
|
|
|
if ($("#message-info").prop("class") == "normal")
|
|
info(null);
|
|
}
|
|
|
|
|
|
|
|
export function changePointOfView(direction, modePDF = false) {
|
|
|
|
// On calcule les contours de notre construction
|
|
var left = tableauTravees['Travee 1'].positionX - (LARGEUR_TRAVEE / 2);
|
|
var right = tableauTravees['Travee ' + nbTravees].positionX + (LARGEUR_TRAVEE / 2);
|
|
var front = LONGUEUR_TRAVEE / 2;
|
|
var back = -(LONGUEUR_TRAVEE / 2);
|
|
|
|
var decalageGauche = tableauTravees['Travee 1'].decalage * (LONGUEUR_TRAVEE / 2);
|
|
var decalageDroite = tableauTravees['Travee ' + nbTravees].decalage * (LONGUEUR_TRAVEE / 2);
|
|
if (decalageGauche < 0 || decalageDroite < 0)
|
|
back = -LONGUEUR_TRAVEE;
|
|
|
|
if (decalageGauche > 0 || decalageDroite > 0)
|
|
front = LONGUEUR_TRAVEE;
|
|
|
|
if (modePDF)
|
|
activeCamera = cameraOrtho;
|
|
else
|
|
activeCamera = camera;
|
|
|
|
switch (direction) {
|
|
case 'dessus':
|
|
camera.position.set(0, 200, 0);
|
|
camera.lookAt(scene.position);
|
|
info("Vue de dessus");
|
|
break;
|
|
case 'avant':
|
|
if (modePDF) {
|
|
cameraOrtho.position.set(0, HAUTEUR_TRAVEE / 2, 80);
|
|
cameraOrtho.lookAt(0, HAUTEUR_TRAVEE / 2, 0);
|
|
|
|
cameraOrtho.left = tableauTravees['Travee 1'].positionX - 40;
|
|
cameraOrtho.right = tableauTravees['Travee ' + nbTravees].positionX + 40;
|
|
cameraOrtho.top = (((cameraOrtho.right - cameraOrtho.left) / aspectRatio) / 2) + 10;
|
|
cameraOrtho.bottom = -(((cameraOrtho.right - cameraOrtho.left) / aspectRatio) / 2) + 10;
|
|
cameraOrtho.far = 100;
|
|
cameraOrtho.near = -100;
|
|
} else {
|
|
camera.position.set(0, 10, 100 + front + (Math.log(nbTravees) * 50));
|
|
camera.lookAt(scene.position);
|
|
}
|
|
info("Vue avant");
|
|
break;
|
|
case 'arriere':
|
|
if (modePDF) {
|
|
cameraOrtho.position.set(0, HAUTEUR_TRAVEE / 2, -80);
|
|
cameraOrtho.lookAt(0, HAUTEUR_TRAVEE / 2, 0);
|
|
|
|
cameraOrtho.left = tableauTravees['Travee 1'].positionX - 40;
|
|
cameraOrtho.right = tableauTravees['Travee ' + nbTravees].positionX + 40;
|
|
cameraOrtho.top = (((cameraOrtho.right - cameraOrtho.left) / aspectRatio) / 2) + 10;
|
|
cameraOrtho.bottom = -(((cameraOrtho.right - cameraOrtho.left) / aspectRatio) / 2) + 10;
|
|
cameraOrtho.far = 100;
|
|
cameraOrtho.near = -100;
|
|
} else {
|
|
camera.position.set(0, 10, -100 + back - (Math.log(nbTravees) * 50));
|
|
camera.lookAt(scene.position);
|
|
}
|
|
info("Vue arrière");
|
|
break;
|
|
case 'gauche':
|
|
if (modePDF) {
|
|
var posLeft = tableauTravees['Travee 1'].positionX - (LARGEUR_TRAVEE / 2);
|
|
cameraOrtho.position.set(posLeft - 50, HAUTEUR_TRAVEE / 2, (decalageGauche + decalageDroite) / 2);
|
|
cameraOrtho.lookAt(0, HAUTEUR_TRAVEE / 2, (decalageGauche + decalageDroite) / 2);
|
|
|
|
cameraOrtho.left = -80;
|
|
cameraOrtho.right = 80;
|
|
cameraOrtho.top = (((cameraOrtho.right - cameraOrtho.left) / aspectRatio) / 2) + 10;
|
|
cameraOrtho.bottom = -(((cameraOrtho.right - cameraOrtho.left) / aspectRatio) / 2) + 10;
|
|
cameraOrtho.near = tableauTravees['Travee 1'].positionX - 20;
|
|
cameraOrtho.far = tableauTravees['Travee ' + nbTravees].positionX + 20;
|
|
|
|
if (DEBUG) {
|
|
log("cameraOrtho.left=" + cameraOrtho.left + " / cameraOrtho.right=" + cameraOrtho.right + " / cameraOrtho.near=" + cameraOrtho.near + " / cameraOrtho.far=" + cameraOrtho.far);
|
|
log("decalageGauche=" + decalageGauche + " / decalageDroite=" + decalageDroite);
|
|
log("cameraPosition=");
|
|
log(cameraOrtho.position);
|
|
}
|
|
} else {
|
|
var z;
|
|
if (decalageDroite == 0)
|
|
z = -decalageGauche * 2;
|
|
else
|
|
z = decalageDroite * 2;
|
|
|
|
camera.position.set(-100 + left, 10, z);
|
|
camera.lookAt(scene.position);
|
|
}
|
|
info("Vue de gauche");
|
|
break;
|
|
case 'droite':
|
|
if (modePDF) {
|
|
var posRight = tableauTravees['Travee ' + nbTravees].positionX + (LARGEUR_TRAVEE / 2);
|
|
cameraOrtho.position.set(posRight + 50, HAUTEUR_TRAVEE / 2, (decalageGauche + decalageDroite) / 2);
|
|
cameraOrtho.lookAt(0, HAUTEUR_TRAVEE / 2, (decalageGauche + decalageDroite) / 2);
|
|
|
|
cameraOrtho.left = -80;
|
|
cameraOrtho.right = 80;
|
|
cameraOrtho.top = (((cameraOrtho.right - cameraOrtho.left) / aspectRatio) / 2) + 10;
|
|
cameraOrtho.bottom = -(((cameraOrtho.right - cameraOrtho.left) / aspectRatio) / 2) + 10;
|
|
cameraOrtho.near = tableauTravees['Travee 1'].positionX - 20;
|
|
cameraOrtho.far = tableauTravees['Travee ' + nbTravees].positionX + 20;
|
|
|
|
if (DEBUG) {
|
|
log("cameraOrtho.left=" + cameraOrtho.left + " / cameraOrtho.right=" + cameraOrtho.right + " / cameraOrtho.near=" + cameraOrtho.near + " / cameraOrtho.far=" + cameraOrtho.far);
|
|
log("decalageGauche=" + decalageGauche + " / decalageDroite=" + decalageDroite);
|
|
log("cameraPosition=");
|
|
log(cameraOrtho.position);
|
|
}
|
|
} else {
|
|
var z;
|
|
if (decalageGauche == 0)
|
|
z = -decalageDroite * 2;
|
|
else
|
|
z = decalageGauche * 2;
|
|
|
|
camera.position.set(100 + right, 10, z);
|
|
camera.lookAt(0, 0, -z);
|
|
}
|
|
info("Vue de droite");
|
|
break;
|
|
case 'perspective':
|
|
camera.position.set(60, 40, 160);
|
|
camera.lookAt(scene.position);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
export function afficherVueAerienne(modePDF = false) {
|
|
|
|
$("div:contains('Close Controls')").click();
|
|
$("#changement-vue div#aerien").addClass('actif');
|
|
|
|
// On masque toit et plancher (si pas déjà masqués)
|
|
if ($("span:contains('afficherToit')").parent().find("input[type='checkbox']").prop('checked'))
|
|
$("span:contains('afficherToit')").click();
|
|
|
|
if ($("span:contains('afficherPlancher')").parent().find("input[type='checkbox']").prop('checked'))
|
|
$("span:contains('afficherPlancher')").click();
|
|
|
|
initPositionCamera(cameraOrtho);
|
|
|
|
// On calcule les limites gauche, droite, haut et bas de la construction, afin de cadrer au mieux.
|
|
var MARGE_GAUCHE = 20;
|
|
var MARGE_DROITE = 50;
|
|
var MARGE_HAUT = 5;
|
|
var MARGE_BAS = 30;
|
|
|
|
var gauche = tableauTravees['Travee 1'].positionX - (LARGEUR_TRAVEE / 2) - MARGE_GAUCHE; // Bord gauche de la construction + marge
|
|
var droite = tableauTravees['Travee ' + nbTravees].positionX + (LARGEUR_TRAVEE / 2) + MARGE_DROITE; // Bord droit + marge
|
|
var largeur = droite - gauche;
|
|
var hauteurCalculee = largeur / aspectRatio;
|
|
|
|
var maxTop = 0;
|
|
var minBottom = 0;
|
|
for (var laTravee in tableauTravees) {
|
|
if (tableauTravees[laTravee].positionZ < maxTop)
|
|
maxTop = tableauTravees[laTravee].positionZ;
|
|
|
|
if (tableauTravees[laTravee].positionZ >= minBottom)
|
|
minBottom = tableauTravees[laTravee].positionZ;
|
|
}
|
|
maxTop -= (LONGUEUR_TRAVEE / 2);
|
|
maxTop = -maxTop + MARGE_HAUT;
|
|
minBottom += (LONGUEUR_TRAVEE / 2);
|
|
minBottom = -minBottom - MARGE_BAS;
|
|
var hauteur = maxTop - minBottom;
|
|
var largeurCalculee = hauteur * aspectRatio;
|
|
|
|
if (hauteurCalculee >= hauteur) {
|
|
cameraOrtho.left = gauche;
|
|
cameraOrtho.right = droite;
|
|
cameraOrtho.top = maxTop + ((hauteurCalculee - hauteur) / 2);
|
|
cameraOrtho.bottom = minBottom - ((hauteurCalculee - hauteur) / 2);
|
|
} else {
|
|
cameraOrtho.top = maxTop;
|
|
cameraOrtho.bottom = minBottom;
|
|
cameraOrtho.left = gauche - ((largeurCalculee - largeur) / 2);
|
|
cameraOrtho.right = droite + ((largeurCalculee - largeur) / 2);
|
|
}
|
|
|
|
|
|
if (DEBUG) {
|
|
log("left/right : " + gauche + " / " + droite + " soit une largeur de " + largeur + " et une hauteur calculée de " + hauteurCalculee);
|
|
log("top/bottom : " + maxTop + " / " + minBottom + " soit une hauteur de " + hauteur + " et une largeur calculée de " + largeurCalculee);
|
|
}
|
|
|
|
activeCamera = cameraOrtho;
|
|
|
|
$("#changement-vue div#aerien").addClass('surligne');
|
|
showMainIncrustations();
|
|
hidePignonIncrustations();
|
|
|
|
// On adapte la taille des incrustations au niveau de zoom : pour ça, pas d'autre choix
|
|
// que de supprimer/recréer les incrustations.
|
|
if (!modePDF)
|
|
redimensionnerIncrustations();
|
|
|
|
$("#legende").hide();
|
|
$("#vue-aerienne").show();
|
|
$("#transparent-overlay").show();
|
|
}
|
|
|
|
/******************************* Gestion du menu contextuel ***********************************************/
|
|
|
|
function addInfo(message) {
|
|
var liText = "<li class=\"blank\">" + message + "</li>";
|
|
|
|
$('.liste-deroulante').append(liText);
|
|
}
|
|
|
|
function addMenu(menuTitle, action, isActive = true) {
|
|
|
|
var liText = liText = "<li data-action=\"" + action + "\"";
|
|
|
|
if (action.match('moveFront')) liText += " class=\"moveFront";
|
|
if (action.match('moveBack')) liText += " class=\"moveBack";
|
|
if (action.match('add')) liText += " class=\"add";
|
|
if (action.match('delete')) liText += " class=\"delete";
|
|
if (action.match('choose')) liText += " class=\"choose";
|
|
if (!isActive) liText += " disabled";
|
|
liText += "\">" + menuTitle + "</li>";
|
|
|
|
$('.liste-deroulante').append(liText);
|
|
}
|
|
|
|
function addSeparator() {
|
|
var liText = "<hr>";
|
|
$('.liste-deroulante').append(liText);
|
|
}
|
|
|
|
|
|
export function chooseFloorHole(traveeSelectionnee) {
|
|
$('.popup-ouverture-image').each(function (i) {
|
|
$(this).parent().removeClass();
|
|
$(this).parent().addClass("normal");
|
|
});
|
|
|
|
$("#popup-plancher").show();
|
|
$("#traveeSelectionnee").val(traveeSelectionnee);
|
|
$("#overlay").show();
|
|
}
|
|
|
|
|
|
export function displayPignonOpenings(traveeSelectionnee) {
|
|
// RAZ des figures
|
|
$('.popup-ouverture-image').each(function (i) {
|
|
$(this).parent().removeClass();
|
|
$(this).parent().addClass("normal");
|
|
});
|
|
|
|
$("#popup-pignon").show();
|
|
$("#traveeSelectionnee").val(traveeSelectionnee);
|
|
$("#overlay").show();
|
|
}
|
|
|
|
|
|
export function displayOpenings(traveeSelectionnee, face) {
|
|
// RAZ des figures
|
|
$('.popup-ouverture-image').each(function (i) {
|
|
$(this).parent().removeClass();
|
|
$(this).parent().addClass("normal");
|
|
});
|
|
disableUnauthorizedOpenings(verifierContraintes(traveeSelectionnee));
|
|
|
|
if (face == 'interieur')
|
|
$("#popup-ouverture-in").show();
|
|
else
|
|
$("#popup-ouverture-out").show();
|
|
|
|
$("#traveeSelectionnee").val(traveeSelectionnee);
|
|
$("#overlay").show();
|
|
}
|
|
|
|
export function disableUnauthorizedOpenings(tableauOuverturesAutorisees) {
|
|
|
|
$('.popup-ouverture-image').each(function (i) {
|
|
|
|
if (!tableauOuverturesAutorisees.includes($(this).parent().attr('id'))) {
|
|
$(this).parent().toggleClass("disabled");
|
|
}
|
|
});
|
|
}
|
|
|
|
export function displayContextualMenu(objet, x, y) {
|
|
|
|
if (facesSelectionnees.length > 1) return;
|
|
|
|
/* -> ex : "Travee 1>AV" => décaler la travée + rajouter ouverture (si permis)
|
|
-> ex : "Travee 1>PDAV" => seulement rajouter une ouverture
|
|
-> ex : "Travee 1>AV>Ouverture F2>Vitre" => seulement supprimer l'ouverture */
|
|
$('.liste-deroulante').empty();
|
|
|
|
addInfo($("#message-info").html());
|
|
addSeparator();
|
|
if (objet.name.includes('Ouverture'))
|
|
addMenu("Supprimer cette ouverture", 'deleteOuverture');
|
|
else {
|
|
if (objet.name.includes('>AV') || objet.name.includes('>AR')) {
|
|
|
|
var decalageActuel = tableauTravees[objet.parent.name]['decalage'];
|
|
if (decalageActuel < 0) {
|
|
addMenu("Reculer cette travée", 'moveBackTravee', false);
|
|
addMenu("Avancer cette travée", 'moveFrontTravee');
|
|
} else {
|
|
if (decalageActuel > 0) {
|
|
addMenu("Reculer cette travée", 'moveBackTravee');
|
|
addMenu("Avancer cette travée", 'moveFrontTravee', false);
|
|
|
|
} else {
|
|
addMenu("Reculer cette travée", 'moveBackTravee');
|
|
addMenu("Avancer cette travée", 'moveFrontTravee');
|
|
}
|
|
}
|
|
addSeparator();
|
|
}
|
|
if (objet.name.includes('plancher')) {
|
|
addMenu("Choisir le solivage", 'chooseFloorHole');
|
|
} else {
|
|
|
|
if (objet.name.includes('PINT')) {
|
|
addMenu("Choisir l'ouverture", 'addPignonOpening');
|
|
} else {
|
|
var nomFace = extraireFace(objet.name);
|
|
// S'il existe déjà une ouverture sur ce module, on grise la possibilité d'en ajouter une autre.
|
|
if (tableauTravees[extraireNomTravee(objet.name)]['nb_ouvertures_' + nomFace] > 0)
|
|
addMenu("Créer une ouverture", 'addOpening', false);
|
|
else
|
|
addMenu("Créer une ouverture", 'addOpening');
|
|
}
|
|
}
|
|
}
|
|
addSeparator();
|
|
addMenu("Annuler la sélection", 'unselect');
|
|
|
|
|
|
// Suivant la position du curseur, on place le menu à gauche ou à droite de cette dernière.
|
|
var left = (x >= (window.innerWidth / 2)) ? (x + 30) + 'px' : (x - $("#div-menu-contextuel").width() - 30) + 'px';
|
|
$("#div-menu-contextuel").css({
|
|
left: left,
|
|
top: y - ($("#div-menu-contextuel").height() / 2) + 'px'
|
|
});
|
|
$("#div-menu-contextuel").show();
|
|
}
|
|
|
|
|
|
|
|
function saveAsImage() {
|
|
var imgData, imgNode;
|
|
var strDownloadMime = "image/octet-stream";
|
|
|
|
try {
|
|
var strMime = "image/jpeg";
|
|
imgData = renderer.domElement.toDataURL(strMime);
|
|
|
|
return imgData.replace(strMime, strDownloadMime);
|
|
} catch (e) {
|
|
console.log(e);
|
|
return;
|
|
}
|
|
}
|
|
|
|
var saveFile = function (strData, filename) {
|
|
var link = document.createElement('a');
|
|
if (typeof link.download === 'string') {
|
|
document.body.appendChild(link); //Firefox requires the link to be in the body
|
|
link.download = filename;
|
|
link.href = strData;
|
|
link.click();
|
|
document.body.removeChild(link); //remove the link when done
|
|
} else {
|
|
location.replace(uri);
|
|
}
|
|
}
|
|
|
|
|
|
export function displayGui() {
|
|
|
|
var controller = new function () {
|
|
this.afficherToit = true;
|
|
this.afficherPlancher = true;
|
|
this.afficherCotes = true;
|
|
this.ossatureBois = false;
|
|
|
|
|
|
this.sauvegarderCeProjet = function () {
|
|
|
|
scene.updateMatrixWorld();
|
|
var reference = exportProjet();
|
|
|
|
var texteFinal = $("#popup-export .texte").html().replace('%s', reference);
|
|
$("#popup-export span.texte").html(texteFinal);
|
|
$("#popup-export").show();
|
|
$("#overlay").show();
|
|
|
|
navigator.permissions.query({
|
|
name: "clipboard-write"
|
|
}).then(result => {
|
|
if (result.state == "granted" || result.state == "prompt") {
|
|
/* write to the clipboard now */
|
|
updateClipboard(reference);
|
|
}
|
|
});
|
|
};
|
|
|
|
|
|
this.importerUnProjet = function () {
|
|
|
|
var refDevis = prompt("Veuillez saisir la référence de votre projet :", "test");
|
|
if (refDevis === null) return;
|
|
|
|
for (var i = 0; i < nbTravees; i++) {
|
|
scene.remove(scene.getObjectByName(PREFIXE_TRAVEE + parseInt(i + 1)));
|
|
}
|
|
nbConstructions = nbTravees = nbOuvertures = 0;
|
|
|
|
// Il faut vider les tableaux utilisés par le système.
|
|
initObjetsSysteme();
|
|
|
|
importProjet(refDevis);
|
|
incrusterCotes();
|
|
scene.updateMatrixWorld();
|
|
};
|
|
|
|
|
|
this.genererDemandePrix = function () {
|
|
|
|
if (!verifierControlesMetier()) return;
|
|
|
|
// Tout d'abord, on enregistre le projet en sous-marin, afin d'inclure sa référence dans le devis.
|
|
scene.updateMatrixWorld();
|
|
var reference = exportProjet();
|
|
|
|
|
|
var modePDF = true;
|
|
var screenshot1, screenshot2, screenshot3, screenshot4, screenshot5, screenshot6, screenshot7, screenshot8, screenshot9;
|
|
|
|
var coordonneesClient = prompt("Veuillez indiquer le nom et prénom à faire figurer dans la demande de prix SVP.", "Client sans nom");
|
|
if (coordonneesClient === null) return;
|
|
var maintenant = new Date();
|
|
|
|
$("#overlay").show();
|
|
$("#popup-attente").show();
|
|
|
|
// On prend tous les screenshots dans le bon ordre et dans le bon mode...
|
|
if (!$("span:contains('ossatureBois')").parent().find("input[type='checkbox']").prop('checked'))
|
|
$("span:contains('ossatureBois')").click();
|
|
if (!$("span:contains('afficherCotes')").parent().find("input[type='checkbox']").prop('checked'))
|
|
$("span:contains('afficherCotes')").click();
|
|
|
|
// 1 - la vue d'implantation
|
|
activeCamera = cameraOrtho;
|
|
scene.getObjectByName('ground').material = blankMaterial;
|
|
scene.getObjectByName('boussole').material.color = COLOR_ARRAY['noir'];
|
|
changerCouleurTextes(COLOR_ARRAY['noir']);
|
|
scene.traverse(function (child) {
|
|
if (child.name.includes('floor_excluded'))
|
|
child.visible = false;
|
|
});
|
|
afficherVueAerienne(modePDF);
|
|
showMainIncrustations();
|
|
hidePignonIncrustations();
|
|
animate();
|
|
screenshot1 = saveAsImage();
|
|
$("#quitter-vue-aerienne").click();
|
|
|
|
activeCamera = cameraOrtho;
|
|
|
|
// 2 - une vue aérienne du plancher
|
|
showPignonIncrustations();
|
|
changePointOfView("dessus", modePDF);
|
|
if ($("span:contains('afficherToit')").parent().find("input[type='checkbox']").prop('checked'))
|
|
$("span:contains('afficherToit')").click();
|
|
animate();
|
|
screenshot2 = saveAsImage();
|
|
$("span:contains('afficherToit')").click();
|
|
|
|
// 3 - une vue aérienne avec charpente
|
|
hidePignonIncrustations();
|
|
if ($("span:contains('afficherPlancher')").parent().find("input[type='checkbox']").prop('checked'))
|
|
$("span:contains('afficherPlancher')").click();
|
|
animate();
|
|
screenshot3 = saveAsImage();
|
|
|
|
// Les vues suivantes n'auront pas de cotes.
|
|
scene.getObjectByName('ground').material = groundMaterial;
|
|
scene.traverse(function (child) {
|
|
if (child.name.includes('floor_excluded'))
|
|
child.visible = true;
|
|
});
|
|
scene.getObjectByName('boussole').material.color = COLOR_ARRAY['blanc'];
|
|
changerCouleurTextes(COLOR_ARRAY['blanc']);
|
|
if ($("span:contains('afficherCotes')").parent().find("input[type='checkbox']").prop('checked'))
|
|
$("span:contains('afficherCotes')").click();
|
|
|
|
// 4 - une vue de face
|
|
changePointOfView("avant", modePDF);
|
|
animate();
|
|
screenshot4 = saveAsImage();
|
|
|
|
// 5 - une vue de derrière
|
|
changePointOfView("arriere", modePDF);
|
|
animate();
|
|
screenshot5 = saveAsImage();
|
|
|
|
// 6 - une vue de gauche
|
|
changePointOfView("gauche", modePDF);
|
|
animate();
|
|
screenshot6 = saveAsImage();
|
|
|
|
// 7 - une vue de droite
|
|
changePointOfView("droite", modePDF);
|
|
animate();
|
|
screenshot7 = saveAsImage();
|
|
|
|
initPositionCamera(cameraOrtho);
|
|
activeCamera = camera;
|
|
|
|
// Enfin, quelques vues en perspective
|
|
if ($("span:contains('afficherToit')").parent().find("input[type='checkbox']").prop('checked'))
|
|
$("span:contains('afficherToit')").click();
|
|
camera.position.set(180, 100, 150);
|
|
camera.lookAt(scene.position);
|
|
animate();
|
|
screenshot8 = saveAsImage();
|
|
|
|
camera.position.set(-180, 100, -100);
|
|
camera.lookAt(scene.position);
|
|
animate();
|
|
screenshot9 = saveAsImage();
|
|
|
|
|
|
// Retour à la vue perspective
|
|
changePointOfView("perspective");
|
|
|
|
if ($("span:contains('ossatureBois')").parent().find("input[type='checkbox']").prop('checked'))
|
|
$("span:contains('ossatureBois')").click();
|
|
if (!$("span:contains('afficherToit')").parent().find("input[type='checkbox']").prop('checked'))
|
|
$("span:contains('afficherToit')").click();
|
|
if (!$("span:contains('afficherPlancher')").parent().find("input[type='checkbox']").prop('checked'))
|
|
$("span:contains('afficherPlancher')").click();
|
|
animate();
|
|
|
|
|
|
// Génération du rapport PDF
|
|
jsreport.serverUrl = URL_JSREPORT;
|
|
|
|
var donneesBrutes = {},
|
|
modules = new Array(),
|
|
donneesJSON;
|
|
donneesBrutes.nomClient = coordonneesClient;
|
|
donneesBrutes.dateDevis = maintenant.toLocaleDateString('fr-FR');
|
|
donneesBrutes.referenceDevis = maintenant.getFullYear() + '' +
|
|
((maintenant.getMonth() + 1) < 10 ? '0' + (maintenant.getMonth() + 1) : (maintenant.getMonth() + 1)) + '' +
|
|
maintenant.getDate() + '' + maintenant.getHours() + '' + maintenant.getMinutes();
|
|
donneesBrutes.referenceProjet = reference;
|
|
|
|
|
|
// C'est ici qu'on calcule le nombre de charpentes et de pignons : c'est plus simple.
|
|
// On rajoute également dans l'inventaire les kits accessoires, correspondants à chaque construction.
|
|
inventaire["CH1T"] = inventaire["CHTS"] = inventaire["PEXT"] = inventaire["PINT"] = 0;
|
|
inventaire["ACC1"] = inventaire["ACC2"] = inventaire["ACC3"] = inventaire["ACC4"] = 0;
|
|
var nbTraveesActuelles = 0;
|
|
for (var travee in tableauTravees) {
|
|
var numTraveeSuivante = parseInt(travee.substr(travee.indexOf(" ") + 1)) + 1;
|
|
var traveeSuivante = tableauTravees["Travee " + numTraveeSuivante];
|
|
|
|
if (tableauTravees[travee].rangDansConstruction === 1) {
|
|
inventaire["CH1T"]++;
|
|
inventaire["PEXT"]++;
|
|
nbTraveesActuelles = 1;
|
|
}
|
|
|
|
if (traveeSuivante) {
|
|
if (traveeSuivante.numConstruction != tableauTravees[travee].numConstruction) {
|
|
// On se trouve sur la dernière travée de cette construction.
|
|
inventaire["PEXT"]++;
|
|
if (nbTraveesActuelles > 0) inventaire["ACC" + nbTraveesActuelles]++;
|
|
} else {
|
|
// Il existe une autre travée dans la même construction
|
|
inventaire["PINT"]++;
|
|
inventaire["CHTS"]++;
|
|
nbTraveesActuelles++;
|
|
}
|
|
} else {
|
|
inventaire["PEXT"]++;
|
|
if (nbTraveesActuelles > 0) inventaire["ACC" + nbTraveesActuelles]++;
|
|
}
|
|
}
|
|
|
|
|
|
// On récupère la liste des modules présents sur le projet et on estime le coût global.
|
|
var coutEstimeBas = 0,
|
|
coutEstimeHaut = 0;
|
|
var keys = Object.keys(inventaire).sort();
|
|
for (var i = 0, key = keys[0]; i < keys.length; key = keys[++i]) {
|
|
var correspondance = key;
|
|
var module = {};
|
|
for (var produit in PRODUITS) {
|
|
if (PRODUITS[produit].codeModule == key) {
|
|
correspondance = produit;
|
|
break;
|
|
}
|
|
}
|
|
module.codeModule = key;
|
|
module.quantite = inventaire[key];
|
|
module.referenceModule = PRODUITS[correspondance]['libelleModule'];
|
|
modules.push(module);
|
|
coutEstimeBas += (module.quantite * PRODUITS[correspondance].coutFourchetteBasse);
|
|
coutEstimeHaut += (module.quantite * PRODUITS[correspondance].coutFourchetteHaute);
|
|
}
|
|
|
|
donneesBrutes.modules = modules;
|
|
donneesBrutes.coutEstimeBas = coutEstimeBas;
|
|
donneesBrutes.coutEstimeHaut = coutEstimeHaut;
|
|
donneesBrutes.screenshot1 = screenshot1;
|
|
donneesBrutes.screenshot2 = screenshot2;
|
|
donneesBrutes.screenshot3 = screenshot3;
|
|
donneesBrutes.screenshot4 = screenshot4;
|
|
donneesBrutes.screenshot5 = screenshot5;
|
|
donneesBrutes.screenshot6 = screenshot6;
|
|
donneesBrutes.screenshot7 = screenshot7;
|
|
donneesBrutes.screenshot8 = screenshot8;
|
|
donneesBrutes.screenshot9 = screenshot9;
|
|
donneesJSON = JSON.stringify(donneesBrutes);
|
|
|
|
var request = {
|
|
template: {
|
|
name: "devis",
|
|
recipe: "phantom-pdf",
|
|
engine: "handlebars",
|
|
phantom: {
|
|
"format": "A4",
|
|
"orientation": "landscape",
|
|
"headerHeight": "0cm",
|
|
"footer": "<div style='text-align:right;font-size:12px'>Dossier {{nomClient }} - page {#pageNum}/{#numPages}</div>",
|
|
"footerHeight": "0.5cm"
|
|
}
|
|
},
|
|
data: donneesJSON
|
|
};
|
|
|
|
jsreport.renderAsync(request).then(function (res) {
|
|
res.download('Demande de prix Econologis.pdf')
|
|
$("#popup-attente").hide();
|
|
$("#overlay").hide();
|
|
});
|
|
};
|
|
};
|
|
|
|
var options = {
|
|
Ajouter: function () {
|
|
|
|
/* Les cas où l'ajout est interdit sont :
|
|
1 - nb maxi de travées (au total) atteint (déjà géré dans creeTravee)
|
|
2 - on atteint le nb maxi de travées par construction */
|
|
if (nbTravees > 1) {
|
|
var voisine = tableauTravees[PREFIXE_TRAVEE + nbTravees];
|
|
if (voisine['rangDansConstruction'] >= NB_TRAVEES_MAXI) {
|
|
log(nbConstructions);
|
|
if (nbConstructions == 2) {
|
|
alerte("Vous avez atteint le nombre maximal de travées autorisées (" + NB_TRAVEES_MAXI + ").");
|
|
return;
|
|
} else {
|
|
$('#overlay').show();
|
|
$('#popup-decalage').show();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nbOuvertures > 0) {
|
|
if (!confirm("Vous allez perdre toutes les ouvertures déjà créées. Continuer ?")) return;
|
|
supprimerToutesOuvertures();
|
|
recreerTrappes();
|
|
}
|
|
|
|
// On repasse volontairement en mode avec textures.
|
|
if ($("span:contains('ossatureBois')").parent().find("input[type='checkbox']").prop('checked'))
|
|
$("span:contains('ossatureBois')").click();
|
|
|
|
var travee = creerTravee();
|
|
if (travee) traitementCreationTravee(travee);
|
|
},
|
|
|
|
Supprimer: function () {
|
|
if (nbTravees == 1) {
|
|
alerte("Au moins une travée requise.");
|
|
return;
|
|
}
|
|
if (nbOuvertures > 0) {
|
|
if (!confirm("Vous allez perdre toutes les ouvertures déjà créées. Continuer ?")) return;
|
|
supprimerToutesOuvertures();
|
|
recreerTrappes();
|
|
}
|
|
|
|
// On repasse volontairement en texture classique.
|
|
if ($("span:contains('ossatureBois')").parent().find("input[type='checkbox']").prop('checked'))
|
|
$("span:contains('ossatureBois')").click();
|
|
|
|
var nomTravee = PREFIXE_TRAVEE + nbTravees;
|
|
var travee = scene.getObjectByName(nomTravee);
|
|
scene.remove(travee);
|
|
delete tableauTravees[nomTravee];
|
|
tableauTravees.length--;
|
|
|
|
// Suppression d'une travée -> on décale suivant X tout le monde vers la droite.
|
|
for (var i = nbTravees - 1; i > 0; i--) {
|
|
var traveePrecedente = scene.getObjectByName(PREFIXE_TRAVEE + i);
|
|
traveePrecedente.translateX(LARGEUR_TRAVEE / 2);
|
|
tableauTravees[traveePrecedente.name]['positionX'] += LARGEUR_TRAVEE / 2;
|
|
}
|
|
retirerObjetModifiable(nomTravee);
|
|
nbTravees--;
|
|
|
|
// On raffiche les cloisons de la travée de gauche
|
|
var voisine = scene.getObjectByName(PREFIXE_TRAVEE + nbTravees);
|
|
voisine.children[indicePDAV].visible = voisine.children[indicePDAR].visible = true;
|
|
voisine.children[indiceToit].children[indicePignonDroit].visible = true;
|
|
|
|
// On modifie l'incrustation pour les pignons de toiture.
|
|
modifierIncrustation(voisine.name, 'PD', 'PEXT', true);
|
|
hidePignonIncrustations();
|
|
|
|
recalculerConstructions();
|
|
incrusterCotes();
|
|
|
|
// On déplace également la boussole pour qu'elle soit toujours à la même distance de la droite de la construction
|
|
scene.getObjectByName('boussole').position.x = tableauTravees["Travee " + nbTravees].positionX + 50;
|
|
}
|
|
}
|
|
|
|
var myGui = new dat.GUI();
|
|
var guitravees = myGui.addFolder('Gestion des travées');
|
|
guitravees.add(options, 'Ajouter');
|
|
guitravees.add(options, 'Supprimer');
|
|
guitravees.open();
|
|
|
|
|
|
var guiEnv = myGui.addFolder("Préférences d'affichage");
|
|
|
|
guiEnv.add(controller, 'afficherToit').onChange(function (actif) {
|
|
|
|
for (var j = 1; j <= nbTravees; j++) {
|
|
var leToit = scene.getObjectByName(PREFIXE_TRAVEE + j + '>Toit');
|
|
if (!actif) {
|
|
for (var i = 0; i < leToit.children.length; i++) {
|
|
if (leToit.children[i].name.includes('toit')) {
|
|
leToit.children[i].visible = false;
|
|
}
|
|
}
|
|
} else {
|
|
for (var i = 0; i < leToit.children.length; i++) {
|
|
if (leToit.children[i].name.includes('toit')) {
|
|
leToit.children[i].visible = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
guiEnv.add(controller, 'afficherPlancher').onChange(function (actif) {
|
|
if (!actif) {
|
|
for (var i = 1; i <= nbTravees; i++) {
|
|
var travee = scene.getObjectByName(PREFIXE_TRAVEE + i);
|
|
travee.children[indiceRoof].visible = false;
|
|
|
|
travee.children[indiceRoof].visible = false;
|
|
}
|
|
} else {
|
|
for (var i = 1; i <= nbTravees; i++) {
|
|
var travee = scene.getObjectByName(PREFIXE_TRAVEE + i);
|
|
travee.children[indiceRoof].visible = true;
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
guiEnv.add(controller, 'afficherCotes').onChange(function (actif) {
|
|
|
|
var cotesX = scene.getObjectByName('CoteX');
|
|
var cotesY = scene.getObjectByName('CoteY');
|
|
|
|
if (!actif) {
|
|
if (cotesX) cotesX.visible = false;
|
|
if (cotesY) cotesY.visible = false;
|
|
} else {
|
|
if (cotesX) cotesX.visible = true;
|
|
if (cotesY) cotesY.visible = true;
|
|
}
|
|
});
|
|
|
|
|
|
guiEnv.add(controller, 'ossatureBois').onChange(function (afficherBois) {
|
|
|
|
var isTravee = new RegExp("^" + PREFIXE_TRAVEE + "[1-8]>AV|AR|PGAV|PGAR|PDAV|PDAR$");
|
|
|
|
scene.traverse(function (child) {
|
|
|
|
if (afficherBois) {
|
|
|
|
if (child instanceof THREE.Mesh &&
|
|
!child.name.includes('Vitre') &&
|
|
!child.name.includes('Porte') &&
|
|
child.name != 'ground' &&
|
|
child.name != 'boussole') {
|
|
|
|
switch (child.material) {
|
|
|
|
case wallMaterial:
|
|
if (isTravee.test(child.name)) {
|
|
child.material = MPL_Material;
|
|
// Il faut récupérer le type d'ouverture présent sur le module.
|
|
objetsModifiables.forEach(function (objet) {
|
|
if (objet.name.includes(child.name + ">Ouverture")) {
|
|
var module = objet.name.substr(objet.name.lastIndexOf(' ') + 1, objet.name.length);
|
|
|
|
switch (module) {
|
|
case "PE":
|
|
child.material = MPE_Material;
|
|
break;
|
|
case "F1d":
|
|
child.material = MF1d_Material;
|
|
break;
|
|
case "F1g":
|
|
child.material = MF1g_Material;
|
|
break;
|
|
case "F2":
|
|
child.material = MF2_Material;
|
|
break;
|
|
case "PE+F1":
|
|
child.material = MPEF_Material;
|
|
break;
|
|
case "PF":
|
|
child.material = MPF_Material;
|
|
break;
|
|
case "PO":
|
|
child.material = MPI_Material;
|
|
break;
|
|
case "PG1":
|
|
child.material = MPG1_Material;
|
|
break;
|
|
case "PG2":
|
|
child.material = MPG2_Material;
|
|
break;
|
|
case "PER":
|
|
child.material = MPE_Material;
|
|
break;
|
|
case "F1dR":
|
|
child.material = MF1d_Material;
|
|
break;
|
|
case "F1gR":
|
|
child.material = MF1g_Material;
|
|
break;
|
|
case "F2R":
|
|
child.material = MF2_Material;
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
break;
|
|
|
|
case pignonMaterial:
|
|
child.material = PEXT_Material;
|
|
break;
|
|
|
|
case roofMaterial:
|
|
child.material = CH1T_Material;
|
|
var newName = child.name.replace('excluded', 'transparent');
|
|
child.name = newName;
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
if (child instanceof THREE.Group && child.name.includes('Ouverture') && !child.name.includes(' PO')) {
|
|
child.visible = false;
|
|
}
|
|
} else {
|
|
|
|
// Texture d'origine
|
|
if (child instanceof THREE.Mesh) {
|
|
if (!child.name.includes('Vitre') && !child.name.includes('Porte')) {
|
|
|
|
if (isTravee.test(child.name))
|
|
child.material = wallMaterial;
|
|
}
|
|
|
|
if (child.material == PEXT_Material) {
|
|
child.material = pignonMaterial;
|
|
}
|
|
|
|
if (child.material == CH1T_Material) {
|
|
child.material = roofMaterial;
|
|
var newName = child.name.replace('transparent', 'excluded');
|
|
child.name = newName;
|
|
}
|
|
}
|
|
|
|
if (child instanceof THREE.Group && child.name.includes('Ouverture') && !child.name.includes(' PO')) {
|
|
child.visible = true;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
guiEnv.open();
|
|
|
|
|
|
var guiMisc = myGui.addFolder("Diverses actions");
|
|
guiMisc.add(controller, 'genererDemandePrix');
|
|
guiMisc.add(controller, 'sauvegarderCeProjet');
|
|
guiMisc.add(controller, 'importerUnProjet');
|
|
guiMisc.open();
|
|
|
|
}
|