Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prefab workflow #10121

Merged
merged 40 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
dd21537
refactor: remove categorizedasset type
aditya-mitra Jan 12, 2024
b23b4c7
add prefab components from drag and drop
aditya-mitra Jan 12, 2024
7c79e98
label for resource items
aditya-mitra Jan 12, 2024
133051a
correct eslint error
aditya-mitra Jan 12, 2024
f12e563
Merge branch 'dev' of https://github.com/EtherealEngine/etherealengin…
dinomut1 Jan 17, 2024
615ce3a
Merge branch 'dev' into feat/assets-default-prefabs
aditya-mitra Jan 18, 2024
9a74a6c
double click to place prefab at origin
aditya-mitra Jan 18, 2024
bdc09ac
add drop on hierarchypanel
aditya-mitra Jan 18, 2024
3415644
Merge branch 'feat/assets-default-prefabs' of https://github.com/Ethe…
dinomut1 Jan 19, 2024
02fef03
Merge branch 'dev' of https://github.com/EtherealEngine/etherealengin…
dinomut1 Jan 19, 2024
2f76862
convert animated model to simple model
aditya-mitra Jan 19, 2024
b484d89
Merge branch 'dev' of https://github.com/EtherealEngine/etherealengin…
JT00y Apr 24, 2024
cbf2bae
update packages
JT00y Apr 24, 2024
fc216b7
Merge branch 'dev' of https://github.com/EtherealEngine/etherealengin…
JT00y Apr 30, 2024
12cc22c
update for prefab asset and model component
JT00y Apr 30, 2024
5df1e6c
add defult prefabs
JT00y Apr 30, 2024
eeceb9c
update for asset load
JT00y May 2, 2024
627f57a
Merge branch 'dev' of https://github.com/EtherealEngine/etherealengin…
JT00y May 8, 2024
974db0a
update with ui and changes
JT00y May 10, 2024
438a7d4
implement dereference WIP. Add GLTF <-> SceneJSON conversion helpers
dinomut1 May 13, 2024
27e11aa
add uuid component
JT00y May 13, 2024
a16e63d
integrate model component into GLTFState
dinomut1 May 14, 2024
9138a67
Merge branch 'prefab-workflow' of https://github.com/EtherealEngine/e…
dinomut1 May 14, 2024
af7892a
Merge branch 'dev' of https://github.com/EtherealEngine/etherealengin…
dinomut1 May 14, 2024
464a723
remove more SceneState references
dinomut1 May 15, 2024
0064ee3
remove PrefabComponents
JT00y May 15, 2024
323872e
Merge branch 'dev' of https://github.com/EtherealEngine/etherealengin…
dinomut1 May 16, 2024
ba95c3e
Merge branch 'dev' of https://github.com/EtherealEngine/etherealengin…
dinomut1 May 16, 2024
f85da18
remove old prefab conditional
dinomut1 May 16, 2024
168d234
Merge branch 'dev' of https://github.com/EtherealEngine/etherealengin…
dinomut1 May 16, 2024
57e6c46
Merge branch 'prefab-workflow' of https://github.com/EtherealEngine/e…
dinomut1 May 16, 2024
1619ef5
fix child entity indexing
dinomut1 May 16, 2024
d4d7b99
correctly manage transform component conversion to gltf
dinomut1 May 16, 2024
aac35e6
fix editor control functions test
dinomut1 May 16, 2024
a4ff3d7
Merge branch 'dev' of https://github.com/EtherealEngine/etherealengin…
dinomut1 May 17, 2024
2f10237
Merge branch 'dev' of https://github.com/EtherealEngine/etherealengin…
dinomut1 May 17, 2024
625adc9
re-add prefab type
dinomut1 May 17, 2024
7d168d4
ci/cd
dinomut1 May 17, 2024
0e4313b
more ci/cd
dinomut1 May 17, 2024
5dad5eb
Merge branch 'dev' into prefab-workflow
dinomut1 May 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@
"request": "launch",
"type": "node-terminal",
},
{
"command": "cd packages/editor && npm run test",
"name": "npm run test - editor",
"request": "launch",
"type": "node-terminal",
},
{
"command": "cd packages/spatial && npm run test",
"name": "npm run test - spatial",
Expand Down
5 changes: 4 additions & 1 deletion packages/client-core/i18n/en/editor.json
Original file line number Diff line number Diff line change
Expand Up @@ -1034,6 +1034,8 @@
"copyURL": "Copy URL",
"openInNewTab": "Open URL in New Tab",
"deleteAsset": "Delete Asset",
"prefab": "Prefab",
"prefab-search" : "Search Prefabs ...",
"components": "Components",
"components-search": "Search Components ...",
"component-detail": {
Expand Down Expand Up @@ -1119,7 +1121,8 @@
"scene-assets": {
"no-category": "No category selected",
"search-placeholder": "Search for an asset ...",
"preview": "Preview"
"preview" : "Preview",
"info-drag-drop": "Drag and Drop these items into the scene"
}
},
"hierarchy": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import {
} from '@etherealengine/ecs'
import { previewScreenshot } from '@etherealengine/editor/src/functions/takeScreenshot'
import { useTexture } from '@etherealengine/engine/src/assets/functions/resourceLoaderHooks'
import { SceneState } from '@etherealengine/engine/src/scene/SceneState'
import { GLTFDocumentState } from '@etherealengine/engine/src/gltf/GLTFDocumentState'
import { ModelComponent } from '@etherealengine/engine/src/scene/components/ModelComponent'
import { getModelSceneID } from '@etherealengine/engine/src/scene/functions/loaders/ModelFunctions'
import { defineState, getMutableState, none, useHookstate, useMutableState } from '@etherealengine/hyperflux'
Expand Down Expand Up @@ -152,7 +152,7 @@ const ThumbnailJobReactor = (props: { src: string }) => {
entity: UndefinedEntity
})
const loadPromiseState = useHookstate(null as Promise<any> | null) // for asset loading
const sceneState = useHookstate(getMutableState(SceneState).scenes) // for model rendering
const sceneState = useHookstate(getMutableState(GLTFDocumentState)) // for model rendering
const [tex] = useTexture(state.fileType.value === 'texture' ? props.src : '') // for texture loading

// Load and render image
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/utils/CommonKnownContentTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Ethereal Engine. All Rights Reserved.
*/
export const CommonKnownContentTypes = {
material: 'model/material',
prefab: 'model/prefab',
lookdev: 'model/lookdev',
xre: 'prefab/xre',
gltf: 'model/gltf',
Expand Down
2 changes: 2 additions & 0 deletions packages/common/src/utils/guessContentType.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export function guessContentType(url: string): string {
//check for xre gltf extension
if (/\.material\.gltf$/.test(contentPath)) {
return CommonKnownContentTypes.material
} else if (/\.prefab\.gltf$/.test(contentPath)) {
return CommonKnownContentTypes.prefab
} else if (/\.lookdev\.gltf$/.test(contentPath)) {
return CommonKnownContentTypes.lookdev
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import {
} from '@etherealengine/spatial/src/transform/components/EntityTree'

import MenuItem from '@mui/material/MenuItem'
import { PopoverPosition } from '@mui/material/Popover'
import Popover, { PopoverPosition } from '@mui/material/Popover'

import { NotificationService } from '@etherealengine/client-core/src/common/services/NotificationService'
import { Engine, EntityUUID, UUIDComponent } from '@etherealengine/ecs'
Expand All @@ -58,8 +58,10 @@ import { EditorState } from '../../services/EditorServices'
import { SelectionState } from '../../services/SelectionServices'
import Search from '../Search/Search'
import useUpload from '../assets/useUpload'
import { PopoverContext } from '../element/PopoverContext'
import { PropertiesPanelButton } from '../inputs/Button'
import { ContextMenu } from '../layout/ContextMenu'
import PrefabList from '../prefabs/PrefabList'
import { HeirarchyTreeNodeType, heirarchyTreeWalker } from './HeirarchyTreeWalker'
import { HierarchyTreeNode, HierarchyTreeNodeProps, RenameNodeData, getNodeElId } from './HierarchyTreeNode'
import styles from './styles.module.scss'
Expand Down Expand Up @@ -440,7 +442,8 @@ function HierarchyPanelContents(props: { sceneURL: string; rootEntityUUID: Entit
{MemoTreeNode}
</FixedSizeList>
)

const anchorElement = useHookstate<HTMLButtonElement | null>(null)
const open = !!anchorElement.value
return (
<>
<div className={styles.panelContainer}>
Expand All @@ -460,11 +463,38 @@ function HierarchyPanelContents(props: { sceneURL: string; rootEntityUUID: Entit
fontSize: '12px',
lineHeight: '0.5'
}}
onClick={() => EditorControlFunctions.createObjectFromSceneElement()}
//onClick={() => EditorControlFunctions.createObjectFromSceneElement()}
onClick={(event) => {
anchorElement.set(event.currentTarget)
}}
>
{t('editor:hierarchy.lbl-addEntity')}
</PropertiesPanelButton>
</div>
<PopoverContext.Provider
value={{
handlePopoverClose: () => {
anchorElement.set(null)
}
}}
>
<Popover
id={open ? 'add-component-popover' : undefined}
open={open}
anchorEl={anchorElement.value as HTMLButtonElement}
onClose={() => anchorElement.set(null)}
anchorOrigin={{
vertical: 'center',
horizontal: 'left'
}}
transformOrigin={{
vertical: 'center',
horizontal: 'right'
}}
>
<PrefabList />
</Popover>
</PopoverContext.Provider>
<ContextMenu open={!!anchorEl} anchorEl={anchorEl} anchorPosition={anchorPosition} onClose={handleClose}>
<MenuItem onClick={() => onRenameNode(contextSelectedItem!)}>{t('editor:hierarchy.lbl-rename')}</MenuItem>
<Hotkeys
Expand Down
3 changes: 2 additions & 1 deletion packages/editor/src/components/panels/ViewportPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ const ViewportDnD = () => {
drop(item: SceneElementType, monitor) {
const vec3 = new Vector3()
getCursorSpawnPosition(monitor.getClientOffset() as Vector2, vec3)

EditorControlFunctions.createObjectFromSceneElement([
{ name: item!.componentJsonID },
{ name: (item as SceneElementType).componentJsonID },
{ name: TransformComponent.jsonID, props: { position: vec3 } }
])
}
Expand Down
35 changes: 35 additions & 0 deletions packages/editor/src/components/prefabs/PrefabEditors.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
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 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'

//will continue to add more prefabs
} as Record<string, string>
}
})
154 changes: 154 additions & 0 deletions packages/editor/src/components/prefabs/PrefabList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/*
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 { startCase } from 'lodash'
import React, { useRef } from 'react'
import { useTranslation } from 'react-i18next'

import { getMutableState, getState, useHookstate } from '@etherealengine/hyperflux'

import PlaceHolderIcon from '@mui/icons-material/GroupAddOutlined'
import { List, ListItemButton, ListItemIcon, ListItemText } from '@mui/material'

import InputText from '@etherealengine/client-core/src/common/components/InputText'
import { ComponentJsonType } from '@etherealengine/engine/src/scene/types/SceneTypes'
import Typography from '@etherealengine/ui/src/primitives/mui/Typography'
import { ComponentEditorsState } from '../../functions/ComponentEditors'
import { EditorControlFunctions } from '../../functions/EditorControlFunctions'
import { addMediaNode } from '../../functions/addMediaNode'
import { usePopoverContextClose } from '../element/PopoverContext'
import { PrefabShelfCategories } from './PrefabEditors'

const PrefabListItem = ({ item }: { item: string }) => {
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)

//add prefab gltfs in the scene via add media node
if (url === 'empty') {
EditorControlFunctions.createObjectFromSceneElement()
} else {
//inside add media use dereference for model component
addMediaNode(url)
}

handleClosePopover()
}}
>
<ListItemIcon style={{ color: 'var(--textColor)' }}>
<Icon />
</ListItemIcon>
<ListItemText
primary={
<Typography variant="subtitle1" color={'var(--textColor)'}>
{startCase(item.replace('-', ' ').toLowerCase())}
</Typography>
}
secondary={
<Typography variant="caption" color={'var(--textColor)'}>
{t(`editor:layout.assetGrid.component-detail.${item}`)}
</Typography>
}
/>
</ListItemButton>
)
}
const ScenePrefabListItem = ({ categoryItems }: { categoryItems: string[]; isCollapsed: boolean }) => {
return (
<>
<List component={'div'} sx={{ bgcolor: 'var(--dockBackground)', width: '100%' }} disablePadding>
{categoryItems.map((item) => (
<PrefabListItem item={item} />
))}
</List>
</>
)
}

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

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

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

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 shelveslist: string[] = []
shelves.map(([category, items]) => {
shelveslist.push(category)
})

const onSearch = (text: string) => {
search.local.set(text)
if (searchTimeout.current) clearTimeout(searchTimeout.current)
searchTimeout.current = setTimeout(() => {
search.query.set(text)
}, 50)
}

return (
<List
sx={{ width: 300, height: 900, bgcolor: 'var(--dockBackground)' }}
subheader={
<div style={{ padding: '0.5rem' }}>
<Typography style={{ color: 'var(--textColor)', textAlign: 'center', textTransform: 'uppercase' }}>
{t('editor:layout.assetGrid.prefab')}
</Typography>
<InputText
placeholder={t('editor:layout.assetGrid.prefab-search')}
value={search.local.value}
sx={{ mt: 1 }}
onChange={(e) => onSearch(e.target.value)}
/>
</div>
}
>
<ScenePrefabListItem categoryItems={shelveslist} isCollapsed={!!search.query.value} />
</List>
)
}

export default PrefabList
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import { recursiveHipsLookup } from '@etherealengine/engine/src/avatar/AvatarBon
import { exportRelativeGLTF } from '../../functions/exportGLTF'
import { EditorState } from '../../services/EditorServices'
import BooleanInput from '../inputs/BooleanInput'
import { PropertiesPanelButton } from '../inputs/Button'
import { Button, PropertiesPanelButton } from '../inputs/Button'
import InputGroup from '../inputs/InputGroup'
import ModelInput from '../inputs/ModelInput'
import SelectInput from '../inputs/SelectInput'
Expand Down Expand Up @@ -139,6 +139,9 @@ export const ModelNodeEditor: EditorComponentType = (props) => {
{errors?.LOADING_ERROR ||
(errors?.INVALID_SOURCE && ErrorPopUp({ message: t('editor:properties.model.error-url') }))}
</InputGroup>
<Button onClick={() => modelComponent.dereference.set(true)} disabled={!modelComponent.src.value}>
Dereference
</Button>
<InputGroup name="Camera Occlusion" label={t('editor:properties.model.lbl-cameraOcclusion')}>
<BooleanInput
value={modelComponent.cameraOcclusion.value}
Expand Down
1 change: 1 addition & 0 deletions packages/editor/src/constants/AssetTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const ItemTypes = {
Node: 'Node',
Material: 'Material',
Lookdev: 'Lookdev',
Prefab: 'Prefab',
Component: 'Component'
}

Expand Down