diff --git a/packages/editor/src/components/properties/InputComponentNodeEditor.tsx b/packages/editor/src/components/properties/InputComponentNodeEditor.tsx index e70907414a..70097c0714 100644 --- a/packages/editor/src/components/properties/InputComponentNodeEditor.tsx +++ b/packages/editor/src/components/properties/InputComponentNodeEditor.tsx @@ -29,7 +29,7 @@ import { SourceComponent } from '@etherealengine/engine/src/scene/components/Sou import { NameComponent } from '@etherealengine/spatial/src/common/NameComponent' import { InputComponent } from '@etherealengine/spatial/src/input/components/InputComponent' import PanToolIcon from '@mui/icons-material/PanTool' -import React, { useEffect } from 'react' +import React from 'react' import { useTranslation } from 'react-i18next' import { EditorControlFunctions } from '../../functions/EditorControlFunctions' import { PropertiesPanelButton } from '../inputs/Button' @@ -56,13 +56,6 @@ export const InputComponentNodeEditor: EditorComponentType = (props) => { value: getComponent(props.entity, UUIDComponent) }) - useEffect(() => { - //convenience to add a sink if none exist - if (inputComponent.inputSinks.value.length === 0) { - addSink() - } - }, [authoringLayerEntities.length]) - const addSink = () => { const sinks = [...(inputComponent.inputSinks.value ?? []), getComponent(props.entity, UUIDComponent)] @@ -100,7 +93,7 @@ export const InputComponentNodeEditor: EditorComponentType = (props) => {
- {options.length > 1 + {options.length > 1 && inputComponent.inputSinks.value?.length > 0 ? inputComponent.inputSinks.value.map((sink, index) => { return (
diff --git a/packages/spatial/src/input/components/InputComponent.ts b/packages/spatial/src/input/components/InputComponent.ts index 6ff480afd1..0ee497ffda 100644 --- a/packages/spatial/src/input/components/InputComponent.ts +++ b/packages/spatial/src/input/components/InputComponent.ts @@ -31,12 +31,10 @@ import { getOptionalComponent, InputSystemGroup, UndefinedEntity, - useExecute, - UUIDComponent + useExecute } from '@etherealengine/ecs' import { defineComponent, - hasComponent, removeComponent, setComponent, useComponent @@ -65,7 +63,7 @@ export const InputComponent = defineComponent({ onInit: () => { return { - inputSinks: [] as EntityUUID[], + inputSinks: ['Self'] as EntityUUID[], activationDistance: 2, highlight: true, grow: false, @@ -78,13 +76,6 @@ export const InputComponent = defineComponent({ }, onSet(entity, component, json) { - if (!json && component.inputSinks.value.length === 0) { - if (hasComponent(entity, UUIDComponent)) { - component.inputSinks.set([getComponent(entity, UUIDComponent)]) - } else { - console.warn('no UUIDComponent at entity, cannot add self as InputSink at entity ' + entity) - } - } if (!json) return if (typeof json.inputSinks === 'object') component.inputSinks.set(json.inputSinks) if (typeof json.highlight === 'boolean') component.highlight.set(json.highlight) diff --git a/packages/spatial/src/input/properties/InputComponentNodeEditor.tsx b/packages/spatial/src/input/properties/InputComponentNodeEditor.tsx deleted file mode 100644 index 77693766fc..0000000000 --- a/packages/spatial/src/input/properties/InputComponentNodeEditor.tsx +++ /dev/null @@ -1,141 +0,0 @@ -/* -CPAL-1.0 License - -The contents of this file are subject to the Common Public Attribution License -Version 1.0. (the "License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at -https://github.com/EtherealEngine/etherealengine/blob/dev/LICENSE. -The License is based on the Mozilla Public License Version 1.1, but Sections 14 -and 15 have been added to cover use of software over a computer network and -provide for limited attribution for the Original Developer. In addition, -Exhibit A has been modified to be consistent with Exhibit B. - -Software distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the -specific language governing rights and limitations under the License. - -The Original Code is Ethereal Engine. - -The Original Developer is the Initial Developer. The Initial Developer of the -Original Code is the Ethereal Engine team. - -All portions of the code written by the Ethereal Engine team are Copyright © 2021-2023 -Ethereal Engine. All Rights Reserved. -*/ - -import { useQuery, UUIDComponent } from '@etherealengine/ecs' -import { getComponent, useComponent } from '@etherealengine/ecs/src/ComponentFunctions' -import { PropertiesPanelButton } from '@etherealengine/editor/src/components/inputs/Button' -import InputGroup from '@etherealengine/editor/src/components/inputs/InputGroup' -import NumericInput from '@etherealengine/editor/src/components/inputs/NumericInput' -import SelectInput from '@etherealengine/editor/src/components/inputs/SelectInput' -import NodeEditor from '@etherealengine/editor/src/components/properties/NodeEditor' -import { - commitProperties, - commitProperty, - EditorComponentType, - updateProperty -} from '@etherealengine/editor/src/components/properties/Util' -import { EditorControlFunctions } from '@etherealengine/editor/src/functions/EditorControlFunctions' -import { SourceComponent } from '@etherealengine/engine/src/scene/components/SourceComponent' -import { NameComponent } from '@etherealengine/spatial/src/common/NameComponent' -import PanToolIcon from '@mui/icons-material/PanTool' -import React, { useEffect } from 'react' -import { useTranslation } from 'react-i18next' -import { InputComponent } from '../components/InputComponent' - -type OptionsType = Array<{ - label: string - value: string -}> - -export const InputComponentNodeEditor: EditorComponentType = (props) => { - const { t } = useTranslation() - - const inputComponent = useComponent(props.entity, InputComponent) - const authoringLayerEntities = useQuery([SourceComponent]) - - const options = authoringLayerEntities.map((entity) => { - return { - label: getComponent(entity, NameComponent), - value: getComponent(entity, UUIDComponent) - } - }) - options.unshift({ - label: 'Self', - value: getComponent(props.entity, UUIDComponent) - }) - - useEffect(() => { - //convenience to add a sink if none exist - if (inputComponent.inputSinks.value.length === 0) { - addSink() - } - }, [authoringLayerEntities.length]) - - const addSink = () => { - const sinks = [...(inputComponent.inputSinks.value ?? []), getComponent(props.entity, UUIDComponent)] - - if (!EditorControlFunctions.hasComponentInAuthoringLayer(props.entity, InputComponent)) { - EditorControlFunctions.addOrRemoveComponent([props.entity], InputComponent, true, { - inputSinks: JSON.parse(JSON.stringify(sinks)) - }) - } else { - commitProperties(InputComponent, { inputSinks: JSON.parse(JSON.stringify(sinks)) }, [props.entity]) - } - } - - const removeSink = (index: number) => { - const sinks = [...inputComponent.inputSinks.value] - sinks.splice(index, 1) - commitProperties(InputComponent, { inputSinks: JSON.parse(JSON.stringify(sinks)) }, [props.entity]) - } - - return ( - - - - - - - {t('editor:properties.input.lbl-addSinkTarget')} - - -
- {options.length > 1 - ? inputComponent.inputSinks.value.map((sink, index) => { - return ( -
- - - - - removeSink(index)}> - {t('editor:properties.input.lbl-removeSinkTarget')} - -
- ) - }) - : null} -
-
- ) -} - -InputComponentNodeEditor.iconComponent = PanToolIcon - -export default InputComponentNodeEditor diff --git a/packages/spatial/src/input/systems/ClientInputSystem.tsx b/packages/spatial/src/input/systems/ClientInputSystem.tsx index 23a0ecaac4..47ff4a2261 100755 --- a/packages/spatial/src/input/systems/ClientInputSystem.tsx +++ b/packages/spatial/src/input/systems/ClientInputSystem.tsx @@ -66,6 +66,7 @@ import { RendererComponent } from '../../renderer/WebGLRendererSystem' import { BoundingBoxComponent } from '../../transform/components/BoundingBoxComponents' import { TransformComponent, TransformGizmoTagComponent } from '../../transform/components/TransformComponent' import { XRSpaceComponent } from '../../xr/XRComponents' +import { XRScenePlacementComponent } from '../../xr/XRScenePlacementComponent' import { XRControlsState, XRState } from '../../xr/XRState' import { XRUIComponent } from '../../xrui/components/XRUIComponent' import { InputComponent } from '../components/InputComponent' @@ -132,7 +133,13 @@ const worldPosInputComponent = new Vector3() const inputXRUIs = defineQuery([InputComponent, VisibleComponent, XRUIComponent]) const inputBoundingBoxes = defineQuery([InputComponent, VisibleComponent, BoundingBoxComponent]) const inputObjects = defineQuery([InputComponent, VisibleComponent, GroupComponent]) -const spatialInputObjects = defineQuery([InputComponent, VisibleComponent, TransformComponent, Not(CameraComponent)]) //TODO may be overkill if visible means it always has transform +const spatialInputObjects = defineQuery([ + InputComponent, + VisibleComponent, + TransformComponent, + Not(CameraComponent), + Not(XRScenePlacementComponent) +]) /** @todo abstract into heuristic api */ const gizmoPickerObjects = defineQuery([InputComponent, GroupComponent, VisibleComponent, TransformGizmoTagComponent]) @@ -344,15 +351,11 @@ const setInputSources = (startEntity: Entity, inputSources: Entity[]) => { const inputEntity = getAncestorWithComponent(startEntity, InputComponent) if (inputEntity) { const inputComponent = getMutableComponent(inputEntity, InputComponent) - if (!inputComponent.inputSinks.value || inputComponent.inputSinks.value.length === 0) { - inputComponent.inputSources.merge(inputSources) - } else { - for (const sinkEntityUUID of inputComponent.inputSinks.value) { - const sinkEntity = UUIDComponent.getEntityByUUID(sinkEntityUUID) - const sinkInputComponent = getMutableComponent(sinkEntity, InputComponent) - sinkInputComponent.inputSources.merge(inputSources) - } + for (const sinkEntityUUID of inputComponent.inputSinks.value) { + const sinkEntity = sinkEntityUUID === 'Self' ? inputEntity : UUIDComponent.getEntityByUUID(sinkEntityUUID) //TODO why is this not sending input to my sinks + const sinkInputComponent = getMutableComponent(sinkEntity, InputComponent) + sinkInputComponent.inputSources.merge(inputSources) } } } diff --git a/packages/spatial/src/xr/XRAnchorSystem.tsx b/packages/spatial/src/xr/XRAnchorSystem.tsx index e02dac4c0c..decc22f1e7 100644 --- a/packages/spatial/src/xr/XRAnchorSystem.tsx +++ b/packages/spatial/src/xr/XRAnchorSystem.tsx @@ -66,6 +66,7 @@ import { TransformComponent } from '../transform/components/TransformComponent' import { updateWorldOriginFromScenePlacement } from '../transform/updateWorldOrigin' import { XRCameraUpdateSystem } from './XRCameraSystem' import { XRAnchorComponent, XRHitTestComponent } from './XRComponents' +import { XRScenePlacementComponent } from './XRScenePlacementComponent' import { ReferenceSpace, XRAction, XRState } from './XRState' export const updateHitTest = (entity: Entity) => { @@ -192,6 +193,7 @@ export const XRAnchorSystemState = defineState({ initial: () => { const scenePlacementEntity = createEntity() setComponent(scenePlacementEntity, NameComponent, 'xr-scene-placement') + setComponent(scenePlacementEntity, XRScenePlacementComponent) setComponent(scenePlacementEntity, TransformComponent) setComponent(scenePlacementEntity, EntityTreeComponent, { parentEntity: Engine.instance.localFloorEntity }) setComponent(scenePlacementEntity, VisibleComponent, true) diff --git a/packages/spatial/src/xr/XRScenePlacementComponent.ts b/packages/spatial/src/xr/XRScenePlacementComponent.ts new file mode 100644 index 0000000000..768492e955 --- /dev/null +++ b/packages/spatial/src/xr/XRScenePlacementComponent.ts @@ -0,0 +1,28 @@ +/* +CPAL-1.0 License + +The contents of this file are subject to the Common Public Attribution License +Version 1.0. (the "License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at +https://github.com/EtherealEngine/etherealengine/blob/dev/LICENSE. +The License is based on the Mozilla Public License Version 1.1, but Sections 14 +and 15 have been added to cover use of software over a computer network and +provide for limited attribution for the Original Developer. In addition, +Exhibit A has been modified to be consistent with Exhibit B. + +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the +specific language governing rights and limitations under the License. + +The Original Code is Ethereal Engine. + +The Original Developer is the Initial Developer. The Initial Developer of the +Original Code is the Ethereal Engine team. + +All portions of the code written by the Ethereal Engine team are Copyright © 2021-2023 +Ethereal Engine. All Rights Reserved. +*/ + +import { defineComponent } from '@etherealengine/ecs/src/ComponentFunctions' + +export const XRScenePlacementComponent = defineComponent({ name: 'XRScenePlacementComponent' })