import { RigidBodyType, ShapeType } from '@dimforge/rapier3d-compat' import React, { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { camelCaseToSpacedString } from '@xrengine/common/src/utils/camelCaseToSpacedString' import { Engine } from '@xrengine/engine/src/ecs/classes/Engine' import { ComponentType, defineQuery, getComponent, hasComponent } from '@xrengine/engine/src/ecs/functions/ComponentFunctions' import { EntityTreeComponent } from '@xrengine/engine/src/ecs/functions/EntityTree' import { CallbackComponent } from '@xrengine/engine/src/scene/components/CallbackComponent' import { ColliderComponent, supportedColliderShapes } from '@xrengine/engine/src/scene/components/ColliderComponent' import { NameComponent } from '@xrengine/engine/src/scene/components/NameComponent' import { UUIDComponent } from '@xrengine/engine/src/scene/components/UUIDComponent' import PanToolIcon from '@mui/icons-material/PanTool' import BooleanInput from '../inputs/BooleanInput' import InputGroup from '../inputs/InputGroup' import SelectInput from '../inputs/SelectInput' import StringInput from '../inputs/StringInput' import NodeEditor from './NodeEditor' import { EditorComponentType, updateProperties, updateProperty } from './Util' const bodyTypeOptions = Object.entries(RigidBodyType) .filter(([value]) => (value as string).length > 1) .map(([label, value]) => { return { label: camelCaseToSpacedString(label as string), value: Number(value) } }) const shapeTypeOptions = Object.entries(ShapeType) .filter(([label, value]) => supportedColliderShapes.includes(value as ShapeType)) .map(([label, value]) => { return { label: camelCaseToSpacedString(label as string), value: Number(value) } }) type OptionsType = Array<{ callbacks: Array<{ label: string value: string }> label: string value: string }> const callbackQuery = defineQuery([CallbackComponent]) export const ColliderNodeEditor: EditorComponentType = (props) => { const { t } = useTranslation() const [options, setOptions] = useState([{ label: 'Self', value: 'Self', callbacks: [] }]) const colliderComponent = getComponent(props.entity, ColliderComponent) useEffect(() => { const options = [] as OptionsType options.push({ label: 'Self', value: 'Self', callbacks: [] }) for (const entity of callbackQuery()) { if (entity === props.entity || !hasComponent(entity, EntityTreeComponent)) continue const callbacks = getComponent(entity, CallbackComponent) options.push({ label: getComponent(entity, NameComponent), value: getComponent(entity, UUIDComponent), callbacks: Object.keys(callbacks).map((cb) => { return { label: cb, value: cb } }) }) } setOptions(options) }, []) const updateIsTrigger = (val) => { const props = { isTrigger: val } as Partial> if (val) { props.target = colliderComponent.target ?? 'Self' props.onEnter = colliderComponent.onEnter ?? '' props.onExit = colliderComponent.onExit ?? '' } updateProperties(ColliderComponent, props) } const triggerProps = () => { //function to handle the changes in target const onChangeTarget = (target) => { updateProperties(ColliderComponent, { target: target === 'Self' ? '' : target, onEnter: '', onExit: '' }) } const targetOption = options.find((o) => o.value === colliderComponent.target) const target = targetOption ? targetOption.value : 'Self' return ( <> {targetOption?.callbacks.length == 0 ? ( ) : ( )} {targetOption?.callbacks.length == 0 ? ( ) : ( )} ) } return ( {colliderComponent.isTrigger && triggerProps()} ) } ColliderNodeEditor.iconComponent = PanToolIcon export default ColliderNodeEditor