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