@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
146 lines (106 loc) • 4.3 kB
JavaScript
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;