diff --git a/src/core/Chef.mjs b/src/core/Chef.mjs index 33b7acbe..49022b7d 100755 --- a/src/core/Chef.mjs +++ b/src/core/Chef.mjs @@ -67,8 +67,10 @@ class Chef { } // If stepping with flow control, we have to start from the beginning - // but still want to skip all previous breakpoints - if (progress > 0 && containsFc) { + // but still want to skip all previous breakpoints. + // If stepping, we need to start from the beginning as the current dish + // value may not be for the correct input, so should be recalculated. + if (progress > 0 && containsFc || step) { recipe.removeBreaksUpTo(progress); progress = 0; } diff --git a/src/web/ControlsWaiter.mjs b/src/web/ControlsWaiter.mjs index c1daeb89..b73f9568 100755 --- a/src/web/ControlsWaiter.mjs +++ b/src/web/ControlsWaiter.mjs @@ -68,27 +68,22 @@ class ControlsWaiter { /** * Handler for the 'Step through' command. Executes the next step of the recipe. */ - stepClick() { - if (this.manager.worker.step) { - // Step has already been clicked so get the data from the output - this.manager.worker.cancelBake(); - const activeTab = this.manager.input.getActiveTab(); - this.manager.worker.loadingOutputs++; - this.app.progress = this.manager.output.outputs[activeTab].progress; - this.app.bake(true); - this.manager.worker.bakeId++; - this.manager.worker.queueInput({ - input: this.manager.output.getOutput(activeTab, true), - inputNum: activeTab, - bakeId: this.manager.worker.bakeId - }); + async stepClick() { + if (this.app.baking) return; + // Reset status using cancelBake + this.manager.worker.cancelBake(true, false); + const activeTab = this.manager.input.getActiveTab(); + + if (this.manager.output.outputs[activeTab].progress === false){ + this.app.progress = 0; } else { - // First click of step, so get the output from the inputWorker - this.manager.input.inputWorker.postMessage({ - action: "step", - data: this.manager.input.getActiveTab() - }); + this.app.progress = this.manager.output.outputs[activeTab].progress; } + + this.manager.input.inputWorker.postMessage({ + action: "step", + data: activeTab + }); } diff --git a/src/web/InputWaiter.mjs b/src/web/InputWaiter.mjs index 5b0bc1ac..c9d5f8f6 100644 --- a/src/web/InputWaiter.mjs +++ b/src/web/InputWaiter.mjs @@ -51,6 +51,8 @@ class InputWaiter { this.maxWorkers = navigator.hardwareConcurrency || 4; this.maxTabs = 4; this.inputTimeout = null; + this.callbacks = {}; + this.callbackID = 0; } /** @@ -279,6 +281,9 @@ class InputWaiter { case "inputSwitch": this.manager.output.inputSwitch(r.data); break; + case "getInput": + this.callbacks[r.data.id](r.data); + break; default: log.error(`Unknown action ${r.action}.`); } @@ -288,6 +293,7 @@ class InputWaiter { * Sends a message to the inputWorker to bake all inputs */ bakeAll() { + this.app.progress = 0; this.manager.controls.toggleBakeButtonFunction(false, true); this.inputWorker.postMessage({ action: "bakeAll" @@ -522,6 +528,57 @@ class InputWaiter { } } + /** + * Get the input value for the specified input + * + * @param {number} inputNum - The inputNum of the input to retrieve from the inputWorker + * @returns {ArrayBuffer | string} + */ + async getInputValue(inputNum) { + return await new Promise(resolve => { + this.getInput(inputNum, false, r => { + resolve(r.data); + }); + }); + } + + /** + * Get the input object for the specified input + * + * @param {number} inputNum - The inputNum of the input to retrieve from the inputWorker + * @returns {object} + */ + async getInputObj(inputNum) { + return await new Promise(resolve => { + this.getInput(inputNum, true, r => { + resolve(r.data); + }); + }); + } + + /** + * Gets the specified input from the inputWorker + * + * @param {number} inputNum - The inputNum of the data to get + * @param {boolean} getObj - If true, get the actual data object of the input instead of just the value + * @param {Function} callback - The callback to execute when the input is returned + * @returns {ArrayBuffer | string | object} + */ + getInput(inputNum, getObj, callback) { + const id = this.callbackID++; + + this.callbacks[id] = callback; + + this.inputWorker.postMessage({ + action: "getInput", + data: { + inputNum: inputNum, + getObj: getObj, + id: id + } + }); + } + /** * Displays information about the input. * diff --git a/src/web/InputWorker.mjs b/src/web/InputWorker.mjs index 67eef210..37de69db 100644 --- a/src/web/InputWorker.mjs +++ b/src/web/InputWorker.mjs @@ -102,6 +102,9 @@ self.addEventListener("message", function(e) { case "step": self.autoBake(r.data, true); break; + case "getInput": + self.getInput(r.data); + break; default: log.error(`Unknown action '${r.action}'.`); } @@ -228,6 +231,34 @@ self.getInputValue = function(inputNum) { return ""; }; +/** + * Gets the stored value or oobject for a specific inputNum and sends it to the inputWaiter. + * + * @param {object} inputData - Object containing data about the input to retrieve + * @param {number} inputData.inputNum - The inputNum of the input to get + * @param {boolean} inputData.getObj - If true, returns the entire input object instead of just the value + * @param {number} inputData.id - The callback ID for the callback to run when returned to the inputWaiter + */ +self.getInput = function(inputData) { + if (inputData.getObj) { + self.postMessage({ + action: "getInput", + data: { + data: self.getInputObj(inputData.inputNum), + id: inputData.id + } + }); + } else { + self.postMessage({ + action: "getInput", + data: { + data: self.getInputValue(inputData.inputNum), + id: inputData.id + } + }); + } +}; + /** * Gets the load progress for a specific inputNum * diff --git a/src/web/OutputWaiter.mjs b/src/web/OutputWaiter.mjs index 016429d7..01844086 100755 --- a/src/web/OutputWaiter.mjs +++ b/src/web/OutputWaiter.mjs @@ -115,7 +115,7 @@ class OutputWaiter { error: null, status: "inactive", bakeId: -1, - progress: 0 + progress: false }; this.outputs[inputNum] = newOutput; @@ -127,7 +127,7 @@ class OutputWaiter { * Updates the value for the output in the output array. * If this is the active output tab, updates the output textarea * - * @param {ArrayBuffer | String} data - The + * @param {ArrayBuffer | String} data * @param {number} inputNum * @param {boolean} set */ diff --git a/src/web/WorkerWaiter.mjs b/src/web/WorkerWaiter.mjs index 622769c8..e57521b2 100644 --- a/src/web/WorkerWaiter.mjs +++ b/src/web/WorkerWaiter.mjs @@ -253,6 +253,9 @@ class WorkerWaiter { */ updateOutput(data, inputNum, bakeId, progress) { this.manager.output.updateOutputBakeId(bakeId, inputNum); + if (progress === this.recipeConfig.length) { + progress = false; + } this.manager.output.updateOutputProgress(progress, inputNum); this.manager.output.updateOutputValue(data, inputNum, false); this.manager.output.updateOutputStatus("baked", inputNum); @@ -463,7 +466,6 @@ class WorkerWaiter { */ queueInput(inputData) { this.loadingOutputs--; - if (this.app.baking && inputData.bakeId === this.bakeId) { this.inputs.push(inputData); this.bakeNextInput(this.getInactiveChefWorker(true));