UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

214 lines (162 loc) • 6.92 kB
import { noop } from "../../../../../src/core/function/noop.js"; import ObservedValue from "../../../../../src/core/model/ObservedValue.js"; import { ParticleEmitterFlag } from "../../../../../src/engine/graphics/particles/particular/engine/emitter/ParticleEmitterFlag.js"; import { ParticleLayer } from "../../../../../src/engine/graphics/particles/particular/engine/emitter/ParticleLayer.js"; import { SimulationStepDefinition } from "../../../../../src/engine/graphics/particles/particular/engine/simulator/SimulationStepDefinition.js"; import { SimulationStepType } from "../../../../../src/engine/graphics/particles/particular/engine/simulator/SimulationStepType.js"; import { BlendingType } from "../../../../../src/engine/graphics/texture/sampler/BlendingType.js"; import { NativeListController } from "../../../../../src/view/controller/controls/NativeListController.js"; import EmptyView from "../../../../../src/view/elements/EmptyView.js"; import DatGuiController from "../DatGuiController.js"; import ParticleLayerController from "./ParticleLayerController.js"; /** * * @param {*} value * @param {Object} enumerable * @returns {string} */ export function enumNameByValue(value, enumerable) { return Object.keys(enumerable)[Object.values(enumerable).indexOf(value)]; } /** * * @param {ParticleEmitter} emitter * @param {ParticleEmitterSystem} system * @param {function} op * @param {*} [arg0] */ function applyEmitterChanges(emitter, system, op, arg0) { const particleEngine = system.particleEngine; const isSleeping = emitter.getFlag(ParticleEmitterFlag.Sleeping); //re-add the emitter particleEngine.remove(emitter); if (system.renderLayer.visibleSet.contains(emitter.mesh)) { //remove from visible layer if present system.renderLayer.visibleSet.forceRemove(emitter.mesh); } //execute operation op(emitter, arg0); //clear flags emitter.clearFlag(ParticleEmitterFlag.Built | ParticleEmitterFlag.Initialized); //update internal state emitter.registerLayerParameters(); emitter.build(); emitter.initialize(); emitter.computeBoundingBox(); particleEngine.add(emitter); emitter.writeFlag(ParticleEmitterFlag.Sleeping, isSleeping); } export class ParticleEmitterController extends EmptyView { /** * * @param {ParticleEmitterSystem} particleEmitterSystem * @constructor */ constructor(particleEmitterSystem) { super(); this.model = new ObservedValue(null); const self = this; function applyChanges() { const emitter = self.model.getValue(); if (emitter !== null) { applyEmitterChanges(emitter, particleEmitterSystem, noop); } } /** * * @param {function(ParticleEmitter)} op * @param {v} [v] */ function makeChange(op, v) { const emitter = self.model.getValue(); if (emitter !== null) { applyEmitterChanges(emitter, particleEmitterSystem, op, v); } } /** * * @param {function(ParticleEmitter)} op * @returns {function(...[*]=)} */ function mutator(op) { return function (arg0) { makeChange(op, arg0); } } /** * * @param {ParticleEmitter} emitter * @param oldEmitter */ function modelSet(emitter, oldEmitter) { self.removeAllChildren(); if (emitter !== null) { const emitterSurrogate = { preWarm: emitter.getFlag(ParticleEmitterFlag.PreWarm), depthRead: !emitter.getFlag(ParticleEmitterFlag.DepthReadDisabled), depthSoft: !emitter.getFlag(ParticleEmitterFlag.DepthSoftDisabled), velocityAlign: emitter.getFlag(ParticleEmitterFlag.AlignOnVelocity), blendingMode: enumNameByValue(emitter.blendingMode, BlendingType), update: function () { applyChanges(); } }; const dat = new DatGuiController(); self.addChild(dat); dat.addControl(emitterSurrogate, 'preWarm').onChange(mutator((emitter, value) => { /** * @type {ParticleEmitter} */ emitter.writeFlag(ParticleEmitterFlag.PreWarm, value); })); dat.addControl(emitterSurrogate, 'depthRead').onChange(mutator((emitter, value) => { /** * @type {ParticleEmitter} */ emitter.writeFlag(ParticleEmitterFlag.DepthReadDisabled, !value); })); dat.addControl(emitterSurrogate, 'depthSoft').onChange(mutator((emitter, value) => { /** * @type {ParticleEmitter} */ emitter.writeFlag(ParticleEmitterFlag.DepthSoftDisabled, !value); })); dat.addControl(emitterSurrogate, 'velocityAlign').onChange(mutator((emitter, value) => { /** * @type {ParticleEmitter} */ emitter.writeFlag(ParticleEmitterFlag.AlignOnVelocity, value); })); dat.addControl(emitterSurrogate, 'blendingMode', Object.keys(BlendingType)).onChange(mutator((emitter, blendModeName) => { emitter.blendingMode = BlendingType[blendModeName]; })); dat.addControl(emitterSurrogate, 'update').name('Apply Changes'); self.addChild(new NativeListController({ model: emitter.layers, elementViewFactory(layer) { const c = new ParticleLayerController(makeChange); c.model.set(layer); return c; }, elementFactory() { const r = new ParticleLayer(); r.steps.add(SimulationStepDefinition.from(SimulationStepType.FixedPhysics, [])) return r; }, operationAdd(list, layer) { makeChange(emitter => { emitter.addLayer(layer); }); } })) } } this.model.onChanged.add(modelSet); } }