curve animation save/load implemented (needs troubleshooting, y axis flattening somewher
parent
8698f47536
commit
d67cba4c6f
|
|
@ -26,7 +26,7 @@ export class CurveEditor {
|
||||||
slider.value = 0;
|
slider.value = 0;
|
||||||
slider.addEventListener('input', () => {
|
slider.addEventListener('input', () => {
|
||||||
this.currentTime = parseFloat(slider.value);
|
this.currentTime = parseFloat(slider.value);
|
||||||
console.log(slider.value);
|
//console.log(slider.value);
|
||||||
this.draw();
|
this.draw();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
92
script.js
92
script.js
|
|
@ -417,6 +417,7 @@ window.onload = () => {
|
||||||
const SEGMENT_SIZE = 17;
|
const SEGMENT_SIZE = 17;
|
||||||
const curveSets = {};
|
const curveSets = {};
|
||||||
let latestEndTime = 1;
|
let latestEndTime = 1;
|
||||||
|
console.log(raw);
|
||||||
|
|
||||||
for (let i = 0; i < curveCount; i++) {
|
for (let i = 0; i < curveCount; i++) {
|
||||||
const motorID = 10;
|
const motorID = 10;
|
||||||
|
|
@ -430,6 +431,9 @@ window.onload = () => {
|
||||||
const endHandleY = view.getUint16(offset, true); offset += 2;
|
const endHandleY = view.getUint16(offset, true); offset += 2;
|
||||||
const endPointY = view.getUint16(offset, true); offset += 2;
|
const endPointY = view.getUint16(offset, true); offset += 2;
|
||||||
|
|
||||||
|
console.log("RECEIVED VALUES RAW:");
|
||||||
|
console.log(startTime, endTime);
|
||||||
|
|
||||||
const toFloat = v => (v / 65535) * 2 - 1;
|
const toFloat = v => (v / 65535) * 2 - 1;
|
||||||
|
|
||||||
const curve = {
|
const curve = {
|
||||||
|
|
@ -498,27 +502,43 @@ window.onload = () => {
|
||||||
const filename = sanitizeFilename(rawInput);
|
const filename = sanitizeFilename(rawInput);
|
||||||
console.log("Sanitized filename:", filename);
|
console.log("Sanitized filename:", filename);
|
||||||
|
|
||||||
|
const frameCount = 800; // or whatever your timeline length is
|
||||||
const frameCount = 500;
|
|
||||||
const numChannels = 5;
|
|
||||||
const frameRate = 50;
|
const frameRate = 50;
|
||||||
const version = 1;
|
const version = 1;
|
||||||
|
|
||||||
const headerSize = 16;
|
const headerSize = 16;
|
||||||
const frameDataSize = frameCount * numChannels * 2;
|
const curveSegments = [];
|
||||||
const keyframeCount = dialKeyframes.reduce((sum, channel) => {
|
|
||||||
return sum + Object.keys(channel).length;
|
|
||||||
}, 0);
|
|
||||||
const keyframeDataSize = keyframeCount * 5;
|
|
||||||
|
|
||||||
// 🔹 Filename encoding
|
// 🔹 Collect all curve segments
|
||||||
|
Object.entries(curveEditor.curveSets).forEach(([motorIDStr, segments]) => {
|
||||||
|
const motorID = parseInt(motorIDStr, 10);
|
||||||
|
segments.forEach(segment => {
|
||||||
|
const toTime = x => Math.max(0, Math.round(curveEditor.xToValue(x) * 100)); // seconds → centiseconds
|
||||||
|
const toUint16 = v => {
|
||||||
|
const normalized = Math.max(-1, Math.min(1, v)); // clamp to [-1, 1]
|
||||||
|
return Math.round((normalized + 1) / 2 * 65535);
|
||||||
|
};
|
||||||
|
|
||||||
|
curveSegments.push({
|
||||||
|
motorID,
|
||||||
|
startTime: segment.startPoint.x,
|
||||||
|
endTime: segment.endPoint.x,
|
||||||
|
startPointY: segment.startPoint.y,
|
||||||
|
startHandleX: segment.startPointHandle.x,
|
||||||
|
startHandleY: segment.startPointHandle.y,
|
||||||
|
endHandleX: segment.endPointHandle.x,
|
||||||
|
endHandleY: segment.endPointHandle.y,
|
||||||
|
endPointY: segment.endPoint.y
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const curveCount = curveSegments.length;
|
||||||
|
const segmentSize = 17;
|
||||||
const filenameBytes = new TextEncoder().encode(filename);
|
const filenameBytes = new TextEncoder().encode(filename);
|
||||||
const filenameLength = filenameBytes.length;
|
const filenameLength = filenameBytes.length;
|
||||||
|
|
||||||
|
const totalSize = 2 + filenameLength + headerSize + 2 + curveCount * segmentSize;
|
||||||
// Total packet size
|
|
||||||
const totalSize = 2 + filenameLength + headerSize + 2 + keyframeDataSize;
|
|
||||||
|
|
||||||
const buffer = new ArrayBuffer(totalSize);
|
const buffer = new ArrayBuffer(totalSize);
|
||||||
const view = new DataView(buffer);
|
const view = new DataView(buffer);
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
|
|
@ -527,7 +547,6 @@ window.onload = () => {
|
||||||
view.setUint16(offset, filenameLength, true); offset += 2;
|
view.setUint16(offset, filenameLength, true); offset += 2;
|
||||||
filenameBytes.forEach(byte => view.setUint8(offset++, byte));
|
filenameBytes.forEach(byte => view.setUint8(offset++, byte));
|
||||||
|
|
||||||
|
|
||||||
// 🔹 Header
|
// 🔹 Header
|
||||||
view.setUint8(offset++, "A".charCodeAt(0));
|
view.setUint8(offset++, "A".charCodeAt(0));
|
||||||
view.setUint8(offset++, "N".charCodeAt(0));
|
view.setUint8(offset++, "N".charCodeAt(0));
|
||||||
|
|
@ -538,41 +557,32 @@ window.onload = () => {
|
||||||
view.setUint8(offset++, frameRate);
|
view.setUint8(offset++, frameRate);
|
||||||
offset += 8; // reserved
|
offset += 8; // reserved
|
||||||
|
|
||||||
// 🔹 Frame data (all zeroes)
|
// 🔹 Curve count
|
||||||
//offset += frameDataSize;
|
view.setUint16(offset, curveCount, true); offset += 2;
|
||||||
|
|
||||||
// 🔹 Keyframe count
|
// 🔹 Curve segments
|
||||||
view.setUint16(offset, keyframeCount, true); offset += 2;
|
curveSegments.forEach(seg => {
|
||||||
|
view.setUint8(offset++, seg.motorID);
|
||||||
const keyframeList = [];
|
view.setUint16(offset, seg.startTime, true); offset += 2;
|
||||||
|
view.setUint16(offset, seg.endTime, true); offset += 2;
|
||||||
|
view.setUint16(offset, seg.startPointY, true); offset += 2;
|
||||||
Object.entries(dialKeyframes).forEach(([motorIdStr, frameMap]) => {
|
view.setUint16(offset, seg.startHandleX, true); offset += 2;
|
||||||
const motorId = parseInt(motorIdStr, 10);
|
view.setUint16(offset, seg.startHandleY, true); offset += 2;
|
||||||
|
console.log("STARTHANDLEY: " + seg.startHandleY);
|
||||||
Object.entries(frameMap).forEach(([frameStr, position]) => {
|
view.setUint16(offset, seg.endHandleX, true); offset += 2;
|
||||||
const frame = parseInt(frameStr, 10);
|
view.setUint16(offset, seg.endHandleY, true); offset += 2;
|
||||||
if (position !== undefined) {
|
view.setUint16(offset, seg.endPointY, true); offset += 2;
|
||||||
keyframeList.push({ motorId, frame, position });
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
console.log("🧵 Curve segments packed:", curveSegments.length);
|
||||||
|
console.log(curveSegments);
|
||||||
// 🔹 Keyframes
|
|
||||||
keyframeList.forEach(({ motorId, frame, position }) => {
|
|
||||||
view.setUint8(offset++, motorId);
|
|
||||||
view.setUint16(offset, frame, true); offset += 2;
|
|
||||||
view.setUint16(offset, position, true); offset += 2;
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log("Keyframe count: " + keyframeCount);
|
|
||||||
console.log(keyframeList);
|
|
||||||
|
|
||||||
// 🔹 Send to ESP32
|
// 🔹 Send to ESP32
|
||||||
const payload = new Uint8Array(buffer);
|
const payload = new Uint8Array(buffer);
|
||||||
|
console.log(payload);
|
||||||
serial.saveFile(payload); // CMD_SAVE_ANIMATION
|
serial.saveFile(payload); // CMD_SAVE_ANIMATION
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function sendDeleteToESP32() {
|
async function sendDeleteToESP32() {
|
||||||
if (!selectedFile) return;
|
if (!selectedFile) return;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue