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

Commit

Permalink
expand only root entity by default (#9319)
Browse files Browse the repository at this point in the history
  • Loading branch information
HexaField authored Nov 22, 2023
1 parent 51f6bf1 commit 8d3d20d
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 77 deletions.
16 changes: 9 additions & 7 deletions packages/editor/src/components/hierarchy/HeirarchyTreeWalker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import { Entity } from '@etherealengine/engine/src/ecs/classes/Entity'
import { getComponent, hasComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions'
import { entityExists } from '@etherealengine/engine/src/ecs/functions/EntityFunctions'
import { EntityTreeComponent } from '@etherealengine/engine/src/ecs/functions/EntityTree'
import { UUIDComponent } from '@etherealengine/engine/src/scene/components/UUIDComponent'
import { getState } from '@etherealengine/hyperflux'
import { EditorState } from '../../services/EditorServices'

export type HeirarchyTreeNodeType = {
depth: number
Expand All @@ -44,13 +47,9 @@ export type HeirarchyTreeCollapsedNodeType = { [key: number]: boolean }
/**
* treeWalker function used to handle tree.
*
* @param {entityNode} collapsedNodes
* @param {entityNode} expandedNodes
*/
export function* heirarchyTreeWalker(
treeNode: Entity,
selectedEntities: Entity[],
collapsedNodes: HeirarchyTreeCollapsedNodeType
): Generator<HeirarchyTreeNodeType> {
export function* heirarchyTreeWalker(treeNode: Entity, selectedEntities: Entity[]): Generator<HeirarchyTreeNodeType> {
if (!treeNode) return

const stack = [] as HeirarchyTreeNodeType[]
Expand All @@ -62,7 +61,10 @@ export function* heirarchyTreeWalker(

if (!entityExists(entityNode)) continue

const isCollapsed = collapsedNodes[entityNode]
const expandedNodes = getState(EditorState).expandedNodes
const entityUUID = getComponent(entityNode, UUIDComponent)

const isCollapsed = !expandedNodes[entityUUID]

const entityTreeComponent = getComponent(entityNode as Entity, EntityTreeComponent)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,12 @@ import AutoSizer from 'react-virtualized-auto-sizer'
import { FixedSizeList } from 'react-window'

import { AllFileTypes } from '@etherealengine/engine/src/assets/constants/fileTypes'
import { Entity } from '@etherealengine/engine/src/ecs/classes/Entity'
import { SceneState } from '@etherealengine/engine/src/ecs/classes/Scene'
import { getComponent, getOptionalComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions'
import { EntityTreeComponent, traverseEntityNode } from '@etherealengine/engine/src/ecs/functions/EntityTree'
import { GroupComponent } from '@etherealengine/engine/src/scene/components/GroupComponent'
import { NameComponent } from '@etherealengine/engine/src/scene/components/NameComponent'
import { getMutableState, getState, useHookstate } from '@etherealengine/hyperflux'
import { getMutableState, getState, none, useHookstate } from '@etherealengine/hyperflux'

import MenuItem from '@mui/material/MenuItem'
import { PopoverPosition } from '@mui/material/Popover'
Expand All @@ -58,7 +57,7 @@ import useUpload from '../assets/useUpload'
import { PropertiesPanelButton } from '../inputs/Button'
import { ContextMenu } from '../layout/ContextMenu'
import { updateProperties } from '../properties/Util'
import { HeirarchyTreeCollapsedNodeType, HeirarchyTreeNodeType, heirarchyTreeWalker } from './HeirarchyTreeWalker'
import { HeirarchyTreeNodeType, heirarchyTreeWalker } from './HeirarchyTreeWalker'
import { HierarchyTreeNode, HierarchyTreeNodeProps, RenameNodeData, getNodeElId } from './HierarchyTreeNode'
import styles from './styles.module.scss'

Expand Down Expand Up @@ -86,7 +85,7 @@ export default function HierarchyPanel() {
const onUpload = useUpload(uploadOptions)
const selectionState = useHookstate(getMutableState(SelectionState))
const [renamingNode, setRenamingNode] = useState<RenameNodeData | null>(null)
const [collapsedNodes, setCollapsedNodes] = useState<HeirarchyTreeCollapsedNodeType>({})
const expandedNodes = useHookstate(getMutableState(EditorState).expandedNodes)
const [nodes, setNodes] = useState<HeirarchyTreeNodeType[]>([])
const nodeSearch: HeirarchyTreeNodeType[] = []
const [selectedNode, _setSelectedNode] = useState<HeirarchyTreeNodeType | null>(null)
Expand All @@ -106,57 +105,70 @@ export default function HierarchyPanel() {
if (searchHierarchy.length > 0) {
const condition = new RegExp(searchHierarchy.toLowerCase())
nodes.forEach((node) => {
if (node.entity && condition.test(getComponent(node.entity as Entity, NameComponent)?.toLowerCase() ?? ''))
if (node.entity && condition.test(getComponent(node.entity, NameComponent)?.toLowerCase() ?? ''))
nodeSearch.push(node)
})
}

useEffect(() => {
if (!activeScene.value) return

const rootUUID = SceneState.getScene(activeScene.value)!.scene.root!

getMutableState(EditorState).expandedNodes.set({ [rootUUID]: true })
}, [activeScene])

useEffect(() => {
if (!activeScene.value) return
setNodes(
Array.from(
heirarchyTreeWalker(
SceneState.getRootEntity(getState(SceneState).activeScene!),
selectionState.selectedEntities.value,
collapsedNodes
selectionState.selectedEntities.value
)
)
)
}, [collapsedNodes, activeScene, selectionState.selectedEntities, entities])
}, [expandedNodes, activeScene, selectionState.selectedEntities, entities])

const setSelectedNode = (selection) => !lockPropertiesPanel.value && _setSelectedNode(selection)

/* Expand & Collapse Functions */
const expandNode = useCallback(
(node: HeirarchyTreeNodeType) => {
setCollapsedNodes({ ...collapsedNodes, [node.entity]: false })
const uuid = getComponent(node.entity, UUIDComponent)
getMutableState(EditorState).expandedNodes[uuid].set(true)
},
[collapsedNodes]
[expandedNodes]
)

const collapseNode = useCallback(
(node: HeirarchyTreeNodeType) => {
setCollapsedNodes({ ...collapsedNodes, [node.entity]: true })
const uuid = getComponent(node.entity, UUIDComponent)
getMutableState(EditorState).expandedNodes[uuid].set(none)
},
[collapsedNodes]
[expandedNodes]
)

const expandChildren = useCallback(
(node: HeirarchyTreeNodeType) => {
handleClose()
traverseEntityNode(node.entity as Entity, (child) => (collapsedNodes[child] = false))
setCollapsedNodes({ ...collapsedNodes })
traverseEntityNode(node.entity, (child) => {
const uuid = getComponent(child, UUIDComponent)
getMutableState(EditorState).expandedNodes[uuid].set(true)
})
},
[collapsedNodes]
[expandedNodes]
)

const collapseChildren = useCallback(
(node: HeirarchyTreeNodeType) => {
handleClose()
traverseEntityNode(node.entity as Entity, (child) => (collapsedNodes[child] = true))
setCollapsedNodes({ ...collapsedNodes })
traverseEntityNode(node.entity, (child) => {
const uuid = getComponent(child, UUIDComponent)
getMutableState(EditorState).expandedNodes[uuid].set(none)
})
},
[collapsedNodes]
[expandedNodes]
)

/* Event handlers */
Expand Down Expand Up @@ -211,16 +223,17 @@ export default function HierarchyPanel() {

const onToggle = useCallback(
(_, node: HeirarchyTreeNodeType) => {
if (collapsedNodes[node.entity as Entity]) expandNode(node)
else collapseNode(node)
const uuid = getComponent(node.entity, UUIDComponent)
if (expandedNodes.value[uuid]) collapseNode(node)
else expandNode(node)
},
[collapsedNodes, expandNode, collapseNode]
[expandedNodes, expandNode, collapseNode]
)

const onKeyDown = useCallback(
(e: KeyboardEvent, node: HeirarchyTreeNodeType) => {
const nodeIndex = nodes.indexOf(node)
const entityTree = getComponent(node.entity as Entity, EntityTreeComponent)
const entityTree = getComponent(node.entity, EntityTreeComponent)
switch (e.key) {
case 'ArrowDown': {
e.preventDefault()
Expand Down Expand Up @@ -317,22 +330,22 @@ export default function HierarchyPanel() {
handleClose()

if (node.entity) {
const entity = node.entity as Entity
const entity = node.entity
setRenamingNode({ entity, name: getComponent(entity, NameComponent) })
} else {
// todo
}
}, [])

const onChangeName = useCallback(
(node: HeirarchyTreeNodeType, name: string) => setRenamingNode({ entity: node.entity as Entity, name }),
(node: HeirarchyTreeNodeType, name: string) => setRenamingNode({ entity: node.entity, name }),
[]
)

const onRenameSubmit = useCallback((node: HeirarchyTreeNodeType, name: string) => {
if (name) {
updateProperties(NameComponent, name, [node.entity])
const groups = getOptionalComponent(node.entity as Entity, GroupComponent)
const groups = getOptionalComponent(node.entity, GroupComponent)
if (groups) for (const obj of groups) if (obj) obj.name = name
}

Expand Down
16 changes: 8 additions & 8 deletions packages/editor/src/components/hierarchy/HierarchyTreeNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ export const HierarchyTreeNode = (props: HierarchyTreeNodeProps) => {

const nodeName = useComponent(node.entity, NameComponent).value

const errors = node.entity ? useOptionalComponent(node.entity as Entity, ErrorComponent) : undefined
const errors = node.entity ? useOptionalComponent(node.entity, ErrorComponent) : undefined

const sceneAssetLoading = useOptionalComponent(node.entity as Entity, SceneAssetPendingTagComponent)
const sceneAssetLoading = useOptionalComponent(node.entity, SceneAssetPendingTagComponent)

const onClickToggle = useCallback(
(e: MouseEvent) => {
Expand Down Expand Up @@ -157,18 +157,18 @@ export const HierarchyTreeNode = (props: HierarchyTreeNodeProps) => {
let beforeNode: Entity

if (place === 'Before') {
const entityTreeComponent = getComponent(node.entity as Entity, EntityTreeComponent)
const entityTreeComponent = getComponent(node.entity, EntityTreeComponent)
parentNode = entityTreeComponent?.parentEntity!
beforeNode = node.entity as Entity
beforeNode = node.entity
} else if (place === 'After') {
const entityTreeComponent = getComponent(node.entity as Entity, EntityTreeComponent)
const entityTreeComponent = getComponent(node.entity, EntityTreeComponent)
parentNode = entityTreeComponent?.parentEntity!
const parentTreeComponent = getComponent(entityTreeComponent?.parentEntity!, EntityTreeComponent)
if (!node.lastChild && parentNode && parentTreeComponent?.children.length > node.childIndex + 1) {
beforeNode = parentTreeComponent.children[node.childIndex + 1]
}
} else {
parentNode = node.entity as Entity
parentNode = node.entity
}

if (!parentNode)
Expand Down Expand Up @@ -267,8 +267,8 @@ export const HierarchyTreeNode = (props: HierarchyTreeNodeProps) => {
preview(getEmptyImage(), { captureDraggingState: true })
}, [preview])

const editors = entityExists(node.entity as Entity)
? getAllComponents(node.entity as Entity)
const editors = entityExists(node.entity)
? getAllComponents(node.entity)
.map((c) => EntityNodeEditor.get(c)!)
.filter((c) => !!c)
: []
Expand Down
2 changes: 1 addition & 1 deletion packages/editor/src/functions/EditorControlFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ const scaleObject = (
transformComponent.scale.z === 0 ? Number.EPSILON : transformComponent.scale.z
)

updateComponent(entity as Entity, componentType, { scale: transformComponent.scale })
updateComponent(entity, componentType, { scale: transformComponent.scale })
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/editor/src/functions/traverseEarlyOut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default function traverseEarlyOut(entity: Entity, cb: (entity: Entity) =>

if (stopTravel) return stopTravel

const entityTreeComponent = getComponent(entity as Entity, EntityTreeComponent)
const entityTreeComponent = getComponent(entity, EntityTreeComponent)

const children = entityTreeComponent.children
if (!children) return stopTravel
Expand Down
1 change: 1 addition & 0 deletions packages/editor/src/services/EditorServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const EditorState = defineState({
projectName: null as string | null,
sceneName: null as string | null,
sceneModified: false,
expandedNodes: {} as Record<EntityUUID, true>,
lockPropertiesPanel: '' as EntityUUID,
panelLayout: {} as LayoutData
})
Expand Down
4 changes: 2 additions & 2 deletions packages/editor/src/systems/EditorControlSystem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -350,14 +350,14 @@ const reactor = () => {

for (const entity of sceneQuery()) {
if (!hasComponent(entity, TransformGizmoComponent)) continue
removeComponent(entity as Entity, TransformGizmoComponent)
removeComponent(entity, TransformGizmoComponent)
}
const lastSelection = selectedEntities[selectedEntities.length - 1].value
if (!lastSelection) return

if (typeof lastSelection === 'string') return // TODO : gizmo for 3d objects without Ids

setComponent(lastSelection as Entity, TransformGizmoComponent)
setComponent(lastSelection, TransformGizmoComponent)

// handle gizmo attachment
}, [selectionState.selectedParentEntities])
Expand Down
32 changes: 0 additions & 32 deletions packages/engine/src/assets/functions/exportModelGLTF.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,40 +23,11 @@ All portions of the code written by the Ethereal Engine team are Copyright © 20
Ethereal Engine. All Rights Reserved.
*/

import { Engine } from '../../ecs/classes/Engine'
import { Entity } from '../../ecs/classes/Entity'
import { getComponent } from '../../ecs/functions/ComponentFunctions'
import { EntityTreeComponent, iterateEntityNode } from '../../ecs/functions/EntityTree'
import { GroupComponent } from '../../scene/components/GroupComponent'
import { ModelComponent } from '../../scene/components/ModelComponent'
import { LocalTransformComponent } from '../../transform/components/TransformComponent'
import createGLTFExporter from './createGLTFExporter'

function composeScene(entity: Entity) {
iterateEntityNode(entity, (child) => {
if (child === entity) return
const entityTree = getComponent(child, EntityTreeComponent)
const parent = entityTree.parentEntity
if (!parent) {
console.error('invalid model state: missing parent entity')
return
}
const parentObject = getComponent(parent, GroupComponent)[0]
const object = getComponent(child, GroupComponent)[0]
const localTransform = getComponent(child, LocalTransformComponent)
parentObject.add(object)
object.matrix.copy(localTransform.matrix)
})
}

function decomposeScene(entity: Entity) {
iterateEntityNode(entity, (child) => {
if (child === entity) return
const object = getComponent(child, GroupComponent)[0]
Engine.instance.scene.add(object)
})
}

export default async function exportModelGLTF(
entity: Entity,
options = {
Expand All @@ -66,7 +37,6 @@ export default async function exportModelGLTF(
embedImages: true
}
) {
//composeScene(entity)
const scene = getComponent(entity, ModelComponent).scene!
const exporter = createGLTFExporter()
const modelName = options.path.split('/').at(-1)!.split('.').at(0)!
Expand All @@ -75,11 +45,9 @@ export default async function exportModelGLTF(
exporter.parse(
scene,
(gltf: ArrayBuffer) => {
//decomposeScene(entity)
resolve(gltf)
},
(error) => {
//decomposeScene(entity)
throw error
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export const HyperspaceTagComponent = defineComponent({
return {
// all internals
sceneVisible: true,
transition: createTransitionState(5, 'OUT'),
transition: createTransitionState(0.5, 'OUT'),
hyperspaceEffectEntity,
ambientLightEntity
}
Expand Down

0 comments on commit 8d3d20d

Please sign in to comment.