UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

154 lines (115 loc) 4.93 kB
import { AxesHelper, Group, Mesh as ThreeMesh, MeshBasicMaterial, SphereBufferGeometry } from "three"; import { Transform } from "../../../src/engine/ecs/transform/Transform.js"; import { Attachment } from "../../../src/engine/ecs/attachment/Attachment.js"; import { BoneAttachmentSocket } from "../../../src/engine/ecs/sockets/BoneAttachmentSocket.js"; import { BoneAttachmentBinding } from "../../../src/engine/ecs/attachment/BoneAttachmentBinding.js"; import Mesh from "../../../src/engine/graphics/ecs/mesh/Mesh.js"; import { TransformAttachmentBinding } from "../../../src/engine/ecs/attachment/TransformAttachmentBinding.js"; import { make3DSymbolicDisplay } from "./make3DSymbolicDisplay.js"; import { AttachmentSockets } from "../../../src/engine/ecs/sockets/AttachmentSockets.js"; import { buildThreeJSHelperEntity } from "./buildThreeJSHelperEntity.js"; import ViewportPosition from "../../../src/engine/ecs/gui/position/ViewportPosition.js"; import LabelView from "../../../src/view/common/LabelView.js"; import HeadsUpDisplay from "../../../src/engine/ecs/gui/hud/HeadsUpDisplay.js"; import GUIElement from "../../../src/engine/ecs/gui/GUIElement.js"; import { MeshEvents } from "../../../src/engine/graphics/ecs/mesh/MeshEvents.js"; /** * * @param {Engine} engine * @return {ComponentSymbolicDisplay} */ export function makeSocketsSymbolicDisplay(engine) { const centerMaterial = new MeshBasicMaterial({ color: 0x00FFFF, transparent: true, opacity: 0.2 }); const centerGeometry = new SphereBufferGeometry(0.05, 10, 10); /** * * @param {AttachmentSockets} sockets * @param {Transform} transform * @param {number} entity * @param {SymbolicDisplayInternalAPI} api */ function factory([sockets, transform, entity], api) { const ecd = engine.entityManager.dataset; const rebuild = () => { ecd.removeEntityEventListener(entity, MeshEvents.DataSet, rebuild); api.update(); }; ecd.addEntityEventListener(entity, MeshEvents.DataSet, rebuild); /** * * @param {AttachmentSocket} socket */ function buildGizmo(socket) { /** * * @type {AttachmentBinding} */ let binding = null; let t = new Transform(); const attachment = new Attachment(); if (socket instanceof BoneAttachmentSocket) { binding = new BoneAttachmentBinding(); /** * * @type {Mesh} */ const mesh = engine.entityManager.dataset.getComponent(entity, Mesh); const bone = mesh.getDescendantObjectByName(socket.boneName); binding.bone = bone; } else { binding = new TransformAttachmentBinding(); } binding.attachment = attachment; binding.parentEntity = entity; binding.parentTransform = transform; binding.socket = socket; binding.attachedTransform = t; const socket_group = new Group(); socket_group.frustumCulled = false; const helper = new AxesHelper(2 * transform.scale.x); helper.frustumCulled = false; const mesh = new ThreeMesh(centerGeometry, centerMaterial); mesh.frustumCulled = false; socket_group.add(mesh); socket_group.add(helper); const builder = buildThreeJSHelperEntity(socket_group, entity); const v = new LabelView(socket.id, { classList: ['__debug-plaque'] }); v.css({ position: 'absolute', whiteSpace: 'pre', left: 0, top: 0 }) builder.add(new HeadsUpDisplay()) .add(new ViewportPosition()) .add(GUIElement.fromView(v)) function update_transform() { binding.update(); /** * * @type {Transform} */ const transform = builder.getComponent(Transform); transform.copy(t); } api.onFrame(update_transform); api.bind(sockets.elements.on.removed, (s) => { if (s === socket) { builder.destroy(); } }); api.emit(builder); } sockets.elements.forEach(buildGizmo); api.bind(sockets.elements.on.added, buildGizmo); } return make3DSymbolicDisplay({ engine, components: [AttachmentSockets, Transform], factory }); }