mirror of
https://github.com/LinoSchmidt/StickExporterTX.git
synced 2026-03-21 01:51:15 +01:00
256 lines
8.8 KiB
TypeScript
256 lines
8.8 KiB
TypeScript
import { blenderPath, blenderScriptPath, dataPath, templatePath, finsishedIconPath } from "./paths";
|
|
import {spawn} from "child_process";
|
|
import logger from "./logger";
|
|
import { setBlenderLoading, setBlenderStatus } from "./ui/menu";
|
|
import { setLogNumber, setPastTime, setRemainingTime, setRenderDisplayProgress, setStatus, setPastTimeNow, setRemainingTimeNow } from "./ui/renderingPage";
|
|
import {imageLoading, imageLoaded} from "./ui/settingsPage";
|
|
import { getLogList, getLogSize, settingList } from "./settings";
|
|
import isValid from "is-valid-path";
|
|
import { pageSetRendering, setProgress, openPage, Page } from "../renderer";
|
|
import { ipcRenderer } from "electron";
|
|
// import { getDoNotDisturb } from "electron-notification-state";
|
|
|
|
export const renderInfo = {
|
|
time: "0min 0sec",
|
|
startTime: 0,
|
|
endTime: 0
|
|
}
|
|
|
|
const blenderStartString = [
|
|
templatePath,
|
|
"--background",
|
|
"--python",
|
|
blenderScriptPath,
|
|
"--",
|
|
dataPath.replaceAll("\\", "/")
|
|
]
|
|
|
|
let blenderConsole = spawn(blenderPath, blenderStartString).on('error', function(err) {
|
|
logger.errorMSG("Could not start blender: " + err.toString());
|
|
});
|
|
let readyToAcceptCommand = false;
|
|
let renderingPicture = false;
|
|
let renderingVideo = false;
|
|
let waitingForRender = false;
|
|
|
|
let logPortionList:number[] = [];
|
|
let currentLogPortion = 0;
|
|
|
|
const estimatedRenderPortion = 0.97;
|
|
function setRenderProgress(log:number, init:boolean, frameCount:number, frame:number) {
|
|
let progress = 0;
|
|
if(init) {
|
|
progress = logPortionList[log-1] * (frame / frameCount * (1 - estimatedRenderPortion)) + currentLogPortion;
|
|
} else {
|
|
progress = logPortionList[log-1] * (frame / frameCount * estimatedRenderPortion + (1 - estimatedRenderPortion)) + currentLogPortion;
|
|
}
|
|
setProgress(progress);
|
|
setRenderDisplayProgress(parseFloat((progress*100).toFixed(2)));
|
|
|
|
const timeNow = new Date().getTime();
|
|
const timeDiff = timeNow - renderInfo.startTime;
|
|
let timeDiffSeconds = timeDiff / 1000;
|
|
let timeDiffMinutes = 0;
|
|
while(timeDiffSeconds > 60) {
|
|
timeDiffMinutes++;
|
|
timeDiffSeconds -= 60;
|
|
}
|
|
renderInfo.time = timeDiffMinutes + "m " + timeDiffSeconds.toFixed(0) + "s";
|
|
setPastTimeNow(renderInfo.time);
|
|
|
|
if(progress > 0) {
|
|
const timeRemaining = (timeDiff / progress) * (1 - progress);
|
|
timeDiffSeconds = timeRemaining / 1000;
|
|
timeDiffMinutes = 0;
|
|
while(timeDiffSeconds > 60) {
|
|
timeDiffMinutes++;
|
|
timeDiffSeconds -= 60;
|
|
}
|
|
setRemainingTimeNow(timeDiffMinutes + "m " + timeDiffSeconds.toFixed(0) + "s");
|
|
}
|
|
}
|
|
|
|
function startBlender() {
|
|
let frames = "0";
|
|
let lastFrame = "0";
|
|
let log = "0";
|
|
|
|
blenderConsole.stdout.on('data', function(data) {
|
|
const dataStr = data.toString();
|
|
|
|
logger.info("Blender: " + dataStr);
|
|
|
|
if (dataStr.includes("Blender started successfully")) {
|
|
renderingPicture = false;
|
|
renderingVideo = false;
|
|
setBlenderStatus("Started");
|
|
}
|
|
if (dataStr.includes("Blender quit")) {
|
|
if(renderingPicture) {
|
|
logger.errorMSG("Rendering preview Failed!");
|
|
} else if(renderingVideo) {
|
|
logger.errorMSG("Rendering video Failed!");
|
|
}
|
|
|
|
readyToAcceptCommand = false;
|
|
renderingPicture = false;
|
|
renderingVideo = false;
|
|
setBlenderStatus("Restarting");
|
|
setBlenderLoading(true);
|
|
setProgress();
|
|
restartBlender();
|
|
}
|
|
|
|
if(dataStr.includes("Frames:")) {
|
|
frames = dataStr.split(":")[1];
|
|
renderingVideo = true;
|
|
readyToAcceptCommand = false;
|
|
setRenderProgress(parseInt(log), true, 0, 0);
|
|
}
|
|
if(dataStr.includes("Fra:") && renderingVideo) {
|
|
lastFrame = dataStr.split(":")[1].split(" ")[0];
|
|
setStatus("Rendering Frame " + lastFrame + "/" + frames);
|
|
setRenderProgress(parseInt(log), false, parseInt(frames), parseInt(lastFrame));
|
|
}
|
|
if(dataStr.includes("Finished") && renderingVideo) {
|
|
pageSetRendering(false);
|
|
renderInfo.endTime = new Date().getTime();
|
|
if(lastFrame == frames) {
|
|
openPage(Page.RenderFinish);
|
|
ipcRenderer.send("renderFinished");
|
|
// TODO: only show notification if not in do not disturb mode, currently not working. Details: https://github.com/felixrieseberg/macos-notification-state/issues/30
|
|
new Notification("Render Finished", {
|
|
body: "Rendering finished successfully!",
|
|
icon: finsishedIconPath
|
|
}).onclick = function() {
|
|
ipcRenderer.send("openApp");
|
|
}
|
|
} else {
|
|
logger.errorMSG("Render Failed!");
|
|
}
|
|
}
|
|
if(dataStr.includes("Init:") && renderingVideo) {
|
|
setStatus("Initialize Frame " + dataStr.split(":")[1] + "/" + frames);
|
|
setRenderProgress(parseInt(log), true, parseInt(frames), parseInt(dataStr.split(":")[1]));
|
|
}
|
|
if(dataStr.includes("Lognr:") && renderingVideo) {
|
|
log = dataStr.split(":")[1];
|
|
if(log !== "1") {
|
|
currentLogPortion += logPortionList[parseInt(log)-2];
|
|
}
|
|
setLogNumber(log);
|
|
}
|
|
|
|
if(dataStr.includes("Waiting for command")) {
|
|
pageSetRendering(false);
|
|
setProgress();
|
|
|
|
if(renderingPicture) {
|
|
imageLoaded();
|
|
}
|
|
|
|
if(!waitingForRender) {
|
|
readyToAcceptCommand = true;
|
|
renderingPicture = false;
|
|
renderingVideo = false;
|
|
setBlenderStatus("Ready");
|
|
setBlenderLoading(false);
|
|
} else {
|
|
waitingForRender = false;
|
|
renderingPicture = true;
|
|
blenderConsole.stdin.write("getRender\n");
|
|
setBlenderStatus("Rendering");
|
|
setBlenderLoading(true);
|
|
imageLoading();
|
|
}
|
|
}
|
|
});
|
|
|
|
blenderConsole.stderr.on('data', function(data:string) {
|
|
logger.errorMSG("Blender: " + data);
|
|
});
|
|
}
|
|
|
|
function restartBlender() {
|
|
pageSetRendering(false);
|
|
blenderConsole.kill();
|
|
blenderConsole = spawn(blenderPath, blenderStartString);
|
|
startBlender();
|
|
}
|
|
|
|
enum blenderCmd {
|
|
getRender,
|
|
startRendering,
|
|
stopRendering,
|
|
}
|
|
|
|
function blender(command:blenderCmd) {
|
|
if(command === blenderCmd.getRender) {
|
|
if(readyToAcceptCommand) {
|
|
readyToAcceptCommand = false;
|
|
renderingPicture = true;
|
|
imageLoading();
|
|
setBlenderStatus("Rendering");
|
|
setBlenderLoading(true);
|
|
blenderConsole.stdin.write("getRender\n");
|
|
} else {
|
|
waitingForRender = true;
|
|
}
|
|
} else if(command === blenderCmd.startRendering) {
|
|
if(readyToAcceptCommand) {
|
|
if(settingList.log == "") {
|
|
logger.warningMSG("No log selected!");
|
|
} else if(!isValid(settingList.log)) {
|
|
logger.warningMSG("Output path is invalid!");
|
|
} else {
|
|
currentLogPortion = 0;
|
|
|
|
const logSizeList:number[] = [];
|
|
getLogList().forEach(function (value, index) {
|
|
logSizeList.push(getLogSize(index));
|
|
});
|
|
|
|
let fullLogSize = 0;
|
|
for(let i = 0; i < logSizeList.length; i++) {
|
|
fullLogSize += logSizeList[i];
|
|
}
|
|
|
|
logPortionList = [];
|
|
logSizeList.forEach(function (value) {
|
|
logPortionList.push(value / fullLogSize);
|
|
});
|
|
|
|
readyToAcceptCommand = false;
|
|
renderingVideo = true;
|
|
pageSetRendering(true);
|
|
setBlenderStatus("Rendering");
|
|
setBlenderLoading(true);
|
|
blenderConsole.stdin.write("startRendering\n");
|
|
|
|
renderInfo.startTime = new Date().getTime();
|
|
setPastTime("0min 0sec");
|
|
setRemainingTime("calculating...");
|
|
}
|
|
}
|
|
} else if(command === blenderCmd.stopRendering) {
|
|
readyToAcceptCommand = false;
|
|
renderingPicture = false;
|
|
renderingVideo = false;
|
|
restartBlender();
|
|
}
|
|
}
|
|
|
|
ipcRenderer.on("isRenderActiveClose", () => {
|
|
if(renderingPicture || renderingVideo) {
|
|
ipcRenderer.send("renderActiveClose");
|
|
} else {
|
|
ipcRenderer.send("renderInactiveClose");
|
|
}
|
|
});
|
|
|
|
export {
|
|
blender,
|
|
blenderCmd,
|
|
startBlender,
|
|
renderingPicture
|
|
} |