UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

146 lines (106 loc) 4.3 kB
import Vector1 from "../../core/geom/Vector1.js"; import { RemainingTimeEstimator } from "../../core/process/task/RemainingTimeEstimator.js"; import TaskState from '../../core/process/task/TaskState.js'; import Clock from "../../engine/Clock.js"; import LabelView from '../common/LabelView.js'; import { LocalizedLabelView } from "../common/LocalizedLabelView.js"; import dom from '../DOM.js'; import SmoothProgressBar from '../elements/progress/SmoothProgressBar.js'; import View from '../View.js'; class TaskProgressView extends View { /** * * @param {Task|TaskGroup} task * @param {Localization} [localization] * @constructor */ constructor({ task, localization=null }) { super(); function makeNameId() { const taskName = typeof task.name === "string" ? task.name : "unknown"; return `system_task.${taskName.replace(/ /g, '_')}.name` } const taskName = new LocalizedLabelView({ id: makeNameId(), localization, classList: ['name'] }); const progressBar = new SmoothProgressBar(); const processFailure = () => { //find failed subtasks/dependencies if (task.children !== undefined) { const failedChildren = task.children.filter(function (t) { return t.state.getValue() === TaskState.FAILED; }); failedChildren.forEach((t) => { this.addChild(new LabelView("Failed subtask: " + t.name)); }); } } /** * * @param {TaskState} state */ function getStateName(state) { for (let stateName in TaskState) { if (TaskState[stateName] === state) { return stateName; } } return "Unknown State"; } const state = new LabelView(task.state, { format: function (v) { return getStateName(v); }, classList: ['state'] }); function updateState() { function className(n) { return `state-${n}`; } for (let stateName in TaskState) { state.removeClass(className(stateName)); } const v = task.state.getValue(); if (v === TaskState.FAILED) { processFailure(); } const name = getStateName(v); state.addClass(className(name)); } state.on.linked.add(updateState); state.bindSignal(task.state.onChanged, updateState); const remainingTimeEstimator = new RemainingTimeEstimator(100); const remainingTime = new Vector1(0); const lRemainingTime = new LabelView(remainingTime, { format: function (v) { return v.toFixed(0); }, classList: ['remaining-time'] }); this.el = dom().addClass('task-progress-view').el; this.addChild(taskName); this.addChild(state); this.addChild(progressBar); this.addChild(lRemainingTime); progressBar.max = 1; const clock = new Clock(); clock.start(); const update = () => { const computedProgressValue = task.computeProgress(); const taskProgress = Number.isNaN(computedProgressValue) ? 0 : computedProgressValue; progressBar.value = taskProgress; remainingTimeEstimator.update(clock.updateElapsedTime(), taskProgress); const computedEstimate = remainingTimeEstimator.estimate(taskProgress); const estimate = Number.isNaN(computedEstimate) ? 0 : computedProgressValue; remainingTime.set(estimate); const state = task.state.getValue(); if (state !== TaskState.FAILED && state !== TaskState.SUCCEEDED && this.isLinked) { requestAnimationFrame(update); } } this.on.linked.add(update); } } export default TaskProgressView;