add visual selection of z top and bottom
This commit is contained in:
parent
1193c3313e
commit
ca4ae077b2
7 changed files with 244 additions and 124 deletions
|
|
@ -166,7 +166,7 @@ export const api = {
|
|||
emit(t,m,o) { return EVENT.publish(t,m,o) },
|
||||
import() { api.ui.load.click() },
|
||||
listeners(topic) { return EVENT.targets(topic) },
|
||||
on(t,l) { return EVENT.on(t,l) },
|
||||
on(t,l) { EVENT.on(t,l); return api.event },
|
||||
settings: settingsUI.trigger_event,
|
||||
topics() { return EVENT.topics() }
|
||||
},
|
||||
|
|
|
|||
|
|
@ -735,6 +735,14 @@ function newInput(label, opt = {}) {
|
|||
ip = height > 1 ? DOC.createElement('textarea') : DOC.createElement('input');
|
||||
|
||||
row.appendChild(newLabel(label));
|
||||
if (opt.selector) {
|
||||
let sel = DOC.createElement('button');
|
||||
sel.classList.add('z-select');
|
||||
sel.addEventListener('click', event => opt.selector('click', { input: ip, event, opt }));
|
||||
sel.addEventListener('mouseenter', event => opt.selector('enter', { input: ip, event, opt }));
|
||||
sel.addEventListener('mouseleave', event => opt.selector('leave', { input: ip, event, opt }));
|
||||
row.appendChild(sel);
|
||||
}
|
||||
row.appendChild(ip);
|
||||
row.setAttribute("class", opt.class || "var-row");
|
||||
if (height > 1) {
|
||||
|
|
|
|||
|
|
@ -203,6 +203,70 @@ export function createPopOp(type, map) {
|
|||
}
|
||||
|
||||
export function createPopOps() {
|
||||
|
||||
const bottom = true;
|
||||
const open = true;
|
||||
const top = true;
|
||||
|
||||
function selector(type, { input, event, opt }) {
|
||||
let which = opt?.top ? 'top' : opt?.bottom ? 'bottom' : 'unknown';
|
||||
let value = parseFloat(input.value);
|
||||
switch (type) {
|
||||
case 'click':
|
||||
let rec = env.poppedRec;
|
||||
let { field } = opt;
|
||||
api.event.emit('cam.zplane.select', { which, onselect(value) {
|
||||
rec[field] = value;
|
||||
input.focus();
|
||||
input.value = value;
|
||||
input.blur();
|
||||
} } );
|
||||
break;
|
||||
case 'enter':
|
||||
api.event.emit('cam.zplane.show', { which, value });
|
||||
break;
|
||||
case 'leave':
|
||||
api.event.emit('cam.zplane.hide', { which });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function isClear() {
|
||||
return env.poppedRec.mode === 'clear';
|
||||
}
|
||||
|
||||
function isTrace() {
|
||||
return env.poppedRec.mode === 'trace';
|
||||
}
|
||||
|
||||
function isShadow() {
|
||||
return env.poppedRec.shadow;
|
||||
}
|
||||
|
||||
function isSurface() {
|
||||
return env.poppedRec.mode === 'surface';
|
||||
}
|
||||
|
||||
function isSurfaceLinear() {
|
||||
return env.poppedRec.mode === 'surface' && env.poppedRec.sr_type === 'linear';
|
||||
}
|
||||
|
||||
function canDogBones() {
|
||||
if (!env.poppedRec) return false;
|
||||
return env.poppedRec.mode === 'follow';
|
||||
}
|
||||
|
||||
function canDogBonesRev() {
|
||||
return canDogBones() && env.poppedRec.dogbone;
|
||||
}
|
||||
|
||||
function zDogSep() {
|
||||
return canDogBones() || zBottom();
|
||||
}
|
||||
|
||||
const ov_topz = { title: LANG.ou_ztop_l, convert: toFloat, units, selector, top, field: "ov_topz" };
|
||||
const ov_botz = { title: LANG.ou_zbot_l, convert: toFloat, units, selector, bottom, field: "ov_botz" };
|
||||
|
||||
createPopOp('level', {
|
||||
tool: 'camLevelTool',
|
||||
spindle: 'camLevelSpindle',
|
||||
|
|
@ -260,8 +324,8 @@ export function createPopOps() {
|
|||
omitthru: UC.newBoolean(LANG.co_omit_s, undefined, { title: LANG.co_omit_l }),
|
||||
sep: UC.newBlank({ class: "pop-sep" }),
|
||||
exp: UC.newExpand("overrides"),
|
||||
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: toFloat, units }),
|
||||
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: toFloat, units }),
|
||||
ov_topz: UC.newInput(LANG.ou_ztop_s, ov_topz),
|
||||
ov_botz: UC.newInput(LANG.ou_zbot_s, ov_botz),
|
||||
exp_end: UC.endExpand(),
|
||||
};
|
||||
|
||||
|
|
@ -304,8 +368,8 @@ export function createPopOps() {
|
|||
revbones: UC.newBoolean(LANG.co_dogr_s, undefined, { title: LANG.co_dogr_l, show: () => env.poppedRec.dogbones }),
|
||||
sep: UC.newBlank({ class: "pop-sep" }),
|
||||
exp: UC.newExpand("overrides"),
|
||||
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: toFloat, units }),
|
||||
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: toFloat, units }),
|
||||
ov_topz: UC.newInput(LANG.ou_ztop_s, ov_topz),
|
||||
ov_botz: UC.newInput(LANG.ou_zbot_s, ov_botz),
|
||||
exp_end: UC.endExpand(),
|
||||
};
|
||||
|
||||
|
|
@ -386,19 +450,6 @@ export function createPopOps() {
|
|||
linear: UC.newBoolean(LANG.ci_line_s, undefined, { title: LANG.ci_line_l }),
|
||||
};
|
||||
|
||||
function canDogBones() {
|
||||
if (!env.poppedRec) return false;
|
||||
return env.poppedRec.mode === 'follow';
|
||||
}
|
||||
|
||||
function canDogBonesRev() {
|
||||
return canDogBones() && env.poppedRec.dogbone;
|
||||
}
|
||||
|
||||
function zDogSep() {
|
||||
return canDogBones() || zBottom();
|
||||
}
|
||||
|
||||
createPopOp('trace', {
|
||||
mode: 'camTraceType',
|
||||
offset: 'camTraceOffset',
|
||||
|
|
@ -437,8 +488,8 @@ export function createPopOps() {
|
|||
revbone: UC.newBoolean(LANG.co_dogr_s, undefined, { title: LANG.co_dogr_l, show: canDogBonesRev }),
|
||||
exp: UC.newExpand("overrides"),
|
||||
sep: UC.newBlank({ class: "pop-sep" }),
|
||||
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: toFloat, units }),
|
||||
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: toFloat, units }),
|
||||
ov_topz: UC.newInput(LANG.ou_ztop_s, ov_topz),
|
||||
ov_botz: UC.newInput(LANG.ou_zbot_s, ov_botz),
|
||||
exp_end: UC.endExpand(),
|
||||
sep: UC.newBlank({ class: "pop-sep" }),
|
||||
menu: UC.newRow([UC.newButton("select", traceAdd)], { class: "ext-buttons f-row" }),
|
||||
|
|
@ -483,8 +534,8 @@ export function createPopOps() {
|
|||
outline: UC.newBoolean(LANG.cp_outl_s, undefined, { title: LANG.cp_outl_l }),
|
||||
exp: UC.newExpand("overrides"),
|
||||
sep: UC.newBlank({ class: "pop-sep" }),
|
||||
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: toFloat, units }),
|
||||
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: toFloat, units }),
|
||||
ov_topz: UC.newInput(LANG.ou_ztop_s, ov_topz),
|
||||
ov_botz: UC.newInput(LANG.ou_zbot_s, ov_botz),
|
||||
exp_end: UC.endExpand(),
|
||||
sep: UC.newBlank({ class: "pop-sep" }),
|
||||
menu: UC.newRow([UC.newButton("select", surfaceAdd)], { class: "ext-buttons f-row" }),
|
||||
|
|
@ -669,28 +720,6 @@ export function createPopOps() {
|
|||
count: UC.newInput('operations', { title: "num operations", convert: toInt, bound: UC.bound(1, 20), post: opRender })
|
||||
};
|
||||
|
||||
function isClear() {
|
||||
return env.poppedRec.mode === 'clear';
|
||||
}
|
||||
|
||||
function isTrace() {
|
||||
return env.poppedRec.mode === 'trace';
|
||||
}
|
||||
|
||||
function isShadow() {
|
||||
return env.poppedRec.shadow;
|
||||
}
|
||||
|
||||
function isSurface() {
|
||||
return env.poppedRec.mode === 'surface';
|
||||
}
|
||||
|
||||
function isSurfaceLinear() {
|
||||
return env.poppedRec.mode === 'surface' && env.poppedRec.sr_type === 'linear';
|
||||
}
|
||||
|
||||
const open = true;
|
||||
|
||||
createPopOp('area', {
|
||||
spindle: 'camAreaSpindle',
|
||||
tool: 'camAreaTool',
|
||||
|
|
@ -756,8 +785,8 @@ export function createPopOps() {
|
|||
exp_end: UC.endExpand(),
|
||||
exp: UC.newExpand("bounds", { }),
|
||||
sep: UC.newBlank({ class: "pop-sep" }),
|
||||
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: toFloat, units }),
|
||||
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: toFloat, units }),
|
||||
ov_topz: UC.newInput(LANG.ou_ztop_s, ov_topz),
|
||||
ov_botz: UC.newInput(LANG.ou_zbot_s, ov_botz),
|
||||
exp_end: UC.endExpand(),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,70 @@ const { ui: UI } = api;
|
|||
|
||||
let meshZTop, meshZBottom;
|
||||
|
||||
{
|
||||
let geo = new THREE.PlaneGeometry(1, 1);
|
||||
let mat = new THREE.MeshBasicMaterial({
|
||||
color: 0x779977,
|
||||
opacity: 0.55,
|
||||
transparent: true,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
meshZTop = new THREE.Mesh(geo, mat);
|
||||
meshZTop.renderOrder = 1;
|
||||
}
|
||||
|
||||
{
|
||||
let geo = new THREE.PlaneGeometry(1, 1);
|
||||
let mat = new THREE.MeshBasicMaterial({
|
||||
color: 0x997777,
|
||||
opacity: 0.55,
|
||||
transparent: true,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
meshZBottom = new THREE.Mesh(geo, mat);
|
||||
meshZBottom.renderOrder = 1;
|
||||
}
|
||||
|
||||
function getBounds() {
|
||||
const settings = api.conf.get();
|
||||
const { stock } = settings;
|
||||
const { x, y, z, center } = stock;
|
||||
const widgets = api.widgets.all();
|
||||
let max = { x, y, z };
|
||||
for (let w of widgets) {
|
||||
max.x = Math.max(max.x, w.track.box.w);
|
||||
max.y = Math.max(max.y, w.track.box.h);
|
||||
max.z = Math.max(max.z, w.track.box.d);
|
||||
}
|
||||
return widgets.length ? { max, center } : {};
|
||||
}
|
||||
|
||||
export function showZTop(zval) {
|
||||
SPACE.world.remove(meshZTop);
|
||||
let { max, center } = getBounds();
|
||||
if (zval && max && center) {
|
||||
meshZTop.position.x = center.x;
|
||||
meshZTop.position.y = center.y;
|
||||
meshZTop.position.z = zval;
|
||||
meshZTop.scale.x = max.x;
|
||||
meshZTop.scale.y = max.y;
|
||||
SPACE.world.add(meshZTop);
|
||||
}
|
||||
}
|
||||
|
||||
export function showZBottom(zval) {
|
||||
SPACE.world.remove(meshZBottom);
|
||||
let { max, center } = getBounds();
|
||||
if (zval && max && center) {
|
||||
meshZBottom.position.x = center.x;
|
||||
meshZBottom.position.y = center.y;
|
||||
meshZBottom.position.z = zval;
|
||||
meshZBottom.scale.x = max.x;
|
||||
meshZBottom.scale.y = max.y;
|
||||
SPACE.world.add(meshZBottom);
|
||||
}
|
||||
}
|
||||
|
||||
export function updateStock() {
|
||||
if (env.isAnimate) {
|
||||
if (env.isIndexed) {
|
||||
|
|
@ -22,16 +86,12 @@ export function updateStock() {
|
|||
SPACE.world.remove(meshZBottom);
|
||||
SPACE.world.remove(env.camStock);
|
||||
env.camStock = null;
|
||||
meshZTop = null;
|
||||
meshZBottom = null;
|
||||
return;
|
||||
}
|
||||
|
||||
api.platform.update_bounds();
|
||||
|
||||
const settings = api.conf.get();
|
||||
const widgets = api.widgets.all();
|
||||
|
||||
const { stock, process } = settings;
|
||||
const { x, y, z, center } = stock;
|
||||
|
||||
|
|
@ -86,57 +146,8 @@ export function updateStock() {
|
|||
lines.material.color = new THREE.Color(isDark() ? 0x555555 : 0xaaaaaa);
|
||||
}
|
||||
|
||||
SPACE.world.remove(meshZTop);
|
||||
if (process.camZTop && widgets.length) {
|
||||
let max = { x, y, z };
|
||||
for (let w of widgets) {
|
||||
max.x = Math.max(max.x, w.track.box.w);
|
||||
max.y = Math.max(max.y, w.track.box.h);
|
||||
max.z = Math.max(max.z, w.track.box.d);
|
||||
}
|
||||
let geo = new THREE.PlaneGeometry(max.x, max.y);
|
||||
let mat = new THREE.MeshBasicMaterial({
|
||||
color: 0x777777,
|
||||
opacity: 0.55,
|
||||
transparent: true,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
meshZTop = new THREE.Mesh(geo, mat);
|
||||
meshZTop._max = max;
|
||||
meshZTop.renderOrder = 1;
|
||||
meshZTop.position.x = center.x;
|
||||
meshZTop.position.y = center.y;
|
||||
meshZTop.position.z = process.camZTop;
|
||||
SPACE.world.add(meshZTop);
|
||||
} else {
|
||||
meshZTop = undefined;
|
||||
}
|
||||
|
||||
SPACE.world.remove(meshZBottom);
|
||||
if (process.camZBottom && widgets.length) {
|
||||
let max = { x, y, z };
|
||||
for (let w of widgets) {
|
||||
max.x = Math.max(max.x, w.track.box.w);
|
||||
max.y = Math.max(max.y, w.track.box.h);
|
||||
max.z = Math.max(max.z, w.track.box.d);
|
||||
}
|
||||
let geo = new THREE.PlaneGeometry(max.x, max.y);
|
||||
let mat = new THREE.MeshBasicMaterial({
|
||||
color: 0x777777,
|
||||
opacity: 0.55,
|
||||
transparent: true,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
meshZBottom = new THREE.Mesh(geo, mat);
|
||||
meshZBottom._max = max;
|
||||
meshZBottom.renderOrder = 1;
|
||||
meshZBottom.position.x = center.x;
|
||||
meshZBottom.position.y = center.y;
|
||||
meshZBottom.position.z = process.camZBottom;
|
||||
SPACE.world.add(meshZBottom);
|
||||
} else {
|
||||
meshZBottom = undefined;
|
||||
}
|
||||
showZTop(process.camZTop);
|
||||
showZBottom(process.camZBottom);
|
||||
|
||||
SPACE.update();
|
||||
}
|
||||
|
|
|
|||
33
src/kiri/mode/cam/cl-zplane.js
Normal file
33
src/kiri/mode/cam/cl-zplane.js
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { api } from '../../app/api.js';
|
||||
import { clearPops, hoverStart } from './init-ui.js';
|
||||
import { showZTop, showZBottom, updateStock } from './cl-stock.js';
|
||||
|
||||
let alert;
|
||||
let plane;
|
||||
let ondone;
|
||||
let lastY;
|
||||
|
||||
export function zPlaneStart(which, onselect) {
|
||||
alert = api.show.alert("[esc] cancels z plane selection");
|
||||
plane = which;
|
||||
ondone = onselect;
|
||||
hoverStart(onHover, onHoverUp);
|
||||
}
|
||||
|
||||
export function zPlaneDone() {
|
||||
api.hide.alert(alert);
|
||||
updateStock();
|
||||
}
|
||||
|
||||
function onHover(data) {
|
||||
const { int, type, point } = data;
|
||||
if (plane === 'top') showZTop(lastY = point.y); else
|
||||
if (plane === 'bottom') showZBottom(lastY = point.y);
|
||||
}
|
||||
|
||||
function onHoverUp(int) {
|
||||
ondone(lastY);
|
||||
clearPops();
|
||||
}
|
||||
|
|
@ -2,23 +2,24 @@
|
|||
|
||||
import { $ } from '../../../moto/webui.js';
|
||||
import { api } from '../../app/api.js';
|
||||
import { load } from '../../../load/file.js';
|
||||
import { animate as anim_2d, animate_clear as anim_2d_clear } from './anim-2d-fe.js';
|
||||
import { animate2 as anim_3d, animate_clear2 as anim_3d_clear } from './anim-3d-fe.js';
|
||||
import { space as SPACE } from '../../../moto/space.js';
|
||||
import { Layers } from '../../app/layers.js';
|
||||
import { Stack } from '../../app/stack.js';
|
||||
import { updateStock } from './cl-stock.js';
|
||||
import { createPopOps } from './cl-ops.js';
|
||||
import { helicalOn, helicalDone } from './cl-helical.js';
|
||||
import { holeSelOn, selectHolesDone, clearHolesRec } from './cl-hole.js';
|
||||
import { load } from '../../../load/file.js';
|
||||
import { Layers } from '../../app/layers.js';
|
||||
import { originSelectDone } from './cl-origin.js';
|
||||
import { recreateTabs } from './cl-tab.js';
|
||||
import { showZTop, showZBottom, updateStock } from './cl-stock.js';
|
||||
import { space as SPACE } from '../../../moto/space.js';
|
||||
import { space } from '../../../moto/space.js';
|
||||
import { Stack } from '../../app/stack.js';
|
||||
import { surfaceOn, surfaceDone } from './cl-surface.js';
|
||||
import { tabAdd, tabDone, tabClear, restoreTabs, rotateTabs, updateTabs, clearTabs, mirrorTabs } from './cl-tab.js';
|
||||
import { traceOn, traceDone, unselectTraces } from './cl-trace.js';
|
||||
import { holeSelOn, selectHolesDone, clearHolesRec } from './cl-hole.js';
|
||||
import { surfaceOn, surfaceDone } from './cl-surface.js';
|
||||
import { helicalOn, helicalDone } from './cl-helical.js';
|
||||
import { originSelectDone } from './cl-origin.js';
|
||||
import { Widget, newWidget } from '../../app/widget.js';
|
||||
import { space } from '../../../moto/space.js';
|
||||
import { recreateTabs } from './cl-tab.js';
|
||||
import { zPlaneStart, zPlaneDone } from './cl-zplane.js';
|
||||
|
||||
const { BufferGeometryUtils } = THREE;
|
||||
|
||||
|
|
@ -62,13 +63,28 @@ export function isDark() {
|
|||
|
||||
export function clearPops() {
|
||||
if (env.func.unpop) env.func.unpop();
|
||||
helicalDone();
|
||||
originSelectDone();
|
||||
selectHolesDone();
|
||||
surfaceDone();
|
||||
tabDone();
|
||||
traceDone();
|
||||
selectHolesDone();
|
||||
helicalDone();
|
||||
zPlaneDone();
|
||||
// unbind
|
||||
hoverDone();
|
||||
}
|
||||
|
||||
export function hoverStart(onhover, onhoverup) {
|
||||
clearPops();
|
||||
env.hover = onhover;
|
||||
env.hoverUp = onhoverup;
|
||||
api.feature.hover = true;
|
||||
}
|
||||
|
||||
export function hoverDone() {
|
||||
env.hover = noop;
|
||||
env.hoverUp = noop;
|
||||
api.feature.hover = false;
|
||||
}
|
||||
|
||||
function animFn() {
|
||||
|
|
@ -288,7 +304,6 @@ export function opRender() {
|
|||
let mark = Date.now();
|
||||
let html = [];
|
||||
let bind = {};
|
||||
let scale = api.view.unit_scale();
|
||||
let notime = false;
|
||||
let inloop = 0;
|
||||
let numloop;
|
||||
|
|
@ -556,10 +571,26 @@ export function opRender() {
|
|||
updateStock();
|
||||
}
|
||||
|
||||
export function zPlaneShow({ which, value }) {
|
||||
if (!value) return;
|
||||
if (which === 'top') showZTop(value); else
|
||||
if (which === 'bottom') showZBottom(value);
|
||||
}
|
||||
|
||||
export function zPlaneHide({ which }) {
|
||||
updateStock();
|
||||
}
|
||||
|
||||
export function zPlaneSelect({ which, onselect }) {
|
||||
clearPops();
|
||||
zPlaneStart(which, value => {
|
||||
onselect(parseFloat(value));
|
||||
});
|
||||
}
|
||||
|
||||
export function init() {
|
||||
|
||||
api.event.on('tool.mesh.face-normal', normal => {
|
||||
// console.log({ env.poppedRec });
|
||||
env.poppedRec.degrees = (Math.atan2(normal.y, normal.z) * RAD2DEG).round(2);
|
||||
env.poppedRec.absolute = true;
|
||||
opRender();
|
||||
|
|
@ -850,17 +881,20 @@ export function init() {
|
|||
}
|
||||
});
|
||||
|
||||
api.event.on("cam.op.add", opAdd);
|
||||
api.event
|
||||
.on("cam.op.add", opAdd)
|
||||
.on("cam.op.del", opDel)
|
||||
.on("cam.op.render", opRender);
|
||||
|
||||
api.event.on("cam.op.del", opDel);
|
||||
api.event
|
||||
.on("cam.tabs.add", tabAdd)
|
||||
.on("cam.tabs.done", tabDone)
|
||||
.on("cam.tabs.clear", tabClear);
|
||||
|
||||
api.event.on("cam.op.render", opRender);
|
||||
|
||||
api.event.on("cam.tabs.add", tabAdd);
|
||||
|
||||
api.event.on("cam.tabs.done", tabDone);
|
||||
|
||||
api.event.on("cam.tabs.clear", tabClear);
|
||||
api.event
|
||||
.on("cam.zplane.show", zPlaneShow)
|
||||
.on("cam.zplane.hide", zPlaneHide)
|
||||
.on("cam.zplane.select", zPlaneSelect);
|
||||
|
||||
// COMMON TAB/TRACE EVENT HANDLERS
|
||||
api.event.on("slice.begin", () => {
|
||||
|
|
|
|||
|
|
@ -1431,6 +1431,11 @@ details[open] summary::after {
|
|||
word-break: break-word;
|
||||
white-space: normal;
|
||||
}
|
||||
.z-select {
|
||||
aspect-ratio: 1;
|
||||
border-radius: 50%;
|
||||
border-color: rgba(128,128,128,0.5) !important;
|
||||
}
|
||||
#oplist {
|
||||
gap: 3px;
|
||||
margin-bottom: 3px;
|
||||
|
|
|
|||
Loading…
Reference in a new issue