UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

178 lines (125 loc) 5.73 kB
import { SurfacePoint3 } from "../../src/core/geom/3d/SurfacePoint3.js"; import Vector2 from "../../src/core/geom/Vector2.js"; import Vector3 from "../../src/core/geom/Vector3.js"; import { obtainTerrain } from "../../src/engine/ecs/terrain/util/obtainTerrain.js"; import { Transform } from "../../src/engine/ecs/transform/Transform.js"; import Mesh from "../../src/engine/graphics/ecs/mesh/Mesh.js"; import { MeshEvents } from "../../src/engine/graphics/ecs/mesh/MeshEvents.js"; import { make_ray_from_viewport_position } from "../../src/engine/graphics/make_ray_from_viewport_position.js"; import BottomLeftResizeHandleView from "../../src/view/elements/BottomLeftResizeHandleView.js"; import ComponentAddAction from "../actions/concrete/ComponentAddAction.js"; import EntityCreateAction from "../actions/concrete/EntityCreateAction.js"; import SelectionAddAction from "../actions/concrete/SelectionAddAction.js"; import SelectionClearAction from "../actions/concrete/SelectionClearAction.js"; import MeshLibraryView from "./library/MeshLibraryView.js"; /** * * @param {Editor} editor */ export function prepareMeshLibrary(editor) { let resolveEngine; const pEngine = new Promise(function (resolve, reject) { resolveEngine = resolve; }); /** * * @type {Promise<GraphicsEngine>} */ const pGraphicsEngine = pEngine.then(function (e) { return e.graphics; }); const pRenderer = pGraphicsEngine.then(function (graphicsEngine) { return graphicsEngine.renderer; }); const pAssetManager = pEngine.then(e => e.assetManager); const meshLibraryView = new MeshLibraryView( editor.meshLibrary, pAssetManager, pRenderer ); function handleDropEvent(event) { event.stopPropagation(); event.preventDefault(); const dataText = event.dataTransfer.getData('text/json'); if (dataText === "") { //no data return; } const data = JSON.parse(dataText); const type = data.type; if (type !== "Mesh") { //wrong type return; } const url = data.url; const engine = editor.engine; const graphics = engine.graphics; const position = new Vector2(event.clientX, event.clientY); graphics.viewport.positionGlobalToLocal(position, position); const normalizedPosition = new Vector2(); //compute world position for drop const ray = make_ray_from_viewport_position(engine, position); const source = ray.origin; const direction = ray.direction; const entityManager = engine.entityManager; const ecd = entityManager.dataset; const terrain = obtainTerrain(ecd); const worldPosition = new Vector3(); const mesh = new Mesh(); mesh.castShadow = true; mesh.receiveShadow = true; const transform = new Transform(); const actions = editor.actions; actions.mark('New Mesh Placed from Library'); const entityCreateAction = new EntityCreateAction(); actions.do(entityCreateAction); const sp3 = new SurfacePoint3(); const hit_found = terrain.raycastFirstSync(sp3, source.x, source.y, source.z, direction.x, direction.y, direction.z); function handleMeshSetEvent() { const bb = mesh.boundingBox; const c0 = new Vector3(bb.x0, bb.y0, bb.z0); const c1 = new Vector3(bb.x1, bb.y1, bb.z1); const diagonal = c0.distanceTo(c1); const offset = direction.clone().multiplyScalar(diagonal); transform.position.add(offset); //remove listener ecd.removeEntityEventListener(entityCreateAction.entity, MeshEvents.DataSet, handleMeshSetEvent); } if (hit_found) { //got a terrain ray hit, set world placement position to that point worldPosition.copy(sp3.position); } else { //set position to the source of the ray pick if there's nothing else available worldPosition.copy(source); //wait for mesh to load ecd.addEntityEventListener(entityCreateAction.entity, MeshEvents.DataSet, handleMeshSetEvent); } transform.position.copy(worldPosition); mesh.url = url; actions.doMany([ new ComponentAddAction(entityCreateAction.entity, transform), new ComponentAddAction(entityCreateAction.entity, mesh), //automatically select newly placed object new SelectionClearAction(), new SelectionAddAction([entityCreateAction.entity]) ]); } function handleDragOverEvent(event) { event.preventDefault(); } meshLibraryView.on.linked.add(function () { resolveEngine(editor.engine); const viewport = editor.engine.graphics.viewport; viewport.el.addEventListener('drop', handleDropEvent); viewport.el.addEventListener('dragover', handleDragOverEvent); }); meshLibraryView.on.unlinked.add(function () { const viewport = editor.engine.graphics.viewport; viewport.el.removeEventListener('drop', handleDropEvent); viewport.el.removeEventListener('dragover', handleDragOverEvent); }); meshLibraryView.size.set(400, 400); const resizeHandleView = new BottomLeftResizeHandleView(meshLibraryView); meshLibraryView.addChild(resizeHandleView); return meshLibraryView; }