diff --git a/packages/editor/src/components/properties/EnvMapEditor.tsx b/packages/editor/src/components/properties/EnvMapEditor.tsx index 5c8cc2bbae..7ac0c1eb53 100644 --- a/packages/editor/src/components/properties/EnvMapEditor.tsx +++ b/packages/editor/src/components/properties/EnvMapEditor.tsx @@ -26,9 +26,12 @@ Ethereal Engine. All Rights Reserved. import React, { useCallback } from 'react' import { useTranslation } from 'react-i18next' -import { useComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' +import { getComponent, useComponent, useQuery } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' +import { EnvMapBakeComponent } from '@etherealengine/engine/src/scene/components/EnvMapBakeComponent' import { EnvmapComponent } from '@etherealengine/engine/src/scene/components/EnvmapComponent' import { getEntityErrors } from '@etherealengine/engine/src/scene/components/ErrorComponent' +import { NameComponent } from '@etherealengine/engine/src/scene/components/NameComponent' +import { UUIDComponent } from '@etherealengine/engine/src/scene/components/UUIDComponent' import { EnvMapSourceType, EnvMapTextureType } from '@etherealengine/engine/src/scene/constants/EnvMapEnum' import ColorInput from '../inputs/ColorInput' @@ -64,6 +67,13 @@ export const EnvMapEditor: EditorComponentType = (props) => { const { t } = useTranslation() const entity = props.entity + const bakeEntities = useQuery([EnvMapBakeComponent]).map((entity) => { + return { + label: getComponent(entity, NameComponent), + value: getComponent(entity, UUIDComponent) + } + }) + const onChangeCubemapURLSource = useCallback((value) => { const directory = value[value.length - 1] === '/' ? value.substring(0, value.length - 1) : value if (directory !== envmapComponent.envMapSourceURL) { @@ -98,6 +108,15 @@ export const EnvMapEditor: EditorComponentType = (props) => { /> )} + {envmapComponent.type.value === EnvMapSourceType.Bake && ( + + + + )} {envmapComponent.type.value === EnvMapSourceType.Texture && (
diff --git a/packages/engine/src/scene/components/EnvMapBakeComponent.ts b/packages/engine/src/scene/components/EnvMapBakeComponent.ts index 07f1b08f94..ab453ae52d 100644 --- a/packages/engine/src/scene/components/EnvMapBakeComponent.ts +++ b/packages/engine/src/scene/components/EnvMapBakeComponent.ts @@ -42,17 +42,14 @@ import { import { getMutableState, getState, none, useHookstate } from '@etherealengine/hyperflux' -import { matches, object } from '../../common/functions/MatchesUtils' +import { matches } from '../../common/functions/MatchesUtils' import { Engine } from '../../ecs/classes/Engine' -import { EngineActions, EngineState } from '../../ecs/classes/EngineState' import { Entity } from '../../ecs/classes/Entity' import { SceneState } from '../../ecs/classes/Scene' -import { defineComponent, getComponent, hasComponent, useComponent } from '../../ecs/functions/ComponentFunctions' +import { defineComponent, getComponent, useComponent } from '../../ecs/functions/ComponentFunctions' import { useEntityContext } from '../../ecs/functions/EntityFunctions' import { EntityTreeComponent, traverseEntityNode } from '../../ecs/functions/EntityTree' import { RendererState } from '../../renderer/RendererState' -import { EngineRenderer } from '../../renderer/WebGLRendererSystem' -import { TransformComponent } from '../../transform/components/TransformComponent' import { envmapParsReplaceLambert, envmapPhysicalParsReplace, diff --git a/packages/engine/src/scene/components/EnvmapComponent.ts b/packages/engine/src/scene/components/EnvmapComponent.tsx similarity index 77% rename from packages/engine/src/scene/components/EnvmapComponent.ts rename to packages/engine/src/scene/components/EnvmapComponent.tsx index f74e5445d7..65c3048fc6 100644 --- a/packages/engine/src/scene/components/EnvmapComponent.ts +++ b/packages/engine/src/scene/components/EnvmapComponent.tsx @@ -23,13 +23,12 @@ All portions of the code written by the Ethereal Engine team are Copyright © 20 Ethereal Engine. All Rights Reserved. */ -import { useEffect, useState } from 'react' +import React, { useEffect } from 'react' import { Color, CubeTexture, DataTexture, EquirectangularReflectionMapping, - Group, Mesh, MeshMatcapMaterial, MeshStandardMaterial, @@ -41,31 +40,22 @@ import { Vector3 } from 'three' -import { getMutableState, getState, useHookstate } from '@etherealengine/hyperflux' +import { EntityUUID } from '@etherealengine/common/src/interfaces/EntityUUID' +import { getMutableState, useHookstate } from '@etherealengine/hyperflux' import { AssetLoader } from '../../assets/classes/AssetLoader' import { isClient } from '../../common/functions/getEnvironment' -import { EngineState } from '../../ecs/classes/EngineState' import { Entity } from '../../ecs/classes/Entity' import { SceneState } from '../../ecs/classes/Scene' -import { - ComponentType, - defineComponent, - defineQuery, - getComponent, - removeQuery, - setComponent, - useComponent, - useOptionalComponent -} from '../../ecs/functions/ComponentFunctions' +import { defineComponent, useComponent } from '../../ecs/functions/ComponentFunctions' import { useEntityContext } from '../../ecs/functions/EntityFunctions' import { RendererState } from '../../renderer/RendererState' -import { TransformComponent } from '../../transform/components/TransformComponent' import { EnvMapSourceType, EnvMapTextureType } from '../constants/EnvMapEnum' import { getPmremGenerator, getRGBArray, loadCubeMapTexture } from '../constants/Util' import { addError, removeError } from '../functions/ErrorFunctions' import { applyBoxProjection, EnvMapBakeComponent, isInsideBox } from './EnvMapBakeComponent' import { GroupComponent } from './GroupComponent' +import { UUIDComponent } from './UUIDComponent' const tempColor = new Color() @@ -79,6 +69,7 @@ export const EnvmapComponent = defineComponent({ EnvMapTextureType.Equirectangular as (typeof EnvMapTextureType)[keyof typeof EnvMapTextureType], envMapSourceColor: new Color(0xfff) as Color, envMapSourceURL: '', + envMapSourceEntityUUID: '' as EntityUUID, envMapIntensity: 1 } }, @@ -88,6 +79,8 @@ export const EnvmapComponent = defineComponent({ if (typeof json?.envMapTextureType === 'string') component.envMapTextureType.set(json.envMapTextureType) if (typeof json?.envMapSourceColor === 'number') component.envMapSourceColor.set(new Color(json.envMapSourceColor)) if (typeof json?.envMapSourceURL === 'string') component.envMapSourceURL.set(json.envMapSourceURL) + if (typeof json?.envMapSourceEntityUUID === 'string') + component.envMapSourceEntityUUID.set(json.envMapSourceEntityUUID) if (typeof json?.envMapIntensity === 'number') component.envMapIntensity.set(json.envMapIntensity) }, @@ -97,6 +90,7 @@ export const EnvmapComponent = defineComponent({ envMapTextureType: component.envMapTextureType.value, envMapSourceColor: component.envMapSourceColor.value, envMapSourceURL: component.envMapSourceURL.value, + envMapSourceEntityUUID: component.envMapSourceEntityUUID.value, envMapIntensity: component.envMapIntensity.value } }, @@ -164,44 +158,40 @@ export const EnvmapComponent = defineComponent({ } }, [component.type, group, component.envMapSourceURL]) - const engineState = useHookstate(getMutableState(EngineState)) - const renderState = useHookstate(getMutableState(RendererState)) - const relativePos = new Vector3() + const entitiesByUUIDState = useHookstate(UUIDComponent.entitiesByUUIDState) + const bakeEntity = entitiesByUUIDState[component.envMapSourceEntityUUID.value].value - useEffect(() => { - if (!engineState.sceneLoaded.value) return - if (component.type.value !== EnvMapSourceType.Default) return - const bakeComponentQuery = defineQuery([EnvMapBakeComponent]) - for (const bakeEntity of bakeComponentQuery()) { - const bakeComponent = getComponent(bakeEntity, EnvMapBakeComponent) - const transformComponent = getComponent(entity, TransformComponent) - relativePos.subVectors(transformComponent.position, getComponent(bakeEntity, TransformComponent).position) - if (!isInsideBox(bakeComponent.bakeScale, relativePos) || !bakeComponent.boxProjection) continue - setComponent(entity, EnvmapComponent, { envMapSourceURL: bakeComponent.envMapOrigin }) - - AssetLoader.loadAsync(component.envMapSourceURL.value, {}).then((texture) => { - if (texture) { - texture.mapping = EquirectangularReflectionMapping - updateEnvMap(group.value, texture) - applyBoxProjection(bakeEntity, group.value) - removeError(entity, EnvmapComponent, 'MISSING_FILE') - texture.dispose() - } else { - addError(entity, EnvmapComponent, 'MISSING_FILE', 'Skybox texture could not be found!') - } - }) - } - return () => { - removeQuery(bakeComponentQuery) - } - }, [group, component.type, engineState.sceneLoaded, renderState.forceBasicMaterials]) + if (component.type.value !== EnvMapSourceType.Bake) return null - return null + return }, errors: ['MISSING_FILE'] }) +const EnvBakeComponentReactor = (props: { envmapEntity: Entity; bakeEntity: Entity }) => { + const { envmapEntity, bakeEntity } = props + const bakeComponent = useComponent(bakeEntity, EnvMapBakeComponent) + const group = useComponent(envmapEntity, GroupComponent) + const renderState = useHookstate(getMutableState(RendererState)) + + useEffect(() => { + AssetLoader.loadAsync(bakeComponent.envMapOrigin.value, {}).then((texture) => { + if (texture) { + texture.mapping = EquirectangularReflectionMapping + updateEnvMap(group.value, texture) + if (bakeComponent.boxProjection.value) applyBoxProjection(bakeEntity, group.value) + removeError(envmapEntity, EnvmapComponent, 'MISSING_FILE') + texture.dispose() + } else { + addError(envmapEntity, EnvmapComponent, 'MISSING_FILE', 'Skybox texture could not be found!') + } + }) + }, [renderState.forceBasicMaterials, bakeComponent.envMapOrigin]) + + return null +} + function updateEnvMap(obj3ds: Object3D[], envmap: Texture | null) { if (!obj3ds?.length) return diff --git a/packages/engine/src/scene/constants/EnvMapEnum.ts b/packages/engine/src/scene/constants/EnvMapEnum.ts index fb45e27e50..fe09db304f 100644 --- a/packages/engine/src/scene/constants/EnvMapEnum.ts +++ b/packages/engine/src/scene/constants/EnvMapEnum.ts @@ -25,6 +25,7 @@ Ethereal Engine. All Rights Reserved. export const EnvMapSourceType = { Skybox: 'Skybox' as const, + Bake: 'Bake' as const, Default: 'Default' as const, Texture: 'Texture' as const, Color: 'Color' as const, diff --git a/packages/projects/default-project/apartment.scene.json b/packages/projects/default-project/apartment.scene.json index e9565b7fd2..33052da650 100644 --- a/packages/projects/default-project/apartment.scene.json +++ b/packages/projects/default-project/apartment.scene.json @@ -337,10 +337,11 @@ { "name": "envmap", "props": { - "type": "Default", + "type": "Bake", "envMapTextureType": "Equirectangular", "envMapSourceColor": 1193046, - "envMapSourceURL": "__$project$__/default-project/apartment-New-EnvMap%20Bake.ktx2", + "envMapSourceURL": "", + "envMapSourceEntityUUID": "1f374932-e649-4b30-b6e7-de990fdee2a1", "envMapIntensity": 1 } }