- {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')}
-
-
-
-
- )
-}
-
-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' })