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