feat: update bucket threshold and enhance mesh info display in UI

This commit is contained in:
CNCKitchen
2026-03-20 19:47:04 +01:00
parent 60e6ee9201
commit 9c50ab83b1
5 changed files with 28 additions and 33 deletions
+5 -7
View File
@@ -296,8 +296,8 @@
<!-- Bucket threshold (shown when Fill is active) -->
<div id="excl-threshold-row" class="form-row slider-row hidden">
<label for="excl-threshold-slider" data-i18n="labels.maxAngle" data-i18n-title="tooltips.maxAngle" title="Maximum dihedral angle between adjacent triangles for the fill to cross">Max angle</label>
<input type="range" id="excl-threshold-slider" min="0" max="180" step="1" value="30" />
<input type="number" class="val" id="excl-threshold-val" value="30" min="0" max="180" step="1" />
<input type="range" id="excl-threshold-slider" min="0" max="180" step="1" value="20" />
<input type="number" class="val" id="excl-threshold-val" value="20" min="0" max="180" step="1" />
</div>
<!-- Footer: count + clear -->
@@ -345,11 +345,9 @@
<button id="license-close" class="license-close-btn" aria-label="Close">&#215;</button>
<h2 id="license-title" data-i18n="license.title">License &amp; Terms</h2>
<ul class="license-list">
<li data-i18n-html="license.item1">This tool is <strong>open-source</strong><a href="https://github.com/CNCKitchen/stlTexturizer" target="_blank" rel="noopener">view &amp; contribute on GitHub</a>.</li>
<li data-i18n-html="license.item2">Free to use for any purpose, including <strong>commercial work</strong> (e.g., texturing STLs for clients or products).</li>
<li data-i18n-html="license.item3">Attribution is <strong>appreciated</strong> but <strong>not required</strong> when using this tool as-is.</li>
<li data-i18n-html="license.item4">You may <strong>not</strong> sell or commercially redistribute this tool itself.</li>
<li data-i18n-html="license.item5">Forks or derivative works must credit <strong>CNC Kitchen</strong> by name and link to <a href="https://cnckitchen.store" target="_blank" rel="noopener">cnckitchen.store</a>.</li>
<li data-i18n-html="license.item1">Free to use for any purpose, including <strong>commercial work</strong> (e.g., texturing STLs for clients or products).</li>
<li data-i18n-html="license.item2">Attribution is <strong>appreciated</strong> but <strong>not required</strong> when using this tool as-is.</li>
<li data-i18n-html="license.item3">Want to support this tool and our work? Check out our <a href="https://geni.us/CNCStoreTexture" target="_blank" rel="noopener">online store</a>!</li>
</ul>
</div>
</div>
+8 -12
View File
@@ -15,7 +15,7 @@ export const TRANSLATIONS = {
// Viewport footer
'ui.wireframe': 'Wireframe',
'ui.controlsHint': 'Left drag: orbit \u00a0·\u00a0 Right drag: pan \u00a0·\u00a0 Scroll: zoom',
'ui.meshInfo': '{n} triangles · {mb} MB',
'ui.meshInfo': '{n} triangles · {mb} MB · {sx} × {sy} × {sz} mm',
// Load STL button
'ui.loadStl': 'Load STL\u2026',
@@ -127,11 +127,9 @@ export const TRANSLATIONS = {
// License popup
'license.btn': 'License & Terms',
'license.title': 'License & Terms',
'license.item1': 'This tool is <strong>open-source</strong> \u2014 <a href="https://github.com/CNCKitchen/stlTexturizer" target="_blank" rel="noopener">view &amp; contribute on GitHub</a>.',
'license.item2': 'Free to use for any purpose, including <strong>commercial work</strong> (e.g., texturing STLs for clients or products).',
'license.item3': 'Attribution is <strong>appreciated</strong> but <strong>not required</strong> when using this tool as-is.',
'license.item4': 'You may <strong>not</strong> sell or commercially redistribute this tool itself.',
'license.item5': 'Forks or derivative works must credit <strong>CNC Kitchen</strong> by name and link to <a href="https://cnckitchen.store" target="_blank" rel="noopener">cnckitchen.store</a>.',
'license.item1': 'Free to use for any purpose, including <strong>commercial work</strong> (e.g., texturing STLs for clients or products).',
'license.item2': 'Attribution is <strong>appreciated</strong> but <strong>not required</strong> when using this tool as-is.',
'license.item3': 'Want to support this tool and our work? Check out our <a href="https://geni.us/CNCStoreTexture" target="_blank" rel="noopener">online store</a>!',
// Sponsor modal
'sponsor.title': 'Thanks for using CNC Kitchen STL Texturizer!',
@@ -162,7 +160,7 @@ export const TRANSLATIONS = {
// Viewport footer
'ui.wireframe': 'Drahtgitter',
'ui.controlsHint': 'Linke Maustaste: Drehen \u00a0·\u00a0 Rechte Maustaste: Verschieben \u00a0·\u00a0 Mausrad: Zoomen',
'ui.meshInfo': '{n} Dreiecke · {mb} MB',
'ui.meshInfo': '{n} Dreiecke · {mb} MB · {sx} × {sy} × {sz} mm',
// Load STL button
'ui.loadStl': 'STL laden\u2026',
@@ -274,11 +272,9 @@ export const TRANSLATIONS = {
// License popup
'license.btn': 'Lizenz & Nutzung',
'license.title': 'Lizenz & Nutzungsbedingungen',
'license.item1': 'Dieses Tool ist <strong>Open Source</strong> \u2014 <a href="https://github.com/CNCKitchen/stlTexturizer" target="_blank" rel="noopener">auf GitHub ansehen &amp; beitragen</a>.',
'license.item2': 'Kostenlos nutzbar f\u00fcr jeden Zweck, auch f\u00fcr <strong>kommerzielle Arbeit</strong> (z.B. Texturierung von STLs f\u00fcr Kunden oder Produkte).',
'license.item3': 'Namensnennung wird <strong>gesch\u00e4tzt</strong>, ist aber bei der Nutzung dieses Tools <strong>nicht erforderlich</strong>.',
'license.item4': 'Das Tool selbst darf <strong>nicht</strong> verkauft oder kommerziell weitervertrieben werden.',
'license.item5': 'Forks oder abgeleitete Werke m\u00fcssen <strong>CNC Kitchen</strong> namentlich nennen und auf <a href="https://cnckitchen.store" target="_blank" rel="noopener">cnckitchen.store</a> verlinken.',
'license.item1': 'Kostenlos nutzbar f\u00fcr jeden Zweck, auch f\u00fcr <strong>kommerzielle Arbeit</strong> (z.B. Texturierung von STLs f\u00fcr Kunden oder Produkte).',
'license.item2': 'Namensnennung wird <strong>gesch\u00e4tzt</strong>, ist aber bei der Nutzung dieses Tools <strong>nicht erforderlich</strong>.',
'license.item3': 'M\u00f6chtest du dieses Tool und unsere Arbeit unterst\u00fctzen? Schau in unserem <a href="https://geni.us/CNCStoreTexture" target="_blank" rel="noopener">Online-Shop</a> vorbei!',
// Sponsor modal
'sponsor.title': 'Danke f\u00fcr die Nutzung des CNC Kitchen STL Texturizers!',
+10 -4
View File
@@ -31,7 +31,7 @@ let exclusionTool = null; // 'brush' | 'bucket' | null
let eraseMode = false;
let brushIsRadius = false;
let brushRadius = 5.0;
let bucketThreshold = 30;
let bucketThreshold = 20;
let isPainting = false;
let selectionMode = false; // false = exclude painted faces; true = include only painted faces
let _lastHoverTriIdx = -1; // last triangle index used for hover preview
@@ -415,7 +415,7 @@ function wireEvents() {
_lastHoverTriIdx = -1; // invalidate hover so next mousemove re-computes
});
exclThresholdVal.addEventListener('change', () => {
bucketThreshold = Math.max(0, Math.min(180, parseFloat(exclThresholdVal.value) || 30));
bucketThreshold = Math.max(0, Math.min(180, parseFloat(exclThresholdVal.value) || 20));
exclThresholdSlider.value = bucketThreshold;
exclThresholdVal.value = bucketThreshold;
_lastHoverTriIdx = -1;
@@ -758,7 +758,10 @@ function loadDefaultCube() {
const triCount = getTriangleCount(geo);
const mb = ((geo.attributes.position.array.byteLength) / 1024 / 1024).toFixed(2);
meshInfo.textContent = t('ui.meshInfo', { n: triCount.toLocaleString(), mb });
const sx = currentBounds.size.x.toFixed(2);
const sy = currentBounds.size.y.toFixed(2);
const sz = currentBounds.size.z.toFixed(2);
meshInfo.textContent = t('ui.meshInfo', { n: triCount.toLocaleString(), mb, sx, sy, sz });
exportBtn.disabled = (activeMapEntry === null);
updatePreview();
@@ -838,7 +841,10 @@ async function handleSTL(file) {
const triCount = getTriangleCount(geometry);
const mb = ((geometry.attributes.position.array.byteLength) / 1024 / 1024).toFixed(2);
meshInfo.textContent = t('ui.meshInfo', { n: triCount.toLocaleString(), mb });
const sx = bounds.size.x.toFixed(2);
const sy = bounds.size.y.toFixed(2);
const sz = bounds.size.z.toFixed(2);
meshInfo.textContent = t('ui.meshInfo', { n: triCount.toLocaleString(), mb, sx, sy, sz });
exportBtn.disabled = (activeMapEntry === null);
updatePreview();
+5 -10
View File
@@ -24,17 +24,15 @@ function buildAxesIndicator(size) {
const pts = [new THREE.Vector3(0, 0, 0), dir.clone().multiplyScalar(r * 0.78)];
const line = new THREE.Line(
new THREE.BufferGeometry().setFromPoints(pts),
new THREE.LineBasicMaterial({ color: hex, depthTest: false, transparent: true, opacity: 0.9 }),
new THREE.LineBasicMaterial({ color: hex, transparent: true, opacity: 0.9 }),
);
line.renderOrder = 999;
group.add(line);
// Cone arrowhead
const cone = new THREE.Mesh(
new THREE.ConeGeometry(r * 0.07, r * 0.22, 8),
new THREE.MeshBasicMaterial({ color: hex, depthTest: false }),
new THREE.MeshBasicMaterial({ color: hex }),
);
cone.renderOrder = 999;
cone.position.copy(dir.clone().multiplyScalar(r * 0.89));
cone.quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), dir);
group.add(cone);
@@ -49,9 +47,8 @@ function buildAxesIndicator(size) {
ctx.textBaseline = 'middle';
ctx.fillText(label, 32, 32);
const sprite = new THREE.Sprite(
new THREE.SpriteMaterial({ map: new THREE.CanvasTexture(c), depthTest: false }),
new THREE.SpriteMaterial({ map: new THREE.CanvasTexture(c) }),
);
sprite.renderOrder = 999;
sprite.position.copy(dir.clone().multiplyScalar(r * 1.18));
sprite.scale.set(r * 0.32, r * 0.32, 1);
group.add(sprite);
@@ -79,9 +76,8 @@ function buildDimensionLabel(text, hex, worldW, worldH) {
ctx.fillText(text, 128, 32);
const mesh = new THREE.Mesh(
new THREE.PlaneGeometry(worldW, worldH),
new THREE.MeshBasicMaterial({ map: new THREE.CanvasTexture(c), transparent: true, depthTest: false, side: THREE.DoubleSide }),
new THREE.MeshBasicMaterial({ map: new THREE.CanvasTexture(c), transparent: true, side: THREE.DoubleSide }),
);
mesh.renderOrder = 998;
return mesh;
}
@@ -98,9 +94,8 @@ function buildDimensions(box, groundZ, scale) {
const addLine = (pts, hex) => {
const line = new THREE.Line(
new THREE.BufferGeometry().setFromPoints(pts),
new THREE.LineBasicMaterial({ color: hex, depthTest: false, transparent: true, opacity: 0.75 }),
new THREE.LineBasicMaterial({ color: hex, transparent: true, opacity: 0.75 }),
);
line.renderOrder = 997;
group.add(line);
};
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 182 KiB