UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

263 lines (195 loc) • 7.38 kB
import List from '../../../src/core/collection/list/List.js'; import Signal from '../../../src/core/events/signal/Signal.js'; import ObservedValue from '../../../src/core/model/ObservedValue.js'; import LabelView from '../../../src/view/common/LabelView.js'; import VirtualListView from '../../../src/view/common/VirtualListView.js'; import dom from "../../../src/view/DOM.js"; import ButtonView from '../../../src/view/elements/button/ButtonView.js'; import EmptyView from "../../../src/view/elements/EmptyView.js"; import View from "../../../src/view/View.js"; import SelectionAddAction from '../../actions/concrete/SelectionAddAction.js'; import SelectionRemoveAction from '../../actions/concrete/SelectionRemoveAction.js'; class EntityView extends EmptyView { /** * * @param entity * @param {EntityComponentDataset} entityDataset * @constructor */ constructor(entity, entityDataset) { super({ classList: [ 'entity-view' ] }); this.model = entity; const lId = new LabelView(entity, { classList: ['id'] }); lId.position.setX(0); this.addChild(lId); this.isSelected = new ObservedValue(false); const dCheckBox = dom('div'); dCheckBox.addClass('selection'); this.isSelected.onChanged.add(function (v) { dCheckBox.setClass('selected', v); }); if (this.on === undefined) { this.on = {}; } const signals = this.on; signals.selected = new Signal(); dCheckBox.on('click', function () { signals.selected.send0(); }); this.el.appendChild(dCheckBox.el); } } class EntityListView extends View { /** * * @param {Editor} editor * @param { (function(entity:number, ecd:EntityComponentDataset, view:View):void)[]} decorators */ constructor({ editor, decorators = [] }) { super(); this.el = document.createElement('div'); this.addClass('entity-list-view'); if (this.on === undefined) { this.on = {}; } this.on.interaction = new Signal(); const hiddenEntities = new List(); const self = this; this.editor = editor; function makeElement(entity) { const entityManager = editor.engine.entityManager; const entityDataset = entityManager.dataset; const entityView = new EntityView(entity, entityDataset); const decorator_count = decorators.length; for (let i = 0; i < decorator_count; i++) { const decorator = decorators[i]; decorator(entity, entityDataset, entityView); } if (editor.selection.contains(entity)) { entityView.isSelected.set(true); } entityView.on.selected.add(function () { const actions = self.editor.actions; actions.mark(); const value = !entityView.isSelected.get(); if (value) { actions.do(new SelectionAddAction([entity])); } else { actions.do(new SelectionRemoveAction([entity])); } }); entityView.el.addEventListener('click', function () { self.on.interaction.dispatch(entity); }); return entityView; } const entityList = new List(); const list = new VirtualListView(entityList, { lineSize: 20, elementFactory: makeElement }); list.size.set(150, 600); const actionAdd = { name: "Add", action: function () { const dataset = editor.engine.entityManager.dataset; if (dataset !== null) { dataset.createEntity(); } } }; const vToolBar = new EmptyView(); const vAddButton = new ButtonView(actionAdd); vAddButton.size.set(100, 20); vToolBar.addChild(vAddButton); this.addChildAt(list, 0, 0, 0, 0); this.addChildAt(vToolBar, 0, 1, 0, 0); function addOne(entity) { //exclude editor-owned entities if (editor.isEditorEntity(entity)) { hiddenEntities.add(entity); } else { entityList.add(entity); } } function removeOne(entity) { const hiddenIndex = hiddenEntities.indexOf(entity); if (hiddenIndex !== -1) { hiddenEntities.remove(hiddenIndex); } else { entityList.removeOneOf(entity); } } function selectOne(entity) { list.renderedViews.forEach(function (v) { if (v.model === entity) { v.isSelected.set(true); } }); } function deselectOne(entity) { list.renderedViews.forEach(function (v) { if (v.model === entity) { v.isSelected.set(false); } }); } this.handlers = { addOne: addOne, removeOne: removeOne, selectOne: selectOne, deselectOne: deselectOne, reset: function () { //reset all entityList.reset(); hiddenEntities.reset(); } }; const layout = () => { const size = this.size; list.size.set(size.x, size.y - 20); vToolBar.size.set(size.x, 20); vToolBar.position.set(0, list.size.y + list.position.y); } const handlers = this.handlers; //listen for selection this.bindSignal(editor.selection.on.added, handlers.selectOne); this.bindSignal(editor.selection.on.removed, handlers.deselectOne); this.size.onChanged.add(layout); this.on.linked.add(layout); } layout() { } link() { super.link(); const entityManager = this.editor.engine.entityManager; const handlers = this.handlers; //list all active const dataset = entityManager.dataset; dataset.traverseEntityIndices(function (id) { handlers.addOne(id); }); //propagate current selection this.editor.selection.forEach(handlers.selectOne); dataset.onEntityCreated.add(handlers.addOne); dataset.onEntityRemoved.add(handlers.removeOne); } unlink() { super.unlink(); const entityManager = this.editor.engine.entityManager; const dataset = entityManager.dataset; const handlers = this.handlers; //clear out entity list this.handlers.reset(); dataset.onEntityCreated.remove(handlers.addOne); dataset.onEntityRemoved.remove(handlers.removeOne); } } export default EntityListView;