@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
305 lines (234 loc) • 9.31 kB
JavaScript
import { passThrough } from "../../src/core/function/passThrough.js";
import { ProcessState } from "../../src/core/process/ProcessState.js";
import LabelView from '../../src/view/common/LabelView.js';
import ListView from "../../src/view/common/ListView.js";
import VirtualListView from '../../src/view/common/VirtualListView.js';
import dom from "../../src/view/DOM.js";
import EmptyView from "../../src/view/elements/EmptyView.js";
import SimpleWindow from '../../src/view/elements/SimpleWindow.js';
import View from "../../src/view/View.js";
import ComponentControlFactory from './ecs/ComponentControlFactory.js';
import EntityEditorView from './ecs/EntityEditor.js';
import EntityListView from './ecs/EntityList.js';
import { HierarchicalEntityListView } from "./ecs/HierarchicalEntityListView.js";
import GridPickCoordinateView from "./GridPickCoordinateView.js";
import { makeEntityDecorators } from "./makeEntityDecorators.js";
import ProcessView from "./process/ProcessView.js";
import ToolSettingsView from "./tools/ToolSettingsView.js";
import ToolView from './tools/ToolView.js';
import { SplitView } from "./v2/SplitView.js";
class ViewManager extends View {
constructor() {
super();
const dRoot = dom('div');
dRoot.addClass('view-manager');
this.el = dRoot.el;
this.storage = [];
//store parameters of previously opened windows
this.memory = {};
}
/**
*
* @param {View} view
* @param {string} [title]
* @returns {SimpleWindowView}
*/
add(view, title = "") {
const simpleWindow = new SimpleWindow(
view,
{
draggable: true,
closeable: false,
resizable: true,
title: title
}
);
this.storage.push({
original: view,
window: simpleWindow
});
this.addChild(simpleWindow);
if (this.memory.hasOwnProperty(title)) {
const windowParams = this.memory[title];
view.size.copy(windowParams.size);
simpleWindow.position.copy(windowParams.position);
}
return simpleWindow;
}
exists(view) {
return this.getInternalIndex(view) !== -1;
}
getInternalIndex(view) {
for (let i = 0; i < this.storage.length; i++) {
const el = this.storage[i];
if (el.original === view) {
return i;
}
}
return -1;
}
remove(view) {
//find the window
const internalIndex = this.getInternalIndex(view);
if (internalIndex === -1) {
return false;
}
const el = this.storage[internalIndex];
//cut from internal index
this.storage.splice(internalIndex, 1);
const vWindow = el.window;
this.removeChild(vWindow);
//remember window parameters
this.memory[vWindow.title.get()] = {
position: vWindow.position.clone(),
size: view.size.clone()
};
return true;
}
}
class EditorView extends View {
main = new EmptyView()
mainViewport = new EmptyView();
/**
*
* @param {Editor} editor
* @constructor
*/
constructor(editor) {
super(editor);
const dRoot = dom('div');
dRoot.addClass('editor-view');
this.el = dRoot.el;
/**
*
* @type {Editor}
*/
this.editor = editor;
/**
*
* @type {View|null}
*/
this.gameView = null;
const decorators = makeEntityDecorators();
const entity_list_view = new HierarchicalEntityListView();
entity_list_view.dataset = editor.engine.entityManager.dataset;
entity_list_view.on.interact.add(inspectEntity);
const entityListView = new EntityListView({ editor, decorators });
this.entityListView = entityListView;
//entity editor
const controllerFactory = new ComponentControlFactory();
const entityEditor = new EntityEditorView(controllerFactory, editor);
this.entityEditor = entityEditor;
function inspectEntity(entity) {
const em = editor.engine.entityManager;
entityEditor.entityManager.set(em);
entityEditor.model.set(entity);
entity_list_view.selection = [entity];
}
this.bindSignal(editor.selection.on.added, function (entity) {
if (editor.selection.length === 1) {
//when first thing is selected - inspect it automatically
inspectEntity(entity);
}
});
entityListView.on.interaction.add(inspectEntity);
this.entityListView = entityListView;
const toolSettings = new ToolSettingsView({});
this.toolSettings = toolSettings;
const toolBar = new ListView(editor.toolEngine.tools, {
elementFactory: function (tool) {
const toolView = new ToolView({ tool, editor });
toolView.el.addEventListener('click', function () {
editor.toolEngine.activate(tool.name);
toolSettings.setTool(tool);
});
const activeTool = editor.toolEngine.active;
function handleActivation() {
toolView.el.classList.toggle('active', activeTool.getValue() === tool);
}
toolView.on.linked.add(handleActivation);
toolView.bindSignal(activeTool.onChanged, handleActivation);
return toolView;
},
classList: ['editor-tool-bar']
});
this.toolBar = toolBar;
//tool bar
const processBar = new ListView(editor.processEngine.processes, {
elementFactory: function (process) {
const toolView = new ProcessView(process);
toolView.el.addEventListener('click', function () {
if (process.__state.getValue() !== ProcessState.Running) {
editor.processEngine.startByName(process.name);
} else {
editor.processEngine.stopByName(process.name);
}
});
return toolView;
},
classList: ['editor-process-bar']
});
this.processBar = processBar;
//selection list
const selectionView = new VirtualListView(editor.selection, {
elementFactory: function (entity) {
const labelView = new LabelView(entity, { format: passThrough });
labelView.el.addEventListener('click', function () {
inspectEntity(entity);
});
return labelView;
},
classList: ['selected-entities']
});
selectionView.size.set(70, 120);
this.selectionView = selectionView;
this.coordinateView = new GridPickCoordinateView(editor);
//
this.bindSignal(this.size.onChanged, this.layout.bind(this));
this.mainViewport.addChild(this.coordinateView);
this.mainViewport.addChild(this.selectionView);
this.mainViewport.addChild(this.toolBar);
this.mainViewport.addChild(this.processBar);
this.mainViewport.addChild(this.toolSettings);
const split = SplitView.from({
fraction: 0.2,
a: entity_list_view,
b: SplitView.from({
fraction: 0.7,
a: this.mainViewport,
b: this.entityEditor,
})
});
this.main.addChild(split);
this.main.size.onChanged.add(split.size.set, split.size);
this.addChild(this.main);
}
layout() {
const size = this.size;
this.main.size.copy(size);
if (this.gameView !== null) {
this.toolBar.size.set(this.gameView.size.x, 36);
this.toolBar.position.set(this.gameView.position.x + 5, this.gameView.position.y + this.gameView.size.y - (this.toolBar.size.y + 5));
// this.processBar.size.set(this.gameView.size.x, 36);
// this.processBar.position.set(this.toolBar.position.x, 5);
}
}
link() {
super.link();
//hijack game view from the engine
this.gameView = this.editor.engine.gameView;
this.mainViewport.addChild(this.gameView);
this.mainViewport.size.onChanged.add(this.gameView.size.set, this.gameView.size);
this.layout();
}
unlink() {
super.unlink();
if (this.gameView !== null) {
//release game view
this.mainViewport.removeChild(this.gameView);
this.mainViewport.size.onChanged.remove(this.gameView.size.set, this.gameView.size);
this.gameView = null;
}
}
}
export default EditorView;