@trap_stevo/legendarybuilderproreact-ui
Version:
The legendary UI & utility API that makes your application a legendary application. ~ Created by Steven Compton
356 lines • 12.3 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
var _excluded = ["type"];
import React, { Suspense, useState, useEffect, useRef, useMemo } from "react";
import { EffectComposer, Bloom, ToneMapping, Exposure } from '@react-three/postprocessing';
import { Canvas, useFrame } from "@react-three/fiber";
import { OrbitControls } from "@react-three/drei";
import { GLTFLoader, FBXLoader, OBJLoader } from "three-stdlib";
import { extend, useLoader } from "@react-three/fiber";
import * as THREE from "three";
import HUDShaderMaterial from "./HUDShaderMaterial.js";
extend({
HUDShaderMaterial: HUDShaderMaterial
});
var selectLoader = function selectLoader(type) {
switch (type) {
case "fbx":
return FBXLoader;
case "gltf":
return GLTFLoader;
case "obj":
return OBJLoader;
default:
throw new Error("Unsupported model type: ", type);
}
};
var defaultLightPresets = {
outdoors: [{
type: "ambient",
intensity: 0.9,
color: "#ffffff"
}, {
type: "directional",
intensity: 2.0,
position: [10, 15, 10],
color: "#fdfbd3",
castShadow: true
}],
fullMoon: [{
type: "ambient",
intensity: 0.5,
color: "#88aaff"
}, {
type: "directional",
intensity: 1.0,
position: [5, 10, 5],
color: "#ccccff",
castShadow: true
}],
studio: [{
type: "ambient",
intensity: 1.0,
color: "#ffffff"
}, {
type: "directional",
intensity: 2.2,
position: [7, 10, 5],
color: "#ffffff",
castShadow: true
}],
cinema: [{
type: "ambient",
intensity: 0.2,
color: "#111111"
}, {
type: "spot",
intensity: 4.5,
position: [0, 15, 10],
color: "#ff8888",
angle: Math.PI / 8,
penumbra: 0.7,
castShadow: true
}, {
type: "spot",
intensity: 3.5,
position: [-8, 5, -10],
color: "#ff4444",
angle: Math.PI / 5,
penumbra: 1,
castShadow: true
}, {
type: "point",
intensity: 1.8,
position: [5, 5, 10],
color: "#6666ff",
castShadow: true
}],
starship: [{
type: "ambient",
intensity: 0.7,
color: "#222288"
}, {
type: "point",
intensity: 2.8,
position: [0, 0, 0],
color: "#ffffff",
castShadow: true
}, {
type: "spot",
intensity: 3.0,
position: [8, 12, 5],
color: "#88ccff",
angle: Math.PI / 4,
penumbra: 1,
castShadow: true
}, {
type: "spot",
intensity: 2.8,
position: [-8, 12, -5],
color: "#88ffff",
angle: Math.PI / 5,
penumbra: 1,
castShadow: true
}],
garage: [{
type: "ambient",
intensity: 0.7,
color: "#555555"
}, {
type: "spot",
intensity: 3.5,
position: [5, 7, 5],
color: "#ffffff",
angle: Math.PI / 4,
penumbra: 0.5,
castShadow: true
}, {
type: "point",
intensity: 2.0,
position: [-5, -5, -5],
color: "#bbbbbb",
castShadow: true
}, {
type: "spot",
intensity: 2.5,
position: [3, 6, 2],
color: "#ffaa00",
angle: Math.PI / 5,
penumbra: 0.7,
castShadow: true
}]
};
var Model = function Model(_ref) {
var url = _ref.url,
textureConfiguration = _ref.textureConfiguration,
modelPosition = _ref.modelPosition,
modelRotation = _ref.modelRotation,
modelScale = _ref.modelScale,
type = _ref.type,
useCustomShader = _ref.useCustomShader,
rotate = _ref.rotate,
_ref$rotationSpeed = _ref.rotationSpeed,
rotationSpeed = _ref$rotationSpeed === void 0 ? 0.01 : _ref$rotationSpeed,
onLoad = _ref.onLoad;
var modelRef = useRef();
var Loader = useMemo(function () {
return selectLoader(type);
}, [type]);
var model = useLoader(Loader, url);
useFrame(function (state) {
if (modelRef.current && rotate) {
modelRef.current.rotation.y += rotationSpeed;
}
if (useCustomShader) {
modelRef.current.traverse(function (child) {
if (child.isMesh) {
child.material.uniforms.uTime.value = state.clock.getElapsedTime();
}
});
}
});
var applyMaterials = function applyMaterials(child, partConfig) {
if (useCustomShader) {
child.material = new THREE.ShaderMaterial({
uniforms: {
tintColor: {
value: new THREE.Color(partConfig.tintColor || textureConfiguration.tintColor)
},
color: {
value: new THREE.Color(partConfig.color || textureConfiguration.color)
},
specular: {
value: partConfig.specular || textureConfiguration.specular
},
roughness: {
value: partConfig.roughness || textureConfiguration.roughness
},
metallic: {
value: partConfig.metallic || textureConfiguration.metallic
},
sheen: {
value: partConfig.sheen || textureConfiguration.sheen
},
specularColor: {
value: new THREE.Color(partConfig.specularColor || textureConfiguration.specularColor)
},
sheenTint: {
value: new THREE.Color(partConfig.sheenTint || textureConfiguration.sheenTint)
},
emittance: {
value: partConfig.emittance || textureConfiguration.emittance
},
emittanceColor: {
value: new THREE.Color(partConfig.emittanceColor || textureConfiguration.emittanceColor)
},
uTime: {
value: 0
}
},
vertexShader: "varying vec2 vUv;\n void main()\n {\n vUv = uv;\n \n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }",
fragmentShader: "uniform vec3 tintColor;\n uniform vec3 color;\n uniform float specular;\n uniform float roughness;\n uniform float metallic;\n uniform float sheen;\n uniform vec3 specularColor;\n uniform vec3 sheenTint;\n uniform float emittance;\n uniform vec3 emittanceColor;\n uniform float uTime;\n varying vec2 vUv;\n void main()\n {\n vec3 finalColor = mix(color, tintColor, 0.5);\n \n finalColor += emittance * emittanceColor;\n \n gl_FragColor = vec4(finalColor, 1.0);\n }"
});
} else {
child.material = new THREE.MeshStandardMaterial({
color: new THREE.Color(partConfig.color || textureConfiguration.color),
metalness: partConfig.metallic || textureConfiguration.metallic,
roughness: partConfig.roughness || textureConfiguration.roughness
});
}
child.material.needsUpdate = true;
};
model.traverse(function (child) {
if (child.isMesh && textureConfiguration && textureConfiguration.parts) {
var _textureConfiguration;
var partConfig = ((_textureConfiguration = textureConfiguration.parts) === null || _textureConfiguration === void 0 ? void 0 : _textureConfiguration[child.name]) || {};
applyMaterials(child, partConfig);
}
});
useEffect(function () {
if (model && onLoad) {
onLoad(model);
}
}, [model]);
return /*#__PURE__*/React.createElement("primitive", {
ref: modelRef,
object: model.scene || model,
position: modelPosition,
rotation: modelRotation,
scale: modelScale
});
};
function HUDModel(_ref2) {
var models = _ref2.models,
_ref2$lightsPreset = _ref2.lightsPreset,
lightsPreset = _ref2$lightsPreset === void 0 ? "studio" : _ref2$lightsPreset,
_ref2$zoomLimits = _ref2.zoomLimits,
zoomLimits = _ref2$zoomLimits === void 0 ? {
min: 69,
max: 269
} : _ref2$zoomLimits,
_ref2$controlsEnabled = _ref2.controlsEnabled,
controlsEnabled = _ref2$controlsEnabled === void 0 ? true : _ref2$controlsEnabled,
_ref2$rotationSpeed = _ref2.rotationSpeed,
rotationSpeed = _ref2$rotationSpeed === void 0 ? 0.00169 : _ref2$rotationSpeed,
_ref2$cameraPosition = _ref2.cameraPosition,
cameraPosition = _ref2$cameraPosition === void 0 ? [47, 187, 169] : _ref2$cameraPosition,
_ref2$cameraTarget = _ref2.cameraTarget,
cameraTarget = _ref2$cameraTarget === void 0 ? [0, 69, 0] : _ref2$cameraTarget,
_ref2$cameraDistanceF = _ref2.cameraDistanceFactor,
cameraDistanceFactor = _ref2$cameraDistanceF === void 0 ? 4 : _ref2$cameraDistanceF,
_ref2$enableZoom = _ref2.enableZoom,
enableZoom = _ref2$enableZoom === void 0 ? true : _ref2$enableZoom,
_ref2$postEffects = _ref2.postEffects,
postEffects = _ref2$postEffects === void 0 ? {
bloom: {
intensity: 1.269,
threshold: 0.9,
radius: 0.6
},
toneMapping: {
exposure: 0.9
}
} : _ref2$postEffects;
var selectedLights = defaultLightPresets[lightsPreset] || defaultLightPresets.studio;
var _useState = useState(cameraPosition),
_useState2 = _slicedToArray(_useState, 2),
dynamicCameraPosition = _useState2[0],
setDynamicCameraPosition = _useState2[1];
var _useState3 = useState(cameraTarget),
_useState4 = _slicedToArray(_useState3, 2),
dynamicCameraTarget = _useState4[0],
setDynamicCameraTarget = _useState4[1];
var calculateIdealCameraPosition = function calculateIdealCameraPosition(model) {
if (!model) {
return;
}
var box = new THREE.Box3().setFromObject(model);
var center = box.getCenter(new THREE.Vector3());
var sphere = box.getBoundingSphere(new THREE.Sphere());
var distance = sphere.radius * cameraDistanceFactor;
setDynamicCameraPosition([center.x, center.y + distance * 0.369, center.z + distance * 1.369]);
setDynamicCameraTarget([center.x, center.y, center.z]);
};
return /*#__PURE__*/React.createElement(Canvas, {
shadows: true,
camera: {
position: dynamicCameraPosition
}
}, selectedLights.map(function (lightConfig, index) {
var type = lightConfig.type,
rest = _objectWithoutProperties(lightConfig, _excluded);
if (type === "ambient") {
return /*#__PURE__*/React.createElement("ambientLight", _extends({
key: index
}, rest));
} else if (type === "directional") {
return /*#__PURE__*/React.createElement("directionalLight", _extends({
key: index
}, rest));
} else if (type === "point") {
return /*#__PURE__*/React.createElement("pointLight", _extends({
key: index
}, rest));
} else if (type === "spot") {
return /*#__PURE__*/React.createElement("spotLight", _extends({
key: index
}, rest));
}
return null;
}), /*#__PURE__*/React.createElement(Suspense, {
fallback: null
}, models.map(function (model, index) {
return /*#__PURE__*/React.createElement(Model, {
key: index,
url: model.url,
textureConfiguration: model.textureConfiguration,
modelPosition: model.position,
modelRotation: model.rotation,
modelScale: model.scale,
type: model.type,
useCustomShader: model.useCustomShader,
rotate: model.rotate,
rotationSpeed: rotationSpeed,
onLoad: function onLoad(loadedModel) {
calculateIdealCameraPosition(loadedModel);
return;
}
});
})), /*#__PURE__*/React.createElement(EffectComposer, null, postEffects.bloom && /*#__PURE__*/React.createElement(Bloom, {
intensity: postEffects.bloom.intensity,
threshold: postEffects.bloom.threshold,
radius: postEffects.bloom.radius
}), postEffects.toneMapping && /*#__PURE__*/React.createElement(ToneMapping, {
exposure: postEffects.toneMapping.exposure
})), controlsEnabled && /*#__PURE__*/React.createElement(OrbitControls, {
minDistance: zoomLimits.min,
maxDistance: zoomLimits.max,
maxPolarAngle: Math.PI / 2,
minPolarAngle: 0,
target: dynamicCameraTarget,
enableZoom: enableZoom
}));
}
;
export default HUDModel;