mylingo3d
Version:
Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor
321 lines • 13.3 kB
JavaScript
import { jsx as _jsx } from "preact/jsx-runtime";
import { last, omit } from "@lincode/utils";
import { Pane } from "tweakpane";
import settings from "../../api/settings";
import mainCamera from "../../engine/mainCamera";
import { setOrbitControls } from "../../states/useOrbitControls";
import { useEffect, useLayoutEffect, useState } from "preact/hooks";
import register from "preact-custom-element";
import { useSelectionTarget, useCameraList, useMultipleSelectionTargets, useCameraStack, useNodeEditor } from "../states";
import { Cancellable } from "@lincode/promiselikes";
import { getSecondaryCamera, setSecondaryCamera } from "../../states/useSecondaryCamera";
import { nonEditorSettings } from "../../api/serializer/types";
import { setupDefaults, setupSchema } from "../../interface/ISetup";
import mainOrbitCamera from "../../engine/mainOrbitCamera";
import getComponentName from "../utils/getComponentName";
import addInputs, { setProgrammatic } from "./addInputs";
import getParams from "./getParams";
import splitObject from "./splitObject";
import { onTransformControls } from "../../events/onTransformControls";
import assignIn from "./assignIn";
import { emitSceneGraphNameChange } from "../../events/onSceneGraphNameChange";
import { dummyDefaults } from "../../interface/IDummy";
import useInit from "../utils/useInit";
import { decreaseEditorMounted, increaseEditorMounted } from "../../states/useEditorMounted";
import useHotkeys from "./useHotkeys";
Object.assign(dummyDefaults, {
stride: { x: 0, y: 0 }
});
const Editor = () => {
const elRef = useInit();
useHotkeys();
useLayoutEffect(() => {
window.onbeforeunload = confirmExit;
function confirmExit() {
return "Are you sure you want to close the current page?";
}
mainOrbitCamera.active = true;
setOrbitControls(true);
settings.gridHelper = true;
increaseEditorMounted();
return () => {
setOrbitControls(false);
settings.gridHelper = false;
decreaseEditorMounted();
};
}, []);
const [cameraStack] = useCameraStack();
const camera = last(cameraStack);
const [selectionTarget] = useSelectionTarget();
const [multipleSelectionTargets] = useMultipleSelectionTargets();
const [cameraList] = useCameraList();
const [pane, setPane] = useState();
const [cameraFolder, setCameraFolder] = useState();
useLayoutEffect(() => {
if (!pane || !cameraFolder)
return;
const mainCameraName = "editor camera";
const options = cameraList.reduce((acc, cam, i) => {
acc[i === 0
? mainCameraName
: getComponentName(cam.userData.manager)] = i;
return acc;
}, {});
const cameraInput = pane.addInput({ camera: cameraList.indexOf(camera) }, "camera", { options });
cameraFolder.add(cameraInput);
cameraInput.on("change", ({ value }) => {
cameraList[value].userData.manager.active = true;
});
const secondaryOptions = {
none: 0,
...omit(options, mainCameraName)
};
const secondaryCameraInput = pane.addInput({
"secondary camera": cameraList.indexOf(getSecondaryCamera() ?? mainCamera)
}, "secondary camera", { options: secondaryOptions });
cameraFolder.add(secondaryCameraInput);
secondaryCameraInput.on("change", ({ value }) => setSecondaryCamera(value === 0 ? undefined : cameraList[value]));
return () => {
cameraInput.dispose();
secondaryCameraInput.dispose();
};
}, [pane, cameraFolder, cameraList, camera]);
useEffect(() => {
const el = elRef.current;
if (!el)
return;
const pane = new Pane({ container: el });
setPane(pane);
setCameraFolder(pane.addFolder({ title: "camera" }));
if (!selectionTarget) {
const [editorParams, editorRest] = splitObject(omit(getParams(setupSchema, setupDefaults, settings), nonEditorSettings), ["gridHelper", "gridHelperSize"]);
addInputs(pane, "editor", settings, setupDefaults, editorParams);
const [rendererParams, rendererRest] = splitObject(editorRest, [
"antiAlias",
"pixelRatio",
"fps",
"logarithmicDepth",
"pbr"
]);
addInputs(pane, "renderer", settings, setupDefaults, rendererParams);
const [sceneParams, sceneRest] = splitObject(rendererRest, [
"exposure",
"defaultLight",
"shadowDistance",
"shadowResolution",
"shadowBias",
"skybox",
"texture",
"color"
]);
addInputs(pane, "lighting & environment", settings, setupDefaults, sceneParams);
const [effectsParams, effectsRest] = splitObject(sceneRest, [
"ambientOcclusion",
"bloom",
"bloomStrength",
"bloomRadius",
"bloomThreshold",
"bokeh",
"bokehAperture",
"bokehFocus",
"bokehMaxBlur",
"lensDistortion",
"lensIor",
"lensBand",
"motionBlur",
"motionBlurStrength"
]);
addInputs(pane, "effects", settings, setupDefaults, effectsParams);
const [outlineParams, outlineRest] = splitObject(effectsRest, [
"outlineColor",
"outlineHiddenColor",
"outlinePattern",
"outlinePulse",
"outlineStrength",
"outlineThickness"
]);
addInputs(pane, "outline effect", settings, setupDefaults, outlineParams);
const [physicsParams, physicsRest] = splitObject(outlineRest, [
"gravity",
"repulsion",
"centripetal"
]);
addInputs(pane, "physics", settings, setupDefaults, physicsParams);
Object.keys(physicsRest).length &&
addInputs(pane, "settings", settings, setupDefaults, physicsRest);
return () => {
pane.dispose();
};
}
const target = selectionTarget;
const handle = new Cancellable();
if (!multipleSelectionTargets.length) {
const { schema, defaults, componentName } = target.constructor;
const [generalParams, generalRest] = splitObject(omit(getParams(schema, defaults, target), [
"rotation",
"innerRotation",
"frustumCulled",
"minAzimuthAngle",
"maxAzimuthAngle"
]), ["name", "id", "physics", "gravity"]);
if (generalParams) {
const { name: nameInput } = addInputs(pane, "general", target, defaults, generalParams);
nameInput?.on("change", () => emitSceneGraphNameChange());
}
const [transformParams0, transformRest] = splitObject(generalRest, [
"x",
"y",
"z",
"rotationX",
"rotationY",
"rotationZ",
"scale",
"scaleX",
"scaleY",
"scaleZ",
"innerX",
"innerY",
"innerZ",
"innerRotationX",
"innerRotationY",
"innerRotationZ",
"width",
"height",
"depth"
]);
if (transformParams0) {
const [innerTransformParams, transformParams] = splitObject(transformParams0, [
"innerX",
"innerY",
"innerZ",
"innerRotationX",
"innerRotationY",
"innerRotationZ",
"width",
"height",
"depth"
]);
addInputs(pane, "transform", target, defaults, transformParams);
innerTransformParams &&
addInputs(pane, "inner transform", target, defaults, innerTransformParams);
handle.watch(onTransformControls(() => {
setProgrammatic();
assignIn(transformParams, target, [
"x",
"y",
"z",
"rotationX",
"rotationY",
"rotationZ",
"scaleX",
"scaleY",
"scaleZ"
]);
pane.refresh();
}));
}
const [displayParams, displayRest] = splitObject(transformRest, [
"visible",
"innerVisible",
"castShadow",
"receiveShadow"
]);
displayParams &&
addInputs(pane, "display", target, defaults, displayParams);
const [effectsParams, effectsRest] = splitObject(displayRest, [
"bloom",
"outline"
]);
effectsParams &&
addInputs(pane, "effects", target, defaults, effectsParams);
const [animationParams, animationRest] = splitObject(effectsRest, [
"animation",
"animationPaused",
"animationRepeat"
]);
animationParams &&
addInputs(pane, "animation", target, defaults, animationParams);
const [adjustMaterialParams, adjustMaterialRest] = splitObject(animationRest, [
"metalnessFactor",
"roughnessFactor",
"opacityFactor",
"envFactor",
"adjustColor",
"reflection",
"illumination",
"toon"
]);
adjustMaterialParams &&
addInputs(pane, "adjust material", target, defaults, adjustMaterialParams);
const [materialParams, materialRest] = splitObject(adjustMaterialRest, [
"fog",
"opacity",
"color",
"texture",
"textureRepeat",
"textureFlipY",
"textureRotation",
"videoTexture",
"wireframe"
]);
materialParams &&
addInputs(pane, "material", target, defaults, materialParams);
const [pbrMaterialParams, pbrMaterialRest] = splitObject(materialRest, [
"metalnessMap",
"metalness",
"roughnessMap",
"roughness",
"normalMap",
"normalScale",
"normalMapType",
"bumpMap",
"bumpScale",
"displacementMap",
"displacementScale",
"displacementBias",
"aoMap",
"aoMapIntensity",
"lightMap",
"lightMapIntensity",
"emissiveMap",
"emissiveIntensity",
"emissiveColor",
"emissive",
"envMap",
"alphaMap"
]);
pbrMaterialParams &&
addInputs(pane, "pbr material", target, defaults, pbrMaterialParams);
if (componentName === "dummy") {
pbrMaterialRest.stride = {
x: target.strideRight,
y: -target.strideForward
};
const { stride: strideInput } = addInputs(pane, componentName, target, defaults, pbrMaterialRest);
strideInput.on("change", ({ value }) => {
Object.assign(pbrMaterialRest, {
strideForward: -value.y,
strideRight: value.x
});
pane.refresh();
});
}
else if (Object.keys(pbrMaterialRest).length)
addInputs(pane, componentName, target, defaults, pbrMaterialRest);
}
return () => {
handle.cancel();
pane.dispose();
};
}, [selectionTarget, multipleSelectionTargets]);
return (_jsx("div", { ref: elRef, className: "lingo3d-ui lingo3d-bg", style: { width: 300, height: "100%", overflowY: "scroll" } }));
};
const EditorParent = () => {
const [nodeEditor] = useNodeEditor();
if (nodeEditor)
return null;
return _jsx(Editor, {});
};
export default EditorParent;
register(EditorParent, "lingo3d-editor");
//# sourceMappingURL=index.js.map