Refine BIM section controls and styling
This commit is contained in:
parent
e343412468
commit
84b28ba12c
|
|
@ -51,6 +51,16 @@
|
||||||
--measure-label: #c4ff67;
|
--measure-label: #c4ff67;
|
||||||
--measure-label-text: #292929;
|
--measure-label-text: #292929;
|
||||||
--measure-dot: #c4ff67;
|
--measure-dot: #c4ff67;
|
||||||
|
--section-axis-x: #ff2b2b;
|
||||||
|
--section-axis-y: #35ff4f;
|
||||||
|
--section-axis-z: #285bff;
|
||||||
|
--section-gizmo-diameter: 1;
|
||||||
|
--section-plane-fill: #606060;
|
||||||
|
--section-plane-alpha: 0.32;
|
||||||
|
--section-plane-edge: #0d0d0d;
|
||||||
|
--section-plane-edge-alpha: 0.8;
|
||||||
|
--section-toolbar-left: calc(12px + var(--tb-size, 25px) + var(--tb-gap, 10px));
|
||||||
|
--section-toolbar-bottom: 123px;
|
||||||
--nodedc-glass-control-bg: var(--modal-element);
|
--nodedc-glass-control-bg: var(--modal-element);
|
||||||
--nodedc-glass-control-hover: color-mix(in srgb, var(--modal-element) 86%, white 8%);
|
--nodedc-glass-control-hover: color-mix(in srgb, var(--modal-element) 86%, white 8%);
|
||||||
--nodedc-glass-control-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.01);
|
--nodedc-glass-control-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.01);
|
||||||
|
|
@ -1928,19 +1938,20 @@ body[data-viewer-mode="guest"] .inspector-restore-tray {
|
||||||
|
|
||||||
.section-toolbar {
|
.section-toolbar {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: calc(12px + var(--tb-size, 52px) + 10px);
|
left: var(--section-toolbar-left);
|
||||||
bottom: 12px;
|
bottom: var(--section-toolbar-bottom);
|
||||||
z-index: 16;
|
z-index: 16;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 6px;
|
gap: var(--tb-gap, 10px);
|
||||||
padding: 6px;
|
height: var(--tb-size, 25px);
|
||||||
border: 1px solid var(--toolbar-border);
|
padding: 0;
|
||||||
border-radius: var(--tb-radius, 12px);
|
border: 0;
|
||||||
background: color-mix(in srgb, var(--toolbar-bg) 88%, transparent);
|
border-radius: 0;
|
||||||
box-shadow: 0 18px 34px rgba(0, 0, 0, 0.28);
|
background: transparent;
|
||||||
backdrop-filter: blur(18px) saturate(124%);
|
box-shadow: none;
|
||||||
-webkit-backdrop-filter: blur(18px) saturate(124%);
|
backdrop-filter: none;
|
||||||
|
-webkit-backdrop-filter: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-toolbar.hidden {
|
.section-toolbar.hidden {
|
||||||
|
|
@ -1948,26 +1959,30 @@ body[data-viewer-mode="guest"] .inspector-restore-tray {
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-tool-btn {
|
.section-tool-btn {
|
||||||
width: 38px;
|
width: var(--tb-size, 25px);
|
||||||
height: 38px;
|
height: var(--tb-size, 25px);
|
||||||
display: inline-grid;
|
display: inline-grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border: 1px solid transparent;
|
border: 1px solid var(--toolbar-border);
|
||||||
border-radius: calc(var(--tb-radius, 12px) - 4px);
|
border-radius: var(--tb-radius, 7px);
|
||||||
background: transparent;
|
background: var(--toolbar-bg);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
font-size: 13px;
|
font-size: var(--tb-icon-size, 13px);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background 120ms ease, border-color 120ms ease, transform 100ms ease;
|
padding: var(--tb-icon-pad, 5px);
|
||||||
|
transition: transform 120ms ease, border-color 120ms ease, box-shadow 120ms ease, background 120ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-tool-btn:hover,
|
.section-tool-btn:hover {
|
||||||
.section-tool-btn.active {
|
transform: translateY(-1px);
|
||||||
border-color: var(--toolbar-outline, rgba(76, 224, 210, 0.7));
|
border-color: var(--toolbar-outline, rgba(76, 224, 210, 0.7));
|
||||||
|
box-shadow: 0 10px 20px color-mix(in srgb, var(--toolbar-outline, rgba(76, 224, 210, 0.7)) 30%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-tool-btn.active {
|
||||||
background: var(--toolbar-bg-active);
|
background: var(--toolbar-bg-active);
|
||||||
color: var(--modal-btn-primary-contrast, #15170f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-tool-btn:active {
|
.section-tool-btn:active {
|
||||||
|
|
@ -1976,8 +1991,8 @@ body[data-viewer-mode="guest"] .inspector-restore-tray {
|
||||||
|
|
||||||
.section-tool-btn svg {
|
.section-tool-btn svg {
|
||||||
display: block;
|
display: block;
|
||||||
width: 21px;
|
width: var(--tb-svg-size, 24px);
|
||||||
height: 21px;
|
height: var(--tb-svg-size, 24px);
|
||||||
fill: none;
|
fill: none;
|
||||||
stroke: currentColor;
|
stroke: currentColor;
|
||||||
stroke-width: 1.8;
|
stroke-width: 1.8;
|
||||||
|
|
@ -1990,21 +2005,14 @@ body[data-viewer-mode="guest"] .inspector-restore-tray {
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-overview {
|
.section-overview {
|
||||||
position: fixed;
|
width: var(--tb-size, 25px);
|
||||||
left: calc(12px + var(--tb-size, 52px) + 10px);
|
height: var(--tb-size, 25px);
|
||||||
bottom: 66px;
|
flex: 0 0 var(--tb-size, 25px);
|
||||||
width: 150px;
|
|
||||||
height: 150px;
|
|
||||||
z-index: 14;
|
|
||||||
display: none;
|
|
||||||
border: 1px solid var(--toolbar-border);
|
|
||||||
border-radius: 12px;
|
|
||||||
background: color-mix(in srgb, var(--toolbar-bg) 84%, transparent);
|
|
||||||
box-shadow: 0 18px 34px rgba(0, 0, 0, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[data-section-mode="active"] .section-overview {
|
|
||||||
display: block;
|
display: block;
|
||||||
|
border: 1px solid var(--toolbar-border);
|
||||||
|
border-radius: var(--tb-radius, 7px);
|
||||||
|
background: var(--toolbar-bg);
|
||||||
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.templates-panel {
|
.templates-panel {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
const SDK_VERSION = "2.6.78"; // соответствует package.json
|
const SDK_VERSION = "2.6.78"; // соответствует package.json
|
||||||
const SDK_URL = "./lib/dc-camera-context.es.js";
|
const SDK_URL = "./lib/dc-camera-context.es.js?v=2";
|
||||||
|
|
||||||
import { createLogo } from "./src/ui/logo.js";
|
import { createLogo } from "./src/ui/logo.js";
|
||||||
import { toolbarConfig, applyToolbarVars } from "./src/ui/toolbar.js";
|
import { toolbarConfig, applyToolbarVars } from "./src/ui/toolbar.js";
|
||||||
import { createTemplatesMenu } from "./src/ui/templatesMenu.js?v=2";
|
import { createTemplatesMenu } from "./src/ui/templatesMenu.js?v=2";
|
||||||
import { createSettingsMenu } from "./src/ui/settingsMenu.js?v=5";
|
import { createSettingsMenu } from "./src/ui/settingsMenu.js?v=6";
|
||||||
import { createMeasurementModal } from "./src/ui/measurementModal.js";
|
import { createMeasurementModal } from "./src/ui/measurementModal.js";
|
||||||
import { createGlassSelect } from "./src/ui/glassSelect.js";
|
import { createGlassSelect } from "./src/ui/glassSelect.js";
|
||||||
import { createSliderControl } from "./src/ui/controls/slider.js";
|
import { createSliderControl } from "./src/ui/controls/slider.js";
|
||||||
|
|
@ -943,6 +943,12 @@ const cssValue = (name, fallback = "") => {
|
||||||
return (v && v.trim()) || fallback;
|
return (v && v.trim()) || fallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const clampNumber = (value, min, max, fallback) => {
|
||||||
|
const num = Number(value);
|
||||||
|
if (!Number.isFinite(num)) return fallback;
|
||||||
|
return Math.max(min, Math.min(max, num));
|
||||||
|
};
|
||||||
|
|
||||||
const hexToRgb01 = (hex) => {
|
const hexToRgb01 = (hex) => {
|
||||||
if (!hex) return [1, 1, 1];
|
if (!hex) return [1, 1, 1];
|
||||||
const clean = hex.trim();
|
const clean = hex.trim();
|
||||||
|
|
@ -998,6 +1004,56 @@ const applyMeasureTheme = () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const sectionPlaneThemeFromCSS = () => ({
|
||||||
|
axes: {
|
||||||
|
x: hexToRgb01(cssValue("--section-axis-x", "#ff2b2b")),
|
||||||
|
y: hexToRgb01(cssValue("--section-axis-y", "#35ff4f")),
|
||||||
|
z: hexToRgb01(cssValue("--section-axis-z", "#285bff")),
|
||||||
|
},
|
||||||
|
gizmoDiameter: clampNumber(parseFloat(cssValue("--section-gizmo-diameter", "1")), 0.5, 1.8, 1),
|
||||||
|
planeFillColor: hexToRgb01(cssValue("--section-plane-fill", "#606060")),
|
||||||
|
planeFillAlpha: clampNumber(parseFloat(cssValue("--section-plane-alpha", "0.32")), 0, 1, 0.32),
|
||||||
|
planeEdgeColor: hexToRgb01(cssValue("--section-plane-edge", "#0d0d0d")),
|
||||||
|
planeEdgeAlpha: clampNumber(parseFloat(cssValue("--section-plane-edge-alpha", "0.8")), 0, 1, 0.8),
|
||||||
|
});
|
||||||
|
|
||||||
|
const applySectionPlaneTheme = () => {
|
||||||
|
if (!sectionPlanesPlugin) return;
|
||||||
|
const theme = sectionPlaneThemeFromCSS();
|
||||||
|
Object.values(sectionPlanesPlugin._controls || {}).forEach((control) => {
|
||||||
|
control?.setStyle?.(theme);
|
||||||
|
});
|
||||||
|
Object.values(sectionPlanesPlugin._overview?._planes || {}).forEach((plane) => {
|
||||||
|
const mesh = plane?._mesh;
|
||||||
|
if (!mesh) return;
|
||||||
|
if (mesh.material) {
|
||||||
|
mesh.material.diffuse = theme.planeFillColor;
|
||||||
|
mesh.material.emissive = theme.planeFillColor;
|
||||||
|
mesh.material.alpha = theme.planeFillAlpha;
|
||||||
|
mesh.material.alphaMode = theme.planeFillAlpha < 1 ? "blend" : "opaque";
|
||||||
|
}
|
||||||
|
if (mesh.edgeMaterial) {
|
||||||
|
mesh.edgeMaterial.edgeColor = theme.planeEdgeColor;
|
||||||
|
mesh.edgeMaterial.edgeAlpha = theme.planeEdgeAlpha;
|
||||||
|
}
|
||||||
|
if (mesh.highlightMaterial) {
|
||||||
|
mesh.highlightMaterial.fillColor = theme.planeFillColor;
|
||||||
|
mesh.highlightMaterial.fillAlpha = theme.planeFillAlpha;
|
||||||
|
mesh.highlightMaterial.edgeColor = theme.planeEdgeColor;
|
||||||
|
mesh.highlightMaterial.edgeAlpha = theme.planeEdgeAlpha;
|
||||||
|
}
|
||||||
|
if (mesh.selectedMaterial) {
|
||||||
|
mesh.selectedMaterial.fillColor = theme.planeFillColor;
|
||||||
|
mesh.selectedMaterial.fillAlpha = theme.planeFillAlpha;
|
||||||
|
mesh.selectedMaterial.edgeColor = theme.planeEdgeColor;
|
||||||
|
mesh.selectedMaterial.edgeAlpha = theme.planeEdgeAlpha;
|
||||||
|
}
|
||||||
|
mesh.opacity = theme.planeFillAlpha;
|
||||||
|
});
|
||||||
|
viewer?.scene?.glRedraw?.();
|
||||||
|
sectionPlanesPlugin._overview?._scene?.glRedraw?.();
|
||||||
|
};
|
||||||
|
|
||||||
const applyHighlightTheme = () => {
|
const applyHighlightTheme = () => {
|
||||||
if (!viewer?.scene?.highlightMaterial) return;
|
if (!viewer?.scene?.highlightMaterial) return;
|
||||||
const hexToRGB = (hex) => {
|
const hexToRGB = (hex) => {
|
||||||
|
|
@ -1229,8 +1285,21 @@ const setSectionAxisActive = (axis) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const positionSectionToolbar = () => {
|
||||||
|
if (!sectionButton || !sectionToolbar) return;
|
||||||
|
const rect = sectionButton.getBoundingClientRect();
|
||||||
|
if (!rect.width || !rect.height) return;
|
||||||
|
const gap = parseFloat(cssValue("--tb-gap", "10")) || 10;
|
||||||
|
const root = document.documentElement;
|
||||||
|
root.style.setProperty("--section-toolbar-left", `${Math.round(rect.right + gap)}px`);
|
||||||
|
root.style.setProperty("--section-toolbar-bottom", `${Math.round(Math.max(8, window.innerHeight - rect.bottom))}px`);
|
||||||
|
};
|
||||||
|
|
||||||
const setSectionModeActive = (active) => {
|
const setSectionModeActive = (active) => {
|
||||||
sectionModeActive = !!active && !!sectionPlanesPlugin && getSectionPlaneIds().length > 0 && !isGuestMode();
|
sectionModeActive = !!active && !!sectionPlanesPlugin && getSectionPlaneIds().length > 0 && !isGuestMode();
|
||||||
|
if (sectionModeActive) {
|
||||||
|
positionSectionToolbar();
|
||||||
|
}
|
||||||
sectionButton?.classList.toggle("active", sectionModeActive);
|
sectionButton?.classList.toggle("active", sectionModeActive);
|
||||||
sectionToolbar?.classList.toggle("hidden", !sectionModeActive);
|
sectionToolbar?.classList.toggle("hidden", !sectionModeActive);
|
||||||
document.body.dataset.sectionMode = sectionModeActive ? "active" : "";
|
document.body.dataset.sectionMode = sectionModeActive ? "active" : "";
|
||||||
|
|
@ -1287,6 +1356,7 @@ const createOrUpdateSectionPlane = (axis = "camera") => {
|
||||||
activeSectionPlaneId = sectionPlane.id || activeSectionPlaneId;
|
activeSectionPlaneId = sectionPlane.id || activeSectionPlaneId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
applySectionPlaneTheme();
|
||||||
sectionPlanesPlugin.showControl(activeSectionPlaneId);
|
sectionPlanesPlugin.showControl(activeSectionPlaneId);
|
||||||
setSectionModeActive(true);
|
setSectionModeActive(true);
|
||||||
setSectionAxisActive(axis);
|
setSectionAxisActive(axis);
|
||||||
|
|
@ -1569,6 +1639,11 @@ window.addEventListener("pointerup", scheduleCameraRearm, true);
|
||||||
window.addEventListener("mouseup", scheduleCameraRearm, true);
|
window.addEventListener("mouseup", scheduleCameraRearm, true);
|
||||||
window.addEventListener("touchend", scheduleCameraRearm, true);
|
window.addEventListener("touchend", scheduleCameraRearm, true);
|
||||||
window.addEventListener("touchcancel", scheduleCameraRearm, true);
|
window.addEventListener("touchcancel", scheduleCameraRearm, true);
|
||||||
|
window.addEventListener("resize", () => {
|
||||||
|
if (sectionModeActive) {
|
||||||
|
positionSectionToolbar();
|
||||||
|
}
|
||||||
|
});
|
||||||
document.addEventListener("visibilitychange", () => {
|
document.addEventListener("visibilitychange", () => {
|
||||||
if (!document.hidden) {
|
if (!document.hidden) {
|
||||||
scheduleCameraRearm();
|
scheduleCameraRearm();
|
||||||
|
|
@ -3099,6 +3174,7 @@ const initViewer = async () => {
|
||||||
overviewVisible: false,
|
overviewVisible: false,
|
||||||
});
|
});
|
||||||
sectionPlanesPlugin.setOverviewVisible(false);
|
sectionPlanesPlugin.setOverviewVisible(false);
|
||||||
|
applySectionPlaneTheme();
|
||||||
setSectionModeActive(false);
|
setSectionModeActive(false);
|
||||||
} else {
|
} else {
|
||||||
console.warn("SectionPlanesPlugin is not available in the loaded SDK build");
|
console.warn("SectionPlanesPlugin is not available in the loaded SDK build");
|
||||||
|
|
@ -3971,6 +4047,9 @@ const loadProjectSnapshot = async (project) => {
|
||||||
if (key && key.startsWith("measure")) {
|
if (key && key.startsWith("measure")) {
|
||||||
applyMeasureTheme();
|
applyMeasureTheme();
|
||||||
}
|
}
|
||||||
|
if (key && key.startsWith("section")) {
|
||||||
|
applySectionPlaneTheme();
|
||||||
|
}
|
||||||
focusCanvasAndControls();
|
focusCanvasAndControls();
|
||||||
},
|
},
|
||||||
onShow: () => {
|
onShow: () => {
|
||||||
|
|
@ -3986,6 +4065,7 @@ const loadProjectSnapshot = async (project) => {
|
||||||
rebuildNavCube(sdk);
|
rebuildNavCube(sdk);
|
||||||
applyHighlightTheme();
|
applyHighlightTheme();
|
||||||
applyMeasureTheme();
|
applyMeasureTheme();
|
||||||
|
applySectionPlaneTheme();
|
||||||
if (displayModeControl && displayModeSelectHost) {
|
if (displayModeControl && displayModeSelectHost) {
|
||||||
displayModeSelect = createGlassSelect({
|
displayModeSelect = createGlassSelect({
|
||||||
host: displayModeSelectHost,
|
host: displayModeSelectHost,
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,14 @@
|
||||||
set("--measure-label", s.measureLabel);
|
set("--measure-label", s.measureLabel);
|
||||||
set("--measure-label-text", s.measureLabelText);
|
set("--measure-label-text", s.measureLabelText);
|
||||||
set("--measure-dot", s.measureDot);
|
set("--measure-dot", s.measureDot);
|
||||||
|
set("--section-axis-x", s.sectionAxisX);
|
||||||
|
set("--section-axis-y", s.sectionAxisY);
|
||||||
|
set("--section-axis-z", s.sectionAxisZ);
|
||||||
|
set("--section-gizmo-diameter", s.sectionGizmoDiameter);
|
||||||
|
set("--section-plane-fill", s.sectionPlaneFill);
|
||||||
|
set("--section-plane-alpha", s.sectionPlaneAlpha);
|
||||||
|
set("--section-plane-edge", s.sectionPlaneEdge);
|
||||||
|
set("--section-plane-edge-alpha", s.sectionPlaneEdgeAlpha);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// ignore corrupted settings
|
// ignore corrupted settings
|
||||||
}
|
}
|
||||||
|
|
@ -89,7 +97,7 @@
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@500;600;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@500;600;700&display=swap" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="./dcViewer.css?v=18">
|
<link rel="stylesheet" href="./dcViewer.css?v=19">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
|
|
@ -107,7 +115,6 @@
|
||||||
<section class="viewer-wrapper">
|
<section class="viewer-wrapper">
|
||||||
<canvas id="viewerCanvas"></canvas>
|
<canvas id="viewerCanvas"></canvas>
|
||||||
<canvas id="navCube"></canvas>
|
<canvas id="navCube"></canvas>
|
||||||
<canvas id="sectionPlanesOverview" class="section-overview" width="150" height="150"></canvas>
|
|
||||||
<div class="drop-hint" id="dropZone">
|
<div class="drop-hint" id="dropZone">
|
||||||
<div class="drop-center">
|
<div class="drop-center">
|
||||||
<div class="drop-plus">+</div>
|
<div class="drop-plus">+</div>
|
||||||
|
|
@ -318,6 +325,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="sectionToolbar" class="section-toolbar hidden" aria-label="Управление разрезом">
|
<div id="sectionToolbar" class="section-toolbar hidden" aria-label="Управление разрезом">
|
||||||
|
<canvas id="sectionPlanesOverview" class="section-overview" width="80" height="80"></canvas>
|
||||||
<button class="section-tool-btn" data-section-action="camera" type="button" title="По камере" aria-label="По камере">
|
<button class="section-tool-btn" data-section-action="camera" type="button" title="По камере" aria-label="По камере">
|
||||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
<path d="M4.5 12s2.75-5 7.5-5 7.5 5 7.5 5-2.75 5-7.5 5-7.5-5-7.5-5Z"></path>
|
<path d="M4.5 12s2.75-5 7.5-5 7.5 5 7.5 5-2.75 5-7.5 5-7.5-5-7.5-5Z"></path>
|
||||||
|
|
@ -349,6 +357,6 @@
|
||||||
<input id="fileInput" class="hidden" type="file"
|
<input id="fileInput" class="hidden" type="file"
|
||||||
accept=".xkt,.glb,.gltf,.bim,.las,.laz,.obj,.stl">
|
accept=".xkt,.glb,.gltf,.bim,.las,.laz,.obj,.stl">
|
||||||
|
|
||||||
<script type="module" src="./dcViewer.js?v=23"></script>
|
<script type="module" src="./dcViewer.js?v=24"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -126510,6 +126510,9 @@ class TransformControl {
|
||||||
scale: [5, 5, 5],
|
scale: [5, 5, 5],
|
||||||
isObject: false
|
isObject: false
|
||||||
});
|
});
|
||||||
|
this._rootNode = rootNode;
|
||||||
|
this._styleScale = 1;
|
||||||
|
this._baseRootScale = 5;
|
||||||
|
|
||||||
const pos = math.vec3();
|
const pos = math.vec3();
|
||||||
this._setPosition = (function() {
|
this._setPosition = (function() {
|
||||||
|
|
@ -126831,6 +126834,16 @@ class TransformControl {
|
||||||
return {
|
return {
|
||||||
setPositionActive: (a) => { positionActive = a; updatePositionHandle(); },
|
setPositionActive: (a) => { positionActive = a; updatePositionHandle(); },
|
||||||
setRotationActive: (a) => { rotationActive = a; updateRotationHandle(); },
|
setRotationActive: (a) => { rotationActive = a; updateRotationHandle(); },
|
||||||
|
setColor: (color) => {
|
||||||
|
if (!color) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
material.diffuse = color;
|
||||||
|
material.emissive = color;
|
||||||
|
if (hoop.highlightMaterial) {
|
||||||
|
hoop.highlightMaterial.fillColor = color;
|
||||||
|
}
|
||||||
|
},
|
||||||
set visible(v) {
|
set visible(v) {
|
||||||
visible = v;
|
visible = v;
|
||||||
updatePositionHandle();
|
updatePositionHandle();
|
||||||
|
|
@ -126868,13 +126881,16 @@ class TransformControl {
|
||||||
{ // Keep gizmo screen size constant
|
{ // Keep gizmo screen size constant
|
||||||
let lastDist = -1;
|
let lastDist = -1;
|
||||||
const setRootNodeScale = size => {
|
const setRootNodeScale = size => {
|
||||||
if (rootNode.scale[0] !== size) {
|
this._baseRootScale = size;
|
||||||
rootNode.scale = [size, size, size];
|
const styledSize = size * (this._styleScale || 1);
|
||||||
|
if (rootNode.scale[0] !== styledSize) {
|
||||||
|
rootNode.scale = [styledSize, styledSize, styledSize];
|
||||||
if (this._handlers && this._handlers.onScreenScale) {
|
if (this._handlers && this._handlers.onScreenScale) {
|
||||||
this._handlers.onScreenScale(rootNode.scale);
|
this._handlers.onScreenScale(rootNode.scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
this._applyRootScale = () => setRootNodeScale(this._baseRootScale || rootNode.scale[0] || 5);
|
||||||
const onSceneTick = scene.on("tick", () => {
|
const onSceneTick = scene.on("tick", () => {
|
||||||
const camera = scene.camera;
|
const camera = scene.camera;
|
||||||
const dist = Math.abs(math.distVec3(camera.eye, pos));
|
const dist = Math.abs(math.distVec3(camera.eye, pos));
|
||||||
|
|
@ -127030,6 +127046,19 @@ class TransformControl {
|
||||||
this.__destroy();
|
this.__destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setStyle(style = {}) {
|
||||||
|
if (style.gizmoDiameter !== undefined) {
|
||||||
|
this._styleScale = style.gizmoDiameter;
|
||||||
|
this._applyRootScale?.();
|
||||||
|
}
|
||||||
|
if (style.axes) {
|
||||||
|
this._displayMeshes.x?.setColor?.(style.axes.x);
|
||||||
|
this._displayMeshes.y?.setColor?.(style.axes.y);
|
||||||
|
this._displayMeshes.z?.setColor?.(style.axes.z);
|
||||||
|
}
|
||||||
|
this._rootNode?.scene?.glRedraw?.();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to assign this Control to Handlers.
|
* Called to assign this Control to Handlers.
|
||||||
* Call with a null or undefined value to disconnect the Control from whatever Handlers it was assigned to.
|
* Call with a null or undefined value to disconnect the Control from whatever Handlers it was assigned to.
|
||||||
|
|
@ -127703,7 +127732,7 @@ class SectionPlanesPlugin extends Plugin {
|
||||||
const planeRoot = (function() {
|
const planeRoot = (function() {
|
||||||
const rootNode = new Node$1(scene, { isObject: false });
|
const rootNode = new Node$1(scene, { isObject: false });
|
||||||
|
|
||||||
rootNode.addChild(new Mesh(rootNode, { // plane
|
const planeMesh = rootNode.addChild(new Mesh(rootNode, { // plane
|
||||||
geometry: new ReadableGeometry(rootNode, {
|
geometry: new ReadableGeometry(rootNode, {
|
||||||
primitive: "triangles",
|
primitive: "triangles",
|
||||||
positions: [
|
positions: [
|
||||||
|
|
@ -127737,7 +127766,7 @@ class SectionPlanesPlugin extends Plugin {
|
||||||
isObject: false
|
isObject: false
|
||||||
}));
|
}));
|
||||||
|
|
||||||
rootNode.addChild(new Mesh(rootNode, { // Visible frame
|
const frameMesh = rootNode.addChild(new Mesh(rootNode, { // Visible frame
|
||||||
geometry: new ReadableGeometry(rootNode, buildTorusGeometry({
|
geometry: new ReadableGeometry(rootNode, buildTorusGeometry({
|
||||||
center: [0, 0, 0],
|
center: [0, 0, 0],
|
||||||
radius: 1.7,
|
radius: 1.7,
|
||||||
|
|
@ -127769,6 +127798,38 @@ class SectionPlanesPlugin extends Plugin {
|
||||||
isObject: false
|
isObject: false
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const setPhongMaterial = (material, color, alpha) => {
|
||||||
|
if (!material) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (color) {
|
||||||
|
material.diffuse = color;
|
||||||
|
material.emissive = color;
|
||||||
|
}
|
||||||
|
if (alpha !== undefined) {
|
||||||
|
material.alpha = alpha;
|
||||||
|
material.alphaMode = alpha < 1 ? "blend" : "opaque";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const setEmphasisMaterial = (material, fillColor, fillAlpha, edgeColor, edgeAlpha) => {
|
||||||
|
if (!material) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fillColor) {
|
||||||
|
material.fillColor = fillColor;
|
||||||
|
}
|
||||||
|
if (fillAlpha !== undefined) {
|
||||||
|
material.fillAlpha = fillAlpha;
|
||||||
|
}
|
||||||
|
if (edgeColor) {
|
||||||
|
material.edgeColor = edgeColor;
|
||||||
|
}
|
||||||
|
if (edgeAlpha !== undefined) {
|
||||||
|
material.edgeAlpha = edgeAlpha;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setPosition: (function() {
|
setPosition: (function() {
|
||||||
const origin = math.vec3();
|
const origin = math.vec3();
|
||||||
|
|
@ -127781,7 +127842,26 @@ class SectionPlanesPlugin extends Plugin {
|
||||||
})(),
|
})(),
|
||||||
setQuaternion: q => { rootNode.quaternion = q; },
|
setQuaternion: q => { rootNode.quaternion = q; },
|
||||||
setScale: s => { rootNode.scale = s; },
|
setScale: s => { rootNode.scale = s; },
|
||||||
setVisible: v => { rootNode.visible = v; }
|
setVisible: v => { rootNode.visible = v; },
|
||||||
|
setStyle: (style = {}) => {
|
||||||
|
setPhongMaterial(planeMesh.material, style.planeFillColor, style.planeFillAlpha);
|
||||||
|
setEmphasisMaterial(
|
||||||
|
planeMesh.ghostMaterial,
|
||||||
|
style.planeFillColor,
|
||||||
|
style.planeFillAlpha,
|
||||||
|
style.planeEdgeColor,
|
||||||
|
style.planeEdgeAlpha
|
||||||
|
);
|
||||||
|
planeMesh.opacity = style.planeFillAlpha;
|
||||||
|
setPhongMaterial(frameMesh.material, style.planeEdgeColor, style.planeEdgeAlpha);
|
||||||
|
setEmphasisMaterial(
|
||||||
|
frameMesh.highlightMaterial,
|
||||||
|
style.planeEdgeColor,
|
||||||
|
style.planeEdgeAlpha,
|
||||||
|
style.planeEdgeColor,
|
||||||
|
style.planeEdgeAlpha
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
let unbindSectionPlane = () => { };
|
let unbindSectionPlane = () => { };
|
||||||
|
|
@ -127803,6 +127883,10 @@ class SectionPlanesPlugin extends Plugin {
|
||||||
},
|
},
|
||||||
setCulled: c => { culled = c; updateVisible(); },
|
setCulled: c => { culled = c; updateVisible(); },
|
||||||
setVisible: v => { visible = v; updateVisible(); },
|
setVisible: v => { visible = v; updateVisible(); },
|
||||||
|
setStyle: style => {
|
||||||
|
planeRoot.setStyle?.(style);
|
||||||
|
ctrl.setStyle?.(style);
|
||||||
|
},
|
||||||
_setSectionPlane: sectionPlane => {
|
_setSectionPlane: sectionPlane => {
|
||||||
unbindSectionPlane();
|
unbindSectionPlane();
|
||||||
if (sectionPlane) {
|
if (sectionPlane) {
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,14 @@ const defaultSettings = {
|
||||||
measureLabel: "#c4ff67",
|
measureLabel: "#c4ff67",
|
||||||
measureLabelText: "#292929",
|
measureLabelText: "#292929",
|
||||||
measureDot: "#c4ff67",
|
measureDot: "#c4ff67",
|
||||||
|
sectionAxisX: "#ff2b2b",
|
||||||
|
sectionAxisY: "#35ff4f",
|
||||||
|
sectionAxisZ: "#285bff",
|
||||||
|
sectionGizmoDiameter: 1,
|
||||||
|
sectionPlaneFill: "#606060",
|
||||||
|
sectionPlaneAlpha: 0.32,
|
||||||
|
sectionPlaneEdge: "#0d0d0d",
|
||||||
|
sectionPlaneEdgeAlpha: 0.8,
|
||||||
};
|
};
|
||||||
|
|
||||||
const STORAGE_KEY = "bimdc-settings-v3";
|
const STORAGE_KEY = "bimdc-settings-v3";
|
||||||
|
|
@ -109,6 +117,14 @@ const applySettings = (s) => {
|
||||||
root.style.setProperty("--measure-label", s.measureLabel);
|
root.style.setProperty("--measure-label", s.measureLabel);
|
||||||
root.style.setProperty("--measure-label-text", s.measureLabelText);
|
root.style.setProperty("--measure-label-text", s.measureLabelText);
|
||||||
root.style.setProperty("--measure-dot", s.measureDot);
|
root.style.setProperty("--measure-dot", s.measureDot);
|
||||||
|
root.style.setProperty("--section-axis-x", s.sectionAxisX);
|
||||||
|
root.style.setProperty("--section-axis-y", s.sectionAxisY);
|
||||||
|
root.style.setProperty("--section-axis-z", s.sectionAxisZ);
|
||||||
|
root.style.setProperty("--section-gizmo-diameter", s.sectionGizmoDiameter);
|
||||||
|
root.style.setProperty("--section-plane-fill", s.sectionPlaneFill);
|
||||||
|
root.style.setProperty("--section-plane-alpha", s.sectionPlaneAlpha);
|
||||||
|
root.style.setProperty("--section-plane-edge", s.sectionPlaneEdge);
|
||||||
|
root.style.setProperty("--section-plane-edge-alpha", s.sectionPlaneEdgeAlpha);
|
||||||
// подсветка объектов
|
// подсветка объектов
|
||||||
root.style.setProperty("--highlight-color", s.highlight);
|
root.style.setProperty("--highlight-color", s.highlight);
|
||||||
};
|
};
|
||||||
|
|
@ -352,6 +368,50 @@ export function createSettingsMenu({ panel, controls = {}, onChange = null, onSh
|
||||||
});
|
});
|
||||||
panel.appendChild(navCube);
|
panel.appendChild(navCube);
|
||||||
|
|
||||||
|
const sectionCut = section("Разрез / сечение");
|
||||||
|
addColor(sectionCut, "Ось X", "sectionAxisX");
|
||||||
|
addColor(sectionCut, "Ось Y", "sectionAxisY");
|
||||||
|
addColor(sectionCut, "Ось Z", "sectionAxisZ");
|
||||||
|
addSettingsSlider({
|
||||||
|
parent: sectionCut,
|
||||||
|
label: "Диаметр гизмо",
|
||||||
|
value: Math.round(Math.max(0.5, Math.min(1.8, Number(state.sectionGizmoDiameter ?? 1))) * 100),
|
||||||
|
min: 50,
|
||||||
|
max: 180,
|
||||||
|
step: 5,
|
||||||
|
formatValue: (val) => `${Math.round(val)}%`,
|
||||||
|
onChange: (val) => {
|
||||||
|
setVal("sectionGizmoDiameter", Math.max(0.5, Math.min(1.8, Number(val) / 100)));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
addColor(sectionCut, "Плоскость", "sectionPlaneFill");
|
||||||
|
addSettingsSlider({
|
||||||
|
parent: sectionCut,
|
||||||
|
label: "Прозрачность плоскости",
|
||||||
|
value: Math.round(Math.max(0, Math.min(1, Number(state.sectionPlaneAlpha ?? 0.32))) * 100),
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
step: 5,
|
||||||
|
formatValue: (val) => `${Math.round(val)}%`,
|
||||||
|
onChange: (val) => {
|
||||||
|
setVal("sectionPlaneAlpha", Math.max(0, Math.min(1, Number(val) / 100)));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
addColor(sectionCut, "Обводка", "sectionPlaneEdge");
|
||||||
|
addSettingsSlider({
|
||||||
|
parent: sectionCut,
|
||||||
|
label: "Прозрачность обводки",
|
||||||
|
value: Math.round(Math.max(0, Math.min(1, Number(state.sectionPlaneEdgeAlpha ?? 0.8))) * 100),
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
step: 5,
|
||||||
|
formatValue: (val) => `${Math.round(val)}%`,
|
||||||
|
onChange: (val) => {
|
||||||
|
setVal("sectionPlaneEdgeAlpha", Math.max(0, Math.min(1, Number(val) / 100)));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
panel.appendChild(sectionCut);
|
||||||
|
|
||||||
const measure = section("Линейка");
|
const measure = section("Линейка");
|
||||||
addColor(measure, "Линия/бордер", "measureLine");
|
addColor(measure, "Линия/бордер", "measureLine");
|
||||||
addColor(measure, "Плашка", "measureLabel");
|
addColor(measure, "Плашка", "measureLabel");
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,14 @@ const PROJECT_THEME = {
|
||||||
measureLabel: "#c4ff67",
|
measureLabel: "#c4ff67",
|
||||||
measureLabelText: "#292929",
|
measureLabelText: "#292929",
|
||||||
measureDot: "#c4ff67",
|
measureDot: "#c4ff67",
|
||||||
|
sectionAxisX: "#ff2b2b",
|
||||||
|
sectionAxisY: "#35ff4f",
|
||||||
|
sectionAxisZ: "#285bff",
|
||||||
|
sectionGizmoDiameter: 1,
|
||||||
|
sectionPlaneFill: "#606060",
|
||||||
|
sectionPlaneAlpha: 0.32,
|
||||||
|
sectionPlaneEdge: "#0d0d0d",
|
||||||
|
sectionPlaneEdgeAlpha: 0.8,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue