UNPKG

mylingo3d

Version:

Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor

85 lines 4.43 kB
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime"; import { Fragment } from "preact"; import { useEffect, useState } from "preact/hooks"; import Loaded from "../../display/core/Loaded"; import { isMeshItem } from "../../display/core/MeshItem"; import Dummy, { dummyTypeMap } from "../../display/Dummy"; import { onSelectionTarget } from "../../events/onSelectionTarget"; import { DUMMY_URL, YBOT_URL } from "../../globals"; import { setSceneGraphExpanded } from "../../states/useSceneGraphExpanded"; import { setSceneGraphTarget } from "../../states/useSceneGraphTarget"; import { addSelectionFrozen, clearSelectionFrozen } from "../../states/useSelectionFrozen"; import downloadBlob from "../../api/files/downloadBlob"; import ContextMenu from "../component/ContextMenu"; import MenuItem from "../component/ContextMenu/MenuItem"; import { useSelectionFrozen, useSelectionTarget } from "../states"; const traverseUp = (obj, expandedSet) => { expandedSet.add(obj); const nextParent = obj.userData.manager?.parent?.outerObject3d ?? obj.parent; nextParent && traverseUp(nextParent, expandedSet); }; const search = (n, target) => { const name = n.toLowerCase(); let found; if (target instanceof Loaded) target.loadedGroup.traverse((item) => { if (found) return; item.name.toLowerCase().includes(name) && (found = item); }); else target.outerObject3d.traverse((item) => { if (found) return; item.name.toLowerCase().includes(name) && (found = item); }); if (!found) return; const expandedSet = new Set(); traverseUp(found, expandedSet); setSceneGraphExpanded(expandedSet); setSceneGraphTarget(found); }; const SceneGraphContextMenu = () => { const [data, setData] = useState(undefined); const [showSearch, setShowSearch] = useState(false); const [selectionTarget] = useSelectionTarget(); const [[selectionFrozen]] = useSelectionFrozen(); useEffect(() => { let [clientX, clientY] = [0, 0]; const cb = (e) => ([clientX, clientY] = [e.clientX, e.clientY]); document.addEventListener("mousemove", cb); const handle = onSelectionTarget(({ target, rightClick }) => { rightClick && setData({ x: clientX, y: clientY, target }); }); return () => { handle.cancel(); document.removeEventListener("mousemove", cb); }; }, []); useEffect(() => { !data && setShowSearch(false); }, [data]); if (!data) return null; return (_jsx(ContextMenu, { data: data, setData: setData, children: showSearch ? (_jsx("input", { ref: (el) => el?.focus(), style: { all: "unset", padding: 6 }, onKeyDown: (e) => { e.stopPropagation(); if (e.key !== "Enter" && e.key !== "Escape") return; e.key === "Enter" && selectionTarget && search(e.target.value, selectionTarget); setData(undefined); } })) : (_jsxs(Fragment, { children: [data.target && (_jsxs(Fragment, { children: [_jsx(MenuItem, { setData: undefined, onClick: () => setShowSearch(true), children: "Search children" }), _jsx(MenuItem, { setData: setData, onClick: () => isMeshItem(selectionTarget) && addSelectionFrozen(selectionTarget), children: "Freeze selection" }), selectionTarget instanceof Dummy && dummyTypeMap.has(selectionTarget) && (_jsx(MenuItem, { setData: setData, onClick: async () => { const url = dummyTypeMap.get(selectionTarget) === "dummy" ? YBOT_URL : DUMMY_URL + "readyplayerme/reference.fbx"; const res = await fetch(url); downloadBlob("model.fbx", await res.blob()); }, children: "Download for Mixamo" }))] })), _jsx(MenuItem, { setData: setData, disabled: !selectionFrozen.size, onClick: () => clearSelectionFrozen(), children: "Unfreeze all" })] })) })); }; export default SceneGraphContextMenu; //# sourceMappingURL=SceneGraphContextMenu.js.map