diff --git a/package-lock.json b/package-lock.json index d217be6..9ca9880 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "license": "MIT", "dependencies": { "@electron/remote": "^2.0.8", + "csv-parse": "^5.2.0", "electron-log": "^4.4.7", "electron-squirrel-startup": "^1.0.0", "electron-updater": "^5.0.1", @@ -4603,6 +4604,11 @@ "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==", "dev": true }, + "node_modules/csv-parse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-5.2.0.tgz", + "integrity": "sha512-ZuLjTp3Qx2gycoB7FKS9q11KgDL3f0wQszTlNOajS3fHa0jypN/zgjmkam+rczX5dXw5z7+KrDW2hWkM4542Ug==" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -14458,6 +14464,11 @@ "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==", "dev": true }, + "csv-parse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-5.2.0.tgz", + "integrity": "sha512-ZuLjTp3Qx2gycoB7FKS9q11KgDL3f0wQszTlNOajS3fHa0jypN/zgjmkam+rczX5dXw5z7+KrDW2hWkM4542Ug==" + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", diff --git a/package.json b/package.json index cca75e3..bea24cd 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,7 @@ }, "dependencies": { "@electron/remote": "^2.0.8", + "csv-parse": "^5.2.0", "electron-log": "^4.4.7", "electron-squirrel-startup": "^1.0.0", "electron-updater": "^5.0.1", diff --git a/src/components/blender-controller.ts b/src/components/blenderController.ts similarity index 86% rename from src/components/blender-controller.ts rename to src/components/blenderController.ts index 231b704..93480ae 100644 --- a/src/components/blender-controller.ts +++ b/src/components/blenderController.ts @@ -2,7 +2,7 @@ import { blenderPath, blenderScriptPath, dataPath, templatePath } from "./paths" import {spawn} from "child_process"; import logger from "./logger"; import { setBlenderLoading, setBlenderStatus } from "./ui/menu"; -import { setLogNumber, setRenderDisplayProgress, setStatus } from "./ui/renderingSide"; +import { setLogNumber, setPastTime, setRemainingTime, setRenderDisplayProgress, setStatus, setPastTimeNow, setRemainingTimeNow } from "./ui/renderingSide"; import {imageLoading, imageLoaded} from "./ui/settingsSide"; import { getLogList, getLogSize, settingList } from "./settings"; import isValid from "is-valid-path"; @@ -26,6 +26,8 @@ let renderingPicture = false; let renderingVideo = false; let waitingForRender = false; +let renderStartTime = new Date().getTime(); + let logPortionList:number[] = []; let currentLogPortion = 0; @@ -39,6 +41,27 @@ function setRenderProgress(log:number, init:boolean, frameCount:number, frame:nu } setProgress(progress); setRenderDisplayProgress(parseFloat((progress*100).toFixed(2))); + + const timeNow = new Date().getTime(); + const timeDiff = timeNow - renderStartTime; + let timeDiffSeconds = timeDiff / 1000; + let timeDiffMinutes = 0; + while(timeDiffSeconds > 60) { + timeDiffMinutes++; + timeDiffSeconds -= 60; + } + setPastTimeNow(timeDiffMinutes + "min " + timeDiffSeconds.toFixed(0) + "sec"); + + if(progress > 0) { + const timeRemaining = (timeDiff / progress) * (1 - progress); + timeDiffSeconds = timeRemaining / 1000; + timeDiffMinutes = 0; + while(timeDiffSeconds > 60) { + timeDiffMinutes++; + timeDiffSeconds -= 60; + } + setRemainingTimeNow(timeDiffMinutes + "min " + timeDiffSeconds.toFixed(0) + "sec"); + } } function startBlender() { @@ -188,6 +211,10 @@ function blender(command:blenderCmd) { setBlenderStatus("Rendering"); setBlenderLoading(true); blenderConsole.stdin.write("startRendering\n"); + + renderStartTime = new Date().getTime(); + setPastTime("0min 0sec"); + setRemainingTime("calculating..."); } } } else if(command === blenderCmd.stopRendering) { diff --git a/src/components/logReader.ts b/src/components/logReader.ts new file mode 100644 index 0000000..fa7a4c0 --- /dev/null +++ b/src/components/logReader.ts @@ -0,0 +1,144 @@ +import logger from "./logger"; +import {parse as csvParse} from "csv-parse"; + +async function openLogFile(filePath:string, rawData:boolean) { + const data = await fetch(filePath).then(function(response) { + return response.text(); + }).then(function(data) { + return data; + }).catch(function(error) { + logger.error("Could not load log file: " + error.toString()); + return ""; + }); + + if(rawData) { + return data; + } else { + let logData:string[]|undefined = undefined; + csvParse(data, {}, (err, output:string[]) => { + if(err) { + logger.errorMSG(`Error parsing csv file: ${err}`); + logData = []; + } else { + logData = output; + } + }); + + while(typeof logData === "undefined") { + await new Promise(resolve => setTimeout(resolve, 100)); + } + return logData; + } +} + +async function getLogTime(filePath:string) { + return await openLogFile(filePath, false).then(function(data) { + if(data.length > 0) { + const time = data[1][1]; + const date = data[1][0]; + + const endTime = data[data.length - 1][1]; + const endDate = data[data.length - 1][0]; + + const dateList = date.split("-"); + const endDateList = endDate.split("-"); + + const timeList = time.split(":"); + timeList.push(timeList[2].split(".")[1]); + timeList[2] = timeList[2].split(".")[0]; + + const endTimeList = endTime.split(":"); + endTimeList.push(endTimeList[2].split(".")[1]); + endTimeList[2] = endTimeList[2].split(".")[0]; + + const year = parseInt(dateList[0]); + const month = parseInt(dateList[1]); + const day = parseInt(dateList[2]); + + const hour = parseInt(timeList[0]); + const minute = parseInt(timeList[1]); + const second = parseInt(timeList[2]); + const millisecond = parseInt(timeList[3]); + + let pastYears = parseInt(endDateList[0]) - year; + let pastMonths = parseInt(endDateList[1]) - month; + let pastDays = parseInt(endDateList[2]) - day; + + let pastHours = parseInt(endTimeList[0]) - hour; + let pastMinutes = parseInt(endTimeList[1]) - minute; + let pastSeconds = parseInt(endTimeList[2]) - second; + let pastMilliseconds = parseInt(endTimeList[3]) - millisecond; + + if(pastMilliseconds < 0) { + pastMilliseconds += 1000; + pastSeconds--; + } + if(pastSeconds < 0) { + pastSeconds += 60; + pastMinutes--; + } + if(pastMinutes < 0) { + pastMinutes += 60; + pastHours--; + } + if(pastHours < 0) { + pastHours += 24; + pastDays--; + } + if(pastDays < 0) { + pastDays += 30; + pastMonths--; + } + if(pastMonths < 0) { + pastMonths += 12; + pastYears--; + } + + return { + start: { + year, + month, + day, + hour, + minute, + second, + millisecond + }, + length: { + years: pastYears, + months: pastMonths, + days: pastDays, + hours: pastHours, + minutes: pastMinutes, + seconds: pastSeconds, + milliseconds: pastMilliseconds + } + } + } else { + return { + start: { + year: 0, + month: 0, + day: 0, + hour: 0, + minute: 0, + second: 0, + millisecond: 0, + }, + length: { + years: 0, + months: 0, + days: 0, + hours: 0, + minutes: 0, + seconds: 0, + milliseconds: 0 + } + }; + } + }); +} + +export { + getLogTime +}; \ No newline at end of file diff --git a/src/components/ui/mainSide.tsx b/src/components/ui/mainSide.tsx index 4bb05b3..2ba8c50 100644 --- a/src/components/ui/mainSide.tsx +++ b/src/components/ui/mainSide.tsx @@ -2,9 +2,10 @@ import React, {useState, useEffect} from "react"; import { dialog } from "@electron/remote"; import { settingList, updateSettings } from "../settings"; import logger from "../logger"; -import {blender, blenderCmd} from "../blender-controller"; +import {blender, blenderCmd} from "../blenderController"; import openFolder from "../openFolder"; import {platformCharacter} from "../paths"; +import {getLogTime} from "../logReader"; function MainSide() { const [logs, setLogs] = useState(settingList.log); @@ -14,21 +15,45 @@ function MainSide() { {log} })); + useEffect(() => { - if(settingList.log == "") { - setLogTable([]); - } else { + async function getData() { const logList = settingList.log.substring(1).slice(0, -1).split('""'); const logListName:string[] = []; - logList.forEach(log => { + const logListTime:string[] = []; + const logListLength:string[] = []; + for(const log of logList) { logListName.push(log.split(platformCharacter())[log.split(platformCharacter()).length - 1].replace(".csv", "")); - }); + const logTime = await getLogTime(log); + const logTimeDisplay = logTime.start.day + "." + logTime.start.month + "." + logTime.start.year + " " + logTime.start.hour + ":" + logTime.start.minute + ":" + logTime.start.second; + logListTime.push(logTimeDisplay); + + let logLengthDisplay = "0:00:00"; + if(logTime.length.years > 0) { + logLengthDisplay = logTime.length.years + "y " + logTime.length.months + "m " + logTime.length.days + "d " + logTime.length.hours + "h " + logTime.length.minutes + "m " + logTime.length.seconds + "s"; + } else if(logTime.length.months > 0) { + logLengthDisplay = logTime.length.months + "m " + logTime.length.days + "d " + logTime.length.hours + "h " + logTime.length.minutes + "m " + logTime.length.seconds + "s"; + } else if(logTime.length.days > 0) { + logLengthDisplay = logTime.length.days + "d " + logTime.length.hours + "h " + logTime.length.minutes + "m " + logTime.length.seconds + "s"; + } else { + logLengthDisplay = logTime.length.hours + "h " + logTime.length.minutes + "m " + logTime.length.seconds + "s"; + } + logListLength.push(logLengthDisplay); + } setLogTable(logListName.map((log, index) => { return - openFolder(logList[index].substring(0, logList[index].lastIndexOf(platformCharacter())))}>{index+1}. {log} + {index+1}. + openFolder(logList[index].substring(0, logList[index].lastIndexOf(platformCharacter())))}>{log} + ({logListLength[index]}) ) } +function setPastTimeNow(time:string) { + pastTimeNow = time; +} + +function setRemainingTimeNow(time:string) { + remainingTimeNow = time; +} + export default RenderingSide; export { setLogNumber, setStatus, - setRenderDisplayProgress + setRenderDisplayProgress, + setPastTime, + setRemainingTime, + setPastTimeNow, + setRemainingTimeNow }; \ No newline at end of file diff --git a/src/components/ui/settingsSide.tsx b/src/components/ui/settingsSide.tsx index d21a9e9..21f7296 100644 --- a/src/components/ui/settingsSide.tsx +++ b/src/components/ui/settingsSide.tsx @@ -1,6 +1,6 @@ import React, {useState, useEffect} from "react"; import { settingList, updateSettings, settingListLoadDefault } from "../settings"; -import {blender, blenderCmd, renderingPicture} from "../blender-controller"; +import {blender, blenderCmd, renderingPicture} from "../blenderController"; import {dataPath} from "../paths"; import path from "path"; diff --git a/src/index.css b/src/index.css index aa4ecac..63aae9c 100644 --- a/src/index.css +++ b/src/index.css @@ -379,7 +379,6 @@ button:hover { width: 100%; background-color: #0d131e; border-radius: 15px; - margin-bottom: 20px; position: relative; overflow: hidden; } diff --git a/src/renderer.tsx b/src/renderer.tsx index ebfd2ab..b7de22f 100644 --- a/src/renderer.tsx +++ b/src/renderer.tsx @@ -6,7 +6,7 @@ import SettingsSite from "./components/ui/settingsSide"; import RenderingSide from "./components/ui/renderingSide"; import "./index.css"; import "./toggle-switchy.css"; -import { startBlender } from "./components/blender-controller"; +import { startBlender } from "./components/blenderController"; import {ipcRenderer} from "electron"; enum Side {