@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
147 lines (125 loc) • 2.95 kB
JavaScript
import { assert } from "../assert.js";
import Signal from "../events/signal/Signal.js";
/**
* Enumerable value abstraction. Think `enum` keyword in TypeScript or any other programming language.
* Given a set of valid values, holds one of such values.
* This is an observable value, meaning you can subscribe to be notified of changes via {@link onChanged} signal.
*
* @example
* const v = new ObservedEnum(7, {
* ONE: 1,
* SEVEN: 7
* });
*
* v.getValue(); // 7
*
* v.set(1);
*
* v.getValue(); // 1
*
* v.set(2); // will throw error, as 2 is not a valid enum value
*/
class ObservedEnum {
/**
* @template T
* @param {T} value
* @param {Object.<string,T>} validSet
*/
constructor(value, validSet) {
assert.isObject(validSet, "validSet");
assert.enum(value, validSet, "value");
/**
*
* @type {T}
* @private
*/
this.__value = value;
/**
*
* @type {Object<string, T>}
* @private
*/
this.__validSet = validSet;
/**
* @readonly
* @type {Signal<T,T>}
*/
this.onChanged = new Signal();
}
/**
* Do not modify result
* @returns {Object<string, T>}
*/
getValidValueSet() {
return this.__validSet;
}
/**
*
* @param {T} value
* @returns {ObservedEnum}
*/
set(value) {
assert.enum(value, this.__validSet, "value")
const oldValue = this.__value;
if (oldValue !== value) {
this.__value = value;
this.onChanged.dispatch(value, oldValue);
}
return this;
}
/**
* @template T
* @param {ObservedEnum<T>} other
* @returns {boolean}
*/
equals(other) {
return this.__value === other.__value;
}
/**
*
* @return {number}
*/
hash() {
let hash = 0;
for (const n of this.__validSet) {
if(this.__validSet[n] === this.__value) {
break;
}
hash++;
}
return hash;
}
/**
*
* @param {ObservedEnum} other
*/
copy(other) {
this.set(other.getValue());
}
/**
*
* @returns {T}
*/
getValue() {
return this.__value;
}
/**
*
* @param {function(T,T)} processor
* @param {*} [thisArg]
* @returns {this}
*/
process(processor, thisArg) {
this.onChanged.add(processor, thisArg);
const v = this.__value;
processor.call(thisArg, v, v);
return this;
}
toJSON() {
return this.__value;
}
fromJSON(obj) {
this.set(obj);
}
}
export default ObservedEnum;