Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

Commit

Permalink
Ir 2114 prefab (#10242)
Browse files Browse the repository at this point in the history
* add prefab gltfs

* add prefab categories

* delete test prefabs

* cleanup

* refactor prefab shelf state structure

---------

Co-authored-by: David Gordon <[email protected]>
  • Loading branch information
JT00y and dinomut1 authored May 24, 2024
1 parent 8b1994f commit dbb8067
Show file tree
Hide file tree
Showing 17 changed files with 904 additions and 54 deletions.
102 changes: 91 additions & 11 deletions packages/editor/src/components/prefabs/PrefabEditors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,96 @@ Ethereal Engine. All Rights Reserved.
import config from '@etherealengine/common/src/config'
import { defineState } from '@etherealengine/hyperflux'

export const PrefabShelfCategories = defineState({
name: 'ee.editor.PrefabShelfCategories',
initial: () => {
return {
//hardcode to test replace with parseStorageProviderURLs
'Point Light Prefab': `${config.client.fileServer}/projects/default-project/assets/pointLight.prefab.gltf`,
'Geometry Prefab': `${config.client.fileServer}/projects/default-project/assets/geo.prefab.gltf`,
'Empty Prefab': 'empty'
export type PrefabShelfItem = {
name: string
url: string
category: string
detail?: string
}

//will continue to add more prefabs
} as Record<string, string>
}
export const PrefabShelfState = defineState({
name: 'ee.editor.PrefabShelfItem',
initial: () =>
[
{
name: '3D Model',
url: `${config.client.fileServer}/projects/default-project/assets/prefabs/3d-model.prefab.gltf`,
category: 'Geo',
detail: 'Blank 3D model ready for your own assets'
},
{
name: 'Primitive Geometry',
url: `${config.client.fileServer}/projects/default-project/assets/prefabs/geo.prefab.gltf`,
category: 'Geo'
},
{
name: 'Point Light',
url: `${config.client.fileServer}/projects/default-project/assets/prefabs/point-light.prefab.gltf`,
category: 'Lighting'
},
{
name: 'Spot Light',
url: `${config.client.fileServer}/projects/default-project/assets/prefabs/spot-light.prefab.gltf`,
category: 'Lighting'
},
{
name: 'Directional Light',
url: `${config.client.fileServer}/projects/default-project/assets/prefabs/directional-light.prefab.gltf`,
category: 'Lighting'
},
{
name: 'Ambient Light',
url: `${config.client.fileServer}/projects/default-project/assets/prefabs/ambient-light.prefab.gltf`,
category: 'Lighting'
},
{
name: 'Hemisphere Light',
url: `${config.client.fileServer}/projects/default-project/assets/prefabs/hemisphere-light.prefab.gltf`,
category: 'Lighting'
},
{
name: 'Box Collider',
url: `${config.client.fileServer}/projects/default-project/assets/prefabs/box-collider.prefab.gltf`,
category: 'Collider',
detail: 'Simple box collider'
},
{
name: 'Sphere Collider',
url: `${config.client.fileServer}/projects/default-project/assets/prefabs/sphere-collider.prefab.gltf`,
category: 'Collider',
detail: 'Simple sphere collider'
},
{
name: 'Cylinder Collider',
url: `${config.client.fileServer}/projects/default-project/assets/prefabs/cylinder-collider.prefab.gltf`,
category: 'Collider',
detail: 'Simple cylinder collider'
},
{
name: 'Mesh Collider',
url: `${config.client.fileServer}/projects/default-project/assets/prefabs/mesh-collider.prefab.gltf`,
category: 'Collider',
detail: 'Simple mesh collider, drag and drop your mesh'
},
{
name: 'Text',
url: `${config.client.fileServer}/projects/default-project/assets/prefabs/text.prefab.gltf`,
category: 'Text'
},
{
name: 'Skybox',
url: `${config.client.fileServer}/projects/default-project/assets/prefabs/skybox.prefab.gltf`,
category: 'Lookdev'
},
{
name: 'Postprocessing',
url: `${config.client.fileServer}/projects/default-project/assets/prefabs/postprocessing.prefab.gltf`,
category: 'Lookdev'
},
{
name: 'Fog',
url: `${config.client.fileServer}/projects/default-project/assets/prefabs/fog.prefab.gltf`,
category: 'Lookdev'
}
] as PrefabShelfItem[]
})
105 changes: 64 additions & 41 deletions packages/editor/src/components/prefabs/PrefabList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,40 +18,29 @@ All portions of the code written by the Ethereal Engine team are Copyright © 20
Ethereal Engine. All Rights Reserved.
*/

import PlaceHolderIcon from '@mui/icons-material/GroupAddOutlined'
import { List, ListItemButton, ListItemIcon, ListItemText } from '@mui/material'
import { startCase } from 'lodash'
import React, { useRef } from 'react'
import { Collapse, List, ListItemButton, ListItemIcon, ListItemText } from '@mui/material'
import React, { useEffect, useRef } from 'react'
import { useTranslation } from 'react-i18next'

import InputText from '@etherealengine/client-core/src/common/components/InputText'
import { ComponentJsonType } from '@etherealengine/engine/src/scene/types/SceneTypes'
import { getMutableState, getState, useHookstate } from '@etherealengine/hyperflux'
import Typography from '@etherealengine/ui/src/primitives/mui/Typography'

import { addMediaNode } from '../../functions/addMediaNode'
import { ComponentEditorsState } from '../../functions/ComponentEditors'
import Icon from '@etherealengine/ui/src/primitives/mui/Icon'
import { EditorControlFunctions } from '../../functions/EditorControlFunctions'
import { addMediaNode } from '../../functions/addMediaNode'
import { usePopoverContextClose } from '../element/PopoverContext'
import { PrefabShelfCategories } from './PrefabEditors'
import { PrefabShelfItem, PrefabShelfState } from './PrefabEditors'

const PrefabListItem = ({ item }: { item: string }) => {
const PrefabListItem = ({ item }: { item: PrefabShelfItem }) => {
const { t } = useTranslation()
const Icon = getState(ComponentEditorsState)[item]?.iconComponent ?? PlaceHolderIcon
const handleClosePopover = usePopoverContextClose()

return (
<ListItemButton
sx={{ pl: 4, bgcolor: 'var(--dockBackground)' }}
onClick={() => {
const PrefabNameShelfCategories = getState(PrefabShelfCategories)
const componentJsons: ComponentJsonType[] = []
const url = PrefabNameShelfCategories[item]
// PrefabNameShelfCategories[item].forEach((component) => {
// componentJsons.push({ name: component.jsonID as string })
// })
//EditorControlFunctions.createObjectFromSceneElement(componentJsons)

const url = item.url
//add prefab gltfs in the scene via add media node
if (url === 'empty') {
EditorControlFunctions.createObjectFromSceneElement()
Expand All @@ -63,60 +52,86 @@ const PrefabListItem = ({ item }: { item: string }) => {
handleClosePopover()
}}
>
<ListItemIcon style={{ color: 'var(--textColor)' }}>
<Icon />
</ListItemIcon>
<ListItemIcon style={{ color: 'var(--textColor)' }}></ListItemIcon>
<ListItemText
primary={
<Typography variant="subtitle1" color={'var(--textColor)'}>
{startCase(item.replace('-', ' ').toLowerCase())}
{item.name}
</Typography>
}
secondary={
<Typography variant="caption" color={'var(--textColor)'}>
{t(`editor:layout.assetGrid.component-detail.${item}`)}
{item.detail ??
t(`editor:layout.assetGrid.component-detail.${item.name.toLowerCase().replaceAll(/\s+/g, '-')}`)}
</Typography>
}
/>
</ListItemButton>
)
}
const ScenePrefabListItem = ({ categoryItems }: { categoryItems: string[]; isCollapsed: boolean }) => {
const ScenePrefabListItem = ({
categoryTitle,
categoryItems,
isCollapsed
}: {
categoryTitle: string
categoryItems: PrefabShelfItem[]
isCollapsed: boolean
}) => {
const open = useHookstate(categoryTitle === 'Empty')
return (
<>
<List component={'div'} sx={{ bgcolor: 'var(--dockBackground)', width: '100%' }} disablePadding>
{categoryItems.map((item) => (
<PrefabListItem item={item} />
))}
</List>
<ListItemButton
onClick={() => open.set((prev) => !prev)}
style={{
backgroundColor: 'var(--dockBackground)',
cursor: 'pointer',
color: 'var(--textColor)',
display: 'flex',
justifyContent: 'space-between',
width: '100%'
}}
>
<Typography>{categoryTitle}</Typography>
<Icon type={isCollapsed || open.value ? 'KeyboardArrowUp' : 'KeyboardArrowDown'} />
</ListItemButton>
<Collapse in={isCollapsed || open.value} timeout={'auto'} unmountOnExit>
<List component={'div'} sx={{ bgcolor: 'var(--dockBackground)', width: '100%' }} disablePadding>
{categoryItems.map((item) => (
<PrefabListItem item={item} />
))}
</List>
</Collapse>
</>
)
}

const usePrefabShelfCategories = (search: string) => {
useHookstate(getMutableState(PrefabShelfCategories)).value
useHookstate(getMutableState(PrefabShelfState)).value

if (!search) {
return Object.entries(getState(PrefabShelfCategories))
return getState(PrefabShelfState)
}

const searchRegExp = new RegExp(search, 'gi')

return Object.entries(getState(PrefabShelfCategories))
.map(([category, items]) => {
const filteredcategory = category.match(searchRegExp)?.length ? category : ''
return [filteredcategory, items] as [string, string]
})
.filter(([_, items]) => !!items.length)
return getState(PrefabShelfState).filter(({ name }) => !!name.match(searchRegExp)?.length)
}

export function PrefabList() {
const { t } = useTranslation()
const search = useHookstate({ local: '', query: '' })
const searchTimeout = useRef<ReturnType<typeof setTimeout> | null>(null)
const shelves = usePrefabShelfCategories(search.query.value)
const validItems = usePrefabShelfCategories(search.query.value)
const inputReference = useRef<HTMLInputElement>(null)

const shelves: Record<string, PrefabShelfItem[]> = {}
for (const item of validItems) {
shelves[item.category] ??= []
shelves[item.category].push(item)
}
const shelveslist: string[] = []
shelves.map(([category, items]) => {
Object.entries(shelves).map(([category, items]) => {
shelveslist.push(category)
})

Expand All @@ -128,9 +143,13 @@ export function PrefabList() {
}, 50)
}

useEffect(() => {
inputReference.current?.focus()
}, [])

return (
<List
sx={{ width: 300, height: 900, bgcolor: 'var(--dockBackground)' }}
sx={{ width: 300, height: 500, bgcolor: 'var(--dockBackground)' }}
subheader={
<div style={{ padding: '0.5rem' }}>
<Typography style={{ color: 'var(--textColor)', textAlign: 'center', textTransform: 'uppercase' }}>
Expand All @@ -141,11 +160,15 @@ export function PrefabList() {
value={search.local.value}
sx={{ mt: 1 }}
onChange={(e) => onSearch(e.target.value)}
inputRef={inputReference}
/>
</div>
}
>
<ScenePrefabListItem categoryItems={shelveslist} isCollapsed={!!search.query.value} />
<PrefabListItem item={{ name: 'Empty', url: 'empty', category: '', detail: 'Basic scene entity' }} />
{Object.entries(shelves).map(([category, items]) => (
<ScenePrefabListItem categoryTitle={category} categoryItems={items} isCollapsed={!!search.query.value} />
))}
</List>
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"asset": {
"version": "2.0",
"generator": "THREE.GLTFExporter"
},
"scenes": [
{
"name": "New Object",
"nodes": [
0
]
}
],
"scene": 0,
"nodes": [
{
"name": "3D Model",
"extensions": {
"EE_uuid": "9a88d4b8-1605-4ecf-b0a2-b083d0231c4f",
"EE_visible": true,
"EE_model": {
"src": "",
"cameraOcclusion": true,
"convertToVRM": false
},
"EE_input": {
"inputSinks": [
"9a88d4b8-1605-4ecf-b0a2-b083d0231c4f"
],
"activationDistance": 2
},
"EE_shadow": {
"cast": true,
"receive": true
},
"EE_loop_animation": {
"activeClipIndex": -1,
"animationPack": "",
"paused": false,
"time": 0,
"timeScale": 1,
"blendMode": 2500,
"loop": 2201,
"clampWhenFinished": false,
"zeroSlopeAtStart": true,
"zeroSlopeAtEnd": true,
"weight": 1
},
"EE_envmap": {
"type": "Skybox",
"envMapTextureType": "Equirectangular",
"envMapSourceColor": 4095,
"envMapSourceURL": "",
"envMapSourceEntityUUID": "",
"envMapIntensity": 1
}
}
}
],
"extensionsUsed": [
"EE_uuid",
"EE_visible",
"EE_model",
"EE_input",
"EE_shadow",
"EE_loop_animation",
"EE_envmap",
"EE_ecs"
]
}
Loading

0 comments on commit dbb8067

Please sign in to comment.