feat(fence): add height selection for fence panels and update related logic
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
- Introduced a new section in the UI for selecting fence heights, visible only when the fence option is enabled. - Updated the fence label to clarify the presence of gates. - Enhanced the JavaScript logic to manage the visibility of fence heights based on user selection. - Modified the fence rendering logic to accommodate different heights and ensure proper visibility based on the selected height. - Updated CSS to style the new fence height controls appropriately. - Adjusted the model configuration to reflect changes in the fence height options.
This commit is contained in:
+16
-3
@@ -312,8 +312,10 @@ let backend=null,projectPanel=null;
|
||||
}
|
||||
|
||||
// Independent site layers: initSiteControls enables all three on each fresh open.
|
||||
const site = { road: false, parcel: false, parking: false, fence: false, savedCamera: null, lastFocus: null };
|
||||
// fenceHeight: index of the manufactured height (tools/fence.mjs FENCE.heights), default the tallest under 2 m
|
||||
const site = { road: false, parcel: false, parking: false, fence: false, fenceHeight: 4, savedCamera: null, lastFocus: null };
|
||||
const siteActive = () => site.road || site.parcel || site.parking;
|
||||
const fenceHeightVisible = e => e.fenceOnly !== undefined ? e.fenceOnly === site.fenceHeight : e.fenceBand === undefined || e.fenceBand <= site.fenceHeight;
|
||||
function meshVisible(m) {
|
||||
if (m.legacySite) return false;
|
||||
switch (m.siteLayer) {
|
||||
@@ -323,7 +325,7 @@ let backend=null,projectPanel=null;
|
||||
case 'road': return site.road;
|
||||
case 'parking': return site.parking;
|
||||
// Each fence part stands on one terrain slab and is shown only together with it.
|
||||
case 'fence': return showTerrain && site.fence && (m.std?.fenceRegion === 'parcel' ? site.parcel : m.std?.fenceRegion === 'north' ? siteActive() : true);
|
||||
case 'fence': return showTerrain && site.fence && fenceHeightVisible(m.std || {}) && (m.std?.fenceRegion === 'parcel' ? site.parcel : m.std?.fenceRegion === 'north' ? siteActive() : true);
|
||||
default: return showTerrain || !m.context;
|
||||
}
|
||||
}
|
||||
@@ -374,6 +376,7 @@ let backend=null,projectPanel=null;
|
||||
const ids = { road: 'siteRoad', parcel: 'siteParcel', parking: 'siteParking', fence: 'siteFence' };
|
||||
const input = $('#' + ids[key]); input.checked = site[key];
|
||||
input.closest('label').classList.toggle('selected', site[key]);
|
||||
if (key === 'fence') $('#fenceHeights').hidden = !site.fence;
|
||||
document.body.classList.toggle('site-active', siteActive());
|
||||
$('#siteMeta').hidden = !siteActive();
|
||||
$('#siteMeta').textContent = 'C.3 + výškopis · mezi body interpolováno';
|
||||
@@ -387,6 +390,13 @@ let backend=null,projectPanel=null;
|
||||
}
|
||||
dirty = true;
|
||||
}
|
||||
function setFenceHeight(index) {
|
||||
const buttons = [...document.querySelectorAll('[data-fence-height]')];
|
||||
if (!buttons.some(b => +b.dataset.fenceHeight === index)) return;
|
||||
site.fenceHeight = index;
|
||||
for (const b of buttons) { const on = +b.dataset.fenceHeight === index; b.classList.toggle('selected', on); b.setAttribute('aria-pressed', on); }
|
||||
dirty = true;
|
||||
}
|
||||
function updateSiteLight() {
|
||||
if(interior.enabled){
|
||||
const center=[1,2,0],lightEye=vadd(center,scale(solar.light,45)),view=lookAt(lightEye,center,Math.abs(solar.light[1])>.999?[0,0,1]:[0,1,0]);
|
||||
@@ -415,14 +425,17 @@ let backend=null,projectPanel=null;
|
||||
const input = $('#' + id); input.onchange = () => setSiteLayer(key, input.checked);
|
||||
setSiteLayer(key, key !== 'fence', false);
|
||||
}
|
||||
document.querySelectorAll('[data-fence-height]').forEach(b => b.onclick = () => setFenceHeight(+b.dataset.fenceHeight));
|
||||
setFenceHeight(site.fenceHeight);
|
||||
$('#siteFit').onclick = () => focusSite();
|
||||
window.SITE_SIM = {
|
||||
getState: () => ({
|
||||
road: site.road, parcel: site.parcel, parking: site.parking, fence: site.fence, terrain: showTerrain,
|
||||
road: site.road, parcel: site.parcel, parking: site.parking, fence: site.fence, fenceHeight: site.fenceHeight, terrain: showTerrain,
|
||||
visibleObjects: meshes.filter(visible).length, referenceElevation: 591.840,
|
||||
projectArea: 1010, digitizedArea: 987.89, houseGeometryUnchanged: true
|
||||
}),
|
||||
setLayer: (key, on, focus = true) => setSiteLayer(key, on, focus),
|
||||
setFenceHeight: index => setFenceHeight(index),
|
||||
focus: mode => focusSite(mode),
|
||||
reset: () => { for (const key of ['road', 'parcel', 'parking', 'fence']) setSiteLayer(key, false, false); setPreset('terrace'); },
|
||||
getCamera: () => ({ theta, phi, distance, target: [...target], aspect }),
|
||||
|
||||
Vendored
+1
-1
@@ -17,7 +17,7 @@ try{
|
||||
document.getElementById('stdSavedState').textContent=JSON.stringify({selection:payload.selection});
|
||||
}catch(error){console.warn('Invalid shared selection:',error);}
|
||||
window.LOCENICE_RESOURCES={config,catalog,assets,references,scene,site,modelBytes};
|
||||
await import('./app.js?v=20261026');
|
||||
await import('./app.js?v=20261026e');
|
||||
}catch(error){
|
||||
console.error(error);const box=document.getElementById('loading');box.className='error';box.innerHTML='<div class="errorDetail"></div><p>Nahrajte celou slozku vcetne js, css, data, models a assets. Otevrete ji pres HTTP(S), nikoli dvojklikem na HTML.</p><a href="./models/dum.glb" download>Stahnout model GLB</a>';
|
||||
box.querySelector('.errorDetail').textContent=error.message;document.getElementById('webStatus').textContent='Chyba nacitani';
|
||||
|
||||
Reference in New Issue
Block a user