@@ -23,10 +23,9 @@ All portions of the code written by the Ethereal Engine team are Copyright © 20
23
23
Ethereal Engine. All Rights Reserved.
24
24
*/
25
25
26
- import { debounce } from 'lodash'
27
- import React , { useCallback , useEffect , useState } from 'react'
26
+ import React , { useEffect } from 'react'
28
27
import { useTranslation } from 'react-i18next'
29
- import { Euler , Quaternion } from 'three'
28
+ import { Euler , Quaternion , Vector3 } from 'three'
30
29
31
30
import { API } from '@etherealengine/client-core/src/API'
32
31
import { getComponent , useComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions'
@@ -42,7 +41,9 @@ import { TransformComponent } from '@etherealengine/engine/src/transform/compone
42
41
import MeetingRoomIcon from '@mui/icons-material/MeetingRoom'
43
42
44
43
import { PortalType , portalPath } from '@etherealengine/common/src/schema.type.module'
45
- import { getPreviewBakeTexture , uploadCubemapBakeToServer } from '../../functions/uploadEnvMapBake'
44
+ import { imageDataToBlob } from '@etherealengine/engine/src/scene/classes/ImageUtils'
45
+ import { useHookstate } from '@hookstate/core'
46
+ import { bakeEnvmapTexture , uploadCubemapBakeToServer } from '../../functions/uploadEnvMapBake'
46
47
import BooleanInput from '../inputs/BooleanInput'
47
48
import { Button } from '../inputs/Button'
48
49
import EulerInput from '../inputs/EulerInput'
@@ -52,17 +53,11 @@ import SelectInput from '../inputs/SelectInput'
52
53
import { ControlledStringInput } from '../inputs/StringInput'
53
54
import Vector3Input from '../inputs/Vector3Input'
54
55
import NodeEditor from './NodeEditor'
55
- import { EditorComponentType , commitProperties , commitProperty , updateProperties , updateProperty } from './Util'
56
+ import { EditorComponentType , commitProperties , commitProperty , updateProperty } from './Util'
56
57
57
58
type PortalOptions = {
58
- name : string
59
- value : string
60
- }
61
-
62
- type PortalFilterOption = {
63
59
label : string
64
60
value : string
65
- data : PortalOptions
66
61
}
67
62
68
63
const rotation = new Quaternion ( )
@@ -73,8 +68,11 @@ const rotation = new Quaternion()
73
68
* @type {class component }
74
69
*/
75
70
export const PortalNodeEditor : EditorComponentType = ( props ) => {
76
- const [ portals , setPortals ] = useState < Array < { value : string ; label : string } > > ( [ ] )
77
- const [ bufferUrl , setBufferUrl ] = useState < string > ( '' )
71
+ const state = useHookstate ( {
72
+ portals : [ ] as PortalOptions [ ] ,
73
+ previewImageData : null as ImageData | null ,
74
+ previewImageURL : ''
75
+ } )
78
76
79
77
const { t } = useTranslation ( )
80
78
const transformComponent = useComponent ( props . entity , TransformComponent )
@@ -85,20 +83,14 @@ export const PortalNodeEditor: EditorComponentType = (props) => {
85
83
} , [ ] )
86
84
87
85
const updateCubeMapBake = async ( ) => {
88
- const imageBlob = await getPreviewBakeTexture ( transformComponent . value . position )
89
- const url = URL . createObjectURL ( imageBlob )
90
- setBufferUrl ( url )
86
+ const imageData = await bakeEnvmapTexture (
87
+ transformComponent . value . position . clone ( ) . add ( new Vector3 ( 0 , 2 , 0 ) . multiply ( transformComponent . scale . value ) )
88
+ )
89
+ const blob = await imageDataToBlob ( imageData )
90
+ state . previewImageData . set ( imageData )
91
+ state . previewImageURL . set ( URL . createObjectURL ( blob ! ) )
91
92
}
92
93
93
- const updateCubeMapBakeDebounced = useCallback ( debounce ( updateCubeMapBake , 500 ) , [ ] ) //ms
94
-
95
- useEffect ( ( ) => {
96
- updateCubeMapBakeDebounced ( )
97
- return ( ) => {
98
- updateCubeMapBakeDebounced . cancel ( )
99
- }
100
- } , [ transformComponent . position ] )
101
-
102
94
const loadPortals = async ( ) => {
103
95
const portalsDetail : PortalType [ ] = [ ]
104
96
try {
@@ -109,7 +101,7 @@ export const PortalNodeEditor: EditorComponentType = (props) => {
109
101
} catch ( error ) {
110
102
throw new Error ( error )
111
103
}
112
- setPortals (
104
+ state . portals . set (
113
105
portalsDetail
114
106
. filter ( ( portal ) => portal . portalEntityId !== getComponent ( props . entity , UUIDComponent ) )
115
107
. map ( ( { portalEntityId, portalEntityName, sceneName } ) => {
@@ -118,19 +110,16 @@ export const PortalNodeEditor: EditorComponentType = (props) => {
118
110
)
119
111
}
120
112
121
- const bakeCubemap = async ( ) => {
122
- const url = await uploadCubemapBakeToServer (
123
- getComponent ( props . entity , NameComponent ) ,
124
- transformComponent . position . value
125
- )
126
- loadPortals ( )
127
- updateProperties ( PortalComponent , { previewImageURL : url } , [ props . entity ] )
113
+ const uploadEnvmap = async ( ) => {
114
+ if ( ! state . previewImageData . value ) return
115
+ const url = await uploadCubemapBakeToServer ( getComponent ( props . entity , NameComponent ) , state . previewImageData . value )
116
+ commitProperties ( PortalComponent , { previewImageURL : url } , [ props . entity ] )
128
117
}
129
118
130
119
const changeSpawnRotation = ( value : Euler ) => {
131
120
rotation . setFromEuler ( value )
132
121
133
- updateProperties ( PortalComponent , { spawnRotation : rotation } )
122
+ commitProperties ( PortalComponent , { spawnRotation : rotation } )
134
123
}
135
124
136
125
const changePreviewType = ( val ) => {
@@ -150,7 +139,7 @@ export const PortalNodeEditor: EditorComponentType = (props) => {
150
139
< InputGroup name = "Portal" label = { t ( 'editor:properties.portal.lbl-portal' ) } >
151
140
< SelectInput
152
141
key = { props . entity }
153
- options = { portals }
142
+ options = { state . portals . value }
154
143
value = { portalComponent . linkedPortalId . value }
155
144
onChange = { commitProperty ( PortalComponent , 'linkedPortalId' ) }
156
145
/>
@@ -185,14 +174,14 @@ export const PortalNodeEditor: EditorComponentType = (props) => {
185
174
onRelease = { commitProperty ( PortalComponent , 'previewImageURL' ) }
186
175
/>
187
176
</ InputGroup >
188
- < InputGroup name = "Preview Image Bake" label = { t ( 'editor:properties.portal.lbl-previewImage ' ) } >
177
+ < InputGroup name = "Preview Image Bake" label = { t ( 'editor:properties.portal.lbl-generateImage ' ) } >
189
178
< div style = { { display : 'flex' , flexDirection : 'column' } } >
190
179
< div style = { { width : 'auto' , display : 'flex' , flexDirection : 'row' } } >
191
180
< Button
192
181
style = { { width : '100%' , fontSize : '11px' , overflow : 'hidden' } }
193
182
type = "submit"
194
183
onClick = { ( ) => {
195
- bakeCubemap ( )
184
+ uploadEnvmap ( )
196
185
} }
197
186
>
198
187
{ t ( 'editor:properties.portal.lbl-saveImage' ) }
@@ -204,10 +193,10 @@ export const PortalNodeEditor: EditorComponentType = (props) => {
204
193
updateCubeMapBake ( )
205
194
} }
206
195
>
207
- { t ( 'editor:properties.portal.lbl-previewImage ' ) }
196
+ { t ( 'editor:properties.portal.lbl-generateImage ' ) }
208
197
</ Button >
209
198
</ div >
210
- < ImagePreviewInput value = { bufferUrl } />
199
+ < ImagePreviewInput value = { state . previewImageURL . value ?? portalComponent . previewImageURL . value } />
211
200
</ div >
212
201
</ InputGroup >
213
202
< InputGroup name = "Spawn Position" label = { t ( 'editor:properties.portal.lbl-spawnPosition' ) } >
0 commit comments