UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

305 lines (234 loc) • 9.31 kB
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;