fixed some bugs with splitting and selecting curve endpoints/handles

master
Jake Wilkinson 2025-11-24 11:47:44 +08:00
parent 105db83017
commit 21ffc99bbb
2 changed files with 130 additions and 85 deletions

View File

@ -215,7 +215,7 @@ export class CurveEditor {
} }
// //
yToMotorPosition(yCanvas) { yToMotorPosition(yCanvas) {
const [minOut, maxOut] = this.exportRange; // Output bounds (0 - 4095) const [minOut, maxOut] = this.exportRange; // Output bounds (0 - 4095)
// Transform yCanvas to the original logical space by adjusting for the current offset and scale. // Transform yCanvas to the original logical space by adjusting for the current offset and scale.
@ -229,7 +229,7 @@ yToMotorPosition(yCanvas) {
// Calculate the final motor position // Calculate the final motor position
return Math.round(flipped * (maxOut - minOut) + minOut); return Math.round(flipped * (maxOut - minOut) + minOut);
} }
// exportRangeToY(value) { // exportRangeToY(value) {
@ -663,14 +663,27 @@ yToMotorPosition(yCanvas) {
} }
for (let curve of this.curves) { for (let curve of this.curves) {
for (let key of ['startPointHandle', 'endPointHandle', 'startPoint', 'endPoint']) { // Pass 1: check handles first
for (let key of ['startPointHandle', 'endPointHandle']) {
const p = curve[key]; const p = curve[key];
if (Math.hypot(p.x - mouse.x, p.y - mouse.y) < 10 / this.scale) { if (Math.hypot(p.x - mouse.x, p.y - mouse.y) < 10 / this.scale) {
this.dragging = { curve, key }; this.dragging = { curve, key };
return; return;
} }
} }
}
// If no handle was hit, then check points
for (let curve of this.curves) {
for (let key of ['startPoint', 'endPoint']) {
const p = curve[key];
if (Math.hypot(p.x - mouse.x, p.y - mouse.y) < 10 / this.scale) {
this.dragging = { curve, key };
return;
} }
}
}
}); });
@ -761,27 +774,61 @@ yToMotorPosition(yCanvas) {
const curves = this.curveSets[motorID]; const curves = this.curveSets[motorID];
if (!curves) return; if (!curves) return;
const tolerance = 2; // pixels/frames tolerance for matching existing points
for (let i = 0; i < curves.length; i++) { for (let i = 0; i < curves.length; i++) {
const curve = curves[i]; const curve = curves[i];
// --- if timeX matches an existing startPoint --- // --- check startPoint ---
if (Math.abs(curve.startPoint.x - timeX) < 1e-3) { if (Math.abs(curve.startPoint.x - timeX) < tolerance) {
if (yPosition !== null) { if (yPosition !== null) {
// move existing point
const yEditor = (yPosition * 800 / 4095); const yEditor = (yPosition * 800 / 4095);
curve.startPoint.y = yEditor; curve.startPoint.y = yEditor;
if (curve.startPointHandle) curve.startPointHandle.y = yEditor; if (curve.startPointHandle) curve.startPointHandle.y = yEditor;
} else {
// remove point by merging with previous
if (i > 0) {
const prev = curves[i - 1];
const merged = {
startPoint: prev.startPoint,
startPointHandle: prev.startPointHandle,
endPointHandle: curve.endPointHandle,
endPoint: curve.endPoint
};
curves.splice(i - 1, 2, merged);
} else {
curves.splice(i, 1); // drop if it's the very first
} }
}
this.curveSets[motorID] = curves;
this.draw(); this.draw();
return; return;
} }
// --- if timeX matches an existing endPoint --- // --- check endPoint ---
if (Math.abs(curve.endPoint.x - timeX) < 1e-3) { if (Math.abs(curve.endPoint.x - timeX) < tolerance) {
if (yPosition !== null) { if (yPosition !== null) {
// move existing point
const yEditor = (yPosition * 800 / 4095); const yEditor = (yPosition * 800 / 4095);
curve.endPoint.y = yEditor; curve.endPoint.y = yEditor;
if (curve.endPointHandle) curve.endPointHandle.y = yEditor; if (curve.endPointHandle) curve.endPointHandle.y = yEditor;
} else {
// remove point by merging with next
if (i < curves.length - 1) {
const next = curves[i + 1];
const merged = {
startPoint: curve.startPoint,
startPointHandle: curve.startPointHandle,
endPointHandle: next.endPointHandle,
endPoint: next.endPoint
};
curves.splice(i, 2, merged);
} else {
curves.splice(i, 1); // drop if it's the very last
} }
}
this.curveSets[motorID] = curves;
this.draw(); this.draw();
return; return;
} }
@ -808,7 +855,6 @@ yToMotorPosition(yCanvas) {
let [left, right] = this.splitCurve(curve, t); let [left, right] = this.splitCurve(curve, t);
// ✅ If yPosition provided, override the split points Y
if (yPosition !== null) { if (yPosition !== null) {
const yEditor = (yPosition * 800 / 4095); const yEditor = (yPosition * 800 / 4095);
left.endPoint.y = yEditor; left.endPoint.y = yEditor;
@ -823,10 +869,7 @@ yToMotorPosition(yCanvas) {
return; return;
} }
} }
} }
adjustAllCurvesToDuration(newTime) { adjustAllCurvesToDuration(newTime) {

View File

@ -547,6 +547,8 @@ export class URDFEditor {
} }
this.selectedJoint = this.hoveredJoint; this.selectedJoint = this.hoveredJoint;
this.selectedJoint.material.emissive.setHex(0x555555); // selection color this.selectedJoint.material.emissive.setHex(0x555555); // selection color
let motorID = this.findJointAncestor(this.selectedJoint, 0).transmission.motorID;
this.curveEditor.selectMotor(motorID);
} }
this.isDragging = true; this.isDragging = true;